/* App frame, shared chrome, view bars and file-tree foundations. */
  /* ——— OS6, in the house style: as if Apple designed it. ———
     The light system palette carried from OS5 — SF throughout, hairline
     separators, white cards on grouped gray, a single blue tint — and the
     one loud thing, the glass dock carried from ArtifactOS through OS4 and
     OS5. */
  :root {
    --bg: #F2F2F7;            /* systemGroupedBackground */
    --card: #FFFFFF;
    --ink: #1C1C1E;           /* label */
    --ink2: #8A8A8E;          /* secondaryLabel */
    --ink3: #AEAEB2;          /* tertiary */
    --line: rgba(60, 60, 67, 0.12);    /* separator */
    --fill: rgba(118, 118, 128, 0.12); /* systemFill */
    --tint: #0A7AFF;
    --radius: 12px;
    --tap: 44px;
    --top-h: 52px;
  }
  * { box-sizing: border-box; }
  /* The document is nailed to the viewport: the PWA itself never
     scrolls and never rubber-bands — only designated scrollers inside
     it move, and a gesture they cannot take dies quietly instead of
     bouncing the whole room, dock and all. Global, by the owner's
     order, the day the board's longest column scrolled the app. */
  html, body {
    margin: 0;
    height: 100%;
    overflow: hidden;
    overscroll-behavior: none;
    background: var(--bg);
    color: var(--ink);
    font-family: -apple-system, system-ui, "Helvetica Neue", sans-serif;
    -webkit-text-size-adjust: 100%;
    -webkit-tap-highlight-color: transparent;
  }
  body { position: fixed; inset: 0; width: 100%; }
  button { font: inherit; color: inherit; background: none; border: none; padding: 0; text-align: inherit; touch-action: manipulation; }
  :focus-visible { outline: 2px solid rgba(10, 122, 255, 0.55); outline-offset: 2px; border-radius: 6px; }

  /* ——— the app frame: the ArtifactOS anchoring, taken back whole. A
     normal-flow container of exactly the dynamic viewport; the dock hangs
     absolute at its bottom edge, and the scroll lives inside main. iOS
     ends the fixed-position viewport well above the app's real bottom, so
     anchoring to this box is what lands the tray on the real edge. ——— */
  .app {
    position: relative;
    height: 100dvh;
    display: flex; flex-direction: column;
  }

  /* ——— chrome: one bar. On home, hamburger and owner hold the ends;
     between them the moon, the view wheel, and the dropdown. Inside a
     card, back left and the trail in the middle. Inbox is not a fifth
     icon: it lives under the owner, and a count sits on that seat. ——— */
  .top {
    flex: 0 0 auto;
    position: relative;
    display: flex; align-items: center; justify-content: space-between;
    height: calc(var(--top-h) + env(safe-area-inset-top));
    padding: env(safe-area-inset-top) 4px 0;
    background: rgba(242, 242, 247, 0.62);
    -webkit-backdrop-filter: blur(20px) saturate(1.6);
    backdrop-filter: blur(20px) saturate(1.6);
    border-bottom: 0.5px solid var(--line);
    z-index: 6;
  }
  /* Home is taller by the wheel's own height, so the flanking
     icons and the scrollable seats share one row instead of stacking. */
  .top:has(.viewbar) {
    height: calc(72px + env(safe-area-inset-top));
    align-items: stretch;
  }
  .topbtn {
    position: relative;
    width: var(--tap); height: var(--tap); flex: 0 0 auto;
    display: inline-flex; align-items: center; justify-content: center;
    color: var(--ink);
    border-radius: 12px;
  }
  .topbtn:active { background: var(--fill); }
  .msgbadge {
    position: absolute;
    top: 6px; right: 4px;
    min-width: 16px; height: 16px;
    padding: 0 4px;
    border-radius: 999px;
    background: #FF3B30;
    color: #fff;
    font-size: 11px; font-weight: 700;
    line-height: 16px; text-align: center;
    letter-spacing: 0;
  }
  .toptitle {
    flex: 1; text-align: center;
    font-size: 1.0625rem; font-weight: 600; letter-spacing: -0.01em;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .toppath {
    flex: 1; min-width: 0;
    display: flex; align-items: center; gap: 0.35rem;
    overflow-x: auto; scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    white-space: nowrap;
    font-size: 1.0625rem; font-weight: 600; letter-spacing: -0.01em;
    padding: 0 2px;
  }
  .toppath::-webkit-scrollbar { display: none; }
  /* Centred while it fits, scrollable once it does not: auto margins on
     the ends collapse exactly when the trail overflows. */
  .toppath > :first-child { margin-left: auto; }
  .toppath > :last-child { margin-right: auto; }
  .toppath .crumb { color: var(--tint); flex: 0 0 auto; }
  .toppath .crumb:active { opacity: 0.55; }
  .toppath .sep { color: var(--ink3); flex: 0 0 auto; font-weight: 400; }
  .toppath .here { color: var(--ink); flex: 0 0 auto; }
  .topback {
    display: inline-flex; align-items: center; gap: 2px;
    min-width: var(--tap); height: var(--tap); padding: 0 8px;
    color: var(--tint); font-size: 1.0625rem;
  }
  .topback:active { opacity: 0.55; }
  .topcluster { display: inline-flex; align-items: center; flex: 0 0 auto; }
  .backchev { font-size: 1.6rem; line-height: 1; margin-top: -3px; }

  main {
    flex: 1; min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    /* The content clears the tray and the Home indicator on its way out —
       the OS4 number, kept: clearance lives in the scroll content, never
       on the tray. */
    padding: 0.45rem 1rem calc(168px + env(safe-area-inset-bottom));
  }
  .page { max-width: 42rem; margin: 0 auto; }

  /* ——— the window opens. A view that scrolls inside itself — board,
     table, graph, loose — owns the room to the bottom edge: main stops
     scrolling, the view fills it, and content clears the dock inside
     its own scroll, sliding under the glass. The sticky heads are the
     only ceiling; nothing ends short of the bottom. ——— */
  main:has(#board[data-view="kanban"]),
  main:has(#board[data-view="table"]),
  main:has(#board[data-view="graph"]),
  main:has(#board[data-view="loose"]) {
    overflow: hidden;
    padding-bottom: 0;
  }
  main:has(#board[data-view="kanban"]) .page,
  main:has(#board[data-view="table"]) .page,
  main:has(#board[data-view="graph"]) .page,
  main:has(#board[data-view="loose"]) .page { height: 100%; }
  /* A windowed view shares its column with the capture field: the
     board is a flex column, capture keeps its height, the view takes
     the rest. */
  #board[data-view="kanban"],
  #board[data-view="table"],
  #board[data-view="graph"],
  #board[data-view="loose"] {
    height: 100%;
    display: flex; flex-direction: column;
  }
  #board[data-view="kanban"] .kanban,
  #board[data-view="table"] .sheetwrap,
  #board[data-view="graph"] .canvas,
  #board[data-view="loose"] .canvas {
    flex: 1; min-height: 0; height: auto;
  }
  /* The table's last rows clear the dock inside the sheet's own scroll. */
  .sheet { margin-bottom: calc(168px + env(safe-area-inset-bottom)); }

  /* the view bar: lives in the top now. A weightier segmented control —
     icons with their own presence, though never the dock's — and a
     tuning row that unfolds beneath it, holding each view's
     sub-specifications. */
  .viewbar {
    flex: 1; min-width: 0;
    display: flex; flex-direction: column; justify-content: center;
    position: relative;
  }

  /* ——— the top wheel: hamburger, moon, the seats, dropdown, owner —
     four flanking icons and a scrollable middle that takes whatever
     they leave, so the wheel still has room to mean something. ——— */
  .viewrow {
    display: flex; align-items: center; gap: 0.2rem;
    width: 100%;
  }
  .sidebtn {
    width: 36px; height: 36px; flex: 0 0 auto;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%;
    border: 0.5px solid rgba(255, 255, 255, 0.8);
    background: rgba(248, 248, 250, 0.5);
    -webkit-backdrop-filter: blur(24px) saturate(1.5);
    backdrop-filter: blur(24px) saturate(1.5);
    box-shadow: 0 3px 12px rgba(30, 32, 38, 0.12);
    color: var(--ink2);
  }
  .sidebtn[aria-pressed="true"], .sidebtn[aria-expanded="true"] { color: var(--tint); }
  .vdrop svg { transition: transform 220ms ease; }
  .vdrop[aria-expanded="true"] svg { transform: rotate(180deg); }
  /* The tray flexes between the four flanking icons — never a
     percentage of a row that is itself sizing to the tray, which is
     how the moon fell off the left edge once. No max-width: the
     wheel takes what hamburger, moon, dropdown and owner leave. */
  .vtray {
    position: relative;
    display: flex;
    flex: 1 1 auto; min-width: 0;
    overflow: hidden;
    border: 0.5px solid rgba(255, 255, 255, 0.8);
    border-radius: 22px;
    background: rgba(248, 248, 250, 0.5);
    -webkit-backdrop-filter: blur(24px) saturate(1.5);
    backdrop-filter: blur(24px) saturate(1.5);
    box-shadow: 0 5px 18px rgba(30, 32, 38, 0.12);
  }
  .vwheel {
    display: flex; align-items: center; gap: 3px;
    flex: 1; min-width: 0; height: 64px;
    overflow-x: auto; overflow-y: hidden;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    touch-action: pan-x;
    scrollbar-width: none;
    scroll-snap-type: x mandatory;
    padding: 4px 0;
    scroll-padding-inline: calc(50% - 30px);
  }
  .vwheel::-webkit-scrollbar { display: none; }
  /* Pads, not padding: a flex scroller does not count its own padding
     toward scrollWidth, and two seats fit inside the tray without it —
     which is how Board could be seen and never reached. The pads are
     flex items, so they actually extend the scroll. */
  .vpad {
    flex: 0 0 calc(50% - 30px);
    width: calc(50% - 30px);
    height: 1px;
    pointer-events: none;
  }
  .vseat {
    flex: 0 0 auto;
    display: flex; align-items: center; justify-content: center;
    width: 60px; height: 56px;
    border-radius: 16px;
    scroll-snap-align: center;
    transform-origin: center center;
    transition: transform 200ms ease-out, opacity 200ms ease-out;
  }
  .vicon {
    width: 40px; height: 40px;
    display: inline-flex; align-items: center; justify-content: center;
    border: 0.5px solid rgba(255, 255, 255, 0.55);
    border-radius: 12px;
    background: rgba(118, 118, 128, 0.10);
    color: var(--ink2);
    transition: width 200ms ease, height 200ms ease, border-radius 200ms ease,
      box-shadow 200ms ease, transform 200ms ease;
  }
  .vicon svg { width: 20px; height: 20px; }
  .vseat-centred .vicon {
    width: 50px; height: 50px;
    border-radius: 14px;
    background: var(--card);
    color: var(--tint);
    box-shadow: 0 4px 12px rgba(30, 32, 38, 0.16);
    transform: translateY(-1px);
  }
  .vseat-centred .vicon svg { width: 25px; height: 25px; }
  .nearside .vicon svg { opacity: 0.15; }

  /* the file tree: everything on the moon base, folded into disclosure
     rows */
  .filerow {
    display: flex; align-items: center; gap: 0.45rem;
    padding: 0.5rem 0.7rem;
    font-size: 0.9375rem;
  }
  .filerow + .filerow { border-top: 0.5px solid var(--line); }
  .filedisc {
    width: 22px; height: 22px; flex: 0 0 auto;
    display: inline-flex; align-items: center; justify-content: center;
    color: var(--ink3);
  }
  .filedisc.leaf { visibility: hidden; }
  .fchev { display: inline-block; font-size: 1.05rem; line-height: 1; transition: transform 160ms ease; }
  .fchev.open { transform: rotate(90deg); }
  .fileicon { color: var(--tint); display: inline-flex; flex: 0 0 auto; }
  .filelabel {
    flex: 1; min-width: 0; text-align: left;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .filelabel:active { opacity: 0.55; }
  .dropbox {
    background: var(--card);
    border-radius: var(--radius);
    padding: 0.7rem 0.85rem 0.85rem;
    margin-bottom: 0.75rem;
  }
  .drophead {
    font-size: 0.8125rem; font-weight: 600; color: var(--ink2);
    margin: 0 0 0.45rem;
  }
  .droprow {
    display: flex; align-items: center; gap: 0.5rem;
    padding: 0.4rem 0;
    border-top: 0.5px solid var(--line);
    font-size: 0.875rem;
  }
  .droprow:first-of-type { border-top: none; }
  .dropname { flex: 1; min-width: 0; text-align: left; }
  .dropmeta { color: var(--ink2); font-size: 0.75rem; flex: 0 0 auto; }
  .dropdel { color: var(--tint); font-size: 0.8125rem; flex: 0 0 auto; }
  .dropadd { margin-top: 0.55rem; }
  .dropadd input[type="file"] { width: 100%; font: inherit; }
  .sharedby { color: var(--ink2); font-size: 0.75rem; margin-top: 0.2rem; }
  .memberbox { margin: 0.4rem 0 0.8rem; }
  .memberrow {
    display: flex; align-items: center; gap: 0.45rem;
    padding: 0.3rem 0; font-size: 0.875rem;
  }
  .convwell {
    margin: 0.85rem 0 0.4rem;
    padding-top: 0.55rem;
    border-top: 0.5px solid var(--line);
  }
  .convhead {
    font-size: 0.8125rem; font-weight: 600; color: var(--ink2);
    margin: 0 0 0.4rem;
  }
  .convrow { padding: 0.35rem 0; border-top: 0.5px solid var(--line); }
  .convrow:first-of-type { border-top: none; }
  .convbody { font-size: 0.9375rem; }
  .views {
    display: flex; width: fit-content;
    background: rgba(242, 242, 247, 0.82);
    -webkit-backdrop-filter: blur(16px) saturate(1.5);
    backdrop-filter: blur(16px) saturate(1.5);
    border-radius: 11px; padding: 3px;
    box-shadow: 0 2px 10px rgba(30, 32, 38, 0.10);
  }
  .views button {
    display: inline-flex; align-items: center; justify-content: center;
    color: var(--ink2);
    padding: 8px 13px; border-radius: 8px;
  }
  .views button svg { display: block; }
  .views button[aria-pressed="true"] {
    background: var(--card);
    color: var(--tint);
    box-shadow: 0 1px 3px rgba(30, 32, 38, 0.14);
  }
  .optbtn {
    width: 38px; height: 38px;
    display: inline-flex; align-items: center; justify-content: center;
    color: var(--ink2);
    background: rgba(242, 242, 247, 0.82);
    -webkit-backdrop-filter: blur(16px) saturate(1.5);
    backdrop-filter: blur(16px) saturate(1.5);
    border-radius: 11px;
    box-shadow: 0 2px 10px rgba(30, 32, 38, 0.10);
  }
  .optbtn[aria-expanded="true"] { color: var(--tint); }
  .viewopts { display: none; }
  /* The open sub-menu floats over the cards at eighty percent of the bar,
     translucent on purpose: the room shows through, nothing beneath
     moves, and the see-through glass quietly asks to be closed again. */
  .viewopts.open {
    position: absolute; top: calc(100% + 0.4rem); left: 50%;
    transform: translateX(-50%);
    width: 80%; max-width: 316px;
    display: flex; align-items: center; flex-wrap: wrap; justify-content: center;
    gap: 0.5rem;
    background: rgba(242, 242, 247, 0.48);
    -webkit-backdrop-filter: blur(18px) saturate(1.5);
    backdrop-filter: blur(18px) saturate(1.5);
    border: 0.5px solid rgba(255, 255, 255, 0.55);
    border-radius: 11px; padding: 8px 14px;
    box-shadow: 0 4px 16px rgba(30, 32, 38, 0.12);
    font-size: 0.8125rem; font-weight: 500; color: var(--ink2);
  }
  .optnote { display: inline-flex; align-items: center; gap: 0.4rem; }
  .optic {
    width: 32px; height: 32px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 10px;
    border: 0.5px solid rgba(255, 255, 255, 0.5);
    background: rgba(118, 118, 128, 0.12);
    color: var(--ink2);
  }
  .optic[aria-pressed="true"] {
    background: var(--card); color: var(--tint);
    box-shadow: 0 2px 8px rgba(30, 32, 38, 0.14);
  }

