/* ═══════════════════════════════════════════════════════════════════════════
   Shown design system — styles.css (v2, 2026-10-02)

   One stylesheet, one foundation, two languages. DESIGN.md (beside this file)
   explains every part of it.

   PART I    STUDIO — ShownRoom's stylesheet, VERBATIM: the tokens, the light
             theme, the base and every component of the dashboard. This is the
             foundation both languages stand on. Do not edit it here; it is
             copied from shownroom-react/src/styles.css (after commit 037cbb2,
             with the 2026-09-30 work in it) and DESIGN.md Part I quotes it.
   PART II   STUDIO ADDITIONS — the authoring pieces the Learning Map editor
             needed and ShownRoom has no equivalent for (ordered groups,
             readiness checks, "In the course" text, the question editor). They
             reuse ShownRoom's own fields (.nt-k, .nt-in) and checkbox (.tdcheck).
   PART III  STAGE — what employees take and read (the course player): one
             thing at a time, bigger type, a little motion.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ═══════════════════════════════════════════════════════════════════════════
   PART I · STUDIO — ShownRoom's stylesheet, verbatim
   ═══════════════════════════════════════════════════════════════════════════ */
:root{
  --bg:#000;--bg-elev:#0a0a0a;--bg-elev2:#111113;
  --hover:rgba(255,255,255,.055);--active:rgba(255,255,255,.09);
  --line:rgba(255,255,255,.09);--line-soft:rgba(255,255,255,.06);
  --txt:#ededed;--txt-2:#a1a1a1;--txt-3:#6e6e6e;
  --accent:#0070f3;--radius:6px;--sw:250px;
  /* mirrors of STATUS_COLORS, for the few places CSS needs a status hue */
  --st-blocked:#f5405e;--st-qa:#f5a623;--st-done:#45d267;
  /* thread rails in the List view — heavier than --line so the nesting
     reads at a glance, the way Reddit's comment threads do. */
  --thread:#313134;--thread-hi:#6f6f74;
  /* the border a control takes on hover — one hex in 26 places before it
     had a name, and the single thing that kept the light theme looking
     half-painted */
  --line-hi:#3a3a44;
  /* "this is live" — the Jam board's socket. Not a status, so not a mirror of
     STATUS_COLORS, and a touch cooler than Done's green so the two never read
     as the same claim */
  --live:#3ecf8e;
  /* Roles the light theme needs a different answer for. Each one's value
     here is what the rules wrote raw before, so dark renders as it did. */
  --bg-side:var(--bg);            /* the sidebar's ground */
  --side-line:var(--line);        /* the sidebar's edge */
  --raise:var(--bg-elev2);        /* what floats or is picked up: menus, popovers, cards */
  --well:#050506;                 /* a lane sunk below the surface it sits in */
  --lit:#fff;                     /* text lit on a neutral ground: hover, selected */
  --tint:#fff;                    /* what faint washes are cut from: white over dark, black over light */
  --nav:var(--txt-2);             /* a sidebar row at rest */
  --sel:var(--active);--sel-txt:#fff;              /* the row you are on */
  --btn:#ededed;--btn-ink:#000;--btn-hi:#fff;      /* the primary button */
  --inv:#ededed;--inv-ink:#000;                    /* a toast: the inverse of the page */
  --glass:rgba(12,12,12,.9);      /* controls floating over a canvas */
  --mark:#eef1f6;                 /* a solid mark on a chart */
  /* A chart mark takes this much of its row's hue (--t): none in dark, where
     marks are light shapes; a deep shade of it in light, so a mark reads as
     part of its bar rather than a black shape laid on top. */
  --mark-t:0%;--mark-p:0%;          /* ahead / passed: how much of the row's ink a mark takes */
  --mark-edge:rgba(255,255,255,.66); /* a mark still ahead: its outline, or its whole fill when it has no outline */
  --mark-ring:var(--mark);        /* the edge of a passed mark */
  --scroll:#222;                  /* scrollbar thumb */
  --warn:#e8a33d;                 /* "not decided yet", not a status */
  --shade:1;                      /* how dark a floating thing's shadow is */
  /* Colour on a light ground. A hue set as TEXT is capped at this OKLCH
     lightness, which keeps its hue and chroma and makes every hue read at
     the same weight (about 4.4-5.5:1 on white). A FILL darkened toward
     near-black keeps most of its hue instead: --dk for a plain fill, --dkg
     for one carrying a white glyph or text, which needs more depth. All three
     are 1 on dark: no cap, and the darkening exactly as written. */
  --ink-l:1;--dk:1;--dkg:1;
  /* A sheet pill: its fill (this much of the hue, into this) and its text
     (this lightness, this much of the hue's chroma). Dark: white on the hue
     darkened a little. Light: the hue's own ink on a pastel of it, the way a
     spreadsheet's coloured chips read on white. */
  --pj-t:82%;--pj-k:#0b0b0e;--pj-l:1;--pj-c:0;
}

/**
 * Light, as a token override and nothing else (2026-09-30, asked for: the
 * colour scheme of a white-canvas task app, in a dark rich blue where it has
 * orange).
 * - A white canvas, and a sidebar in a warm off-white with no edge of its own.
 * - Near-black type, hairlines that barely show, and shadows at a third of
 *   their dark strength.
 * - One accent, #1c3fbf, for what is picked and what acts: the row you are on
 *   is tinted with it, and the primary button is filled with it.
 *
 * Every raw colour that assumed a dark ground is a token above, whose dark
 * value is what the rule wrote before. So this block is the whole theme.
 *
 * Still dark, on purpose:
 * - the video player and the tape thumbnails;
 * - the drawn artifacts, which are paper and slate with their own light;
 * - the doors, which draw before the app has read the theme.
 *
 * The accent is the one hue that changes. #0070f3 is the dark theme's, and on
 * white it reads as a link. The status hues do not change: a theme is not a
 * reason for QA amber to stop being QA.
 */
:root[data-theme="light"]{
  --bg:#ffffff;--bg-side:#fcfaf8;--bg-elev:#ffffff;--bg-elev2:#fcfaf8;
  --raise:#ffffff;--well:#f5f3f0;
  --hover:rgba(40,32,24,.045);--active:rgba(40,32,24,.075);
  --line:#e8e5e0;--line-soft:#f0eee9;--line-hi:#d4d0c9;
  --txt:#202020;--txt-2:#5c5a56;--txt-3:#87847f;
  --thread:#ddd9d2;--thread-hi:#aaa59d;
  --accent:#1c3fbf;
  --lit:#111;--tint:#000;--nav:var(--txt);
  --sel:color-mix(in srgb,var(--accent) 9%,#fff);--sel-txt:var(--accent);
  --btn:var(--accent);--btn-ink:#fff;--btn-hi:color-mix(in srgb,var(--accent) 84%,#000);
  --inv:#262626;--inv-ink:#fff;
  --glass:rgba(255,255,255,.9);
  --mark-p:100%;--mark-t:60%;--mark-edge:transparent;--mark-ring:#fff;
  --scroll:#e2ded7;
  --shade:.3;
  --ink-l:.55;--dk:.3;--dkg:.65;
  --pj-t:24%;--pj-k:#fff;--pj-l:.42;--pj-c:1;
}
*{box-sizing:border-box}
html,body,#root{height:100%}
body{margin:0;background:var(--bg);color:var(--txt);
  font-family:"Geist",-apple-system,BlinkMacSystemFont,"Segoe UI",Inter,Roboto,sans-serif;
  font-size:14px;line-height:1.45;-webkit-font-smoothing:antialiased;letter-spacing:-.006em}
button{font-family:inherit;color:inherit;cursor:pointer;border:none;background:none;padding:0}
a{color:inherit;text-decoration:none}
.mono,.link-url,.badge{font-family:"Geist Mono",ui-monospace,monospace}
::-webkit-scrollbar{width:8px;height:8px}
::-webkit-scrollbar-thumb{background:var(--scroll);border-radius:8px}

/* ---------- shell ---------- */
.app{display:flex;height:100%}
.sidebar{width:var(--sw);flex:0 0 auto;border-right:1px solid var(--side-line);display:flex;flex-direction:column;background:var(--bg-side)}
.brandrow{padding:14px 16px}
/* the wordmark is the logo file (Wordmark.jsx), white on transparent;
   the light theme turns it black rather than shipping a second file */
.wordmark{display:block;width:auto;user-select:none;-webkit-user-drag:none}
:root[data-theme="light"] .wordmark{filter:invert(1)}
.nav{flex:1;overflow-y:auto;padding:6px 10px}
.grp{margin-top:16px}
.grp-h{padding:0 8px 6px;color:var(--txt-3);font-size:11px;font-weight:500}
.nav-item,.launch-item{display:flex;align-items:center;gap:10px;width:100%;padding:7px 8px;border-radius:var(--radius);color:var(--nav);font-size:13.5px;text-align:left}
.nav-item .ico,.foot-item .ico{width:16px;height:16px;flex:none;display:grid;place-items:center;color:currentColor}
.nav-item:hover,.launch-item:hover{background:var(--hover);color:var(--txt)}
.launch-item.active,.nav-item.active{background:var(--sel);color:var(--sel-txt)}
.nav-item.active .badge{color:currentColor;opacity:.8}
/* places the real tool has that aren't built here yet — they stay in the
   map, they just don't answer */
.nav-item.inert{cursor:default}
.nav-item.inert:hover{background:transparent;color:var(--txt-2)}
/* three short groups rather than one long one, so the headings sit closer */
.nav .grp+.grp{margin-top:13px}
/* A near-white tile on purpose: favicons are drawn for light browser tabs,
   so a dark mark on a dark chip disappears — one client's did. */
.lico{overflow:hidden;display:grid;place-items:center;flex:none;
  background:#f1f1f1;box-shadow:inset 0 0 0 1px rgba(0,0,0,.12)}
/* Favicons arrive at every scale — some bleed to the edge, some are already
   inset — so "cover" made the outline round the mark look different on every
   row. Contain plus a proportional inset gives every mark the same margin. */
.lico img{width:100%;height:100%;display:block;box-sizing:border-box;
  object-fit:contain;padding:16%}

.lico.fallback{font-weight:700;color:#fff;text-transform:uppercase;box-shadow:none}
.lname{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.badge{margin-left:auto;font-size:11px;color:var(--txt-3)}
.tagpill{margin-left:auto;font-size:10px;color:var(--txt-3);border:1px solid var(--line);border-radius:20px;padding:1px 7px}
.side-foot{border-top:1px solid var(--line);padding:8px}
.foot-item{display:flex;align-items:center;gap:10px;width:100%;padding:7px 8px;border-radius:var(--radius);color:var(--nav);font-size:13.5px}
.main{flex:1;min-width:0;display:flex;flex-direction:column}
.topbar{height:42px;border-bottom:1px solid var(--line);display:flex;align-items:center;padding:0 12px;font-size:13px;color:var(--txt-3)}
.crumb-sep{margin:0 8px;color:var(--txt-3)}
.content{flex:1;overflow-y:auto;padding:22px 26px 60px;scrollbar-gutter:stable}

/* the launch bar belongs to the window chrome, not to the page: it runs
   edge to edge under the breadcrumbs and stays put while you scroll */
.lc-head{position:sticky;top:-22px;z-index:6;display:flex;align-items:center;gap:11px;
  margin:-22px -26px 18px;padding:9px 12px;background:var(--bg);border-bottom:1px solid var(--line)}
.lc-tools{display:flex;align-items:center;gap:0;margin-left:-4px}
.lc-tool{width:24px;height:24px;border-radius:6px;display:grid;place-items:center;color:var(--txt-3)}
.lc-tool:hover{background:var(--hover);color:var(--txt)}
.lc-tool.on{color:var(--accent)}
.lc-tool.live{color:var(--txt-2)}
.lc-tool.off{color:var(--txt-3);opacity:.8}
.lc-tool.open{background:var(--hover);color:var(--txt)}
.lc-bellwrap{position:relative;display:inline-flex}
/* the launch header wears the launch mark; the coloured initial it used
   to draw was the one place in the app that ignored LaunchIcon */
.lc-head .lico{flex:none}
.lc-name{margin:0;font-size:17px;font-weight:600;letter-spacing:-.02em}
/**
 * The **enclosed group** — one track, holding its options.
 *
 * This is the app's one shape for "pick among these". Loose pills floating on
 * the page say each is its own button that happens to sit near the others;
 * a track says they are one control with several positions, which is what
 * they actually are. Anywhere a row of chips selects something, it gets this.
 *
 * `.segwrap` is the same track for groups whose children are not plain
 * buttons — the status filter's chips are a toggle and an × in one shell, so
 * they cannot be `.seg button`, but they belong in the same box.
 */
.seg,.segwrap{display:inline-flex;align-items:center;background:var(--bg-elev);
  border:1px solid var(--line);border-radius:9px;padding:2px}
.seg{margin-left:auto}
.segwrap{gap:2px;flex-wrap:wrap}
.seg button{display:inline-flex;align-items:center;gap:6px;padding:5px 12px;border-radius:6px;color:var(--txt-2);font-size:12.5px;font-weight:500}
.seg button:hover{color:var(--txt)}
/* The lit chip carries a **lit top edge** — one inset hairline of white at
   7%. It is what makes the selected position read as a raised key rather than
   a painted rectangle, and it was on the launch bar only; every enclosed
   track has it now, which is the point of there being one track language. */
.seg button.on{background:var(--active);color:var(--lit);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.07)}

/* ---------- home ---------- */
/* one column: the side panel's facts live in the Overview card now, so the
   page is the reading width every other page is */
.home{max-width:1180px;margin:0 auto}
.home-name{font-size:30px;font-weight:700;letter-spacing:-.01em;margin:0 0 4px}
.block{margin-top:26px}
.block-h{font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--txt-3);margin-bottom:10px}
.desc{margin:0;font-size:14px;line-height:1.6;color:var(--txt-2);max-width:62ch}

/* ---------- comments ---------- */
.cmts{display:flex;flex-direction:column;gap:16px;margin-bottom:16px}
.cmt{display:flex;gap:10px}
.cmt-body{flex:1;min-width:0}
.cmt-top{display:flex;align-items:center;gap:8px}
.cmt-who{font-size:12.5px;font-weight:600}
.cmt-at{font-size:11px;color:var(--txt-3);font-family:"Geist Mono",monospace}
.cmt-text{font-size:13px;color:var(--txt-2);line-height:1.55;margin:2px 0 0}
.cmt-empty{font-size:12.5px;color:var(--txt-3);margin:0 0 14px}
/* fills the block — a composer narrower than the comments above it read
   as a stray box rather than the bottom of the same section */
.cmt-composer{display:flex;flex-direction:column;gap:8px}
.cmt-composer textarea{width:100%;min-height:76px;resize:vertical;background:var(--bg-elev);
  border:1px solid var(--line);border-radius:10px;padding:10px 12px;color:var(--txt);
  font-size:13px;font-family:inherit;outline:none}
.cmt-composer textarea:focus{border-color:var(--accent)}
.btn-primary:disabled{opacity:.35;cursor:default}

/* ---------- zones ---------- */
/* The Overview panel's box (the workstream panels that also wore it are
   gone — see Workstreams.jsx). */
.zones{display:grid;grid-template-columns:1fr;gap:16px}
.zones + .zones{margin-top:16px}
/* No bottom padding — the last card sits flush with the zone's edge. */
.zone{padding:16px 18px 12px;display:flex;flex-direction:column;min-width:0;
  border:1px solid var(--line-soft);border-radius:12px;background:var(--bg)}
.zone-head{display:flex;align-items:center;gap:9px}
.zone-title{font-size:15px;font-weight:600;letter-spacing:-.01em}
.zone-cta{margin-left:auto;display:inline-flex;align-items:center;gap:5px;border:1px solid var(--line);border-radius:7px;padding:5px 10px;font-size:12px;font-weight:500;color:var(--txt-2);white-space:nowrap}
.zone-cta:hover{border-color:var(--line-hi);color:var(--txt);background:var(--bg-elev2)}

/* ---------- launch overview (production status + influencer rings) ---------- */
.overview-sub{margin-top:20px}
.overview-sub:first-of-type{margin-top:10px}
.overview-sub-divider{padding-top:20px;border-top:1px solid var(--line-soft)}
.overview-sub-h{font-size:11px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--txt-3);margin-bottom:12px}
.overview-sub-note{text-transform:none;font-weight:500;letter-spacing:0;color:var(--txt-3)}

.statusbar{display:flex;gap:2px;height:10px;border-radius:6px;overflow:hidden;background:var(--bg-elev)}
.statusbar-seg{height:100%}
.statuslegend{display:flex;flex-wrap:wrap;gap:8px 18px;margin-top:14px;font-size:12px;color:var(--txt-2)}
.statuslegend-item b{color:var(--txt);font-weight:600;margin-left:3px;font-family:"Geist Mono",monospace}
.statuslegend-dot{width:8px;height:8px;border-radius:50%;display:inline-block;margin-right:6px;vertical-align:middle}



.status-quiet{color:var(--txt-3);font-weight:500;white-space:nowrap}
.tag{display:inline-flex;align-items:center;white-space:nowrap;border-radius:5px;padding:4px 10px;font-size:11px;font-weight:600}
.tag.rev{background:#e8730f;color:#fff}
.avatar{border-radius:50%;display:grid;place-items:center;font-weight:700;color:#fff;flex:none;
  overflow:hidden;text-transform:uppercase}
.avatar.photo{background:color-mix(in srgb,var(--line-hi) 42%,var(--bg));box-shadow:inset 0 0 0 1px rgba(255,255,255,.1)}
.avatar img{width:100%;height:100%;object-fit:cover;display:block}
.dot{width:6px;height:6px;border-radius:50%;flex:none}
.bi{width:13px;height:13px;display:block;flex:none}
.chip{font-size:9px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;padding:2px 6px;border-radius:4px}

/* ---------- links ---------- */
.links{border:1px solid var(--line);border-radius:12px;overflow:hidden}
.link-row{display:flex;align-items:center;padding:11px 14px;border-bottom:1px solid var(--line)}
.link-row:last-child{border-bottom:none}
.link-row:hover{background:var(--bg-elev)}
.link-ico{width:16px;height:16px;display:inline-flex;align-items:center;justify-content:center;margin-right:10px;color:var(--txt-3)}
.link-ico svg{width:16px;height:16px}
.link-name{font-size:13.5px;font-weight:600;flex:1;min-width:0}
.link-url{font-size:12px;color:var(--txt-3);white-space:nowrap}

/* ---------- drawer ---------- */
.scrim{position:fixed;inset:0;background:rgba(0,0,0,.6);backdrop-filter:blur(2px);z-index:60}
.drawer{position:fixed;top:0;right:0;bottom:0;width:min(520px,92vw);background:var(--bg-elev);border-left:1px solid var(--line);z-index:61;display:flex;flex-direction:column;box-shadow:-20px 0 60px rgb(0 0 0/calc(.6*var(--shade)))}
.drawer-top{display:flex;align-items:center;gap:10px;padding:16px 18px;border-bottom:1px solid var(--line)}
.drawer-title{font-size:16px;font-weight:600;letter-spacing:-.02em;flex:1}
.drawer-x{width:30px;height:30px;border-radius:8px;display:grid;place-items:center;font-size:19px;color:var(--txt-2);border:1px solid var(--line)}
.drawer-x:hover{background:var(--hover);color:var(--lit)}
.drawer-body{flex:1;overflow-y:auto;padding:16px 18px 40px}
.drawer-body .crumbs{display:flex;align-items:center;gap:6px;font-size:12.5px;color:var(--txt-3);margin-bottom:16px}
.meta-row{display:grid;grid-template-columns:1fr 1fr;gap:14px;padding-bottom:16px;border-bottom:1px solid var(--line)}
.mk{font-size:10.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--txt-3);margin-bottom:6px}
.mv{display:flex;align-items:center;gap:8px;font-size:13.5px;font-weight:500}
.sec{margin-top:20px}
.sec-h{display:flex;align-items:center;gap:8px;font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--txt-3);margin-bottom:10px}
.sec-h .btn-ghost{margin-left:auto}
.sec-hint{font-weight:400;text-transform:none;letter-spacing:0}
.btn-ghost{border:1px dashed var(--line);border-radius:7px;padding:5px 10px;font-size:11.5px;color:var(--txt-2);text-transform:none;letter-spacing:0}
.btn-ghost:hover{border-style:solid;border-color:var(--line-hi);color:var(--lit)}
.btn-primary{background:var(--btn);color:var(--btn-ink);border-radius:var(--radius);padding:7px 12px;font-size:12.5px;font-weight:500;align-self:flex-end}
.btn-primary:hover{background:var(--btn-hi)}
.compose{display:flex;flex-direction:column;gap:8px}
.compose textarea{width:100%;min-height:76px;resize:vertical;background:var(--bg-elev);border:1px solid var(--line);border-radius:10px;padding:10px 12px;color:var(--txt);font-size:13px;font-family:inherit;outline:none}
.compose textarea:focus{border-color:var(--accent)}
.chip-link{display:inline-flex;align-items:center;gap:8px;border:1px solid var(--line);border-radius:20px;padding:5px 12px;font-size:12px;color:var(--txt-2);font-family:"Geist Mono",monospace}
.notes{display:flex;flex-direction:column;gap:8px}
.note{display:flex;align-items:flex-start;gap:10px;border:1px solid var(--line);border-left:2px solid #f5a623;border-radius:9px;background:var(--bg-elev);padding:11px 13px}
.note.done{border-left-color:#45d267;opacity:.62}
.note.done:hover{opacity:1}
.note-chk{width:16px;height:16px;flex:none;margin-top:1px;border-radius:5px;border:1.5px solid var(--line-hi);display:grid;place-items:center;color:transparent}
.note-chk:hover{border-color:#45d267;color:oklch(from #45d267 min(l, var(--ink-l)) c h)}
.note-chk.on{background:#45d267;border-color:#45d267;color:#000}
.note-body{flex:1;min-width:0}
.note-text{font-size:13px;line-height:1.45}
.note.done .note-text{color:var(--txt-3);text-decoration:line-through}
.note-meta{display:flex;align-items:center;gap:6px;margin-top:7px;font-size:11px;color:var(--txt-3);font-family:"Geist Mono",monospace}
.note-state{margin-left:auto;font-family:"Geist",sans-serif;font-weight:600}
.muted{color:var(--txt-3);font-size:12.5px;margin:0}
.old-toggle{font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--txt-3)}
.old-toggle:hover{color:var(--txt-2)}
.old-list{margin-top:10px;border:1px solid var(--line-soft);border-radius:9px;overflow:hidden}
.old-row{display:flex;align-items:center;gap:10px;width:100%;text-align:left;padding:10px 12px;font-size:12.5px;border-bottom:1px solid var(--line-soft)}
.old-row:last-child{border-bottom:none}
.old-row:hover{background:var(--bg-elev)}
.old-label{flex:1;min-width:0}
.old-count{font-size:11px;color:var(--txt-3);font-family:"Geist Mono",monospace}
.old-status{font-size:11px;color:var(--txt-3)}

@media (max-width:1100px){.home{grid-template-columns:1fr}}

/* ---------- list view ---------- */
/* Capped like every other reading surface. Full-bleed put the status six
   hundred pixels from the task it belonged to. */
.listwrap{width:100%;max-width:1180px;margin-inline:auto}
.lsec{margin-bottom:26px}
.lsec-h{display:flex;align-items:center;gap:9px;margin-bottom:10px}
.lsec-ico{width:24px;height:24px;border-radius:6px;background:var(--bg-elev);border:1px solid var(--line);
  display:grid;place-items:center;color:var(--txt-2);flex:none}
.lsec-name{font-size:14px;font-weight:600}
.lsec-count{font-size:11px;color:var(--txt-3);font-family:"Geist Mono",monospace}
.statusmix{margin-left:6px;flex:1;max-width:260px;height:6px;border-radius:6px;overflow:hidden;
  display:flex;gap:1px;background:color-mix(in srgb,var(--tint) 5%,transparent)}
.statusmix i{height:100%}
.lsec-cta{margin-left:auto;display:inline-flex;align-items:center;gap:5px;border:1px solid var(--line);
  border-radius:7px;padding:4px 10px;font-size:11.5px;font-weight:500;color:var(--txt-2);white-space:nowrap}
.lsec-cta:hover{border-color:var(--line-hi);color:var(--txt);background:var(--bg-elev2)}
/* the two ways to add to a workstream, side by side at the heading's end */
.lsec-ctas{margin-left:auto;display:inline-flex;align-items:center;gap:6px}
.lsec-ctas .lsec-cta{margin-left:0}
.tdesc{margin:0;font-size:13px;line-height:1.55;color:var(--txt-2);white-space:pre-wrap}
.tlinks{display:flex;flex-wrap:wrap;gap:6px;margin-top:10px}

.tblwrap{overflow:hidden;border:1px solid var(--line);border-radius:10px}
.tblwrap table{width:100%;border-collapse:collapse;font-size:13px}
.tblwrap th{text-align:left;color:var(--txt-3);font-size:11px;font-weight:500;letter-spacing:.02em;
  padding:10px 14px;background:var(--bg-elev)}
.tblwrap td{padding:11px 14px;border-top:1px solid var(--line-soft);vertical-align:middle}
.tblwrap tr.clk{cursor:pointer}
.tblwrap tr.clk:hover td{background:var(--hover)}
.tkt{font-weight:600}
.tkt-sum{color:var(--txt-3);margin-left:9px}
/* a pending version has no artifact yet — its date is when it's wanted, not when it landed */
.due-open{color:var(--txt-2)}
.ltbl th:nth-child(1),.ltbl td:nth-child(1){min-width:300px}
.ltbl th:nth-child(2),.ltbl td:nth-child(2){width:170px}
.ltbl th:nth-child(3),.ltbl td:nth-child(3){width:90px}
.ltbl th:nth-child(4),.ltbl td:nth-child(4){width:90px;font-family:"Geist Mono",monospace;font-size:11.5px}

/* list view — the second layer: notes written against a version.
   One indent step, shared by the padding and the thread rails, so they can't
   drift apart. 15px rather than 20: six levels of 20px eats 120px of the
   task column before the text starts, and this tree goes deeper than that. */
.ltbl{--step:15px;--tw:2px;
  /* the deliverable's gutter: the artifact (--thumb), then the gap to its
     title (--g is both). --s0 is the first level's cell, twice the distance
     from the mark's centre to 6px short of the title, so the elbow's arm
     ends where every other level's does. */
  --thumb:24px;--g:34px;--s0:32px}
/* A deliverable carries its artifact — the bulb, the frame, the clapperboard,
   the same object the Overview's columns draw (there it is faded when not
   delivered yet, here an empty slot, as a row of history should) — and
   nothing under it does.
   That is the whole separation: one column only deliverables occupy, so the
   eye runs down it and lands on each V without reading a word. */
.lthumb{position:relative;flex:none;width:var(--thumb);height:31px}
.lrow .lcell{gap:10px}
.lrow>td{padding-top:8px;padding-bottom:8px}
.lrow .tkt{font-size:13.5px;letter-spacing:-.01em}
.lrow.is-done .tkt{color:var(--txt-2);font-weight:500}
/* A task at the deliverables' level: the same title column and the same bold
   title — it is a ticket at the same level, and a lighter one read as a note
   that had lost its indent. The empty slot where the artifact would be is
   the whole difference. Finished, it is struck through the way a finished
   subtask is, because it is one. */
/* the deliverable's file: the tool's mark and its name, quiet until pointed at */
.lasset{display:inline-flex;align-items:center;gap:5px;height:20px;padding:0 8px 0 6px;flex:none;
  border:1px solid var(--line);border-radius:20px;font-size:11px;font-weight:500;color:var(--txt-3);
  text-decoration:none;transition:color .12s,border-color .12s,background .12s}
.lasset .bi{width:12px;height:12px}
.lasset:hover{color:var(--txt);border-color:var(--line-hi);background:var(--bg-elev2)}
.lasset:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.lrow.is-task.is-done .tkt{color:var(--txt-3);text-decoration:line-through;text-decoration-color:var(--txt-3)}
.lcell{display:flex;align-items:center;gap:8px;min-width:0}
/* The control sits at the right edge, in one column for every row whatever
   its depth — on the left it rode the indent, so a deep tree became a
   staircase of chevrons. It carries its own child count, which is why the
   separate count pill beside the title is gone. */
.lcaret{display:inline-flex;align-items:center;gap:5px;height:18px;flex:none;
  padding:0 6px 0 7px;border-radius:20px;
  border:1px solid var(--line);background:var(--bg);color:var(--txt-3);
  transition:color .12s,border-color .12s,background .12s}
.lcaret:hover{color:var(--txt);border-color:var(--line-hi);background:var(--bg-elev2)}
.lcaret-n{font-size:10.5px;font-family:"Geist Mono",monospace;line-height:1}
.lcaret svg{width:10px;height:10px;transform:rotate(-90deg);transition:transform .14s}
.lcaret.open svg{transform:none}
.lnotes{font-size:10.5px;font-family:"Geist Mono",monospace;color:var(--txt-3);
  border:1px solid var(--line);border-radius:20px;padding:0 6px;flex:none}
.lrow-note td{border-top-color:transparent;padding-top:7px;padding-bottom:7px}
.lrow-note:hover td{background:var(--hover)}
/* Bent connectors rather than rails. Each ancestor level gets a cell that
   either carries its vertical on down or is blank; the row's own cell bends —
   down from the parent, then a turn into the title. The last child stops its
   vertical at the turn, which is the whole point: a branch that ends should
   look ended, and six full-height rails looked like a ladder instead of a
   tree. The rows are flush, so the verticals of adjacent rows meet and read
   as one line. */
/* The tree is anchored to the CELL, not to the text beside it. In flow it
   was a flex item in a centre-aligned row, so it was only as tall as its own
   content and each row’s verticals stopped short of the row edges — the
   segments never met. Absolute against the td it spans the full row box, and
   the 1px bleed at the bottom crosses the transparent row border so one
   row’s vertical lands exactly on the next one’s. */
.lrow-note>td:first-child{position:relative}
.ltree{position:absolute;left:calc(14px + var(--thumb) / 2 - var(--s0) / 2);top:0;bottom:-1px;display:flex;pointer-events:none}
.ltree i{position:relative;display:block;width:var(--step);flex:none}
/* the first level hangs off the artifact: its rail drops from under the
   mark's centre and turns into text that starts where the deliverable's
   title does, so the icon column belongs to deliverables alone */
.ltree i:first-child{width:var(--s0)}
.ltree i::before{content:"";position:absolute;left:50%;top:0;bottom:0;
  width:var(--tw);margin-left:calc(var(--tw) / -2);background:var(--thread)}
/* a blank level: the ancestor has nothing more below, so nothing runs through */
.ltree i:not(.lt-v):not(.lt-el)::before{display:none}
/* the elbow: down to the middle, then across */
/* The elbow is ONE box with two borders and a rounded corner, not a vertical
   and a horizontal meeting at a right angle: the turn is where the eye
   follows the branch, and a bend reads as a connection where a corner reads
   as two lines that happen to touch. A last child needs nothing else — the
   box stops at the turn, which is what makes the branch look ended. */
.ltree i.lt-el::before{left:50%;right:0;top:0;bottom:auto;height:50%;width:auto;
  margin-left:calc(var(--tw) / -2);background:none;
  border-left:var(--tw) solid var(--thread);border-bottom:var(--tw) solid var(--thread);
  border-bottom-left-radius:8px}
/* a middle child carries its rail on past the turn to the sibling below */
.ltree i.lt-el:not(.end)::after{content:"";position:absolute;left:50%;top:50%;bottom:0;
  width:var(--tw);margin-left:calc(var(--tw) / -2);background:var(--thread)}
.lrow-note:hover .ltree i::before{background:var(--thread-hi)}
.lrow-note:hover .ltree i.lt-el::before{background:none;border-color:var(--thread-hi)}
.lrow-note:hover .ltree i.lt-el::after{background:var(--thread-hi)}
.lcell-sub{padding-left:calc(var(--g) + (var(--d,1) - 1) * var(--step))}
.ntxt{font-size:12.5px;color:var(--txt-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ntxt.done{color:var(--txt-3);text-decoration:line-through;text-decoration-color:var(--txt-3)}

/* ---------- control view ---------- */
.ctrl{max-width:1240px;margin:0 auto}
.kpis{display:grid;grid-template-columns:repeat(6,1fr);gap:10px;margin-bottom:14px}
.kpi{border:1px solid var(--line);border-radius:10px;background:var(--bg-elev);padding:12px 13px;
  display:flex;flex-direction:column;gap:3px;min-width:0}
.kpi-l{font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--txt-3)}
.kpi-v{font-size:21px;font-weight:600;letter-spacing:-.02em;line-height:1.15}
.kpi-s{font-size:11px;color:var(--txt-3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

.loadmix-wrap{margin-bottom:18px}
.loadmix{display:flex;gap:2px;height:8px;border-radius:6px;overflow:hidden;background:var(--bg-elev)}
.loadmix i{height:100%}
.loadlegend{display:flex;flex-wrap:wrap;gap:8px 18px;margin-top:10px;font-size:12px;color:var(--txt-2)}
.loadlegend-i b{color:var(--txt);font-weight:600;margin-left:3px;font-family:"Geist Mono",monospace}
.loaddot{width:8px;height:8px;border-radius:50%;display:inline-block;margin-right:6px;vertical-align:middle}

.cfilters{display:flex;flex-wrap:wrap;gap:18px;margin-bottom:14px}
.cfilter{display:flex;flex-direction:column;gap:6px}
.cfilter-l{font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--txt-3)}
.seg.seg-inline{margin-left:0}

.ctbl th.sortable{cursor:pointer;user-select:none}
.ctbl th.sortable:hover,.ctbl th.on{color:var(--txt)}
.ctbl tr.idle td{opacity:.5}
.ctbl tr:hover td{background:var(--hover)}
.cname{display:flex;align-items:center;gap:9px;font-weight:600}
.onloan{font-size:10px;font-weight:600;letter-spacing:.03em;color:var(--txt-3);
  border:1px solid var(--line);border-radius:20px;padding:1px 8px}
.ptcell{display:flex;align-items:center;gap:10px}
.ptbar{flex:1;max-width:120px;height:6px;border-radius:6px;background:color-mix(in srgb,var(--tint) 7%,transparent);overflow:hidden}
.ptbar i{display:block;height:100%;border-radius:6px}
.ptnum{font-family:"Geist Mono",monospace;font-size:12px;white-space:nowrap}
.cact{width:36px}
.crelease{display:grid;place-items:center;width:22px;height:22px;border-radius:6px;
  border:1px solid var(--line);color:var(--txt-3);opacity:0;transition:.12s}
.ctbl tr:hover .crelease{opacity:1}
.crelease:hover{color:oklch(from #f75f8f min(l, var(--ink-l)) c h);border-color:rgba(247,95,143,.45)}
.cempty{font-size:12.5px;color:var(--txt-3);text-align:center;padding:22px 0}

.csec-h{display:flex;align-items:center;gap:9px;margin:28px 0 12px}
.csec-t{font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--txt-3)}
.csec-h .muted{font-size:12px}
/* The free pool is a second `.ctbl`, not a card grid — see ControlView. The
   only thing it needs of its own is a button small enough to live in a cell. */
.pooladd{display:inline-flex;align-items:center;gap:5px;background:var(--accent);
  border:1px solid var(--accent);border-radius:7px;padding:3px 9px;
  font-size:11.5px;font-weight:500;color:#fff;white-space:nowrap}
.pooladd:hover{filter:brightness(1.1)}
.pooladd svg{width:11px;height:11px}
.cnote{display:block;font-size:11.5px;color:var(--txt-3);line-height:1.55;margin:22px 0 0;max-width:820px}
.cnote b{color:var(--txt-2);font-weight:600}

@media (max-width:1100px){.kpis{grid-template-columns:repeat(3,1fr)}}

.ctbl th:nth-child(2),.ctbl td:nth-child(2){width:140px}
.ctbl th:nth-child(3),.ctbl td:nth-child(3){width:215px}
.ctbl th:nth-child(4),.ctbl td:nth-child(4){width:80px}
.ctbl th:nth-child(5),.ctbl td:nth-child(5){width:110px;white-space:nowrap}
.ctbl th:nth-child(6),.ctbl td:nth-child(6){width:86px}

/* ---------- team view (one column) ---------- */
.teamv{max-width:820px;margin:0 auto}
.tsearch-row{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-bottom:22px}
.tsearch{position:relative;flex:1;min-width:280px}
.tsearch-i{position:absolute;left:12px;top:50%;transform:translateY(-50%);color:var(--txt-3);display:grid;place-items:center}
.tsearch input{width:100%;background:var(--bg-elev);border:1px solid var(--line);border-radius:9px;
  padding:10px 12px 10px 36px;color:var(--txt);font-size:13px;font-family:inherit;outline:none}
.tsearch input:focus{border-color:var(--accent)}
.tsearch-note{font-size:11.5px}
.tsearch-note b{color:var(--txt-2);font-weight:600}
/* the one button that puts a whole pod on the launch */
.team-assign{display:inline-flex;align-items:center;gap:8px;height:44px;padding:0 14px;border-radius:10px;
  border:1px solid var(--line);background:var(--bg-elev);color:var(--txt);font-size:13px;font-weight:500}
.team-assign:hover,.team-assign.open{border-color:var(--line-hi);background:var(--bg-elev2)}
.team-assign svg{color:var(--txt-3)}
.tsearch-pop{position:absolute;top:calc(100% + 6px);left:0;right:0;z-index:30;background:var(--raise);
  border:1px solid var(--line);border-radius:10px;padding:5px;box-shadow:0 18px 50px rgb(0 0 0/calc(.73*var(--shade)));
  display:flex;flex-direction:column;gap:3px}
.tsearch-hit{display:flex;align-items:center;gap:9px;width:100%;text-align:left;padding:7px 9px;border-radius:7px}
.tsearch-hit:hover{background:var(--hover)}
.tsh-id{display:flex;flex-direction:column;min-width:0;flex:1;gap:1px}
.tsh-n{font-size:12.5px;font-weight:600}
.tsh-r{font-size:11px;color:var(--txt-3)}
.tsh-add{font-size:11px;font-weight:600;color:var(--accent)}

.tsec-block{margin-bottom:26px}
.tsec-name{font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--txt-3);margin-bottom:10px}
/**
 * **A role is a row, not a card.** Every role had a bordered panel with a
 * heading, a count, a full-width row per person and a dashed Add footer;
 * fifteen people came to about two thousand pixels and the page read as a
 * stack of tabs rather than as a team. One table per section, one row per
 * role, and the people as chips: a role with three people is one row three
 * chips wide instead of a panel four rows tall.
 *
 * The role labels are a **fixed 150px column** on purpose. Sized to content
 * they would step in and out with the longest name in each section, and the
 * reason a list like this is readable is that you can run down one edge
 * rather than hunt for the next heading.
 */
.troster{list-style:none;margin:0;padding:0;border:1px solid var(--line);
  border-radius:12px;background:var(--bg-elev);overflow:hidden}
.trow{display:grid;grid-template-columns:150px minmax(0,1fr);gap:12px;align-items:start;
  padding:7px 12px;border-bottom:1px solid var(--line-soft)}
.trow:last-child{border-bottom:none}
.trow:hover{background:var(--hover)}
.trow-r{font-size:10.5px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;
  color:var(--txt-3);padding-top:7px;line-height:1.3}
.trow-p{display:flex;flex-wrap:wrap;align-items:center;gap:5px;min-width:0}
.trow-empty{font-size:11.5px;color:var(--txt-3)}

/* the same object the Overview's assignee field uses, so a person on a launch
   looks the same wherever you meet one */
/* a pod member has no × — see TeamView — so the chip closes up on the right */
.tchip{display:inline-flex;align-items:center;gap:6px;padding:3px 9px 3px 3px;
  border:1px solid var(--line);border-radius:20px;background:var(--bg-elev2)}
.tchip b{font-size:12px;font-weight:500;color:var(--txt);white-space:nowrap}
.tchip em{font-style:normal;font-size:10.5px;color:var(--txt-3);white-space:nowrap}
.tchip.loan{border-style:dashed;padding-right:4px}
.tchip button{width:16px;height:16px;border-radius:50%;display:grid;place-items:center;
  font-size:12px;line-height:1;color:var(--txt-3)}
.tchip button:hover{background:var(--hover);color:oklch(from #f75f8f min(l, var(--ink-l)) c h)}

.trow-add{width:22px;height:22px;border-radius:50%;border:1px dashed var(--line-hi);
  display:grid;place-items:center;color:var(--txt-3)}
.trow-add:hover,.trow-add.open{border-style:solid;border-color:var(--accent);color:var(--lit)}
.trow-add svg{width:11px;height:11px}

/* ---------- to-do (cross-launch queue) ---------- */
.todowrap{max-width:1040px;margin:0 auto}
.tdbar{display:flex;align-items:center;gap:12px;margin-bottom:20px}
.tdopen{margin-left:auto;font-size:12px;color:var(--txt-3);font-family:"Geist Mono",monospace}
.tdgroup{margin-bottom:22px}
.tdgroup-h{display:flex;align-items:center;gap:8px;font-size:11px;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:var(--txt-3);margin-bottom:4px;padding:0 2px}
.tdgroup-n{font-family:"Geist Mono",monospace;font-weight:500;letter-spacing:0;text-transform:none}
.tdrow{display:flex;align-items:center;gap:10px;padding:9px 12px;border-radius:9px;cursor:pointer;
  border-bottom:1px solid var(--line-soft)}
.tdrow:last-child{border-bottom:none}
.tdrow:hover{background:var(--hover)}
.tdcheck{width:17px;height:17px;flex:none;border-radius:5px;border:1.5px solid var(--line-hi);
  display:grid;place-items:center;color:#000;transition:.12s}
.tdcheck:hover{border-color:var(--accent)}
.tdcheck.on{background:#45d267;border-color:#45d267}
/* the note is the row; the metadata line sits under it */
.tdbody{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}
.tdname{font-size:13.5px;line-height:1.4;color:var(--txt)}
.tdmeta{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:11px;color:var(--txt-3);
  min-width:0}
/* a separator between the parts, so they read as one line of metadata
   instead of four unaligned chips — the gaps alone left the eye hunting for
   a column that was never going to line up, since every piece is a different
   width on every row */
.tdmeta > * + *::before{content:"·";margin-right:8px;color:var(--line-hi)}
.tdatt{display:inline-flex;align-items:center;gap:4px;flex:none;font-size:11px;color:var(--txt-3);
  font-family:"Geist Mono",monospace}
.tdrow{cursor:default}
.tdlink,.tdcheck{cursor:pointer}
.tdrow.done .tdname{color:var(--txt-3);text-decoration:line-through;text-decoration-color:var(--txt-3)}
/* a bare text node in a flex row cannot be ellipsised, so the name gets its
   own span — "Set of animation templates" was running under the status pill */
.tdlaunch-n{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tdlaunch{display:inline-flex;align-items:center;gap:6px;font-size:11px;color:var(--txt-2);
  white-space:nowrap;flex:none;max-width:200px;overflow:hidden}
.tdlaunch .lico{width:14px;height:14px;font-size:7px}
.tdlaunch-n{max-width:180px}
.tdstatus{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;font-weight:500;
  white-space:nowrap;flex:none;width:148px}
.tddue{display:inline-flex;align-items:center;gap:5px;font-size:11px;color:var(--txt-3);flex:none;
  font-family:"Geist Mono",monospace;white-space:nowrap;flex:none;width:74px;justify-content:flex-end}
.tddue.late{color:oklch(from #f5405e min(l, var(--ink-l)) c h)}

/* ---------- quick capture (q) ---------- */
.qc-scrim{position:fixed;inset:0;background:rgba(0,0,0,.55);backdrop-filter:blur(3px);z-index:80}
/* sits high rather than centred: it's an overlay on the work behind it,
   not a page of its own. */
.qc{position:fixed;z-index:81;left:50%;top:14vh;transform:translateX(-50%);
  width:min(560px,92vw);background:var(--bg-elev);border:1px solid var(--line);border-radius:14px;
  box-shadow:0 30px 80px rgb(0 0 0/calc(.7*var(--shade))),0 0 0 1px rgba(255,255,255,.02);
  display:flex;flex-direction:column}
.qc-head{display:flex;align-items:center;gap:9px;padding:11px 14px;border-bottom:1px solid var(--line-soft)}
.qc-kbd{width:20px;height:20px;border-radius:5px;border:1px solid var(--line);background:var(--bg-elev2);
  display:grid;place-items:center;font-size:10.5px;font-weight:600;color:var(--txt-2);
  font-family:"Geist Mono",monospace}
.qc-t{font-size:12.5px;font-weight:500;color:var(--txt-2);flex:1}
.qc-x{width:26px;height:26px;border-radius:7px;display:grid;place-items:center;color:var(--txt-3)}
.qc-x:hover{background:var(--hover);color:var(--lit)}
.qc-body{position:relative;z-index:2;padding:13px 14px 12px;display:flex;flex-direction:column;gap:11px}
.qc-note{width:100%;resize:none;background:transparent;border:none;outline:none;padding:0;
  color:var(--txt);font-family:inherit;font-size:15.5px;line-height:1.5;letter-spacing:-.01em}
.qc-note::placeholder{color:var(--txt-3)}
.qc-row{display:flex;align-items:flex-start;gap:8px;position:relative}
/* both chips are one control: an 18px tile, then the word, at one height —
   a chip leading with a tile beside one with a bare icon read as two kinds
   of button. The first chip steps left so its tile sits under the text. */
.qc-chip{display:inline-flex;align-items:center;gap:7px;height:30px;border:1px solid var(--line);border-radius:8px;
  padding:0 10px 0 5px;font-size:12px;color:var(--txt-2);background:var(--bg-elev)}
.qc-row > .qc-chip:first-child{margin-left:-6px}
.qc-chip .lico,.qc-hit .lico{width:18px;height:18px;border-radius:5px;font-size:9px}
.qc-tile{width:18px;height:18px;border-radius:5px;flex:none;display:grid;place-items:center;
  background:var(--bg-elev2);border:1px solid var(--line);color:var(--txt-2)}
.qc-tile svg{width:11px;height:11px}
/* no project yet: an empty slot, dashed, with the way to fill it */
.qc-tile.add,.qc-hit.none .qc-tile{background:transparent;border-style:dashed}
.qc-hit.none{color:var(--txt-3)}
.qc-chip:hover{background:var(--hover);color:var(--txt)}
.qc-chip b{font-weight:600;color:var(--txt)}
.qc-pick{position:relative;flex:1;min-width:0}
.qc-search{width:100%;background:var(--bg-elev);border:1px solid var(--accent);border-radius:8px;
  padding:6px 11px;color:var(--txt);font-family:inherit;font-size:12.5px;outline:none}
.qc-search::placeholder{color:var(--txt-3)}
.qc-hits{position:absolute;left:0;right:0;top:calc(100% + 6px);z-index:2;
  background:var(--raise);border:1px solid var(--line);border-radius:10px;padding:4px;
  box-shadow:0 18px 44px rgb(0 0 0/calc(.6*var(--shade)));max-height:min(228px,40vh);overflow-y:auto}
.qc-hit{display:flex;align-items:center;gap:9px;width:100%;padding:6px 8px;border-radius:7px;
  font-size:12.5px;color:var(--txt-2);text-align:left}
.qc-hit.on{background:var(--active);color:var(--lit)}
.qc-hit .qc-key{margin-left:auto}
.qc-foot{position:relative;z-index:1;border-radius:0 0 13px 13px;display:flex;align-items:center;gap:16px;padding:11px 14px;
  border-top:1px solid var(--line-soft);background:var(--bg-elev2)}
.qc-hints{flex:1;display:flex;align-items:center;gap:20px;flex-wrap:wrap}
.qc-hint{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;color:var(--txt-3)}
.qc-key{display:inline-grid;place-items:center;height:19px;min-width:19px;padding:0 5px;
  border:1px solid var(--line);border-radius:5px;background:var(--bg-elev2);color:var(--txt-2);
  font-family:"Geist Mono",monospace;font-size:10px;font-weight:500;line-height:1}
.qc-key + .qc-key{margin-left:-3px}
.qc-foot .btn-primary{align-self:auto}
.qc-foot .btn-primary:disabled{opacity:.35;cursor:default;background:var(--btn)}

/* ---------- tapes ---------- */
.tapes-wrap{max-width:1240px;margin:0 auto}
.page-h{display:flex;align-items:baseline;gap:10px;margin-bottom:16px}
.page-h h1{margin:0;font-size:22px;font-weight:600;letter-spacing:-.025em}
.page-h .sub{font-size:12.5px;color:var(--txt-3)}
/* Record is the one thing you make here, so it sits where every library
   page's primary action sits — the right of the track row. */
.rec-btn{display:inline-flex;align-items:center;gap:8px;background:var(--accent);color:#fff;
  border-radius:8px;font-weight:500;border:1px solid var(--accent)}
.rec-btn:hover{background:color-mix(in srgb,var(--accent),var(--tint) 17%)}
.rec-btn .rec-dot{width:7px;height:7px;border-radius:50%;background:#fff;box-shadow:0 0 0 3px rgba(255,255,255,.25)}

/**
 * **The shelf is a video grid — YouTube's shape.** A tape is a recording
 * and it is picked the way any video is: by its picture and its title. So a
 * 16:9 still per card, the running time on a dark badge in its corner, and
 * under it the recorder's face beside the title (two lines at most), who
 * made it, and views · when. It was a row with a 96px still and a summary;
 * the summary is gone from tapes altogether, and the transcript is what you
 * read one by.
 */
.tgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:30px 18px;padding-top:4px}
.tcard{display:flex;flex-direction:column;gap:12px;min-width:0;text-align:left;color:inherit;border-radius:14px}
.tcard:focus-visible{outline:2px solid var(--accent);outline-offset:5px}
.tape-thumb{position:relative;aspect-ratio:16/9;display:grid;place-items:center;overflow:hidden;
  border-radius:12px;box-shadow:inset 0 0 0 1px var(--line);background:var(--bg-elev)}
.tt-art{position:absolute;inset:0;width:100%;height:100%;display:block;
  transition:transform .35s cubic-bezier(.2,.8,.3,1)}
.tcard:hover .tt-art{transform:scale(1.04)}
.tt-play{position:relative;z-index:2;width:46px;height:46px;border-radius:50%;background:rgba(0,0,0,.55);
  backdrop-filter:blur(4px);display:grid;place-items:center;color:#fff;opacity:0;transform:scale(.85);
  transition:opacity .16s,transform .16s cubic-bezier(.2,.8,.3,1)}
.tt-play svg{width:18px;height:18px;margin-left:2px}
.tcard:hover .tt-play,.tcard:focus-visible .tt-play{opacity:1;transform:scale(1)}
.tt-dur{position:absolute;right:8px;bottom:8px;z-index:2;padding:2px 6px;border-radius:5px;
  background:rgba(0,0,0,.82);color:#fff;font-size:11.5px;font-weight:600;letter-spacing:.01em;
  font-variant-numeric:tabular-nums}
.tape-thumb.empty{background:#141416}
.tape-thumb.empty .tt-emptyico{color:var(--txt-3)}
.tcard-meta{display:flex;align-items:flex-start;gap:11px;padding-right:6px}
.tcard-meta .avatar{flex:none;margin-top:1px}
.tcard-text{display:flex;flex-direction:column;gap:3px;min-width:0}
.tcard-t{font-size:14px;font-weight:600;line-height:1.38;letter-spacing:-.01em;color:var(--txt);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.tcard-by,.tcard-s{font-size:12.5px;line-height:1.35;color:var(--txt-3)}
.tcard:hover .tcard-by{color:var(--txt-2)}

/* player — no video file, so the stage is a gradient with a drifting cursor */
.player{position:relative;border-radius:14px;overflow:hidden;background:#000;border:1px solid var(--line);
  aspect-ratio:16/9;flex:0 0 auto}
.player .pv-stage{position:absolute;inset:0;overflow:hidden}
.player .pv-mock{position:absolute;inset:0}
.player .pv-cursor{position:absolute;width:16px;height:16px;z-index:3;
  transition:left .25s linear,top .25s linear;filter:drop-shadow(0 1px 2px rgba(0,0,0,.6))}
.player .pv-cap{position:absolute;left:50%;transform:translateX(-50%);bottom:64px;z-index:4;max-width:80%;
  background:rgba(0,0,0,.78);color:#fff;font-size:14px;line-height:1.4;padding:5px 12px;border-radius:7px;
  text-align:center;display:none}
.player.cc .pv-cap{display:block}
.player .pv-bigplay{position:absolute;inset:0;z-index:5;display:grid;place-items:center;background:rgba(0,0,0,.18);transition:.15s}
.player .pv-bigplay button{width:70px;height:70px;border-radius:50%;background:rgba(0,0,0,.5);backdrop-filter:blur(6px);
  border:1px solid rgba(255,255,255,.3);color:#fff;display:grid;place-items:center}
.player.playing .pv-bigplay{opacity:0;pointer-events:none}
.player .pv-controls{position:absolute;left:0;right:0;bottom:0;z-index:6;padding:8px 12px 10px;
  background:linear-gradient(transparent,rgba(0,0,0,.72));display:flex;flex-direction:column;gap:7px}
.player .pv-scrub{position:relative;height:5px;border-radius:4px;background:rgba(255,255,255,.22);cursor:pointer}
.player .pv-scrub:hover{height:7px}
.player .pv-buf{position:absolute;left:0;top:0;bottom:0;width:82%;background:rgba(255,255,255,.16);border-radius:4px}
.player .pv-fill{position:absolute;left:0;top:0;bottom:0;background:var(--accent);border-radius:4px}
.player .pv-chm{position:absolute;top:50%;width:3px;height:11px;background:rgba(255,255,255,.55);
  transform:translate(-50%,-50%);border-radius:2px}
.player .pv-knob{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;background:#fff;
  transform:translate(-50%,-50%);box-shadow:0 1px 4px rgba(0,0,0,.5);opacity:0;transition:opacity .12s}
.player .pv-scrub:hover .pv-knob{opacity:1}
.player .pv-row{display:flex;align-items:center;gap:12px;color:#fff}
.player .pv-row button{color:#fff;display:grid;place-items:center;opacity:.92}
.player .pv-row button:hover{opacity:1}
.player .pv-time{font-size:12px;font-family:"Geist Mono",monospace;color:rgba(255,255,255,.85)}
.player .pv-spacer{margin-left:auto}
.player .pv-speed{font-size:11.5px;font-weight:700;font-family:"Geist Mono",monospace;
  border:1px solid rgba(255,255,255,.3);border-radius:6px;padding:3px 7px;min-width:44px}
.player .pv-vol{display:flex;align-items:center;gap:6px}
.player .pv-voltrack{width:60px;height:4px;border-radius:3px;background:rgba(255,255,255,.28);position:relative}
.player .pv-volfill{position:absolute;left:0;top:0;bottom:0;background:#fff;border-radius:3px}
@media (prefers-reduced-motion:reduce){.player .pv-cursor{transition:none}}

/* full view */
.content.tapemode{padding:0;overflow:hidden;display:flex;flex-direction:column}
.tv-wrap{flex:1;min-height:0;display:grid;grid-template-columns:minmax(0,1fr) 372px;overflow:hidden}
.tv-left{display:flex;flex-direction:column;min-width:0;overflow-y:auto;padding:16px 22px 26px}
.tv-back{display:inline-flex;align-items:center;gap:7px;color:var(--txt-2);font-size:12.5px;font-weight:500;
  margin-bottom:14px;width:max-content}
.tv-back:hover{color:var(--txt)}
.tv-info{padding-top:16px}
.tv-title{font-size:19px;font-weight:600;letter-spacing:-.02em;line-height:1.25;margin:0}
.tv-sub{display:flex;align-items:center;gap:9px;margin-top:10px;color:var(--txt-3);font-size:12.5px}
.tv-sub>*{flex:0 0 auto}
.tv-sub b{color:var(--txt);font-weight:500}
.tv-views{display:inline-flex;align-items:center;gap:5px}
.tv-actions{display:flex;align-items:center;gap:8px;margin-top:16px;flex-wrap:wrap;
  border-top:1px solid var(--line);padding-top:16px}
.tv-act{display:inline-flex;align-items:center;gap:7px;border:1px solid var(--line);border-radius:8px;
  padding:7px 12px;color:var(--txt-2);font-size:12.5px;font-weight:500}
.tv-act:hover{border-color:var(--line-hi);color:var(--txt)}
.tv-act.prime{background:var(--btn);border-color:var(--btn);color:var(--btn-ink);font-weight:500}
.tv-act.prime:hover{background:var(--btn-hi);border-color:var(--btn-hi)}

/* the transcript rail — a conversation, not a log. Each turn sits under the
   speaker's face and name; inside it the lines are quiet paragraphs with a
   small muted time, and the line being spoken is lit by an accent bar on its
   left edge rather than a filled blue box, so the column stays calm while it
   moves. */
.tv-right{border-left:1px solid var(--line);display:flex;flex-direction:column;min-height:0;background:var(--bg)}
.tr-head{display:flex;align-items:baseline;gap:10px;padding:18px 20px 12px;flex:0 0 auto}
.tr-head h2{margin:0;font-size:14px;font-weight:600;letter-spacing:-.01em;color:var(--txt)}
.tr-meta{font-size:11.5px;color:var(--txt-3);font-variant-numeric:tabular-nums}
.tr-search{display:flex;align-items:center;gap:8px;margin:0 16px 10px;padding:0 11px;height:34px;flex:0 0 auto;
  background:var(--bg-elev);border:1px solid var(--line);border-radius:9px;color:var(--txt-3)}
.tr-search:focus-within{border-color:var(--line-hi);color:var(--txt-2)}
.tr-search input{flex:1;min-width:0;background:none;border:none;outline:none;color:var(--txt);
  font:inherit;font-size:12.5px;font-weight:400;letter-spacing:0;text-transform:none}
.tr-search input::placeholder{color:var(--txt-3)}
.tr-scroll{flex:1;min-height:0;overflow-y:auto;padding:4px 10px 28px;
  -webkit-mask-image:linear-gradient(180deg,transparent 0,#000 12px,#000 calc(100% - 24px),transparent);
  mask-image:linear-gradient(180deg,transparent 0,#000 12px,#000 calc(100% - 24px),transparent)}
.tr-turn{padding:10px 0 6px}
.tr-turn + .tr-turn{border-top:1px solid var(--line-soft)}
.tr-spk{display:flex;align-items:center;gap:9px;padding:4px 10px 6px}
.tr-spk b{font-size:12.5px;font-weight:600;color:var(--txt)}
.tr-spk span{margin-left:auto;font-size:10.5px;font-family:"Geist Mono",monospace;color:var(--txt-3)}
.tr-line{display:grid;grid-template-columns:40px minmax(0,1fr);gap:8px;width:100%;padding:6px 10px;
  border-radius:8px;text-align:left;color:inherit;transition:background .12s}
.tr-line:hover{background:var(--bg-elev)}
.tr-ts{padding-top:3px;font-size:10.5px;font-family:"Geist Mono",monospace;color:var(--txt-3);
  font-variant-numeric:tabular-nums;transition:color .12s}
.tr-line:hover .tr-ts{color:var(--accent)}
.tr-text{font-size:13.5px;line-height:1.6;color:var(--txt-2);transition:color .12s}
.tr-line.on{background:color-mix(in srgb,var(--accent) 8%,transparent);box-shadow:inset 2px 0 0 var(--accent)}
.tr-line.on .tr-ts{color:var(--accent)}
.tr-line.on .tr-text{color:var(--txt)}
.tr-text mark{background:rgba(245,166,35,.28);color:var(--txt);border-radius:3px;padding:0 1px}
.tr-none{margin:18px 12px;font-size:12.5px;color:var(--txt-3)}

/* preview modal */
/* Same shell as every other sheet — scrim, radius, shadow, header. It used
   to carry its own heavier scrim and a taller header, which made it read as
   a different product the moment it opened next to the others. */
.tpv-scrim{position:fixed;inset:0;background:rgba(0,0,0,.62);backdrop-filter:blur(2px);z-index:80}
.tpv{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);width:min(1060px,calc(100vw - 64px));
  max-height:calc(100vh - 64px);display:flex;flex-direction:column;background:var(--bg-elev);border:1px solid var(--line);
  border-radius:14px;box-shadow:0 30px 90px rgb(0 0 0/calc(.72*var(--shade)));z-index:81;overflow:hidden}
.tpv-head{display:flex;align-items:center;gap:10px;padding:14px 16px;border-bottom:1px solid var(--line)}
.tpv-t h3{margin:0;font-size:15px;font-weight:600;letter-spacing:-.02em}
.tpv-sub{display:block;margin-top:2px;font-size:11.5px;color:var(--txt-3)}
.tpv-x{margin-left:auto;width:26px;height:26px;border-radius:7px;display:grid;place-items:center;
  color:var(--txt-2);font-size:15px}
.tpv-x:hover{background:var(--hover);color:var(--lit)}
.tpv-body{display:grid;grid-template-columns:minmax(0,1fr) 300px;min-height:0;overflow:hidden}
.tpv-left{padding:16px 18px;min-width:0;display:flex;flex-direction:column;gap:14px;overflow-y:auto}
.tpv-left .player{border-radius:10px}
.tpv-acts{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.tpv-views{margin-left:auto;display:inline-flex;align-items:center;gap:5px;font-size:12px;color:var(--txt-3);
  font-family:"Geist Mono",monospace}
.tpv-side{border-left:1px solid var(--line);padding:16px 18px 20px;overflow-y:auto;background:var(--bg)}
.tms-h{font-size:10px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--txt-3);margin:20px 0 8px}
.tms-h:first-child{margin-top:0}
.tms-row{display:flex;align-items:center;justify-content:space-between;gap:10px;font-size:13px;color:var(--txt);margin-bottom:10px}
/* the same switch the pod triggers use, so a toggle means one thing here */
.tsw{width:32px;height:18px;border-radius:20px;flex:none;background:color-mix(in srgb,var(--line-hi) 72%,var(--bg));position:relative;
  box-shadow:inset 0 0 0 1px var(--line);transition:background .14s}
.tsw i{position:absolute;top:2px;left:2px;width:14px;height:14px;border-radius:50%;background:#8b8b96;
  transition:transform .16s cubic-bezier(.2,.8,.3,1),background .14s}
.tsw.on{background:color-mix(in srgb,#45d267 calc(100% - 58% * var(--dk)),#07070a)}
.tsw.on i{transform:translateX(14px);background:#eafaef}
.tms-link{display:flex;gap:6px;margin-bottom:8px}
.tms-link input{flex:1;min-width:0;background:var(--bg-elev);border:1px solid var(--line);border-radius:8px;
  padding:7px 10px;color:var(--txt-2);font-size:11.5px;font-family:"Geist Mono",monospace}
.tms-link.off input{color:var(--txt-3);font-family:inherit;font-size:12px}
.tms-copy{background:var(--btn);color:var(--btn-ink);border-radius:8px;padding:7px 13px;font-size:12.5px;font-weight:500;flex:none}
.tms-copy:hover{background:var(--btn-hi)}
.tms-reset{border:1px solid var(--line);border-radius:8px;padding:7px 12px;font-size:12.5px;color:var(--txt-2);width:100%}
.tms-reset:hover{border-color:var(--line-hi);color:var(--txt)}
.tms-add{display:flex;gap:6px}
.tms-add input{flex:1;min-width:0;background:var(--bg-elev);border:1px solid var(--line);border-radius:8px;
  padding:7px 10px;color:var(--txt);font-size:12.5px;font-family:inherit}
.tms-add input:focus{outline:none;border-color:var(--line-hi)}
.tms-addbtn{background:var(--btn);color:var(--btn-ink);border-radius:8px;padding:7px 14px;font-size:12.5px;font-weight:500;flex:none}
.tms-addbtn:hover{background:var(--btn-hi)}
.tms-people{display:flex;flex-wrap:wrap;gap:6px;margin-top:9px}
.tassignee{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--line);border-radius:20px;
  padding:3px 5px 3px 4px;font-size:12px;color:var(--txt-2)}
.tassignee .chx{color:var(--txt-3);padding:0 3px;display:grid;place-items:center}
.tassignee .chx:hover{color:var(--lit)}
.tms-empty{font-size:12.5px;color:var(--txt-3);margin-top:9px}
.tms-viewer{display:flex;align-items:center;gap:8px;padding:6px 0;font-size:12.5px}
.tms-vn{color:var(--txt)}
.tms-va{margin-left:auto;font-size:11px;color:var(--txt-3);font-family:"Geist Mono",monospace}
@media (max-width:900px){.tpv-body{grid-template-columns:1fr}
  .tpv-side{border-left:none;border-top:1px solid var(--line)}}

.tv-toast{position:fixed;bottom:26px;left:50%;transform:translateX(-50%);background:var(--inv);color:var(--inv-ink);
  font-size:12.5px;font-weight:600;padding:9px 16px;border-radius:9px;z-index:9999;box-shadow:0 8px 30px rgb(0 0 0/calc(.4*var(--shade)))}

/* ---------- jam (storyboard canvas) ---------- */
.content.jammode{padding:0;overflow:hidden;scrollbar-gutter:auto;display:flex;flex-direction:column}
.content.jammode>.lc-head{position:static;margin:0;padding:9px 12px;flex:none;border-bottom:none}
/* a window into the jam space rather than a wall of it: inset from the
   frame on three sides, hairline edge, corners rounded */
/* No dot floor. It was a full-pane radial-gradient whose background-image
   string was rebuilt on every pan frame, so the whole viewport re-rasterised
   for a gesture that should only re-composite a layer — and the board reads
   better on flat black anyway. */
.jamwrap{position:relative;flex:1;min-height:0;overflow:hidden;cursor:grab;
  margin:4px;border:1px solid var(--line);border-radius:12px;
  background-color:var(--bg-elev)}
/* a middle-drag starts over whatever is under the cursor, so the pan cursor
   has to beat the pointer/grab the chips and buttons set for themselves */
.jamwrap.grabbing,.jamwrap.grabbing *{cursor:grabbing}
/* **The board is not text.** Nothing on it is there to be selected, and a
   press that started a selection — a pan begun over a scene, a shift-click
   on a scene name, which is how a run is picked — painted the whole strip
   blue with no way to click it off, because Chrome keeps a selection
   through a press on unselectable content. So the board opts out, and the
   ticket, the forms and the dialogs that open over it opt back in: they are
   documents. JamView clears any selection on a press on the board. */
.jamwrap{user-select:none;-webkit-user-select:none}
.jamwrap :is(.ticket,.nt,.jask,.confirm,input,textarea,[contenteditable="true"]){user-select:text;-webkit-user-select:text}
/* No permanent compositor layer — that is what made the board blurry.
   `will-change:transform` pins the element to its own GPU texture, rasterised
   once and then *scaled* by the compositor, so every zoom stretched an old
   bitmap instead of re-rendering the text at the new size. The spec says as
   much: will-change is a hint for the duration of the change, not a state to
   leave switched on.

   So the layer is created for the drag and released after it. A pan is
   translate-only, which is exactly where compositing is free and lossless —
   the texture is correct, it just moves. A zoom changes the raster scale, so
   it runs with no forced layer and the browser repaints the board crisply at
   the new scale. */
.jamcanvas{position:absolute;top:0;left:0;transform-origin:0 0}
.jamwrap.grabbing .jamcanvas{will-change:transform}

/* floating windows */
.jwin{position:absolute;background:var(--bg-elev);border:1px solid color-mix(in srgb,var(--line-hi) 75%,var(--bg));border-radius:14px;
  box-shadow:0 14px 44px rgb(0 0 0/calc(.55*var(--shade)))}
.jwin-bar{display:flex;align-items:center;gap:8px;padding:7px 12px;cursor:grab;
  font-size:11.5px;font-weight:600;color:var(--txt-2);border-bottom:1px solid var(--line-soft)}
.jwin-bar:active{cursor:grabbing}
.jwin-bar .muted{color:var(--txt-3);font-weight:500;font-family:"Geist Mono",monospace}
.jt-ic{display:grid;place-items:center;color:var(--txt-3)}
.jt-close{margin-left:auto;width:20px;height:20px;border-radius:5px;display:grid;place-items:center;color:var(--txt-3)}
.jt-close:hover{background:var(--hover);color:var(--lit)}
.jt-body{padding:11px 12px 13px;display:flex;flex-direction:column;gap:10px;
  max-height:520px;overflow-y:auto}

/* the storyboard: one block per part, scenes as columns inside it.
   Design on top, Animation underneath, and none of it moves — the order
   of the scenes is the edit, not a layout preference. */
.jstrip{position:absolute;left:0;top:0;padding:4px}
.jblock{flex:none;background:var(--bg-elev);border:1px solid color-mix(in srgb,var(--line-hi) 62%,var(--bg));border-radius:12px;overflow:hidden;
  box-shadow:0 10px 30px rgb(0 0 0/calc(.45*var(--shade)))}
.jpart-dot{width:7px;height:7px;border-radius:50%;flex:none}
.jpart-n{font-size:10px;color:var(--txt-3);font-family:"Geist Mono",monospace;font-weight:500;
  text-transform:none;letter-spacing:0}

.jgrid{display:grid;align-items:stretch}
.jgrid-k{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:10px 0;
  font-size:9.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--txt-3);
  border-right:1px solid var(--line);border-bottom:1px solid var(--line-soft);background:color-mix(in srgb,var(--tint) 1.5%,transparent)}
.jgrid-l{writing-mode:vertical-rl;transform:rotate(180deg);white-space:nowrap}

/* insert a scene on the divider between two: quiet until you go looking */
.jins{position:absolute;left:-11px;top:50%;transform:translateY(-50%);z-index:3;
  width:22px;height:22px;border-radius:50%;display:grid;place-items:center;
  color:var(--txt-3);
  background:var(--bg-elev2);border:1px solid var(--line);opacity:0;transition:opacity .12s}
.jscene-h:hover .jins,.jins:focus-visible{opacity:1}
.jins:hover{color:#fff;background:var(--accent);border-color:var(--accent)}
.jscene-h{position:relative;display:flex;align-items:center;gap:7px;padding:9px 11px;
  border-right:1px solid var(--line-soft);border-bottom:1px solid var(--line-soft)}
.jscene-n{font-size:12.5px;font-weight:600;letter-spacing:-.01em}
/* the scene names repeated at the board's foot, a step quieter than the header */
.jscene-h.jscene-f{border-bottom:none;border-top:1px solid var(--line-soft)}
/* Cutting the next version sits straight after the version pill it follows
   on from, and is built to the same metrics as that pill — same size, same
   mono, one step up in weight — so the pair reads as one object rather than
   a label with a button bolted on. White because it is the one action in the
   header, and only on the column you are pointing at: sixteen white chips
   down the strip would be the loudest thing on the page. */
/* **One small control on the board.** A scene's version, the cut beside
   it, what it dropped, a file's Split and its merge chevron were four sizes
   of one thing — 13, 15 and 22px tall, corners of 4, 5, 6 and 20px — so a
   row of them read as parts from four kits. One box now: 20px tall, 6px
   corners, a hairline, 10px type at 600; the chevron is the same box,
   square. Versions and counts stay in mono, as every V and tally in this app is. */
.jscene-v,.jscene-nv,.jdrop-n,.jlink-b button{display:inline-flex;align-items:center;justify-content:center;
  gap:3px;flex:none;height:20px;padding:0 7px;border:1px solid var(--line);border-radius:6px;
  font-size:10px;font-weight:600;line-height:1;white-space:nowrap;color:var(--txt-3)}
.jscene-v,.jscene-nv,.jdrop-n{font-family:"Geist Mono",monospace}
.jscene-nv{color:color-mix(in srgb,var(--btn-ink),var(--btn) 4%);background:color-mix(in srgb,var(--btn) 96%,var(--bg));
  border-color:transparent;opacity:0;transition:opacity .12s,background .12s}
.jscene-h:hover .jscene-nv,.jscene-nv:focus-visible{opacity:1}
.jscene-nv:hover{background:var(--btn-hi)}
.jscene-nv.armed{opacity:1;color:#0a0a0a;background:#f5a623;border-color:#f5a623}

.jlane{min-width:0;display:flex;flex-direction:column;gap:6px;padding:9px;
  border-right:1px solid var(--line-soft);border-bottom:1px solid var(--line-soft)}
.jlane.over{background:color-mix(in srgb,var(--accent) 8%,transparent);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--accent) 35%,transparent)}
.jlane-h{display:none}
.jlane-body{display:flex;flex-direction:column;gap:5px;min-height:34px}
.jchg-m{display:flex;align-items:center;gap:9px;font-size:9.5px;color:var(--txt-3);
  font-family:"Geist Mono",monospace}
.jchg-m span{display:inline-flex;align-items:center;gap:3px}
.jchg .ksubbar{margin:0;gap:6px}
.jchg .ksubn{font-size:9px}
.jlane-empty{font-size:10.5px;color:#4d4d4d;padding:1px}
/* the fifth row: the Aspect file a scene is reviewed on. One file often
   covers a run of scenes, so the cells merge across them. */
/* One line, one height. A fixed min-height keeps every cell identical
   whether or not it has a Merge button — stacking them made the cells with
   actions taller than the ones without. */
.jlink{display:flex;align-items:center;gap:8px;min-width:0;min-height:36px;padding:0 10px;
  border-right:1px solid var(--line-soft);background:color-mix(in srgb,var(--tint) 1.2%,transparent)}
.jlink-t{display:flex;align-items:center;gap:8px;min-width:0;flex:1}
.jlink-u{flex:none;max-width:100%;font-size:10.5px;color:var(--txt-2);font-family:"Geist Mono",monospace;
  overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
.jlink-u:hover{color:var(--txt)}
.jlink-n{font-size:10px;color:var(--txt-3);white-space:nowrap}
.jlink-b{display:flex;align-items:center;gap:5px;flex:none;margin-left:auto}
.jlink-b button:hover{border-color:var(--line-hi);color:var(--txt);background:var(--hover)}
/* the chevron alone: the word doubled the button's width for no more meaning,
   and the tooltip says it anyway */
/* .jlink-b button is (0,1,1) and beat a bare .jlink-merge, so its asymmetric
   padding survived and pushed the glyph off centre — match the specificity */
.jlink-b button.jlink-merge{width:20px;padding:0}
.jlink-merge svg{width:12px;height:12px}
.jlink-b svg{opacity:.8}
.jlink-b button:hover svg{opacity:1}
.jlink:last-of-type{border-right:none}

/* a change: drag it down to animation, back up to design, or drop it out.
   The status pill is the work on it — click walks it on. */
.jchg{display:flex;flex-direction:column;gap:5px;padding:6px;border-radius:7px;
  background:var(--bg-elev);border:1px solid var(--line);cursor:grab;font-size:11.5px;line-height:1.35}
.jchg:hover{border-color:var(--line-hi)}
.jchg:active{cursor:grabbing}
.jchg-r{display:flex;align-items:center;gap:6px}
.jchg-st{align-self:flex-start;display:inline-flex;align-items:center;gap:5px;font-size:9.5px;
  font-weight:600;border:1px solid;border-radius:20px;padding:1px 7px 1px 5px;white-space:nowrap}
.jchg-st i{width:5px;height:5px;border-radius:50%;flex:none}
.jchg-st:not(.held):hover{background:color-mix(in srgb,var(--tint) 5%,transparent)}
.jchg-st.held{cursor:default;opacity:.75}
.jchg-t{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* In a scene cell the chip stacks exactly as it always did — the group is
   not a box there, it is nothing. In the band it becomes the second line. */
.jchg-f{display:contents}
/* the column order the stacked chip has always read in, restored by hand
   because `display:contents` hands each child its own place in the flow */
.jchg-r{order:0}
.jchg-span{order:1}
.jchg-st{order:2}
.jchg-m{order:3}
.jchg .ksubbar{order:4}
.jchg-add{font-size:10.5px;color:var(--txt-3);text-align:left;padding:1px}
.jchg-add:hover{color:var(--txt)}
.jchg-in{background:var(--bg-elev);border:1px solid var(--accent);border-radius:7px;padding:5px 7px;
  color:var(--txt);font-family:inherit;font-size:11.5px;outline:none}

/* the buffer reads as the gap it is: a black trench between the two crafts,
   not a third colour competing with them */
.jgrid-k.buffer,.jlane.buffer{background:var(--well)}
.jlane.buffer .jchg{background:color-mix(in srgb,var(--bg-elev2) 70%,var(--well))}
.jdrop-n{margin-left:auto}
/* the last column and the bottom row close the block off */
.jgrid > *:nth-child(n):last-child,
.jscene-h:last-of-type,.jlane:last-of-type{border-right:none}

/* task panels */
.jt-filters{display:flex;flex-direction:column;gap:6px}
.catseg{display:flex;flex-wrap:wrap;gap:5px}
.catseg button{font-size:10.5px;font-weight:600;color:var(--txt-3);border:1px solid var(--line);
  border-radius:20px;padding:2px 9px;background:var(--bg)}
.catseg button:hover{color:var(--txt)}
.catseg button.on{background:var(--active);color:var(--lit);border-color:var(--line-hi)}
.jt-grid{display:grid;grid-template-columns:1fr 1fr;gap:9px}
.kmine-card{--cc:#8f8f8f;--sc:#8f8f8f;text-align:left;border:1px solid var(--line);
  border-left:2px solid var(--cc);border-radius:10px;padding:10px 11px;background:var(--bg-elev);
  display:flex;flex-direction:column;gap:8px}
.kmine-card:hover{border-color:var(--line-hi);background:var(--bg-elev2)}
.km-top{display:flex;align-items:center;gap:8px}
.km-cat{display:inline-flex;align-items:center;gap:6px;font-size:9.5px;font-weight:700;letter-spacing:.07em;
  color:var(--txt-3)}
.km-dot{width:5px;height:5px;border-radius:50%;background:var(--cc)}
.km-top .avatar{margin-left:auto}
.km-title{font-size:12.5px;font-weight:500;line-height:1.35;color:var(--txt)}
.km-foot{display:flex;align-items:center;gap:9px;font-size:10.5px}
.km-status{display:inline-flex;align-items:center;gap:5px;font-weight:500}
.km-sdot{width:5px;height:5px;border-radius:50%}
.km-due{display:inline-flex;align-items:center;gap:4px;color:var(--txt-3);font-family:"Geist Mono",monospace}
.jdock-empty{grid-column:1/-1;font-size:12px;color:var(--txt-3);padding:10px 2px}
.jt-people{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.jt-flabel{font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--txt-3);margin-right:2px}
.jt-chip{display:inline-flex;align-items:center;gap:6px;font-size:11px;color:var(--txt-2);
  border:1px solid var(--line);border-radius:20px;padding:2px 9px 2px 3px;background:var(--bg)}
.jt-chip:first-of-type{padding-left:9px}
.jt-chip:hover{border-color:var(--line-hi);color:var(--txt)}
.jt-chip.on{background:var(--active);color:var(--lit);border-color:var(--line-hi)}

/* canvas chrome */
/* capped to the room left of the centred toolbar, so on a laptop it wraps
   upward instead of running underneath it */
.jamhint{position:absolute;bottom:16px;left:16px;font-size:11px;color:var(--txt-3);z-index:3;pointer-events:none;
  max-width:calc(50% - 150px)}
/* the zoom, in the notches' idiom: tucked into the board's bottom-right
   corner, flush with both edges, rounded only on the corner that faces the
   board — the frame's own rounding (it clips) curves the other */
.jamctrl{position:absolute;bottom:0;right:0;z-index:4;display:flex;align-items:center;gap:2px;padding:6px 6px 5px 7px;
  background:var(--glass);border-top:1px solid var(--line);border-left:1px solid var(--line);
  border-radius:14px 0 0 0;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px)}
.jamctrl > button{width:28px;height:28px;border-radius:8px;color:var(--txt-2);display:grid;place-items:center;font-size:15px}
.jamctrl > button:hover{background:var(--hover);color:var(--lit)}
/* **How hard a scroll zooms** is somebody's hand, not the board's: a
   trackpad and a notched wheel send very different deltas, and one fixed
   step is wrong for one of them. The bolt says the number; it takes the
   accent once it is off 1×, the way a touched field is marked. */
.jz-sep{width:1px;height:16px;background:var(--line);margin:0 3px;flex:none}
.jzp{position:relative;display:flex}
.jzp-b{display:inline-flex;align-items:center;gap:4px;height:28px;padding:0 8px 0 6px;border-radius:8px;
  color:var(--txt-2);font-size:11px;font-family:"Geist Mono",monospace;font-variant-numeric:tabular-nums}
.jzp-b svg{flex:none;color:var(--txt-3)}
.jzp-b:hover,.jzp-b.open{background:var(--hover);color:var(--lit)}
.jzp-b.changed svg{color:var(--accent)}
.jzp-pop{position:absolute;right:-34px;bottom:calc(100% + 13px);width:244px;padding:13px 14px 12px;
  background:var(--raise);border:1px solid var(--line);border-radius:12px;
  box-shadow:0 14px 36px rgb(0 0 0/calc(.5*var(--shade)));display:flex;flex-direction:column;gap:9px}
.jzp-h{display:flex;align-items:baseline;justify-content:space-between;gap:10px}
.jzp-h b{font-size:12px;font-weight:600;color:var(--txt)}
.jzp-h span{font-size:12px;font-family:"Geist Mono",monospace;color:var(--txt-2);font-variant-numeric:tabular-nums}
.jzp-pop input[type=range]{width:100%;margin:2px 0 0;accent-color:var(--accent);cursor:pointer}
.jzp-ends{display:flex;justify-content:space-between;margin-top:-4px;font-size:10px;color:var(--txt-3)}
.jzp-pop .seg{margin:0;align-self:stretch;display:flex}
.jzp-pop .seg button{flex:1;justify-content:center;padding:4px 0;font-size:11.5px;font-family:"Geist Mono",monospace}
.jzp-note{margin:0;font-size:10.5px;line-height:1.45;color:var(--txt-3)}
.jamctrl .z{min-width:44px;text-align:center;font-size:11px;color:var(--txt-2);font-family:"Geist Mono",monospace}
.jtoolbar{position:absolute;bottom:16px;left:50%;transform:translateX(-50%);display:flex;align-items:center;
  gap:2px;background:#0c0c0c;border:1px solid var(--line);border-radius:12px;padding:5px;z-index:3;
  box-shadow:0 10px 30px rgb(0 0 0/calc(.5*var(--shade)))}
.jtb{position:relative;display:flex;flex-direction:column;align-items:center;gap:3px;padding:7px 12px;
  border-radius:9px;color:var(--txt-3);font-size:11px;font-weight:500}
.jtb:hover{background:var(--hover);color:var(--txt-2)}
.jtb.on{background:var(--active);color:var(--lit)}
.jtb-sep{width:1px;height:30px;background:var(--line);margin:0 3px}
.jtb-n{position:absolute;top:5px;right:9px;font-size:9px;font-weight:700;color:#fff;background:var(--accent);
  border-radius:20px;padding:0 4px;min-width:13px;text-align:center}
.jtb-dot{position:absolute;top:8px;right:14px;width:6px;height:6px;border-radius:50%;background:var(--accent)}

/* ---------- ticket view (opened version) ---------- */
/* Jira's shape: the work at three quarters of the width, the fields that
   describe it in the last quarter. */
/* docked to the right edge rather than floating in the middle: the launch
   stays visible behind it, and opening a ticket never feels like leaving */
.ticket{position:fixed;top:0;right:0;bottom:0;z-index:61;transition:width .16s cubic-bezier(.2,.8,.3,1);
  width:min(920px,94vw);display:flex;flex-direction:column;
  background:var(--bg-elev);border-left:1px solid var(--line);overflow:hidden;
  box-shadow:-24px 0 70px rgb(0 0 0/calc(.6*var(--shade)))}
/* full screen: the ticket takes the window, rail and all */
/* centred instead of docked — same panel, floating in the middle */
.ticket.center{top:50%;right:auto;bottom:auto;left:50%;transform:translate(-50%,-50%);
  height:min(880px,90vh);border:1px solid var(--line);border-radius:14px;
  box-shadow:0 30px 90px rgb(0 0 0/calc(.72*var(--shade)))}

/* its own page: no scrim, no docking — it has an address, so a link to it
   can be pasted into Slack. It is a floating window on the black ground,
   centred, and exactly as tall as its content: as a panel the ticket fills
   the window because it is a drawer, but a page that stretches to the
   bottom of a tall monitor is mostly empty and the fields column running
   down beside nothing reads as a box drawn around the page. So the card
   ends where the work ends and the ground shows underneath, and the whole
   page scrolls rather than the two columns inside it. */
.content.ticketpage{scrollbar-gutter:auto;display:flex;flex-direction:column;align-items:center;padding:20px 28px 72px}
.ticket.page{position:relative;inset:auto;width:100%;max-width:1180px;flex:none;min-height:0;z-index:auto;transition:none;
  border:1px solid var(--line);border-radius:14px;overflow:hidden;
  box-shadow:0 24px 70px -24px rgb(0 0 0/calc(.85*var(--shade))),0 0 0 1px rgba(0,0,0,.6)}
.ticket.page .ticket-body{flex:none}
/* content-height card: the columns don't scroll, the page does */
.ticket.page .ticket-main,
.ticket.page .ticket-side{overflow:visible}
.ticket.page .ticket-main{padding:22px 26px 44px}
/* one surface — the card is the container now, so the fields don't need a
   second tone to be told apart from the work; the hairline is enough */
.ticket.page .ticket-side{background:transparent}
.ticket.page .ticket-gone{min-height:360px;padding:40px}
.ticket-back{display:inline-flex;align-items:center;gap:5px;font-size:12px;color:var(--txt-3);
  border:1px solid var(--line);border-radius:7px;padding:3px 9px 3px 6px;margin-right:4px}
.ticket-back:hover{border-color:var(--line-hi);color:var(--txt)}
.ticket-copied{position:absolute;top:44px;right:14px;z-index:5;background:var(--inv);color:var(--inv-ink);
  font-size:11.5px;font-weight:600;padding:5px 10px;border-radius:7px;box-shadow:0 8px 24px rgb(0 0 0/calc(.5*var(--shade)))}
.ticket-gone{flex:1;display:grid;place-items:center;text-align:center;color:var(--txt-3);font-size:13px;gap:12px}
.ticket-gone p{margin:0}
.ticket-top{display:flex;align-items:center;gap:10px;padding:11px 14px;border-bottom:1px solid var(--line-soft)}
.ticket-badge{width:24px;height:24px;border-radius:7px;display:grid;place-items:center;color:#fff;
  font-weight:700;font-size:11px;flex:none}
.ticket-name{font-size:14.5px;font-weight:600;letter-spacing:-.02em}
.ticket-chip{font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  border-radius:5px;padding:2px 7px}
.ticket-tools{margin-left:auto;display:flex;align-items:center;gap:2px}
.ticket-x{width:26px;height:26px;border-radius:7px;display:grid;place-items:center;color:var(--txt-2);
  border:1px solid var(--line);margin-left:6px}
.ticket-x:hover{background:var(--hover);color:var(--lit)}
/* the tab labels start on the content's left edge, and the underline is the
   label's width: padded 14px with 12px inside each tab, "Details" began 4px
   right of the breadcrumb and its underline 8px left of it */
.ticket-tabs{display:flex;gap:22px;padding:0 22px;border-bottom:1px solid var(--line);flex:none}
.ticket.page .ticket-tabs{padding:0 26px}
.ticket-tabs button{padding:9px 0;font-size:12.5px;font-weight:500;color:var(--txt-3);
  border-bottom:2px solid transparent;margin-bottom:-1px}
.ticket-tabs button:hover{color:var(--txt-2)}
.ticket-tabs button.on{color:var(--txt);border-bottom-color:var(--accent)}
.ticket-body{flex:1;min-height:0;display:grid;grid-template-columns:minmax(0,1fr) 296px}
.ticket-main{min-width:0;overflow-y:auto;padding:18px 22px 40px}
/* The fields sit on a surface a step *up* from the work, not a step down —
   pure black beside the #0a0a0a body read as a hole cut out of the page. */
.ticket-side{border-left:1px solid var(--line);overflow-y:auto;padding:18px 16px 30px;
  background:var(--bg-elev2)}
.ticket-main .crumbs{display:flex;align-items:center;gap:6px;font-size:12.5px;color:var(--txt-3);margin-bottom:10px}
.ticket-h1{margin:0 0 20px;font-size:21px;font-weight:600;letter-spacing:-.025em;line-height:1.3}
.ticket-desc{margin:0;font-size:13.5px;line-height:1.6;color:var(--txt-2);max-width:64ch}
.tsec{margin-bottom:24px}
.tsec-h{display:flex;align-items:center;gap:8px;font-size:11px;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:var(--txt-3);margin-bottom:11px}
.tsec-n{font-family:"Geist Mono",monospace;color:var(--txt-2);font-weight:500}
.tsec-h .btn-ghost{margin-left:auto}

/* subtask cards */
.stk-add{width:100%;background:var(--btn);color:var(--btn-ink);border-radius:8px;padding:8px 12px;
  font-size:12.5px;font-weight:600;margin-bottom:10px}
.stk-add:hover{background:var(--btn-hi)}
.stk-list{display:flex;flex-direction:column;gap:9px}
.stk{border:1px solid var(--line);border-left:2px solid var(--line);border-radius:10px;
  background:var(--bg-elev);padding:12px 14px}
.stk.done{opacity:.6}
.stk.done:hover{opacity:1}
.stk-top{display:flex;align-items:center;gap:9px;margin-bottom:9px}
.stk-pill{display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:600;
  border:1px solid var(--line);border-radius:20px;padding:2px 10px;background:var(--bg)}
.stk-pill:hover{background:var(--hover)}
.stk-idx{font-size:10.5px;color:var(--txt-3);font-family:"Geist Mono",monospace}
.stk-top .avatar{margin-left:auto}
.stk-title{font-size:13.5px;font-weight:500;line-height:1.45}
.stk.done .stk-title{color:var(--txt-3);text-decoration:line-through}
.stk-kids{margin-top:11px;border:1px solid var(--line-soft);border-radius:8px;padding:7px 9px;background:var(--bg)}
.stk-kids-h{display:flex;align-items:center;gap:7px;width:100%;font-size:10px;font-weight:700;
  letter-spacing:.06em;text-transform:uppercase;color:var(--txt-3);padding:1px 0 6px}
.stk-kids-h:hover{color:var(--txt-2)}
.stk-kids-n{font-family:"Geist Mono",monospace;color:var(--txt-2)}
.stk-kids-p{margin-left:auto;text-transform:none;letter-spacing:0;font-size:10.5px;font-weight:600;color:oklch(from #f75f8f min(l, var(--ink-l)) c h)}
.stk-kids-p.all{color:oklch(from #45d267 min(l, var(--ink-l)) c h)}
/* children nest here too, so depth is paid out as padding and marked with a
   rail — the same indent language the list view uses, at the tighter step a
   narrow card can afford */
.stk-kid{display:flex;align-items:center;gap:8px;padding:4px 2px;font-size:12px;min-width:0;
  padding-left:calc(var(--kd,0) * 13px + 2px);position:relative}
.stk-kid[style*="--kd"]::before{content:"";position:absolute;left:calc(var(--kd,0) * 13px - 7px);
  top:0;bottom:0;width:1px;background:var(--thread)}
.stk-kid[style*="--kd:0"]::before{display:none}
.stk-kid-n{font-size:10px;color:var(--txt-3);font-family:"Geist Mono",monospace;flex:none}
.stk-kid-c{display:inline-flex;align-items:center;gap:4px;flex:none;height:16px;padding:0 5px;
  border:1px solid var(--line);border-radius:20px;color:var(--txt-3)}
.stk-kid-c:hover{color:var(--txt);border-color:var(--line-hi)}
.stk-kid-cn{font-size:9.5px;font-family:"Geist Mono",monospace;line-height:1}
.stk-kid-c svg{transform:rotate(-90deg);transition:transform .14s}
.stk-kid-c.open svg{transform:none}
.stk-kids-d{font-size:10px;font-weight:500;text-transform:none;letter-spacing:0;color:var(--txt-3)}
.stk-kid-st{font-size:10.5px;font-weight:600;flex:none;white-space:nowrap}
.stk-kid-t{color:var(--txt-2);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.stk-more{font-size:11px;color:var(--txt-3);padding:3px 2px}
.stk-more:hover{color:var(--txt)}
.stk-foot{display:flex;align-items:center;gap:14px;margin-top:11px;padding-top:9px;
  border-top:1px solid var(--line-soft);font-size:11px;color:var(--txt-3)}
.stk-due{display:inline-flex;align-items:center;gap:5px;font-family:"Geist Mono",monospace}
.stk-by{margin-left:auto;display:inline-flex;align-items:center;gap:5px}

/* composer */
.ticket-main .compose{margin-bottom:12px}
.compose-row{display:flex;align-items:center;gap:10px}
.compose-row .muted{flex:1;font-size:11.5px}
.compose-row .btn-primary{align-self:auto}

/* activity */
.ticket-act{display:flex;flex-direction:column;gap:16px}
.act-row{display:flex;gap:11px}
.act-head{font-size:12.5px;color:var(--txt-3)}
.act-head b{color:var(--txt);font-weight:600}
.act-when{margin-left:8px;font-family:"Geist Mono",monospace;font-size:11px}
.act-text{font-size:13px;line-height:1.5;color:var(--txt-2);margin-top:3px}

/* right rail fields */
.tf{margin-bottom:17px}
.tf-k{font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--txt-3);margin-bottom:7px}
.tf-hint{margin-left:6px;font-weight:400;text-transform:none;letter-spacing:0;font-size:10.5px}
.tf-v{font-size:13px}
.tf-status{display:inline-flex;align-items:center;gap:7px;font-weight:500}
.tf-launch{display:inline-flex;align-items:center;gap:7px;color:var(--txt-2)}
.tf-due{display:inline-flex;align-items:center;gap:6px;font-family:"Geist Mono",monospace;color:var(--txt-2)}
.tf-due.late{color:oklch(from #f5405e min(l, var(--ink-l)) c h)}
.tf-effort{display:flex;gap:4px}
.tf-effort button{flex:1;height:26px;border:1px solid var(--line);border-radius:6px;font-size:11.5px;
  font-weight:600;color:var(--txt-3);font-family:"Geist Mono",monospace}
.tf-effort button:hover{border-color:var(--line-hi);color:var(--txt)}
.tf-effort button.on{background:var(--accent);border-color:var(--accent);color:#fff}
.tf-people{display:flex;flex-wrap:wrap;gap:6px;align-items:center}
.tf-add{font-size:11.5px;color:var(--txt-3);border:1px solid var(--line);border-radius:20px;padding:3px 10px}
.tf-add:hover{border-color:var(--line-hi);color:var(--txt)}
.tf-pick{margin-top:7px;border:1px solid var(--line);border-radius:9px;background:var(--bg-elev2);padding:4px}
.tf-pick button{display:flex;align-items:center;gap:8px;width:100%;padding:5px 7px;border-radius:6px;
  font-size:12.5px;color:var(--txt-2);text-align:left}
.tf-pick button:hover{background:var(--hover);color:var(--lit)}
.ticket-action{width:100%;border:1px solid var(--line);border-radius:8px;padding:8px 12px;
  font-size:12.5px;font-weight:500;color:var(--txt-2);margin-top:6px}
.ticket-action:hover{border-color:var(--line-hi);color:var(--lit);background:var(--hover)}
/* the second way out of a version. Same footprint as Address all — they are
   alternatives, not a primary and a secondary — with the count of what would
   travel on the right, because that number is the whole decision. */
.ticket-action-2{display:flex;align-items:center;justify-content:center;gap:8px}
.ticket-action-2 .ticket-action-n{font-size:10.5px;font-family:"Geist Mono",monospace;
  color:var(--txt-3);border:1px solid var(--line);border-radius:20px;padding:0 6px}
.ticket-action-2:hover .ticket-action-n{color:var(--txt-2);border-color:var(--line-hi)}
/* a note that was never addressed and travelled to the next version: it is
   closed here, but "Done" would be a lie about what happened to it */
/* struck through would say "done" about a thing nobody did */
.stk.moved .stk-title{text-decoration:none;color:var(--txt-2)}
.stk.moved .stk-pill{opacity:.5}
.stk-moved{font-size:10px;font-family:"Geist Mono",monospace;color:oklch(from #f5a623 min(l, var(--ink-l)) c h);
  border:1px solid rgba(245,166,35,.35);border-radius:20px;padding:0 7px;white-space:nowrap}
.ticket-side .old-toggle{display:flex;align-items:center;gap:7px;font-size:10px;font-weight:700;
  letter-spacing:.06em;text-transform:uppercase;color:var(--txt-3)}
.ticket-side .old-toggle:hover{color:var(--txt-2)}

@media (max-width:900px){
  .ticket-body{grid-template-columns:1fr;overflow-y:auto}
  .ticket-side{border-left:none;border-top:1px solid var(--line)}
}

/* ---------- new ticket form (stacks on the ticket panel) ---------- */
.nt-scrim{position:fixed;inset:0;background:rgba(0,0,0,.5);z-index:70}
.nt{position:fixed;top:0;right:0;bottom:0;z-index:71;width:min(920px,94vw);
  display:flex;flex-direction:column;background:var(--bg-elev);border-left:1px solid var(--line);
  box-shadow:-24px 0 70px rgb(0 0 0/calc(.6*var(--shade)))}
.nt-top{display:flex;align-items:center;gap:10px;padding:14px 16px;border-bottom:1px solid var(--line)}
.nt-t{font-size:15px;font-weight:600;letter-spacing:-.02em;flex:1}
.nt-split{flex:1;min-height:0;display:grid;grid-template-columns:1fr 1fr}
.nt-body{min-width:0;overflow-y:auto;padding:16px 16px 28px}

/* left half: the cross-launch queue you can hang this ticket off */
.nt-queue{min-width:0;display:flex;flex-direction:column;border-right:1px solid var(--line);
  background:var(--bg);padding:16px 14px 12px}
.nt-qh{display:flex;align-items:baseline;gap:8px;margin-bottom:9px}
.nt-qh .nt-k{margin-bottom:0}
.nt-qn{margin-left:auto;font-size:11px;color:var(--txt-3);font-family:"Geist Mono",monospace}
.nt-qsearch{width:100%;background:var(--bg-elev);border:1px solid var(--line);border-radius:8px;
  padding:7px 10px;color:var(--txt);font-size:12.5px;font-family:inherit;outline:none;margin-bottom:9px}
.nt-qsearch:focus{border-color:var(--accent)}
.nt-qlist{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:5px}
.nt-q{display:flex;align-items:flex-start;gap:9px;width:100%;text-align:left;padding:8px 10px;
  border:1px solid var(--line);border-radius:9px;background:var(--bg-elev)}
.nt-q:hover{border-color:var(--line-hi)}
.nt-q.on{border-color:var(--accent);background:color-mix(in srgb,var(--accent) 10%,transparent)}
.nt-q-chk{width:15px;height:15px;flex:none;margin-top:1px;border-radius:5px;border:1.5px solid var(--line-hi);
  display:grid;place-items:center;color:transparent}
.nt-q.on .nt-q-chk{background:var(--accent);border-color:var(--accent);color:#fff}
.nt-q-body{flex:1;min-width:0}
.nt-q-t{display:block;font-size:12.5px;line-height:1.4;color:var(--txt)}
.nt-q-meta{display:flex;align-items:center;gap:6px;margin-top:5px;font-size:10.5px;color:var(--txt-3)}
.nt-q-meta .lico{width:13px;height:13px;font-size:7px;border-radius:4px}
.nt-q-due{margin-left:auto;display:inline-flex;align-items:center;gap:4px;font-family:"Geist Mono",monospace}
.nt-qhint{margin:10px 0 0;font-size:10.5px;line-height:1.5;color:var(--txt-3)}

/* a queue row that is tracked on a ticket reports that ticket */
.tdlink{display:inline-flex;align-items:center;gap:6px;flex:none;
  font-size:11px;color:var(--txt-3);cursor:pointer;border-bottom:1px solid transparent}
.tdlink:hover{color:var(--txt-2);border-bottom-color:var(--line)}
.tdlink-s{font-weight:600}
.nt-f{margin-bottom:16px}
.nt-row{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.nt-k{font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--txt-3);margin-bottom:7px}
.nt-hint{font-weight:400;text-transform:none;letter-spacing:0}
.nt-parent{display:flex;align-items:center;gap:7px;font-size:13px;color:var(--txt-2)}
.nt-parent b{color:var(--txt);font-weight:500}
.nt-types{display:grid;grid-template-columns:1fr 1fr;gap:6px}
.nt-type{border:1px solid var(--line);border-radius:8px;padding:9px 11px;font-size:12.5px;
  font-weight:500;color:var(--txt-2);background:var(--bg-elev);text-align:left}
.nt-type:hover{border-color:var(--line-hi);color:var(--txt)}
.nt-type.on{border-color:var(--accent);background:color-mix(in srgb,var(--accent) 12%,transparent);color:var(--lit)}
.nt-note{margin:8px 0 0;font-size:11.5px;line-height:1.5;color:var(--txt-3)}
.nt-in,.nt-due input,.nt-link input,.nt-select select,.nt-editor textarea{
  width:100%;background:var(--bg-elev);border:1px solid var(--line);border-radius:8px;
  padding:8px 11px;color:var(--txt);font-size:13px;font-family:inherit;outline:none}
.nt-in:focus,.nt-due input:focus,.nt-link input:focus,.nt-editor textarea:focus{border-color:var(--accent)}
.nt-select{position:relative;display:flex;align-items:center;gap:8px;
  background:var(--bg-elev);border:1px solid var(--line);border-radius:8px;padding-left:11px}
.nt-select select{border:none;background:none;padding-left:0;appearance:none;cursor:pointer}
.nt-due{display:flex;gap:6px}
.nt-due input[type=date]{flex:1;min-width:0}
.nt-time{display:flex;align-items:center;gap:5px;background:var(--bg-elev);border:1px solid var(--line);
  border-radius:8px;padding:0 9px;color:var(--txt-3);flex:none}
.nt-time input{border:none;background:none;padding:8px 0;width:66px;color:var(--txt);
  font-family:"Geist Mono",monospace;font-size:12.5px}
.nt input[type=date]::-webkit-calendar-picker-indicator,
.nt input[type=time]::-webkit-calendar-picker-indicator{filter:invert(.6);cursor:pointer}
.nt-editor{border:1px solid var(--line);border-radius:8px;overflow:hidden;background:var(--bg-elev)}
.nt-bar{display:flex;align-items:center;gap:2px;padding:5px 6px;border-bottom:1px solid var(--line-soft)}
.nt-bar button{width:26px;height:24px;border-radius:5px;color:var(--txt-3);font-size:11.5px;
  display:grid;place-items:center;font-family:"Geist Mono",monospace}
.nt-bar button:hover{background:var(--hover);color:var(--txt)}
.nt-editor textarea{border:none;border-radius:0;resize:vertical;min-height:86px;line-height:1.5}
.nt-editor textarea:focus{border:none}
.nt-link{display:flex;align-items:center;gap:6px;margin-bottom:6px}
.nt-link .chx{color:var(--txt-3);padding:4px}
.nt-link .chx:hover{color:var(--lit)}
.nt-foot{display:flex;align-items:center;justify-content:flex-end;gap:8px;
  padding:12px 16px;border-top:1px solid var(--line);background:var(--bg-elev2)}
.nt-foot .btn-primary{align-self:auto}
.nt-foot .btn-primary:disabled{opacity:.35;cursor:default;background:var(--btn)}

/* what a created ticket carries onto its card */
.stk-desc{margin:7px 0 0;font-size:12.5px;line-height:1.5;color:var(--txt-3)}
.stk-links{display:flex;flex-direction:column;gap:4px;margin-top:9px}
.stk-link{display:flex;align-items:center;gap:10px;border:1px solid var(--line-soft);border-radius:7px;
  padding:5px 9px;font-size:11.5px;color:var(--txt-2);font-family:"Geist Mono",monospace}
.stk-link:hover{border-color:var(--line-hi);color:var(--txt)}
.stk-link-l{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.stk-link-h{flex:none;color:var(--txt-3)}

/* ---------- kanban (tickets by status) ---------- */
.content.kanbanmode{overflow:hidden;display:flex;flex-direction:column}
.kwrap{flex:1;min-height:0;display:flex;flex-direction:column;width:100%}

.kboard{flex:1;min-height:0;display:flex;overflow-x:auto;overflow-y:hidden;
  border:1px solid var(--line);border-radius:12px;background:var(--bg)}
.kboard{scrollbar-width:thin;scrollbar-color:transparent transparent}
.kboard:hover{scrollbar-color:color-mix(in srgb,var(--line-hi) 75%,var(--bg)) transparent}
.kboard::-webkit-scrollbar{height:8px}
.kboard::-webkit-scrollbar-thumb{background:transparent;border-radius:8px}
.kboard:hover::-webkit-scrollbar-thumb{background:var(--line-hi)}
/* **Every column one width.** The basis was a fixed 248px, but a flex item
   will not shrink below its content's minimum, and a card's link is one
   unbreakable line — so a column holding a long Figma URL came out 377px
   beside another at 335, each status a different size. `min-width:0` lets
   the basis hold and the link ellipsise; columns grow together to fill a
   wide screen and scroll on a narrow one. */
.kcol{flex:1 0 280px;min-width:0;min-height:0;display:flex;flex-direction:column;border-right:1px solid var(--line-soft)}
.kcol:last-child{border-right:none}
.kcol.shut{flex:0 0 44px}
.kcol-h{display:flex;align-items:center;gap:7px;padding:11px 12px;border-bottom:1px solid var(--line-soft);flex:none}
.kcol.shut .kcol-h{flex-direction:column;gap:9px;padding:11px 6px;border-bottom:none}
.kcol.shut .kname{writing-mode:vertical-rl;letter-spacing:.08em}
.kdot{width:7px;height:7px;border-radius:50%;flex:none}
.kname{font-size:10.5px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;color:var(--txt-2);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.kcount{font-size:11px;color:var(--txt-3);font-family:"Geist Mono",monospace}
.kcollapse{margin-left:auto;color:var(--txt-3);font-size:13px;line-height:1;padding:0 2px}
.kcol.shut .kcollapse{margin-left:0;order:-1}
.kcollapse:hover{color:var(--lit)}
/* the column scrollbar only shows while you are in that column */
.kcards{flex:1;min-height:0;overflow-y:auto;padding:9px;display:flex;flex-direction:column;gap:8px;
  scrollbar-width:thin;scrollbar-color:transparent transparent}
.kcards:hover{scrollbar-color:color-mix(in srgb,var(--line-hi) 75%,var(--bg)) transparent}
.kcards::-webkit-scrollbar{width:6px}
.kcards::-webkit-scrollbar-thumb{background:transparent;border-radius:8px}
.kcards:hover::-webkit-scrollbar-thumb{background:color-mix(in srgb,var(--line-hi) 75%,var(--bg))}
.kcards:hover::-webkit-scrollbar-thumb:hover{background:var(--line-hi)}
.kempty{font-size:11.5px;color:var(--txt-3);padding:6px 2px}

.kcard{width:100%;min-width:0;text-align:left;background:var(--raise);border:1px solid var(--line);
  border-radius:9px;padding:10px 11px;display:flex;flex-direction:column;gap:8px}
.kcard:hover{border-color:var(--line-hi);background:color-mix(in srgb,var(--raise),var(--tint) 1.2%)}
.ktags{display:flex;align-items:center;gap:5px}
.ktag{font-size:9px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;padding:2px 6px;
  border-radius:4px;background:color-mix(in srgb,var(--tint) 6%,transparent);color:var(--txt-2);white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;max-width:112px}
.ktag.subtag{background:color-mix(in srgb,var(--tint) 10%,transparent);color:var(--txt)}
.ktags .avatar{margin-left:auto}
.effbadge{font-size:9.5px;font-weight:700;font-family:"Geist Mono",monospace;color:var(--txt-3);
  border:1px solid var(--line);border-radius:4px;padding:1px 5px}
.ktitle{font-size:13px;font-weight:500;line-height:1.4;color:var(--txt)}
.ktitle.sm{font-size:12.5px;font-weight:400;color:var(--txt-2)}
.kframe{display:flex;align-items:center;gap:7px;min-width:0;max-width:100%;font-size:11px;color:var(--txt-3);
  font-family:"Geist Mono",monospace}
.kframe-u{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
.kframe .bi{width:13px;height:13px;flex:none}
.kfoot{display:flex;align-items:center;gap:8px;font-size:10.5px;color:var(--txt-3)}
.kdue{display:inline-flex;align-items:center;gap:5px;font-family:"Geist Mono",monospace}
.kdue.over{color:oklch(from #f5405e min(l, var(--ink-l)) c h)}
/* the subtask bar: one segment per child, coloured by its status, so a card
   says how much of its own work is moving without being opened */
.ksubbar{display:flex;align-items:center;gap:7px;margin-top:2px}
.ksubmix{flex:1;height:3px;border-radius:3px;overflow:hidden;display:flex;gap:1px;
  background:color-mix(in srgb,var(--tint) 6%,transparent);opacity:.9}
.ksubmix i{flex:1;height:100%}
.ksubn{font-size:11px;color:var(--txt-3);font-family:"Geist Mono",monospace;flex:0 0 auto}
.ksubc{border-left-width:2px}
.ksubparent{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* ---------- ticket toolbar (list + kanban) ---------- */
.tbar{display:flex;align-items:center;gap:8px;margin-bottom:14px;flex:none;width:100%}
.tbm{position:relative;flex:none}
.tbm-btn{display:inline-flex;align-items:center;gap:7px;height:32px;padding:0 10px;border-radius:8px;
  border:1px solid var(--line);background:var(--bg-elev);color:var(--txt-2);font-size:12.5px;font-weight:500}
.tbm-btn:hover,.tbm-btn.open{border-color:var(--line-hi);color:var(--txt)}
.tbm-btn.on{border-color:var(--line-hi);background:var(--active);color:var(--lit)}
.tbm-btn>svg:last-child{color:var(--txt-3)}
.tbm.wide .tbm-btn{min-width:164px}
.tbm.wide .tbm-l{flex:1;text-align:left}
.tbm-l{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:150px}
/* the menu itself is Picker's (.pick-pop): search field, keyboard, portal */

/* subtasks switch */
.tbsw{display:inline-flex;align-items:center;gap:9px;height:32px;padding:0 12px 0 8px;border-radius:8px;
  border:1px solid var(--line);background:var(--bg-elev);color:var(--txt-2);font-size:12.5px;font-weight:500;flex:none}
.tbsw:hover{border-color:var(--line-hi);color:var(--txt)}
.tbsw i{width:26px;height:15px;border-radius:20px;background:color-mix(in srgb,var(--line-hi) 66%,var(--bg));position:relative;transition:.15s;flex:none}
.tbsw i:after{content:"";position:absolute;top:2px;left:2px;width:11px;height:11px;border-radius:50%;
  background:#8f8f8f;transition:.15s}
.tbsw.on{color:var(--lit)}
.tbsw.on i{background:var(--accent)}
.tbsw.on i:after{left:13px;background:#fff}

/* search takes whatever is left */
.tbsearch{flex:1;min-width:120px;display:flex;align-items:center;gap:8px;height:32px;padding:0 11px;
  border-radius:8px;border:1px solid var(--line);background:var(--bg-elev);color:var(--txt-3)}
.tbsearch:focus-within{border-color:var(--accent);color:var(--txt-2)}
.tbsearch input{flex:1;min-width:0;background:none;border:none;outline:none;color:var(--txt);
  font-family:inherit;font-size:12.5px}
.tbsearch input::placeholder{color:var(--txt-3)}
.tbsearch-x{color:var(--txt-3);font-size:15px;line-height:1;padding:0 2px}
.tbsearch-x:hover{color:var(--lit)}
.tbclear{height:32px;padding:0 11px;border-radius:8px;border:1px solid var(--line);
  color:var(--txt-3);font-size:12.5px;flex:none}
.tbclear:hover{border-color:var(--line-hi);color:var(--lit)}

@media (max-width:1100px){
  .tbar{flex-wrap:wrap}
  .tbsearch{order:9;flex-basis:100%}
}



/* ---------- all launches (workspace directory) ---------- */
.pjwrap{width:100%}
.pj-head{display:flex;align-items:baseline;gap:11px;margin:6px 0 14px}
.pj-head h1{margin:0;font-size:22px;font-weight:600;letter-spacing:-.025em}
.pj-n{font-size:12.5px;color:var(--txt-3)}
.pj-new{margin-left:auto;align-self:center;display:inline-flex;align-items:center;gap:6px}
.pjtbl{width:100%;border-collapse:collapse;font-size:13px}
.pjtbl th{text-align:left;font-weight:500;font-size:11px;color:var(--txt-3);padding:7px 12px;
  border-bottom:1px solid var(--line);background:var(--bg-elev2);white-space:nowrap}
.pj-th{cursor:pointer;user-select:none}
.pj-th:hover{color:var(--txt-2)}
.pj-th.on{color:var(--txt)}
.pj-th.on:after{content:" ▲";font-size:8px;color:var(--txt-3)}
.pj-th.on.desc:after{content:" ▼"}
.pjtbl td{padding:6px 12px;border-bottom:1px solid var(--line-soft);vertical-align:middle}
.pjtbl tbody tr:last-child td{border-bottom:none}
.pjtbl tbody tr.clk{cursor:pointer}
.pjtbl tbody tr.clk:hover{background:var(--hover)}
.pj-name{display:inline-flex;align-items:center;gap:8px;min-width:0}
.pj-name b{font-weight:600;letter-spacing:-.01em}
.pj-prog{display:flex;align-items:center;gap:10px;min-width:190px}
.pj-bar{flex:1;height:3px;border-radius:3px;background:#1e1e22;overflow:hidden}
.pj-bar i{display:block;height:100%;border-radius:3px}
.pj-count{font-size:11.5px;color:var(--txt-2);font-family:"Geist Mono",monospace;white-space:nowrap;width:62px}
.pj-due{font-size:12px;color:var(--txt-2);font-family:"Geist Mono",monospace;white-space:nowrap}
.pj-due.late{color:oklch(from #f5405e min(l, var(--ink-l)) c h)}
.pj-empty{padding:18px 14px}

/* ---------- opened to-do (deliberately thin) ---------- */
.tsheet{position:fixed;top:0;right:0;bottom:0;z-index:61;width:min(480px,92vw);
  display:flex;flex-direction:column;background:var(--bg-elev);border-left:1px solid var(--line);
  box-shadow:-24px 0 70px rgb(0 0 0/calc(.6*var(--shade)))}
.tsheet-top{display:flex;align-items:center;gap:10px;padding:13px 15px;border-bottom:1px solid var(--line-soft)}
.tsheet-k{flex:1;font-size:10.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--txt-3)}
.tsheet-body{flex:1;min-height:0;overflow-y:auto;padding:18px 18px 28px;display:flex;flex-direction:column;gap:16px}
.tsheet-h1{margin:0;font-size:19px;font-weight:600;letter-spacing:-.02em;line-height:1.35}
.tsheet-h1.done{color:var(--txt-3);text-decoration:line-through}
.tsheet-meta{display:flex;align-items:center;gap:10px;font-size:12px;color:var(--txt-3)}
.tsheet-chip{display:inline-flex;align-items:center;gap:7px;border:1px solid var(--line);border-radius:20px;
  padding:3px 10px 3px 4px;color:var(--txt-2)}
.tsheet-due{display:inline-flex;align-items:center;gap:5px;font-family:"Geist Mono",monospace}
.tsheet-due.late{color:oklch(from #f5405e min(l, var(--ink-l)) c h)}
.tsheet-who{margin-left:auto}
.tsheet-desc{width:100%;min-height:110px;resize:vertical;background:var(--bg-elev);border:1px solid var(--line);
  border-radius:10px;padding:11px 13px;color:var(--txt-2);font-family:inherit;font-size:13.5px;
  line-height:1.6;outline:none}
.tsheet-desc:focus{border-color:var(--accent);color:var(--txt)}
.tsheet-atts{display:flex;flex-wrap:wrap;gap:6px}
.stk .tsheet-atts{margin-top:9px}
.stk .tsheet-att{display:inline-flex;align-items:center;gap:6px}
.tsheet-att{font-size:11px;color:var(--txt-3);border:1px solid var(--line);border-radius:7px;
  padding:4px 9px;font-family:"Geist Mono",monospace}
.tsheet-link{display:flex;align-items:center;gap:8px;width:100%;border:1px solid var(--line);
  border-radius:10px;padding:10px 12px;font-size:12.5px;color:var(--txt-3);background:var(--bg-elev)}
.tsheet-link:hover{border-color:var(--line-hi)}
.tsheet-link-t{flex:1;min-width:0;text-align:left;color:var(--txt);overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.tsheet-nolink{margin:0;font-size:11.5px;line-height:1.5;color:var(--txt-3)}
.tsheet-nolink b{color:var(--txt-2);font-weight:500}
.tdrow{cursor:pointer}

/* ---------- home (your notes, then your launches) ---------- */
.hview{max-width:1100px;width:100%;margin:0 auto}
.hview-h{display:flex;align-items:baseline;gap:12px;margin:2px 0 20px}
.hview-h h1{margin:0;font-size:22px;font-weight:600;letter-spacing:-.025em}
.hview-day{font-size:12.5px;color:var(--txt-3)}
.hsec{margin-bottom:30px}
.hsec-h{display:flex;align-items:center;gap:9px;font-size:11px;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:var(--txt-3);margin-bottom:12px}
.hsec-n{font-family:"Geist Mono",monospace;color:var(--txt-2);font-weight:500}
.hsec-h .btn-ghost{margin-left:auto}
/* the switch to each half’s own page; it opens a screen rather than holding a
   state, so no segment is ever "on" */
/* Statuses combine, so more than one chip can be lit at once. Only the ones
   you picked are on the header — laying all ten out ran the row past the
   width of the page for a control that is empty most of the time, so the rest
   live behind the ＋. */
.hsec-stat{margin-left:8px;text-transform:none;letter-spacing:0}
/* A chip on the bar is two controls in one shell: the body switches the
   status on and off, the × takes it off the bar altogether. Off is the
   quieter state but it is still *there* — that is the difference between a
   filter you prepped and one you deleted.

   On is **blue with white text**, off is grey. No status dot: the chip's own
   colour already says whether it is doing anything, and a second colour on
   the left said it twice.

   Padding lives on the shell and is cancelled where the split controls
   provide their own — the plain chip is a bare <button> and was getting no
   padding at all once the padding moved onto .stchip-t, which is why it read
   as cropped. */
/* inside the track, so no border of its own — the box already draws the
   edge, and a border inside a border is two lines saying one thing */
.stchip{display:inline-flex;align-items:center;height:24px;
  border:1px solid transparent;border-radius:6px;background:transparent;
  font-size:11.5px;font-weight:500;color:var(--txt-2);overflow:hidden;
  transition:background .12s,border-color .12s,color .12s}
button.stchip{padding:0 12px}
.stchip-t{display:inline-flex;align-items:center;gap:7px;height:100%;
  padding:0 7px 0 12px;color:inherit;font:inherit}
.stchip b{font-weight:500;font-size:10px;color:var(--txt-3);font-family:"Geist Mono",monospace}
.stchip-x{display:inline-flex;align-items:center;height:100%;padding:0 11px 0 6px;
  font-size:14px;line-height:1;color:var(--txt-3)}

/* off — grey, and quiet */
.stchip:not(.on){color:var(--txt-3)}
.stchip:not(.on):hover{color:var(--txt-2);border-color:var(--line-hi)}

/* On — **the status's own colour**, not one accent for all of them: a row of
   identical blue chips says which filters are running but not what they are,
   and the colour is the fastest read on the page.

   Darkened against near-black rather than used at full strength, the same
   rule the workstream tiles follow: STATUS_COLORS are tuned to be read *as
   text* on a dark ground, so white on them fails outright — white on raw
   #f5a623 is 2.2:1. Mixed 62% with near-black the hue is unchanged and the
   worst case (QA amber) measures 4.7:1 and the rest 6.8 to 7.5. */
.stchip.on{background:color-mix(in srgb,var(--s,var(--accent)) calc(100% - 38% * var(--dkg)),#07070a);
  border-color:color-mix(in srgb,var(--s,var(--accent)) calc(100% - 26% * var(--dkg)),#07070a);color:#fff}
.stchip.on b{color:rgba(255,255,255,.74)}
.stchip.on .stchip-x{color:rgba(255,255,255,.74)}
.stchip.on .stchip-x:hover{color:#fff;background:rgba(0,0,0,.22)}
.stchip:not(.on) .stchip-x:hover{color:var(--txt);background:color-mix(in srgb,var(--tint) 7%,transparent)}
/* "Needs you" is the default, not a status — it stays neutral so it cannot be
   mistaken for one, and so it never collides with In Progress blue */
button.stchip.on{background:var(--active);border-color:var(--line-hi);color:var(--lit)}
/* the custom filter: one chip, whatever it holds — the count says how much,
   the menu says what. Neutral when lit, like Needs you, because it stands
   for several statuses and wearing one of their colours would name one. */
.stcustom{display:inline-flex}
button.stchip.stcustom-btn{gap:7px;padding:0 9px 0 12px}
.stcustom-btn svg{width:10px;height:10px;opacity:.7;transition:transform .14s}
.stcustom-btn.open svg{transform:rotate(180deg)}
.stcustom-btn b{min-width:15px;height:15px;padding:0 4px;border-radius:8px;display:inline-grid;place-items:center;
  background:color-mix(in srgb,var(--tint) 8%,transparent);line-height:1}
.stcustom-btn.on b{background:var(--accent);color:#fff}

/* One popover for every pick-from-a-list in the app (`Picker`). The status
   menu and the project menu each had their own before, identical apart from
   the rows. */
.pick{position:relative;display:inline-flex}
.pick-pop{position:fixed;z-index:200;width:250px;
  display:flex;flex-direction:column;padding:5px;
  background:var(--raise);border:1px solid var(--line);border-radius:10px;
  box-shadow:0 14px 40px -12px rgb(0 0 0/calc(.8*var(--shade)))}
/* the popover sets its own type: it is a menu, not part of whatever heading
   it happens to hang off */
.pick-pop,.pick-pop *{text-transform:none;letter-spacing:normal}
.pick-q{margin:1px 1px 5px;padding:7px 10px;border:1px solid var(--line);border-radius:7px;
  background:color-mix(in srgb,var(--tint) 5%,transparent);color:var(--txt);
  font-family:inherit;font-size:12.5px;font-weight:400;letter-spacing:normal;text-transform:none}
.pick-q:focus{outline:none;border-color:var(--line-hi);background:color-mix(in srgb,var(--tint) 7%,transparent)}
.pick-q::placeholder{color:var(--txt-3);font-weight:400;letter-spacing:normal;text-transform:none}
.pick-list{display:flex;flex-direction:column;gap:1px;max-height:264px;overflow-y:auto}
.pick-list button{display:flex;align-items:center;gap:8px;width:100%;padding:6px 8px;
  border-radius:6px;font-size:12.5px;font-weight:400;color:var(--txt-2);text-align:left}
/* hover and keyboard land on the same state, so walking with ↓ looks like
   pointing at it */
.pick-list button.at{background:var(--hover);color:var(--txt)}
.pick-list button.on{color:var(--lit)}
.pick-list button.on::after{content:"✓";margin-left:auto;font-size:11px;color:var(--accent)}
.pick-list .dot{width:7px;height:7px;border-radius:50%;flex:none}
.pick-list .lico{flex:none}
.pick-l{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pick-list b{font-weight:500;font-size:10px;color:var(--txt-3);font-family:"Geist Mono",monospace}
.pick-list b.zero{opacity:.45}
.pick-list button.on b{margin-right:2px}
.pick-none{margin:8px;font-size:11.5px;color:var(--txt-3)}

.stadd{position:relative;display:inline-flex}
.stadd-btn{display:inline-flex;align-items:center;gap:5px;height:24px;padding:0 9px;
  border:1px dashed var(--line);border-radius:6px;color:var(--txt-3);font-size:11.5px}
.stadd-btn:hover,.stadd-btn.open{border-style:solid;border-color:var(--line-hi);color:var(--txt)}
.stadd-pop{position:absolute;top:calc(100% + 6px);left:0;z-index:40;min-width:206px;
  display:flex;flex-direction:column;gap:1px;padding:5px;
  background:var(--raise);border:1px solid var(--line);border-radius:10px;
  box-shadow:0 14px 40px -12px rgb(0 0 0/calc(.8*var(--shade)))}
.stadd-pop button{display:flex;align-items:center;gap:8px;width:100%;padding:6px 8px;
  border-radius:6px;font-size:12px;color:var(--txt-2);text-align:left}
.stadd-pop button:hover{background:var(--hover);color:var(--txt)}
.stadd-pop button.on{color:var(--lit)}
.stadd-pop button.on::after{content:"✓";margin-left:auto;font-size:11px;color:var(--accent)}
.stadd-pop .dot{width:7px;height:7px;border-radius:50%;flex:none}
.stadd-l{flex:1;min-width:0}
.stadd-pop b{font-weight:500;font-size:10px;color:var(--txt-3);font-family:"Geist Mono",monospace}
.stadd-pop b.zero{opacity:.45}
.stadd-pop button.on b{margin-right:2px}
.hsec-h .tbm-btn{padding:4px 10px;font-size:12px}
.hsec-seg{margin-left:auto;text-transform:none;letter-spacing:0}
.hsec-seg button{font-size:12px;font-weight:500;padding:4px 11px}
.hsec-seg b{margin-left:7px;font-weight:500;font-size:10.5px;color:var(--txt-3);
  font-family:"Geist Mono",monospace}
.hsec-seg button:hover b{color:var(--txt-2)}
.hsec-seg button.on b{color:var(--txt-2)}
/* the notes list is the same rows the queue always had — no page chrome */
.hsec .todowrap{max-width:none}

/* Home: the tickets assigned to you, same card as the Kanban board */
.hkrow{display:grid;grid-template-columns:repeat(auto-fill,minmax(258px,1fr));gap:10px;align-items:start}
.hkrow .kcard{background:var(--bg-elev)}
.kstatus{display:inline-flex;align-items:center;gap:6px;align-self:flex-start;font-size:11px;
  font-weight:600;border:1px solid var(--line);border-radius:20px;padding:2px 10px;background:var(--bg)}
.ktrack{font-size:9.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase}

/* Home digest + the notes and to-do pages */
.hstats{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-bottom:26px}
.hstat{text-align:left;border:1px solid var(--line);border-radius:11px;background:var(--bg-elev);
  padding:13px 14px;display:flex;flex-direction:column;gap:4px}
.hstat:hover{border-color:var(--line-hi);background:var(--bg-elev2)}
.hstat-v{font-size:21px;font-weight:600;letter-spacing:-.02em;font-family:"Geist Mono",monospace}
.hstat-k{font-size:10.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--txt-3)}
.hnext{border:1px solid var(--line);border-radius:11px;
  max-height:min(42vh,440px);overflow:hidden auto;overscroll-behavior:contain}
.hnext-row{display:flex;align-items:center;gap:11px;width:100%;text-align:left;padding:10px 13px;
  border-bottom:1px solid var(--line-soft);font-size:13px}
.hnext-row:last-child{border-bottom:none}
.hnext-row:hover{background:var(--hover)}
.hnext-kind{flex:none;width:50px;font-size:9.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--txt-3)}
.hnext-kind.nk-ticket{color:var(--accent)}
.hnext-st{flex:none;display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:500;width:132px}
.hnext-due{flex:none;display:inline-flex;align-items:center;gap:5px;font-size:11px;color:var(--txt-3);
  font-family:"Geist Mono",monospace;width:74px;justify-content:flex-end}
.hnext-due.late{color:oklch(from #f5405e min(l, var(--ink-l)) c h)}
.notewrap,.tkwrap{width:100%;max-width:1100px;margin:0 auto}
.notewrap .todowrap{max-width:none}
.kbd{font-family:"Geist Mono",monospace;font-weight:500;border:1px solid var(--line);border-radius:4px;
  padding:0 4px;color:var(--txt-2)}
.tkgroup{margin-bottom:22px}
.tkgroup-h{display:flex;align-items:center;gap:8px;font-size:11px;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:var(--txt-3);margin-bottom:11px}
.tkgroup-n{font-family:"Geist Mono",monospace;color:var(--txt-2);font-weight:500}









/* a change opened as a ticket: the panel is the established one, these are
   the two controls it doesn't already have */
.tf-status.as-btn{cursor:pointer}
.tf-status.as-btn:disabled{cursor:default;opacity:.8}
.tsec-p{margin-left:auto;font-size:11px;color:var(--txt-3);font-family:"Geist Mono",monospace;font-weight:400}
.lc-tool.del:hover{background:rgba(245,64,94,.12);color:oklch(from #f5405e min(l, var(--ink-l)) c h)}
.jchg{cursor:pointer}
.jchg:active{cursor:grabbing}







/* the ask-first dialog, over everything including an open ticket */
.confirm-scrim{position:fixed;inset:0;background:rgba(0,0,0,.6);backdrop-filter:blur(2px);z-index:90}
.confirm{position:fixed;z-index:91;top:50%;left:50%;transform:translate(-50%,-50%);
  width:min(420px,92vw);background:var(--raise);border:1px solid var(--line);border-radius:12px;
  padding:20px;box-shadow:0 24px 60px rgb(0 0 0/calc(.6*var(--shade)))}
.confirm-h{margin:0 0 8px;font-size:16px;font-weight:600;letter-spacing:-.01em}
.confirm-b{margin:0 0 18px;font-size:13px;line-height:1.55;color:var(--txt-2)}
.confirm-f{display:flex;justify-content:flex-end;gap:8px}
.confirm-no{font-size:12.5px;font-weight:600;color:var(--txt-2);border:1px solid var(--line);
  border-radius:8px;padding:8px 14px}
.confirm-no:hover{border-color:var(--line-hi);color:var(--txt)}
.confirm-yes{font-size:12.5px;font-weight:600;color:#fff;background:#e2374f;border-radius:8px;padding:8px 14px}
.confirm-yes:hover{background:#f5405e}

/* the ticket's overflow menu */
.tmore{position:relative;display:inline-flex}
.tmore-pop{position:absolute;top:calc(100% + 6px);right:0;z-index:5;min-width:200px;
  background:var(--raise);border:1px solid var(--line);border-radius:10px;padding:4px;
  box-shadow:0 16px 40px rgb(0 0 0/calc(.55*var(--shade)));display:flex;flex-direction:column;gap:1px}
.tmore-pop button{display:flex;align-items:center;gap:9px;width:100%;text-align:left;font-size:12.5px;
  color:var(--txt-2);border-radius:7px;padding:8px 10px}
.tmore-pop button:hover{background:var(--hover);color:var(--txt)}
.tmore-pop button.danger{color:oklch(from #f5405e min(l, var(--ink-l)) c h)}
.tmore-pop button.danger:hover{background:rgba(245,64,94,.12)}







/* the account menu, hung off the sidebar footer */
.side-foot{position:relative}
.foot-item.on{background:var(--hover);color:var(--txt)}
/* wider than the sidebar on purpose: a name and its badge need the room */
.pmenu{position:absolute;left:8px;width:296px;bottom:calc(100% + 6px);z-index:40;
  background:var(--raise);border:1px solid var(--line);border-radius:12px;overflow:hidden;
  box-shadow:0 20px 50px rgb(0 0 0/calc(.6*var(--shade)))}
.pmenu-who{display:flex;align-items:center;gap:12px;padding:14px 14px 13px}
.pmenu-id{min-width:0}
.pmenu-n{display:flex;align-items:center;gap:8px;font-size:14px;font-weight:600;letter-spacing:-.01em;color:var(--txt);white-space:nowrap}
.pmenu-access{font-size:10px;font-weight:500;color:var(--txt-3);border:1px solid var(--line);
  border-radius:20px;padding:1px 7px}
.pmenu-title{font-size:12.5px;color:var(--txt-2);margin-top:2px}
.pmenu-sec{display:flex;flex-direction:column;gap:9px;padding:12px 14px;
  border-top:1px solid var(--line-soft)}
.pmenu-teams{display:flex;flex-wrap:wrap;gap:6px}
.pmenu-team{font-size:11px;color:var(--txt-2);border:1px solid var(--line);border-radius:20px;padding:2px 9px}
.pmenu-mail{font-size:12.5px;color:var(--accent);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pmenu-mail:hover{text-decoration:underline}
.pmenu-list{padding:5px;border-top:1px solid var(--line-soft)}
.pmenu-item{display:block;width:100%;text-align:left;font-size:13px;color:var(--txt-2);
  border-radius:7px;padding:8px 9px}
.pmenu-item:hover{background:var(--hover);color:var(--txt)}
.pmenu-item.out{color:var(--txt-3)}
.pmenu-item.out:hover{background:rgba(245,64,94,.12);color:oklch(from #f5405e min(l, var(--ink-l)) c h)}
/* a name too long for the row gives way before its chip does */
.pmenu-nm{min-width:0;overflow:hidden;text-overflow:ellipsis}
.pmenu-access.admin{color:var(--accent);border-color:color-mix(in srgb,var(--accent) 45%,transparent)}
/* The Google account's mark is its first letter on a neutral ground. There
   is no picture: the app draws no remote images but favicons, and a seat's
   colour here would make the account look like one more roster person —
   which is exactly the confusion this header exists to prevent. */
.pmenu-me{width:40px;height:40px;flex:none;border-radius:50%;display:grid;place-items:center;
  background:var(--bg-elev);border:1px solid var(--line);color:var(--txt);font-size:16px;font-weight:600}
.pmenu-acct{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* who the app is drawn for, under who signed in */
.pmenu-as{display:flex;flex-direction:column;gap:9px;padding:11px 14px 12px;border-top:1px solid var(--line-soft)}
.pmenu-k{font-size:10.5px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;color:var(--txt-3)}
.pmenu-seat{display:flex;align-items:center;gap:10px}
.pmenu-seat-n{display:flex;align-items:center;gap:7px;font-size:13px;font-weight:600;color:var(--txt);white-space:nowrap}
.pmenu-seat-s{margin-top:1px;font-size:12px;color:var(--txt-2)}
.pmenu-switch{display:flex;flex-wrap:wrap;gap:6px}
.pmenu-btn{display:inline-flex;align-items:center;gap:6px;height:28px;padding:0 10px;border-radius:7px;
  border:1px solid var(--line);background:var(--bg-elev);color:var(--txt);font-size:12.5px;white-space:nowrap}
.pmenu-btn:hover,.pmenu-btn.open{border-color:var(--line-hi);background:var(--hover)}
.pmenu-btn.quiet{background:none;color:var(--txt-2)}
.pmenu-btn.quiet:hover{color:var(--txt)}
/* the live boards' name and colour for this person */
.pmenu-live{display:flex;align-items:center;gap:8px;padding:9px 14px;border-top:1px solid var(--line-soft);
  font-size:11.5px;color:var(--txt-2)}
.pmenu-live b{color:var(--txt);font-weight:600}
/* the footer's seat, and — only while an admin is looking through somebody
   else's — a caption saying so, in the mockup label's amber: this is not
   your own view, the way that is not the real workspace */
.foot-id{display:flex;flex-direction:column;min-width:0;text-align:left;line-height:1.2}
.foot-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.foot-as{font-size:10px;font-weight:600;letter-spacing:.02em;color:oklch(from var(--warn) min(l, var(--ink-l)) c h)}


/* the notification centre, off the sidebar footer */
.notif-count{margin-left:auto;min-width:17px;height:17px;padding:0 5px;border-radius:9px;
  background:var(--accent);color:#fff;font-size:10px;font-weight:600;display:grid;place-items:center;
  font-family:"Geist Mono",monospace}
.ncen{position:absolute;left:8px;width:392px;bottom:calc(100% + 6px);z-index:40;max-height:min(620px,78vh);
  display:flex;flex-direction:column;background:var(--raise);border:1px solid var(--line);
  border-radius:12px;overflow:hidden;box-shadow:0 20px 50px rgb(0 0 0/calc(.6*var(--shade)))}
.ncen-top{display:flex;align-items:center;gap:9px;padding:12px 12px 11px 14px;border-bottom:1px solid var(--line-soft)}
.ncen-t{font-size:14px;font-weight:600;letter-spacing:-.01em;color:var(--txt)}
.ncen-n{min-width:18px;height:18px;padding:0 6px;border-radius:9px;background:var(--accent);color:#fff;
  font-size:10px;font-weight:600;display:grid;place-items:center;font-family:"Geist Mono",monospace}
.ncen-all{margin-left:auto;font-size:11.5px;color:var(--txt-3)}
.ncen-all:hover:not(:disabled){color:var(--txt)}
.ncen-all:disabled{opacity:.4;cursor:default}
.ncen-tabs{display:flex;gap:4px;padding:9px 10px;border-bottom:1px solid var(--line-soft)}
.ncen-tabs button{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;color:var(--txt-3);
  border:1px solid transparent;border-radius:20px;padding:3px 10px}
.ncen-tabs button:hover{color:var(--txt-2);background:var(--hover)}
.ncen-tabs button.on{color:var(--txt);background:var(--active);border-color:var(--line)}
.ncen-tabs b{font-size:9.5px;font-family:"Geist Mono",monospace;color:var(--accent)}
.ncen-list{flex:1;min-height:0;overflow-y:auto;padding:4px}
.ncen-day{font-size:9.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--txt-3);
  padding:10px 10px 5px}
.ncen-row{position:relative;display:flex;align-items:flex-start;gap:10px;width:100%;text-align:left;
  border-radius:9px;padding:9px 22px 9px 10px}
.ncen-row:hover{background:var(--hover)}
.ncen-row.unread{background:color-mix(in srgb,var(--accent) 5.5%,transparent)}
.ncen-row.unread:hover{background:color-mix(in srgb,var(--accent) 10%,transparent)}
.ncen-body{display:flex;flex-direction:column;gap:3px;min-width:0;flex:1}
.ncen-line{font-size:12.5px;color:var(--txt-2);line-height:1.45}
.ncen-line b{color:var(--txt);font-weight:600}
.ncen-detail{font-size:12px;color:var(--txt-3);line-height:1.45;overflow:hidden;text-overflow:ellipsis;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.ncen-meta{display:flex;align-items:center;flex-wrap:wrap;gap:10px;margin-top:2px;font-size:10.5px;color:var(--txt-3)}
.ncen-kind{display:inline-flex;align-items:center;gap:5px;font-weight:600}
.ncen-kind i{width:5px;height:5px;border-radius:50%}
.ncen-launch{display:inline-flex;align-items:center;gap:5px}
.ncen-track{font-family:"Geist Mono",monospace}
.ncen-dot{position:absolute;right:10px;top:14px;width:6px;height:6px;border-radius:50%;background:var(--accent)}
.ncen-empty{display:flex;flex-direction:column;align-items:center;gap:10px;padding:46px 20px;
  font-size:12.5px;color:var(--txt-3)}
/* **The feed as a page** (the popover's expand): the same rows with room to
   breathe — the whole detail rather than two lines of it, how long ago each
   one was, and a count on each day. A reading surface, so a reading width:
   a notification is a sentence, and at 1180px a line runs out of the eye. */
.nfpage{width:100%;max-width:960px;margin-inline:auto}
.nfp-list{border:1px solid var(--line);border-radius:11px;background:var(--bg-elev);padding:6px 6px 8px}
.nfp-list .ncen-day{display:flex;align-items:baseline;gap:8px;padding:12px 12px 6px}
.nfp-list .ncen-day b{font-family:"Geist Mono",monospace;font-size:10px;font-weight:500;letter-spacing:0;color:var(--txt-3)}
.nfp-list .ncen-row{gap:12px;padding:12px 30px 12px 12px}
.nfp-list .ncen-line{font-size:13.5px}
.nfp-list .ncen-detail{font-size:12.5px;display:block;-webkit-line-clamp:unset;overflow:visible}
.nfp-list .ncen-meta{font-size:11px}
.nfp-list .ncen-dot{top:19px;right:12px}
.nfp-when{flex:none;margin-left:auto;padding-left:12px;font-size:11px;color:var(--txt-3);
  font-family:"Geist Mono",monospace;white-space:nowrap;line-height:1.7}
.nfp-all:disabled{opacity:.4;cursor:default;border-style:dashed}
.nfp-foot{margin-top:14px}




/* A launch's workstreams as three flat states. The tile colour is the
   state — grey nothing, blue in progress, green done — and the glyph is what
   says which workstream. Colours come from STATUS_COLORS. */
.wsr{display:flex;align-items:center;gap:6px}
/* 20px, the same footprint as the launch mark beside it in the row — the
   two read as one size or the row looks assembled from spare parts.
   Depth comes from one light source: a lit top edge, a darker floor, and a
   little of the tile's own colour thrown onto the row under it. All of it
   is inset shadow rather than a border, so the 20px box stays 20px. */
.wsr-1{position:relative;display:grid;place-items:center;width:20px;height:20px;flex:none;
  border-radius:6px;transition:transform .14s cubic-bezier(.2,.8,.3,1),box-shadow .14s,filter .14s}
.wsr-ic{width:10px;height:10px;display:block;position:relative}

/* nothing here yet — a slot, not a hole. Transparent read as a gap in the
   row rather than as one of four things. */
.wsr-1.none{background:linear-gradient(180deg,color-mix(in srgb,var(--tint) 5%,transparent),color-mix(in srgb,var(--tint) 1.2%,transparent));
  box-shadow:inset 0 0 0 1px var(--line),inset 0 1px 0 rgba(255,255,255,.04)}
.wsr-1.none .wsr-ic{color:#666;opacity:.75}

/* The status colours are tuned to sit on near-black as text, so at full
   strength a white glyph on top of them has almost no contrast — #45d267
   especially. Darken the fill and keep the hue: still STATUS_COLORS, still
   unmistakably blue and green, but the glyph reads. The gradient is kept
   shallow (56% → 42%) because its lightest point is the worst case: white
   on it measures 5.3:1 for green and 7.4:1 for blue — a shade under the
   flat 52% fill it replaces, still clear of 4.5:1. */
.wsr-1.open,.wsr-1.review,.wsr-1.done{
  background:linear-gradient(180deg,
    color-mix(in srgb,var(--t) calc(100% - 44% * var(--dkg)),#0b0b0e),
    color-mix(in srgb,var(--t) calc(100% - 58% * var(--dkg)),#07070a));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.2),
    inset 0 0 0 1px color-mix(in srgb,var(--t) calc(100% - 40% * var(--dkg)),#07070a),
    0 1px 4px -1px color-mix(in srgb,var(--t) 50%,transparent)}
.wsr-1.open .wsr-ic,.wsr-1.review .wsr-ic,.wsr-1.done .wsr-ic{color:#fff;filter:drop-shadow(0 1px 0 rgba(0,0,0,.28))}

/* the one in play gets a halo — of four tiles it is the only one anybody
   can act on, and the ring is what the eye lands on first */
/* No ring on the one in play. It had a light travelling round it (a conic
   gradient whose angle was animated through a registered @property), which
   said "somebody is on it right now"; across sixty rows it was dozens of
   layers repainting every frame and the directory lagged for it, and once it
   stood still the outline was saying nothing the blue fill does not already
   say (2026-09-28, both pulled). */

.wsr-1:hover{transform:translateY(-1px);filter:brightness(1.12)}
.wsr-1.open:hover,.wsr-1.review:hover,.wsr-1.done:hover{box-shadow:inset 0 1px 0 rgba(255,255,255,.26),
  inset 0 0 0 1px color-mix(in srgb,var(--t) calc(100% - 30% * var(--dkg)),#07070a),
  0 3px 9px -2px color-mix(in srgb,var(--t) 60%,transparent)}







/* ongoing above the line, everything not asking for anything below it */
.pj-grp td{padding:14px 12px 5px;font-size:9.5px;font-weight:700;letter-spacing:.08em;
  text-transform:uppercase;color:var(--txt-3);border-bottom:1px solid var(--line)}
.pjtbl tbody tr:first-child .pj-grp td,.pj-grp:first-child td{padding-top:4px}
.pj-grp td span{margin-left:8px;font-family:"Geist Mono",monospace;font-weight:500;letter-spacing:0;
  color:var(--txt-2)}
.pj-grp td b{margin-left:10px;font-size:10.5px;font-weight:400;letter-spacing:0;text-transform:none;
  color:#4d4d4d}
.pj-grp.off td{color:#5c5c5c}
/* below the line the rows step back — still readable, no longer competing */
/* the pod band inside a state band — the Gantt's group head, in a table row:
   a tinted strip, the name in the same small caps, the count trailing it,
   and a caret because a pod you are not staffing should fold away */
/* the same #0d0d0d the header row is painted in, not --bg-elev2: a band
   lighter than the header read as the louder of the two, when it is the
   quieter thing. A sub-band of a divider, so it takes --txt-3 and only comes
   up on hover. */
.pj-band td{padding:0 12px;background:var(--bg-elev2);border-bottom:1px solid var(--line-soft)}
.pj-band button{display:flex;align-items:center;gap:7px;width:100%;height:26px;
  font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--txt)}
.pj-band button:hover{color:var(--lit)}
.pj-band b{font-weight:500;letter-spacing:0;text-transform:none;font-size:11px;
  color:var(--txt-3);font-family:"Geist Mono",monospace}
.pj-band.off button{color:var(--txt-2)}
.pj-caret{display:inline-block;font-size:9px;line-height:1;color:var(--txt-3);
  transition:transform .14s}
.pj-caret.shut{transform:rotate(-90deg)}
.pj-off{opacity:.62}
.pj-off:hover{opacity:1}












/* the to-dos tracked on a change — the same jotted notes as the queue, with
   their done state, attachable after the fact */
.tnotes{display:flex;flex-direction:column;gap:4px;margin-top:8px}
.tnote-row{display:flex;align-items:center;gap:10px;border:1px solid var(--line-soft);
  border-radius:8px;padding:9px 11px;font-size:13px;color:var(--txt)}
.tnote-row:hover{border-color:var(--line-hi)}
.tnote-row.done .tnote-t{color:var(--txt-3);text-decoration:line-through}
.tnote-t{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tnote-due{display:inline-flex;align-items:center;gap:5px;flex:none;font-size:11px;color:var(--txt-3);
  font-family:"Geist Mono",monospace}
.tnote-x{flex:none;color:transparent;display:grid;place-items:center}
.tnote-row:hover .tnote-x{color:var(--txt-3)}
.tnote-x:hover{color:oklch(from #f5405e min(l, var(--ink-l)) c h)}
.tnotes-pick{display:flex;flex-direction:column;gap:3px;margin-top:8px;padding:5px;
  background:var(--bg-elev);border:1px solid var(--line);border-radius:9px}
.tnote-opt{display:flex;align-items:center;gap:9px;width:100%;text-align:left;font-size:12.5px;
  color:var(--txt-2);border-radius:7px;padding:8px 9px}
.tnote-opt:hover{background:var(--hover);color:var(--txt)}
.tnotes-pick .muted{padding:8px 9px;font-size:12.5px}







/* ---------- EOD review ---------- */
/* Read like a stack of short notes, because that is what they are: three
   lines each. The page is capped — an EOD read edge-to-edge on a wide
   monitor is one word per line. */
.eodwrap{width:100%;max-width:1080px;margin-inline:auto}
.eod-head{display:flex;align-items:center;gap:10px;margin:2px 0 18px}
.eod-step{width:30px;height:30px;border:1px solid var(--line);border-radius:8px;display:grid;
  place-items:center;color:var(--txt-2)}
.eod-step:hover:not(:disabled){background:var(--hover);color:var(--lit)}
.eod-step:disabled{opacity:.3;cursor:default}
.eod-date{display:flex;flex-direction:column;gap:2px}
.eod-date h1{margin:0;font-size:19px;font-weight:600;letter-spacing:-.02em}
.eod-date span{font-size:12px;color:var(--txt-3)}
.eod-bn{color:oklch(from var(--st-blocked) min(l, var(--ink-l)) c h);font-weight:600}
.eod-today{margin-left:auto;font-size:12px;color:var(--txt-2);border:1px solid var(--line);
  border-radius:7px;padding:5px 11px}
.eod-today:hover{border-color:var(--line-hi);color:var(--lit)}

/* the only part of the page that needs acting on tonight */
.eod-blocks{border:1px solid color-mix(in srgb,var(--st-blocked) 34%,transparent);
  background:color-mix(in srgb,var(--st-blocked) 7%,transparent);
  border-radius:11px;padding:12px 14px;margin-bottom:18px}
.eod-blocks h2{margin:0 0 9px;font-size:10.5px;font-weight:700;letter-spacing:.07em;
  text-transform:uppercase;color:oklch(from var(--st-blocked) min(l, var(--ink-l)) c h)}
.eod-brow{display:flex;align-items:center;gap:8px;padding:5px 0;font-size:12.5px;
  border-top:1px solid var(--line-soft)}
.eod-brow:first-of-type{border-top:none}
.eod-brow b{font-weight:600;flex:none}
.eod-why{color:var(--txt-3);font-size:12px;min-width:0}

.eod-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(324px,1fr));gap:12px}
.eod-card{border:1px solid var(--line);border-radius:12px;background:var(--bg-elev);
  padding:13px 15px 14px;display:flex;flex-direction:column;gap:11px;text-align:left}
.eod-card.has-block{border-color:color-mix(in srgb,var(--st-blocked) 30%,var(--line))}
.eod-card-h{display:flex;align-items:center;gap:9px}
.eod-who{display:flex;flex-direction:column;gap:1px;min-width:0}
.eod-who b{font-size:13px;font-weight:600;letter-spacing:-.01em}
.eod-who span{font-size:11px;color:var(--txt-3)}

.eod-lines{display:flex;flex-direction:column;gap:9px}
.eod-l{display:flex;flex-direction:column;gap:3px}
.eod-k{font-size:9.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--txt-3)}
.eod-l.block .eod-k{color:oklch(from var(--st-blocked) min(l, var(--ink-l)) c h)}
.eod-l ul{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:3px}
.eod-l li{font-size:12.5px;color:var(--txt-2);line-height:1.45}
.eod-ref{font-size:12.5px;color:var(--txt);border-bottom:1px solid var(--line);padding-bottom:1px}
.eod-ref:hover{border-bottom-color:var(--accent);color:var(--lit)}
.eod-ref-l{font-size:10.5px;color:var(--txt-3);margin-left:5px;border:none}

/* **What ShownRoom didn't see.** A line somebody added reads as theirs: a
   small hollow mark where a generated line has none, the words plain rather
   than a ticket link, and a quiet × to take it back out. */
.eod-added{position:relative;display:flex;align-items:flex-start;gap:6px;padding-left:12px}
.eod-added::before{content:"";position:absolute;left:1px;top:.62em;width:5px;height:5px;border-radius:50%;
  box-shadow:inset 0 0 0 1.2px var(--txt-3)}
.eod-l.block .eod-added::before{box-shadow:inset 0 0 0 1.2px var(--st-blocked)}
.eod-added span{color:var(--txt);min-width:0}
.eod-rm{flex:none;width:18px;height:18px;margin-left:auto;border-radius:5px;display:grid;place-items:center;
  color:var(--txt-3);opacity:.45;transition:opacity .12s,background .12s}
.eod-rm svg{width:10px;height:10px}
.eod-added:hover .eod-rm,.eod-rm:focus-visible{opacity:1}
.eod-rm:hover{background:var(--hover);color:var(--txt)}
.eod-why.added{color:var(--txt-2)}
.eod-why.added::before{content:"·";margin:0 7px 0 1px;color:var(--txt-3)}
/* the card's one control, at its foot however long the card runs */
.eod-addbtn{margin-top:auto;align-self:flex-start;display:inline-flex;align-items:center;gap:6px;
  padding:4px 9px 4px 7px;margin-left:-7px;border-radius:7px;font-size:12px;color:var(--txt-3)}
.eod-addbtn svg{width:11px;height:11px}
.eod-addbtn:hover{background:var(--hover);color:var(--txt)}
.eod-add{margin-top:auto;display:flex;flex-direction:column;gap:8px;padding-top:10px;border-top:1px solid var(--line-soft)}
.eod-addseg{align-self:flex-start}
.eod-addseg button{font-size:11.5px;padding:3px 9px}
.eod-addin{height:34px;padding:0 11px;border-radius:8px;background:var(--bg);border:1px solid var(--line);
  color:var(--txt);font:inherit;font-size:12.5px;font-weight:400;letter-spacing:0;text-transform:none;outline:none}
.eod-addin::placeholder{color:var(--txt-3)}
.eod-addin:focus{border-color:var(--accent);box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 18%,transparent)}
.eod-addgo{display:flex;justify-content:flex-end;gap:6px}
.eod-addno{font-size:12px;color:var(--txt-3);padding:5px 10px;border-radius:7px}
.eod-addno:hover{color:var(--txt);background:var(--hover)}
.eod-addok{font-size:12px;font-weight:600;color:#fff;background:var(--accent);padding:5px 12px;border-radius:7px}
.eod-addok:disabled{opacity:.4;cursor:not-allowed}


.eod-empty{color:var(--txt-3);font-size:13px;padding:34px 0;text-align:center}

.eod-ph{margin-bottom:12px}
.eod-people{border:1px solid var(--line);border-radius:12px;overflow:hidden}
.eod-prow+.eod-prow{border-top:1px solid var(--line-soft)}
.eod-phead{display:flex;align-items:center;gap:10px;width:100%;padding:10px 14px;text-align:left}
.eod-phead:hover{background:var(--hover)}
.eod-prow.open{background:var(--bg-elev)}
/* one mark per weekday: it ended clear, it ended stuck, or it was a weekend */
.eod-strip{margin-left:auto;display:inline-flex;gap:3px;align-items:center}
.eod-strip i{width:7px;height:16px;border-radius:2px;background:var(--line);display:block}
.eod-strip i.clear{background:color-mix(in srgb,var(--st-done) calc(100% - 50% * var(--dk)),#07070a)}
.eod-strip i.blocked{background:color-mix(in srgb,var(--st-blocked) calc(100% - 38% * var(--dk)),#07070a)}
.eod-strip i.off{height:7px;background:var(--line-soft)}
/* today: not written up yet, so it is outlined rather than marked either way */
.eod-strip i.today{background:transparent;box-shadow:inset 0 0 0 1px var(--line-hi)}
.eod-rate{width:74px;text-align:right;font-size:12px;color:var(--txt-3);white-space:nowrap}
.eod-rate.low{color:oklch(from var(--st-blocked) min(l, var(--ink-l)) c h)}
.eod-pbody{padding:0 14px 14px}
/* nested under a person: the day replaces the name, and the card drops its
   own border so it doesn't read as a card inside a row */
.eod-card.bare{border:none;background:transparent;padding:0 0 4px 36px}
.eod-when{font-size:11px;font-weight:600;letter-spacing:.02em;color:var(--txt-2)}
.eod-sort{align-self:center}

/* ---------- Gantt (portfolio schedule) ---------- */
/* Two columns held by CSS vars so every row, the ruler and the grid overlay
   line up without a shared parent grid. --cw is `minmax(0,1fr)` when the
   chart is fitted to the viewport and a px width when it is zoomed. */
/* The chart is the page, so it takes the height the page has. .content
   already goes overflow:hidden in gttmode; without flex:1 here the panel sat
   at its content height and left the bottom third of the window empty — and
   the emptier the filter, the more empty window, which reads as a broken
   layout rather than as a short list. The content padding's 60px tail goes
   with it: that was clearance for a scrolling page, and this one does not
   scroll — its inner track does. */
.gt{width:100%;flex:1;display:flex;flex-direction:column;min-height:0}
.gt-seg{flex:none}
.gt-sum{display:flex;align-items:center;gap:7px;margin:-4px 0 12px;flex-wrap:wrap}
.gt-chip{display:inline-flex;align-items:center;gap:7px;font-size:11.5px;color:var(--txt-2);
  border:1px solid var(--line);border-radius:20px;padding:4px 11px 4px 9px}
.gt-chip i{width:8px;height:8px;border-radius:2px;background:var(--t);flex:none}
.gt-chip b{color:var(--txt-3);font-weight:500}
.gt-chip:hover{border-color:var(--line-hi);color:var(--txt)}
.gt-chip.on{background:color-mix(in srgb,var(--t) 14%,transparent);
  border-color:color-mix(in srgb,var(--t) 45%,transparent);color:var(--lit)}
.gt-chip.on b{color:var(--lit)}
.gt-clear{font-size:11.5px;color:var(--txt-3);padding:4px 6px}
.gt-clear:hover{color:var(--txt)}

.gt-scroll{flex:1;min-height:0;overflow:auto;border:1px solid var(--line);border-radius:12px;
  background:var(--bg-elev)}
.gt-scroll.fit{overflow-x:hidden}
/* The rows keep their 30px whatever height the panel has. Letting them grow
   into the slack was tried: it fills the panel, and it also means the row
   height changes every time you touch a filter, so the chart never looks
   like the same chart twice. A tight strip of bars with space under it is
   the denser read and the stabler one. */
/* min-height, not a stretch. The rows keep their 30px — the panel just has
   to be full-height underneath them, or the month rules and the today line
   stop dead at the last row and leave a hard edge across the middle of the
   chart with black below it. Growing the rows into the slack was tried and
   pulled: it fills the space, and it also means row height changes every
   time you touch a filter, so the chart never looks like the same chart. */
.gt-inner{position:relative;min-width:min-content;min-height:100%;
  display:flex;flex-direction:column}
/* real rows keep their own heights — only the filler takes the slack.
   Letting every row grow into it was tried and pulled: it fills the panel,
   and it also changes row height every time you touch a filter, so the chart
   never looks like the same chart twice. */
.gt-row{flex:none}
/* `.gt-fill` was already taken — it is the progress bar inside a row. One
   class, one thing: this is the slack under the last row. */
.gt-rest{flex:1 1 0;min-height:0}
.gt-rest .gt-c{border:none}
.gt-row{display:grid;grid-template-columns:var(--lw) var(--cw);align-items:center;min-width:0}
.gt-l{position:sticky;left:0;z-index:3;display:flex;align-items:center;gap:7px;height:100%;
  padding:0 12px 0 8px;background:var(--bg-elev);border-right:1px solid var(--line);min-width:0}
.gt-c{position:relative;height:100%;min-width:0}

/* month rules and the today line, drawn once behind everything */
.gt-grid{position:absolute;top:0;bottom:0;left:var(--lw);right:0;z-index:0;pointer-events:none}
.gt-grid i{position:absolute;top:0;bottom:0;width:1px;background:var(--line-soft)}
.gt-now{position:absolute;top:0;bottom:0;width:1px;background:color-mix(in srgb,#f5405e 70%,transparent)}

/* **The ruler is two bands with air between them**, months above and days
   below. They were already on different offsets and still touched: 11px type
   pinned at top:11 runs to 24, a 9.5px tick pinned at bottom:6 starts at 19,
   so "May" and "May 4" overlapped by five pixels and read as one smeared
   label. The height buys each band a whole line plus about 9px of clearance,
   which is what "enough space for themselves" costs. */
.gt-ruler{height:48px;position:sticky;top:0;z-index:4;background:var(--bg-elev);
  border-bottom:1px solid var(--line)}
.gt-ruler .gt-l{border-bottom:1px solid var(--line);z-index:5}
.gt-count{font-size:11px;color:var(--txt-3)}
.gt-mo{position:absolute;top:6px;z-index:1;font-size:11px;line-height:14px;
  color:var(--txt-2);padding-left:7px;white-space:nowrap}
.gt-today{position:absolute;bottom:5px;z-index:2;transform:translateX(-50%);font-size:9.5px;font-weight:700;
  letter-spacing:.04em;color:#fff;background:#f5405e;border-radius:4px;padding:1px 5px;white-space:nowrap}

.gt-ghead{height:28px}
.gt-ghead .gt-l{background:var(--bg-elev2)}
.gt-ghead button{display:flex;align-items:center;gap:7px;white-space:nowrap;font-size:10.5px;font-weight:700;
  letter-spacing:.07em;text-transform:uppercase;color:var(--txt-3);width:100%}
.gt-ghead b{font-weight:500;letter-spacing:0;text-transform:none;font-size:11px;color:var(--txt-3);opacity:.7}
/* the quiet band says why it is quiet once, at the top, instead of every row
   carrying a label for the state it is *not* in */
.gt-ghead .gt-c em{position:absolute;top:50%;left:12px;transform:translateY(-50%);
  font-style:normal;font-size:10.5px;color:var(--txt-3);opacity:.6;white-space:nowrap}
.gt-ghead.quiet .gt-l,.gt-ghead.quiet .gt-c{background:var(--bg-elev)}
.gt-ghead.quiet .gt-l{border-top:1px solid var(--line)}
.gt-ghead.quiet .gt-c{border-top:1px solid var(--line)}
.gt-ghead .gt-c{background:var(--bg-elev2);border-bottom:1px solid var(--line-soft)}

.gt-item{height:30px}
.gt-item:hover .gt-l,.gt-item:hover .gt-c{background:var(--hover)}
.gt-item:hover .gt-l{background:color-mix(in srgb,var(--bg-elev2),var(--tint) 1.5%)}
.gt-caret{color:var(--txt-3);font-size:10px;width:14px;flex:none;transition:transform .12s}
.gt-caret.shut{transform:rotate(-90deg)}
.gt-caret:hover{color:var(--txt)}
/* the row's link: name and state together, the whole width up to the ✎ */
.gt-go{display:flex;align-items:center;gap:8px;flex:1;min-width:0;height:100%;color:inherit;text-decoration:none;border-radius:5px}
.gt-go:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
.gt-go:hover .gt-name b{color:var(--lit);text-decoration:underline;text-underline-offset:3px;text-decoration-color:color-mix(in srgb,var(--tint) 35%,transparent)}
.gt-go:hover .gt-note{filter:brightness(1.3)}
.gt-name{display:flex;align-items:center;gap:8px;min-width:0;font-size:12.5px;color:var(--txt-2);padding-left:4px}
.gt-name b{font-weight:500;color:var(--txt);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.gt-name:hover b{color:var(--lit)}
.gt-note{margin-left:auto;font-size:10.5px;color:oklch(from var(--t) min(l, var(--ink-l)) c h);white-space:nowrap;flex:none}
.gt-item.live .gt-note,.gt-item.done .gt-note,.gt-item.queued .gt-note{color:var(--txt-3)}

/* the plan, how far along it you are, and the gap between that and today */
.gt-plan{position:absolute;top:50%;transform:translateY(-50%);height:13px;border-radius:4px;
  background:color-mix(in srgb,var(--t) 12%,transparent);
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--t) 34%,transparent)}
.gt-fill{position:absolute;top:50%;transform:translateY(-50%);height:13px;border-radius:4px;
  background:color-mix(in srgb,var(--t) calc(100% - 32% * var(--dk)),#07070a);min-width:2px}
.gt-slip{position:absolute;top:50%;transform:translateY(-50%);height:13px;border-radius:0 4px 4px 0;
  background:repeating-linear-gradient(115deg,
    color-mix(in srgb,var(--t) 26%,transparent) 0 3px,transparent 3px 7px)}

/* week rules and labels only exist zoomed in — at Fit they would be 29
   ticks in 900px of chart */
/* **Is anyone on this?** The rows are separated rather than sorted on, so
   the whole answer is the band they are in. Inside it they step back the way
   the directory's Not-ongoing rows do — nothing there is asking for anything
   today — and come back to full strength on hover, because stepping back is
   meant to stop them competing, not to make them unreadable. They draw no
   bar at all, only the ＋ that would give them one, because until then there
   is nothing there to draw a bar for. */
.gt-item.quiet{opacity:.55;transition:opacity .12s}
.gt-item.quiet:hover{opacity:1}
/* a step further back than Not ongoing: those are waiting on a decision,
   these have had one */
.gt-item.arch{opacity:.4}
.gt-item.arch .gt-name b{font-weight:400}
/* the ＋ that stands in for the bar. Always visible — it is the only thing in
   the row's chart column, so hiding it until hover would leave the row blank */
/* It lives in the left column beside the note, next to where the milestone
   ＋ sits on a live row — one control, one place. Out in the chart column it
   also needed to be sticky, because in Weeks view that column is thousands of
   pixels wide and an absolute ＋ scrolls straight off; in the left column,
   which is sticky already, the problem does not exist.
   **Always visible, never hover-only.** On a live row the ＋ is an extra; on
   these it is the only thing the row offers, and hiding the one way out of
   "no dates yet" until you happen to be over it is how a row reads as dead. */
.gt-plus{flex:none;margin-left:7px;
  width:19px;height:19px;border-radius:6px;display:grid;place-items:center;
  font-size:12px;line-height:1;color:var(--txt-3);border:1px dashed var(--line-hi)}
.gt-plus:hover,.gt-plus.open{color:var(--lit);border-style:solid;border-color:var(--accent);
  background:color-mix(in srgb,var(--accent) 16%,transparent)}

/* **Pending, not saved.** The row has moved up into Ongoing and drawn its
   bar, but nothing is written yet, so it is drawn the way an unsaved thing
   should be: outlined rather than filled, on the accent rather than on its
   state colour, because until you press Add it has no state — it is a
   proposal. The marks are the real ones, at the dates in the open form. */
.gt-item.draft .gt-l,.gt-item.draft .gt-c{background:color-mix(in srgb,var(--accent) 7%,transparent)}
.gt-item.draft .gt-plan{background:color-mix(in srgb,var(--accent) 16%,transparent);
  border:1px dashed color-mix(in srgb,var(--accent) 70%,transparent)}
.gt-item.draft .gt-fill,.gt-item.draft .gt-slip{display:none}
.gt-item.draft .gt-note{color:var(--accent)}

/* **Which one am I editing?** A panel floating over twenty near-identical
   bars says nothing about which one it belongs to, so the row says it: the
   whole row goes blue and its bar wears a ring that breathes. This one is
   deliberately *not* the draft's whisper — a draft is a quiet "this is not
   real yet", where this is answering a question you are asking right now, so
   it is a full step louder and half a second quicker. The ring pulses rather
   than the bar's opacity: dimming the thing you are editing to show that you
   are editing it is the wrong way round. */
@keyframes gt-onedit{
  0%,100%{box-shadow:0 0 0 1.5px color-mix(in srgb,var(--accent) 40%,transparent)}
  50%{box-shadow:0 0 0 3.5px color-mix(in srgb,var(--accent) 95%,transparent)}
}
.gt-item.onedit .gt-l,.gt-item.onedit .gt-c{background:color-mix(in srgb,var(--accent) 13%,transparent)}
.gt-item.onedit .gt-name b{color:var(--lit)}
.gt-item.onedit .gt-add{opacity:1;color:#fff;background:var(--accent)}
.gt-item.onedit .gt-plan{animation:gt-onedit 1.4s ease-in-out infinite}
/* the two ends, grabbable while this row is the one being edited */
.gt-grip{position:absolute;top:50%;transform:translateY(-50%);z-index:4;
  width:9px;height:19px;margin-left:-4.5px;cursor:ew-resize;border-radius:3px;
  background:var(--accent);box-shadow:0 0 0 1px rgba(0,0,0,.5)}
.gt-grip:hover{background:var(--lit)}

/* a pending row is both — the louder one wins the bar */
.gt-item.draft.onedit .gt-plan{animation:gt-onedit 1.4s ease-in-out infinite}

@media (prefers-reduced-motion:reduce){
  .gt-item.onedit .gt-plan{animation:none;
    box-shadow:0 0 0 2px color-mix(in srgb,var(--accent) 80%,transparent)}
}
.gt-item.draft .gt-ms{border-color:var(--accent);background:var(--bg-elev)}
.gt-item.draft .gt-mspin:hover .gt-ms{box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 30%,transparent)}
.gt-item.draft .gt-ms.tri,.gt-item.draft .gt-ms.bar,.gt-item.draft .gt-ms.tick{
  background:color-mix(in srgb,var(--accent) 80%,#fff)}

/* **It breathes because it is not settled.** Same rule the workstream tiles
   follow: motion means something is happening right now, stillness means it
   is waiting on a person. A draft is the most unsettled thing on the chart —
   it exists only while the panel is open — so the bar and the words that say
   so move together, on one rhythm.

   Opacity only, and only between .72 and 1. It is a chart people read while
   it is on screen, so anything that changes size or position would drag the
   eye off the rows that matter; a shallow fade is felt rather than watched.
   Two seconds is about a slow breath — fast enough to read as alive, slow
   enough that it never becomes a blink. */
@keyframes gt-pending{
  0%,100%{opacity:.72}
  50%{opacity:1}
}
.gt-item.draft .gt-plan,
.gt-item.draft .gt-note{animation:gt-pending 2s ease-in-out infinite}

@media (prefers-reduced-motion:reduce){
  .gt-item.draft .gt-plan,
  .gt-item.draft .gt-note{animation:none}
}
.gt-msadd-l{margin:0 0 6px;font-size:10.5px;color:var(--txt-3)}
.gt-msname{width:100%;box-sizing:border-box;font:inherit;font-size:11.5px;color:var(--txt);
  background:var(--bg);border:1px solid var(--line);border-radius:7px;padding:6px 8px;
  margin-bottom:9px}
.gt-msname:focus{border-color:var(--accent);outline:none}
.gt-pods{display:grid;grid-template-columns:1fr 1fr;gap:5px;margin-bottom:10px}
.gt-pods button{font-size:11.5px;color:var(--txt-2);border:1px solid var(--line);
  border-radius:7px;padding:5px 8px;text-align:center}
.gt-pods button:hover{border-color:var(--line-hi);color:var(--txt)}
.gt-pods button.on{background:var(--hover);border-color:var(--line-hi);color:var(--txt)}
.gt-span{display:flex;align-items:center;gap:9px;margin-bottom:7px}
.gt-span>span{flex:none;width:54px;font-size:10.5px;color:var(--txt-3);line-height:1.25}
.gt-span input[type=date]{flex:1;min-width:0;margin:0}

/* **Every date in the plan, one list.** Three fixed columns — mark, name,
   field — so the fields make a single column down the form and the mark
   column absorbs the six different shape widths without touching the marks
   themselves. There is no fourth column for the ↺: reserved on every row it
   is dead margin on the three that never have one, and reserved only where
   it appears it shifts the fields sideways the moment you pin one. It goes
   beside the name instead, where it costs nothing when absent. */
.gt-dates{list-style:none;margin:0 0 11px;padding:0}
/* Four columns: the mark, its name, the date, and the way to take it off.
   The remove slot is reserved on every row — the ends cannot be removed, but
   if the column collapsed there the fields above and below it would not line
   up, which is the whole reason this list exists. */
.gt-dates li{display:grid;grid-template-columns:14px 1fr 122px 17px;align-items:center;
  gap:7px;padding:2px 0}
.gt-dates li>.gt-ms{position:static;margin:0;transform:none;justify-self:center}
.gt-dates li>.gt-ms.diamond{transform:rotate(45deg)}
/* where the bar begins and ends — deliberately not one of the six milestone
   silhouettes, because these are not things that happen */
.gt-edge{justify-self:center;width:2px;height:13px;border-radius:1px;background:var(--line-hi)}
.gt-dlabel{display:flex;align-items:center;gap:3px;min-width:0;
  font-size:10.5px;color:var(--txt-3)}
.gt-dlabel b{font-weight:400;white-space:nowrap}
.gt-dlabel.req::after{content:'*';color:var(--accent)}
.gt-dates input[type=date]{width:100%;box-sizing:border-box;font:inherit;font-size:11.5px;
  color:var(--txt);background:transparent;border:1px solid var(--line);border-radius:7px;
  padding:5px 7px;color-scheme:dark;transition:border-color .12s,background .12s}
.gt-dates input[type=date]:hover{border-color:var(--line-hi)}
.gt-dates input[type=date]:focus{outline:none;border-color:var(--accent);background:var(--bg-elev)}
.gt-dates input[type=date]::-webkit-calendar-picker-indicator{filter:invert(.5);cursor:pointer}
/* the way back to the rule, present only once you have left it */
.gt-undo{flex:none;width:14px;height:14px;border-radius:4px;display:grid;place-items:center;
  font-size:10px;line-height:1;color:var(--txt-3)}
.gt-undo:hover{background:var(--hover);color:var(--lit)}
.gt-drop{width:17px;height:17px;border-radius:5px;display:grid;place-items:center;
  font-size:13px;line-height:1;color:var(--txt-3)}
.gt-drop:hover{background:var(--hover);color:var(--lit)}
.gt-dlabel b{overflow:hidden;text-overflow:ellipsis}
/* the way back to the rule, present only once you have left it */
.gt-undo{width:18px;height:18px;border-radius:5px;display:grid;place-items:center;
  font-size:11px;line-height:1;color:var(--txt-3)}
.gt-undo:hover{background:var(--hover);color:var(--lit)}
.gt-undo.off{opacity:0;pointer-events:none}

.gt-msadd-go:disabled{background:var(--bg-elev);color:var(--txt-3);cursor:default}
.gt-msadd-go:disabled:hover{filter:none}

/* Milestones: **shape carries the kind, fill carries whether it has passed.**
   Colour is spoken for — it means schedule state on this chart — so four more
   hues would be four more things to un-learn. Each mark is dark-cored with a
   light rim so it reads on the bar and on the empty track alike. */
/* The pin carries the position and the hit area; the mark inside carries
   only the shape. z-index 2 keeps it above the bars and **below** the sticky
   left column, which is the Weeks-view bug: at the same z-index the mark won
   on DOM order and scrolled out over the launch names. */
.gt-mspin{position:absolute;top:50%;left:0;transform:translateY(-50%);z-index:2;
  width:20px;height:24px;margin-left:-10px;display:grid;place-items:center}
.gt-mspin .gt-ms{position:static;margin:0;transform:none}
.gt-mspin .gt-ms.diamond{transform:rotate(45deg)}
/* A mark is grabbable on the row you opened, and nowhere else. There was a
   chart-wide Edit toggle first; the row's own pencil made it redundant, and a
   mode that arms two hundred marks to answer a question about one of them is
   a mode that only exists to be forgotten switched on. */
.gt-item.draft .gt-mspin,.gt-mspin.live{cursor:ew-resize}
.gt-item.draft .gt-mspin .gt-ms,.gt-mspin.live .gt-ms{box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 22%,transparent)}
.gt-scroll.dragging{cursor:ew-resize}
.gt-scroll.dragging .gt-mspin:not(.held){opacity:.45}
.gt-mspin.held .gt-ms{box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 50%,transparent)}

.gt-ms{position:absolute;top:50%;z-index:2;width:8px;height:8px;margin-left:-4px;
  transform:translateY(-50%);box-sizing:border-box;
  background:var(--bg-elev);border:1.5px solid color-mix(in srgb,oklch(from var(--t,var(--txt-2)) min(l, var(--ink-l)) c h) var(--mark-t),var(--mark-edge))}
.gt-ms.done{background:color-mix(in srgb,oklch(from var(--t,var(--txt-2)) min(l, var(--ink-l)) c h) var(--mark-p),var(--mark));border-color:var(--mark-ring)}
.gt-ms.diamond{transform:translateY(-50%) rotate(45deg);border-radius:1.5px}
.gt-ms.circle{border-radius:50%;width:9px;height:9px;margin-left:-4.5px}
.gt-ms.square{border-radius:1.5px}
.gt-ms.tri{border:none;width:9px;height:8px;margin-left:-4.5px;background:color-mix(in srgb,oklch(from var(--t,var(--txt-2)) min(l, var(--ink-l)) c h) var(--mark-t),var(--mark-edge));
  clip-path:polygon(50% 0,100% 100%,0 100%)}
.gt-ms.tri.done{background:color-mix(in srgb,oklch(from var(--t,var(--txt-2)) min(l, var(--ink-l)) c h) var(--mark-p),var(--mark))}
/* the finish line, lying down — a wide short bar against the tick's thin
   tall one, which is the pair of these six easiest to confuse */
.gt-ms.bar{border:none;width:11px;height:4px;margin-left:-5.5px;border-radius:2px;
  background:color-mix(in srgb,oklch(from var(--t,var(--txt-2)) min(l, var(--ink-l)) c h) var(--mark-t),var(--mark-edge))}
.gt-ms.bar.done{background:color-mix(in srgb,oklch(from var(--t,var(--txt-2)) min(l, var(--ink-l)) c h) var(--mark-p),var(--mark))}
.gt-ms.tick{border:none;width:3px;height:12px;margin-left:-1.5px;border-radius:1.5px;
  background:color-mix(in srgb,oklch(from var(--t,var(--txt-2)) min(l, var(--ink-l)) c h) var(--mark-t),var(--mark-edge))}
.gt-ms.tick.done{background:color-mix(in srgb,oklch(from var(--t,var(--txt-2)) min(l, var(--ink-l)) c h) var(--mark-p),var(--mark))}
/* one you put there yourself, against three the fixture guessed */
.gt-ms.mine{box-shadow:0 0 0 2px color-mix(in srgb,var(--accent) 60%,transparent)}
.gt-item:hover .gt-ms{border-color:var(--lit)}
.gt-ms{cursor:default}
/* brighten on hover, never *fill* — hollow means the date is still ahead,
   and a hover that solidifies it says the opposite for as long as you look */
.gt-ms:hover{border-color:var(--lit)}
.gt-ms.tri:hover,.gt-ms.bar:hover,.gt-ms.tick:hover{background:var(--lit)}

/* the mark's own tooltip. Three lines, because a milestone is a name, a date
   and a meaning, and the browser's own tooltip can carry one of those. */
.gt-tip{position:fixed;z-index:300;width:260px;transform:translate(-50%,-100%);
  pointer-events:none;background:var(--raise);border:1px solid var(--line);
  border-radius:10px;padding:9px 11px;box-shadow:0 16px 40px rgb(0 0 0/calc(.6*var(--shade)))}
.gt-tip.below{transform:translate(-50%,0)}
.gt-tip b{display:block;font-size:12.5px;font-weight:600;color:var(--txt)}
.gt-tip-d{display:flex;align-items:baseline;gap:7px;margin-top:2px;
  font-size:11px;color:var(--txt-2);font-family:"Geist Mono",monospace}
.gt-tip-d i{font-style:normal;color:var(--txt-3)}
.gt-tip p{margin:6px 0 0;font-size:11px;line-height:1.45;color:var(--txt-3)}
.gt-tip-mine{display:inline-block;margin-top:7px;font-size:10px;letter-spacing:.03em;
  text-transform:uppercase;color:var(--accent)}

/* the key, right of the state chips */
.gt-key{display:flex;align-items:center;gap:13px;margin-left:auto;flex-wrap:wrap}
.gt-mstog{font-size:11.5px;color:var(--txt-3);border:1px solid var(--line);
  border-radius:20px;padding:4px 11px}
.gt-mstog:hover{border-color:var(--line-hi);color:var(--txt)}
.gt-mstog.on{color:var(--txt);border-color:var(--line-hi);background:var(--bg-elev2)}

.gt-keyi{display:inline-flex;align-items:center;gap:7px;font-size:11px;color:var(--txt-3)}
.gt-keyi .gt-ms{position:static;margin:0;transform:none;flex:none}
.gt-keyi .gt-ms.diamond{transform:rotate(45deg)}

/* ＋ on the row, out of the way until you are on that row */
.gt-add{flex:none;width:18px;height:18px;margin-left:7px;border-radius:5px;
  display:grid;place-items:center;line-height:0;
  color:var(--txt-3);opacity:0;transition:opacity .12s}
.gt-item:hover .gt-add,.gt-add.open{opacity:1}
.gt-add:hover,.gt-add.open{background:var(--hover);color:var(--txt)}

.gt-msadd{position:fixed;z-index:200;background:var(--raise);border:1px solid var(--line);
  border-radius:11px;padding:11px;box-shadow:0 18px 44px rgb(0 0 0/calc(.6*var(--shade)))}
.gt-msadd-h{margin:0 0 9px;font-size:11px;font-weight:600;letter-spacing:.03em;
  text-transform:uppercase;color:var(--txt-3)}
.gt-msadd-k{display:flex;flex-wrap:wrap;gap:5px;margin-bottom:9px}
.gt-msadd-k button{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;
  color:var(--txt-2);border:1px solid var(--line);border-radius:7px;padding:4px 8px}
.gt-msadd-k button:hover{border-color:var(--line-hi);color:var(--txt)}
.gt-msadd-k button.on{background:var(--hover);border-color:var(--line-hi);color:var(--txt)}
.gt-msadd-k .gt-ms{position:static;margin:0;transform:none;flex:none}
.gt-msadd-k .gt-ms.diamond{transform:rotate(45deg)}
.gt-msadd input[type=date]{width:100%;box-sizing:border-box;font:inherit;font-size:11.5px;
  color:var(--txt);background:var(--bg);border:1px solid var(--line);border-radius:7px;
  padding:6px 8px;margin-bottom:9px;color-scheme:dark}
.gt-msadd-go{width:100%;margin-top:3px;font-size:11.5px;font-weight:500;color:#fff;
  background:var(--accent);border-radius:7px;padding:6px}
.gt-msadd input[type=date]::-webkit-calendar-picker-indicator{filter:invert(.55);cursor:pointer}
.gt-msadd-go:hover{filter:brightness(1.1)}
.gt-msadd-n{margin:9px 0 0;font-size:10.5px;line-height:1.45;color:var(--txt-3)}

.gt-grid i.wk{background:color-mix(in srgb,var(--tint) 2.8%,transparent)}
.gt-wk{position:absolute;bottom:5px;line-height:13px;font-size:9.5px;color:var(--txt-3);padding-left:6px;white-space:nowrap}
.gt-none{color:var(--txt-3);font-size:12.5px;padding:24px 12px}
.content.gttmode{overflow:hidden;display:flex;flex-direction:column;padding-bottom:22px}

/* ---------- new project (the creation wizard) ---------- */
/* Centred rather than docked: creating a project is a task you finish, not a
   panel you work beside. The summary rail is the old "Review" step, on
   screen the whole time. */
.np-scrim{position:fixed;inset:0;background:rgba(0,0,0,.62);backdrop-filter:blur(2px);z-index:80}
.np{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:81;
  width:min(940px,94vw);max-height:min(760px,90vh);display:flex;flex-direction:column;
  background:var(--bg-elev);border:1px solid var(--line);border-radius:14px;overflow:hidden;
  box-shadow:0 30px 90px rgb(0 0 0/calc(.72*var(--shade)))}
.np-top{display:flex;align-items:center;gap:10px;padding:14px 16px;border-bottom:1px solid var(--line)}
.np-t{font-size:15px;font-weight:600;letter-spacing:-.02em;flex:1}
.np-x{width:26px;height:26px;border-radius:7px;color:var(--txt-2);font-size:17px;line-height:1;
  display:grid;place-items:center}
.np-x:hover{background:var(--hover);color:var(--lit)}

.np-steps{display:flex;align-items:center;gap:4px;padding:10px 14px;border-bottom:1px solid var(--line-soft)}
.np-step{display:inline-flex;align-items:center;gap:8px;padding:5px 11px;border-radius:7px;
  font-size:12.5px;color:var(--txt-3)}
.np-step:not(:disabled):hover{background:var(--hover);color:var(--txt)}
.np-step:disabled{cursor:default;opacity:.55}
.np-step.on{color:var(--lit);background:var(--active)}
.np-num{width:17px;height:17px;border-radius:50%;display:grid;place-items:center;font-size:9.5px;
  font-weight:700;border:1px solid var(--line);color:var(--txt-3)}
.np-step.on .np-num{background:var(--accent);border-color:var(--accent);color:#fff}
.np-step.done .np-num{border-color:color-mix(in srgb,#45d267 50%,transparent);color:oklch(from #45d267 min(l, var(--ink-l)) c h)}

.np-split{flex:1;min-height:0;display:grid;grid-template-columns:minmax(0,1fr) 264px}
.np-body{min-width:0;overflow-y:auto;padding:18px 18px 26px}
.np-body .nt-f:last-child{margin-bottom:0}

/* templates: the common project should be one click, not four screens */
.np-tpls{display:grid;grid-template-columns:repeat(4,1fr);gap:6px}
.np-tpl{border:1px solid var(--line);border-radius:9px;padding:9px 10px;background:var(--bg-elev);
  text-align:left;display:flex;flex-direction:column;gap:3px}
.np-tpl b{font-size:12.5px;font-weight:500;color:var(--txt)}
.np-tpl span{font-size:10.5px;color:var(--txt-3)}
.np-tpl:hover{border-color:var(--line-hi)}
.np-tpl.on{border-color:var(--accent);background:color-mix(in srgb,var(--accent) 12%,transparent)}
.np-tpl.on b{color:var(--lit)}

.np-quick{display:flex;flex-wrap:wrap;gap:5px;margin-bottom:7px}
.np-q{border:1px solid var(--line);border-radius:20px;padding:4px 11px;font-size:11.5px;color:var(--txt-2)}
.np-q:hover{border-color:var(--line-hi);color:var(--txt)}
.np-q.on{border-color:var(--accent);background:color-mix(in srgb,var(--accent) 14%,transparent);color:var(--lit)}

.np-chk{width:16px;height:16px;flex:none;border-radius:5px;border:1.5px solid var(--line-hi);
  display:grid;place-items:center;color:transparent}
.np-chk.on{background:var(--accent);border-color:var(--accent);color:#fff}

/* one list: picking a workflow lifts it to the top, where it takes its
   order and the default marker. The original mirrored the set into a second
   list to do that, which put the same nine rows on screen twice. */
.np-flows{display:flex;flex-direction:column;gap:5px}
.np-flow{display:flex;align-items:center;border:1px solid var(--line);border-radius:9px;
  background:var(--bg-elev);padding-right:7px}
.np-flow:hover{border-color:var(--line-hi)}
.np-flow.on{border-color:color-mix(in srgb,var(--t) 55%,transparent);
  background:color-mix(in srgb,var(--t) 9%,var(--bg-elev))}
.np-flow-hit{flex:1;min-width:0;display:flex;align-items:center;gap:10px;padding:9px 11px;text-align:left}
.np-flow-i{width:22px;height:22px;border-radius:6px;flex:none;display:grid;place-items:center;
  color:oklch(from var(--t) min(l, var(--ink-l)) c h);background:color-mix(in srgb,var(--t) 15%,transparent)}
.np-flow-b{min-width:0;display:flex;flex-direction:column;gap:1px}
.np-flow-b b{font-size:12.5px;font-weight:500;color:var(--txt)}
.np-flow-b span{font-size:10.5px;color:var(--txt-3)}
.np-flow-t{display:flex;align-items:center;gap:3px;flex:none}
.np-def{font-size:10px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;
  border:1px solid var(--line);border-radius:20px;padding:3px 9px;color:var(--txt-3)}
.np-def:hover{border-color:var(--line-hi);color:var(--txt)}
.np-def.on{border-color:color-mix(in srgb,var(--t) 60%,transparent);color:var(--lit);
  background:color-mix(in srgb,var(--t) 22%,transparent)}
.np-arr{width:22px;height:22px;border-radius:6px;color:var(--txt-3);font-size:12px}
.np-arr:hover:not(:disabled){background:var(--hover);color:var(--lit)}
.np-arr:disabled{opacity:.25;cursor:default}

.np-scenes{display:flex;align-items:center;gap:6px;margin-bottom:9px}
.np-step-btn{width:28px;height:28px;border:1px solid var(--line);border-radius:7px;color:var(--txt-2);font-size:14px}
.np-step-btn:hover{border-color:var(--line-hi);color:var(--lit)}
.np-num-in{width:52px;text-align:center;background:var(--bg-elev);border:1px solid var(--line);
  border-radius:7px;padding:6px 0;color:var(--txt);font-family:"Geist Mono",monospace;font-size:13px;outline:none}
.np-num-in:focus{border-color:var(--accent)}
.np-sc-note{font-size:11px;color:var(--txt-3)}

.np-opt{display:flex;align-items:flex-start;gap:10px;width:100%;text-align:left;padding:10px 11px;
  border:1px solid var(--line);border-radius:9px;background:var(--bg-elev)}
.np-opt:hover{border-color:var(--line-hi)}
.np-opt.on{border-color:var(--accent);background:color-mix(in srgb,var(--accent) 8%,transparent)}
.np-opt b{display:block;font-size:12.5px;font-weight:500;color:var(--txt)}
.np-opt i{display:block;margin-top:2px;font-size:11px;font-style:normal;color:var(--txt-3);line-height:1.45}
.np-empty{margin:0 0 16px;font-size:12.5px;color:var(--txt-3);border:1px dashed var(--line);
  border-radius:9px;padding:14px}
.np-empty b{color:var(--txt-2);font-weight:500}
.np-extra{display:flex;align-items:center;gap:6px;margin-bottom:6px}
.np-extra-b{flex:none;width:150px}
.np-extra-b select{font-size:12px}
.np-rm{width:26px;height:26px;border-radius:7px;color:var(--txt-3);font-size:15px;flex:none}
.np-rm:hover{background:var(--hover);color:var(--lit)}

/* the rail — what step 4 used to say, said continuously */
.np-rail{border-left:1px solid var(--line);background:var(--bg-elev2);overflow-y:auto;padding:16px 15px 20px}
.np-rail-h{font-size:9.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  color:var(--txt-3);margin:0 0 8px}
.np-rail-h:not(:first-child){margin-top:18px}
.np-sum{display:grid;grid-template-columns:auto minmax(0,1fr);gap:6px 10px;font-size:11.5px}
.np-sum span{color:var(--txt-3)}
.np-sum b{font-weight:500;color:var(--txt);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.np-sum b.dim{color:var(--txt-3);font-weight:400}
.np-rail-flows{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:5px}
.np-rail-flows li{display:flex;align-items:center;gap:7px;font-size:11.5px;color:var(--txt-2)}
.np-rail-flows i{width:7px;height:7px;border-radius:2px;background:var(--t);flex:none}
.np-rail-flows em{margin-left:auto;font-style:normal;font-size:9.5px;font-weight:700;letter-spacing:.05em;
  text-transform:uppercase;color:var(--txt-3)}
.np-rail-e{margin:0;font-size:11.5px;color:oklch(from var(--st-blocked) min(l, var(--ink-l)) c h)}
.np-rail-n{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:4px;
  font-size:11.5px;color:var(--txt-3)}
.np-rail-n b{color:var(--txt);font-weight:600;font-family:"Geist Mono",monospace}
.np-savetpl{display:flex;align-items:flex-start;gap:9px;margin-top:20px;padding-top:14px;
  border-top:1px solid var(--line-soft);cursor:pointer}
.np-savetpl span{font-size:11.5px;color:var(--txt-2)}
.np-savetpl i{display:block;margin-top:3px;font-size:10.5px;font-style:normal;color:var(--txt-3);line-height:1.45}

.np-foot{background:var(--bg-elev2)}
.np-gap{flex:1}
.np-next{border-style:solid}

/* ---------- company knowledge ---------- */
.kbwrap{width:100%;max-width:1180px;margin-inline:auto}
/* ---------- the library pages: masthead, toolbar, list ----------
 *
 * Company knowledge, Apps and Tapes were three pages doing one job — a shelf
 * of things with a filter over it — in three visual languages: a 13px page
 * heading with counts crammed into the sub-line, loose bordered filter pills
 * that never joined the `.seg` track, and a grid of cards per item. They
 * share this now, which is the point: one masthead, one toolbar row, one
 * list. See `PageMast.jsx`.
 */
.pmast{display:flex;align-items:flex-end;gap:32px;padding-bottom:22px;margin-bottom:18px;
  border-bottom:1px solid var(--line)}
.pmast-t{min-width:0}
.pmast h1{margin:0;font-size:26px;font-weight:600;letter-spacing:-.035em;line-height:1.1}
.pmast p{margin:10px 0 0;max-width:64ch;font-size:12.5px;line-height:1.6;color:var(--txt-3)}
.pfacts{display:flex;align-items:flex-end;flex:none;margin-left:auto}
.pfact{--fc:var(--accent);position:relative;display:flex;flex-direction:column;align-items:flex-start;
  gap:5px;padding:2px 18px;text-align:left;border-left:1px solid var(--line)}
.pfact:first-child{border-left:none}
.pfact:last-child{padding-right:0}
.pfact.warn{--fc:var(--st-qa)}
.pfact.good{--fc:var(--st-done)}
.pfact b{font-family:"Geist Mono",monospace;font-size:21px;font-weight:500;letter-spacing:-.03em;
  line-height:1;color:var(--txt-3);transition:color .14s}
.pfact span{font-size:9.5px;font-weight:600;letter-spacing:.07em;text-transform:uppercase;
  color:var(--txt-3);white-space:nowrap;transition:color .14s}
.pfact.warn:not(:disabled) b{color:oklch(from var(--st-qa) min(l, var(--ink-l)) c h)}
.pfact:not(:disabled):not(.inert):hover b,.pfact:not(:disabled):not(.inert):hover span{color:var(--txt)}
.pfact.on b{color:var(--lit)}
.pfact.on span{color:var(--txt-2)}
.pfact:disabled{opacity:.4}
.pfact.inert{cursor:default}
.pfact.on::after{content:"";position:absolute;left:18px;right:18px;bottom:-23px;height:2px;
  border-radius:2px;background:var(--fc)}
.pfact:first-child.on::after{left:0}
.pfact:last-child.on::after{right:0}

/* The track on the left, the one thing you can make on the right. A page's
   primary action used to sit in the heading beside the title, which put it
   above the controls that decide what it would be made *of* — pick the area,
   then add to it. */
.pgbar{display:flex;align-items:flex-start;gap:12px;margin-bottom:20px}
/* the track wraps inside its own box; the action stays pinned to the top
   right rather than being pushed onto a third line of its own */
.pgbar .seg{margin-left:0;flex:0 1 auto;min-width:0;flex-wrap:wrap}
.pgbar .seg button b{font-family:"Geist Mono",monospace;font-size:10.5px;font-weight:500;
  color:var(--txt-3);transition:color .14s}
.pgbar .seg button.on b{color:var(--txt-2)}
.pgbar .seg button svg{opacity:.65;margin-right:-2px}
.pgbar .seg button.on svg{opacity:1;color:var(--accent)}
.pgbar-go{margin-left:auto;flex:none;height:32px;padding:0 13px;display:inline-flex;align-items:center;
  gap:6px;font-size:12.5px}

/**
 * **A thing on a shelf is a row, not a card.** Seventeen pages, eleven apps
 * and seven tapes were all card grids, and each one spent a bordered panel
 * to say a title and a line of description — the same shape Team and
 * Control's free pool lost, for the same reason. A card per thing reads as a
 * *place* rather than as a line in a list, and you cannot run your eye down
 * a column that does not exist.
 *
 * The box and the row live here; each page sets only its own
 * `grid-template-columns`, because what differs between a page, an app and a
 * tape is which facts they carry, not how a list looks.
 */
.pglist{border:1px solid var(--line);border-radius:11px;background:var(--bg-elev);overflow:hidden}
.pgrow{display:grid;align-items:center;gap:16px;width:100%;text-align:left;padding:14px 18px;
  border-bottom:1px solid var(--line-soft);transition:background .12s}
.pgrow:last-child{border-bottom:none}
.pgrow:hover{background:var(--hover)}
.pgrow-b{display:flex;flex-direction:column;gap:4px;min-width:0}
.pgrow-t{display:flex;align-items:center;gap:7px;min-width:0;font-size:13px;font-weight:600;
  letter-spacing:-.01em;color:var(--txt);line-height:1.35}
.pgrow-s{font-size:12px;color:var(--txt-3);line-height:1.45;white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis}
.pgrow-o{display:flex;align-items:center;gap:7px;min-width:0;font-size:11.5px;color:var(--txt-3);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* One row of chrome, not two and a half. Search is the primary verb on a
   page of seventeen procedures, so it is the biggest control on it. */
.kbfind{display:flex;align-items:center;gap:8px;margin-bottom:14px}
.kbsearch{flex:1;min-width:0;display:flex;align-items:center;gap:10px;height:40px;padding:0 14px;
  border:1px solid var(--line);border-radius:10px;background:var(--bg-elev);color:var(--txt-3);
  transition:border-color .14s,background .14s,color .14s}
.kbsearch:focus-within{border-color:var(--accent);background:var(--bg-elev2);color:var(--txt-2)}
.kbsearch input{flex:1;min-width:0;background:none;border:none;outline:none;font-family:inherit;
  font-size:13px;font-weight:400;letter-spacing:0;text-transform:none;color:var(--txt)}
.kbsearch input::placeholder{color:var(--txt-3)}
.kbsearch-x{flex:none;width:20px;height:20px;border-radius:50%;display:grid;place-items:center;
  font-size:14px;line-height:1;color:var(--txt-3)}
.kbsearch-x:hover{background:var(--hover);color:var(--txt)}
.kbkind{flex:none;display:inline-flex;align-items:center;gap:9px;height:40px;padding:0 13px;
  border:1px solid var(--line);border-radius:10px;background:var(--bg-elev);
  font-size:12.5px;color:var(--txt-2);white-space:nowrap}
.kbkind:hover,.kbkind.open{border-color:var(--line-hi);color:var(--txt)}
.kbkind.set{border-color:color-mix(in srgb,var(--accent) 50%,transparent);color:var(--lit)}
.kbkind i{width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;
  border-top:4.5px solid currentColor;opacity:.55}
.kb-new{flex:none;height:40px;padding:0 15px;display:inline-flex;align-items:center;gap:7px;
  font-size:12.5px}

/* The areas were a second row of bordered pills with styling of their own —
   the same control as the type filter above them, drawn a different way,
   which is how one page ends up with three tab languages. */
/* **The route was a 230px panel, permanently open, for a thing you read once
   in your first month.** Four columns of checkboxes at the top of the page
   for everyone, including the person who has been here four years — and a
   second copy of nine pages that are in the list underneath anyway. It is a
   line now, and the line is a way in rather than a duplicate. */
.kbpath{display:flex;align-items:center;gap:14px;width:100%;text-align:left;margin-bottom:34px;
  padding:11px 14px;border:1px solid var(--line);border-radius:11px;
  background:linear-gradient(92deg,color-mix(in srgb,var(--accent) 8%,var(--bg-elev)),var(--bg-elev) 46%);
  transition:border-color .14s}
.kbpath:hover{border-color:color-mix(in srgb,var(--accent) 55%,transparent)}
.kbpath-i{flex:none;width:30px;height:30px;border-radius:9px;display:grid;place-items:center;
  color:var(--accent);background:color-mix(in srgb,var(--accent) 14%,transparent);
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--accent) 30%,transparent),
    inset 0 1px 0 rgba(255,255,255,.1)}
.kbpath-b{display:flex;flex-direction:column;gap:2px;min-width:0}
.kbpath-b b{font-size:12.5px;font-weight:600;letter-spacing:-.01em;color:var(--txt)}
.kbpath-b>span{font-size:11.5px;color:var(--txt-3)}
.kbpath-p{margin-left:auto;flex:none;display:flex;align-items:center;gap:10px}
.kbpath-p i{display:block;width:104px;height:3px;border-radius:2px;background:var(--line);overflow:hidden}
.kbpath-p i em{display:block;height:100%;border-radius:2px;background:var(--accent)}
.kbpath-p>span{font-family:"Geist Mono",monospace;font-size:11px;color:var(--txt-3)}
.kbpath-go{flex:none;font-size:14px;color:var(--txt-3);transition:transform .16s,color .16s}
.kbpath:hover .kbpath-go{color:var(--lit);transform:translateX(3px)}

.kbroute{margin-bottom:26px}
.kbroute-p{margin-left:auto;font-family:"Geist Mono",monospace;font-size:11px;color:var(--txt-3)}
.kbphase{margin-bottom:22px}
.kbphase-h{display:flex;align-items:center;gap:12px;margin-bottom:7px}
.kbphase-h b{font-size:9.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--txt-3)}
.kbphase-h i{flex:1;height:1px;background:var(--line)}

.kb-sec{margin-bottom:40px}
.kb-sec-h{display:flex;align-items:baseline;gap:10px;margin-bottom:14px;padding-left:2px}
.kb-sec-h h2{margin:0;font-size:13px;font-weight:600;letter-spacing:-.01em}
.kb-sec-h span{font-size:11.5px;color:var(--txt-3)}

/**
 * **A page is a row, not a card.** Seventeen pages across five sections of
 * three-across cards, each restating the same five facts in a stack, came to
 * about fourteen hundred pixels to say seventeen titles — and a card per
 * thing reads as a *place* rather than as a line in a list, which is the
 * shape Team and Control's free pool both lost for the same reason. You
 * cannot run your eye down a column that does not exist.
 *
 * Two lines, the way `NoteRow` is two lines: the title is what you scan for
 * and the summary is what tells you whether to open it, so they take the
 * width, and the facts *about* the page — who owns it, when anyone last
 * checked — sit quiet in fixed columns on the right.
 */
.kbrow{grid-template-columns:26px minmax(0,1fr) 146px 84px}
.kbrow-n{font-family:"Geist Mono",monospace;font-size:11px;color:var(--txt-3);text-align:center}
.kbphase .kbrow{grid-template-columns:18px 26px minmax(0,1fr) 146px 84px}
.kbrow-read{flex:none;font-style:normal;font-size:9.5px;color:oklch(from #45d267 min(l, var(--ink-l)) c h);opacity:.85}

/* **The review date is the state.** There was a freshness pill in a column of
   its own and on fifteen rows of seventeen it read "Current" in green, which
   is the sidebar-attention-dot mistake: lit on everything, so signalling
   nothing. The date is always there, because when anyone last checked is
   always worth knowing, and it takes a colour only when the answer is a
   problem. */
.kbrow-f{display:flex;align-items:center;justify-content:flex-end;gap:5px;font-family:"Geist Mono",monospace;
  font-size:11px;color:var(--txt-3);white-space:nowrap}
.kbrow-f i{flex:none;width:5px;height:5px;border-radius:50%;background:var(--t)}
.kbrow-f.due,.kbrow-f.stale{color:oklch(from var(--t) min(l, var(--ink-l)) c h)}
.kbrow-f.locked{font-family:inherit;gap:6px}
.kbrow.locked .kbrow-t{color:var(--txt-2)}
.kbrow.locked .kbrow-s{opacity:.72}

/**
 * **The type is a tile, not a text badge.** `KINDS` says the type is how to
 * *read* a page — a procedure, some background, a rule, a thing to copy —
 * which makes it the first thing you want off a row and the last thing worth
 * spending a word on. Four silhouettes do it without one, so a shelf of
 * mixed types reads as mixed at a glance and colour is free to be decoration
 * rather than the only signal.
 *
 * The finish is the **workstream tile's** (`.wsr-1`), this app's one answer
 * to a small square coloured object: the hue darkened into a shallow
 * gradient, a lit top edge, a hairline of its own colour, a little of it
 * thrown on the row below. `KINDS` colours are tuned to be read as *text* on
 * near-black, so a white glyph on one at full strength fails; mixed down the
 * hue is unchanged and the glyph reads. Radius scales with size the way
 * `LaunchIcon`'s does, so a 26px tile in a row and a 30px one on the page
 * share a footprint.
 */
.kbtile{position:relative;display:grid;place-items:center;flex:none;color:#fff;
  background:linear-gradient(180deg,color-mix(in srgb,var(--t) calc(100% - 44% * var(--dkg)),#0b0b0e),
    color-mix(in srgb,var(--t) calc(100% - 58% * var(--dkg)),#07070a));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.2),
    inset 0 0 0 1px color-mix(in srgb,var(--t) calc(100% - 40% * var(--dkg)),#07070a),
    0 1px 4px -1px color-mix(in srgb,var(--t) 50%,transparent);
  transition:transform .14s cubic-bezier(.2,.8,.3,1),filter .14s}
.kbtile svg{display:block;filter:drop-shadow(0 1px 0 rgba(0,0,0,.28))}
.kbtile.locked{color:#6a6a6a;
  background:linear-gradient(180deg,color-mix(in srgb,var(--tint) 5%,transparent),color-mix(in srgb,var(--tint) 1.2%,transparent));
  box-shadow:inset 0 0 0 1px var(--line),inset 0 1px 0 rgba(255,255,255,.04)}
.kbtile.locked svg{filter:none}
.kbrow:hover .kbtile{transform:translateY(-1px);filter:brightness(1.12)}

/* the reader leads with the same tile, and says what the type means — a
   badge reading "SOP" tells a new person nothing */
.kb-doc-k{display:flex;align-items:center;gap:11px}
.kb-doc-k b{display:block;font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--txt-2)}
.kb-doc-k em{display:block;margin-top:2px;font-style:normal;font-size:11.5px;color:var(--txt-3)}

@media (max-width:1000px){
  .kbrow,.kbphase .kbrow{grid-template-columns:26px minmax(0,1fr) 84px}
  .approw,.applist.community .approw{grid-template-columns:28px minmax(0,1fr) 92px}
  .kbphase .kbrow .kbrow-n,.pgrow-o,.approw-cat{display:none}
  .pmast{flex-direction:column;align-items:flex-start;gap:18px}
  .pfacts{margin-left:0}
  .pfact.on::after{bottom:-21px}
}

/* freshness is derived, so it can be shown without anyone maintaining it */
.kb-stamp{display:inline-flex;align-items:center;gap:5px;font-size:10px;color:oklch(from var(--t) min(l, var(--ink-l)) c h)}
.kb-stamp i{width:6px;height:6px;border-radius:50%;background:var(--t);flex:none}
.kb-stamp.fresh{color:var(--txt-3)}
.kb-stamp.fresh i{background:color-mix(in srgb,#45d267 70%,transparent)}

/* the reader */
.kb-doc{max-width:820px;margin-inline:auto}
.kb-doc-bar{display:flex;align-items:center;gap:12px;margin-bottom:20px}
.kb-back{font-size:12px;color:var(--txt-2);border:1px solid var(--line);border-radius:7px;padding:5px 11px}
.kb-back:hover{border-color:var(--line-hi);color:var(--lit)}
.kb-crumb{font-size:11.5px;color:var(--txt-3)}
.kb-mark{margin-left:auto;font-size:11.5px;color:var(--txt-2);border:1px solid var(--line);
  border-radius:7px;padding:5px 11px}
.kb-mark:hover{border-color:var(--line-hi);color:var(--lit)}
.kb-mark.on{color:oklch(from #45d267 min(l, var(--ink-l)) c h);border-color:color-mix(in srgb,#45d267 40%,transparent);
  background:color-mix(in srgb,#45d267 10%,transparent)}
.kb-doc-in>h1{margin:11px 0 0;font-size:25px;font-weight:600;letter-spacing:-.03em;line-height:1.25}
.kb-lead{margin:9px 0 0;font-size:14px;line-height:1.6;color:var(--txt-2)}
.kb-meta{display:flex;flex-wrap:wrap;align-items:center;gap:6px 18px;margin:16px 0 0;
  padding:12px 0;border-top:1px solid var(--line-soft);border-bottom:1px solid var(--line-soft);
  font-size:11.5px;color:var(--txt-3)}
.kb-meta span{display:inline-flex;align-items:center;gap:7px}
.kb-meta-f.due,.kb-meta-f.stale{color:oklch(from var(--t) min(l, var(--ink-l)) c h)}
.kb-warn{margin:16px 0 0;font-size:12.5px;line-height:1.55;border-radius:9px;padding:11px 13px;
  border:1px solid color-mix(in srgb,var(--st-qa) 32%,transparent);
  background:color-mix(in srgb,var(--st-qa) 8%,transparent);color:var(--txt-2)}
.kb-warn.stale{border-color:color-mix(in srgb,var(--st-blocked) 34%,transparent);
  background:color-mix(in srgb,var(--st-blocked) 8%,transparent)}
.kb-doc-in section{margin-top:26px}
.kb-doc-in h2{margin:0 0 8px;font-size:12px;font-weight:700;letter-spacing:.07em;
  text-transform:uppercase;color:var(--txt-3)}
.kb-doc-in p{margin:0 0 10px;font-size:13.5px;line-height:1.7;color:var(--txt-2)}
.kb-doc-in p:last-child{margin-bottom:0}
.kb-doc-in b{color:var(--txt);font-weight:600}
.kb-doc-in ul{margin:0;padding-left:18px;display:flex;flex-direction:column;gap:7px}
.kb-doc-in li{font-size:13.5px;line-height:1.65;color:var(--txt-2)}
.kb-doc-in li::marker{color:#4a4a4a}
.kb-note{border-left:2px solid var(--accent);padding:2px 0 2px 14px}
.kb-note p{color:var(--txt-3);font-size:12.5px}
.kb-doc-foot{display:flex;flex-wrap:wrap;gap:8px;margin:34px 0 60px;padding-top:14px;
  border-top:1px solid var(--line-soft);font-size:11.5px;color:var(--txt-3)}
.kb-doc-foot b{font-weight:500;color:var(--txt-2)}
.kb-none{font-size:13px;color:var(--txt-3);padding:30px 0}
.kb-none button{color:var(--accent);font-size:13px}
.kb-gate{margin-top:26px;border:1px solid var(--line);border-radius:12px;background:var(--bg-elev);
  padding:20px 22px;display:flex;flex-direction:column;align-items:flex-start;gap:9px}
.kb-gate-i{width:30px;height:30px;border-radius:9px;display:grid;place-items:center;
  background:var(--bg-elev2);color:var(--txt-2);box-shadow:inset 0 0 0 1px var(--line)}
.kb-gate b{font-size:13.5px;font-weight:600}
.kb-gate p{margin:0;max-width:52ch}
.kb-gate .btn-primary{align-self:flex-start;margin-top:4px}
.kb-asked{font-size:12px;color:oklch(from #45d267 min(l, var(--ink-l)) c h);margin-top:4px}

/* knowledge editor — a page is a Markdown file, and the form says so */
.kb-edit{font-size:11.5px;color:var(--txt-2);border:1px solid var(--line);border-radius:7px;padding:5px 11px;
  margin-left:auto}
.kb-edit:hover{border-color:var(--line-hi);color:var(--lit)}
.kb-edit+.kb-mark{margin-left:0}
.kb-ed{max-width:880px;margin-inline:auto}
.kb-edtabs{margin-left:auto;flex:none}
.kb-ed .kb-doc-bar .btn-primary{align-self:auto;padding:6px 13px;font-size:12.5px}
.kb-edform{display:flex;flex-direction:column}
.kb-edrow{display:grid;grid-template-columns:repeat(4,1fr);gap:12px}
.kb-md{width:100%;min-height:340px;resize:vertical;background:var(--bg-elev);border:1px solid var(--line);
  border-radius:9px;padding:14px 16px;color:var(--txt);font-family:"Geist Mono",monospace;font-size:12.5px;
  line-height:1.75;outline:none;tab-size:2}
.kb-md:focus{border-color:var(--accent)}
.kb-cheat{display:flex;flex-wrap:wrap;align-items:center;gap:7px;margin:9px 0 0;font-size:11px;color:var(--txt-3)}
.kb-cheat code{font-family:"Geist Mono",monospace;font-size:10.5px;color:var(--txt-2);
  border:1px solid var(--line);border-radius:5px;padding:2px 7px}
.kb-cheat span{flex:1;min-width:220px}
.kb-edpreview{max-width:none;margin:0}
.kb-edpreview .kb-doc-in{border:1px solid var(--line);border-radius:12px;padding:22px 26px 30px;
  background:var(--bg-elev)}
.kb-edpreview .kb-doc-in>h1{margin-top:9px}

/* ---------- launch header: three groups, not seven peers ---------- */
/* Seven buttons at one level made the bar read as a list of equals. They are
   not: Home is the launch, the middle four are ways of looking at its work,
   and the last two are who is on it. The dividers say so at no cost. */
.seg.seg-grouped{gap:1px;padding:3px}
.seg-grouped button{padding:5px 10px;gap:5px;border-radius:6px}
.seg-div{width:1px;align-self:stretch;margin:2px 5px;background:var(--line);flex:none}
.seg-grouped button.on{background:var(--active);color:var(--lit)}
.seg-grouped button svg{opacity:.75}
.seg-grouped button.on svg{opacity:1}

/* The artifact at row size. The full paper sheet it replaced was an object
   resting in the row and needed ~70px to earn that; everything that made it
   read as an object turned to a smudge below about 60px, so the small
   version is drawn rather than scaled (ArtifactMini.jsx). */
.amini{width:24px;height:31px;display:block;position:absolute;left:50%;top:50%;
  transform:translate(-50%,-50%);filter:drop-shadow(0 1px 2px rgba(0,0,0,.45));
  transition:transform .16s cubic-bezier(.2,.8,.3,1)}
.amini.pending{filter:none}
:is(.lrow,.hwatch-row,.wscol):hover .amini{transform:translate(-50%,-50%) translateY(-1px) rotate(-3deg)}

/* Hover is the one moment the artifact can act, so **each object does the one
   thing that object does** rather than sharing a generic lift. A bulb turns
   on; a clapperboard claps. Anything reusable here would be the tell that
   these are icons rather than things.

   Both are transitions rather than animations, so the gesture runs backwards
   when you leave the row instead of snapping. The one animation — the strike
   flicker — starts and ends on the resting value for the same reason: pulling
   it mid-flight cannot leave the bulb stuck dim. */
.amini .am-glow{opacity:.5;transform-box:view-box;transform-origin:12px 11.4px;
  transition:opacity .24s ease,transform .24s ease}
.amini .am-fil{transition:stroke .24s ease}
:is(.lrow,.hwatch-row,.wscol):hover .amini .am-glow{opacity:1;transform:scale(1.16)}
:is(.lrow,.hwatch-row,.wscol):hover .amini .am-fil{stroke:#fff0bd}
:is(.lrow,.hwatch-row,.wscol):hover .amini .am-bulb{animation:am-strike .62s ease-out}
/* a filament does not come up clean — it catches, drops and holds */
@keyframes am-strike{
  0%{opacity:1}11%{opacity:.6}20%{opacity:1}32%{opacity:.76}44%{opacity:1}100%{opacity:1}
}
/* the stick rests a few degrees open and shuts on the hinge pin, with the
   overshoot a real one has when it hits the slate */
.amini .am-stick{transform-box:view-box;transform-origin:2.9px 10.4px;
  transform:rotate(-7deg);transition:transform .22s cubic-bezier(.3,1.8,.5,1)}
:is(.lrow,.hwatch-row,.wscol):hover .amini .am-stick{transform:rotate(0deg)}

@media (prefers-reduced-motion:reduce){
  .amini .am-glow,.amini .am-fil,.amini .am-stick{transition:none}
  :is(.lrow,.hwatch-row,.wscol):hover .amini .am-bulb{animation:none}
}


/* Something is being made here. Two idioms people already read without a
   legend: the placeholder's border marches, and the content fills in line by
   line and clears again. Only on In Progress — see ArtifactMini. */
@keyframes am-ants{to{stroke-dashoffset:-11.2}}
@keyframes am-fill{
  0%{transform:scaleX(.06);opacity:.2}
  45%{transform:scaleX(1);opacity:.9}
  70%{transform:scaleX(1);opacity:.9}
  100%{transform:scaleX(1);opacity:.2}
}
.am-work .am-slot{animation:am-ants 1.1s linear infinite}
.am-work .am-bars rect{transform-box:fill-box;transform-origin:left center;
  animation:am-fill 2.4s cubic-bezier(.4,0,.2,1) infinite}
.am-work .am-bars rect:nth-child(2){animation-delay:.32s}
.am-work .am-bars rect:nth-child(3){animation-delay:.64s}
@media (prefers-reduced-motion:reduce){
  .am-work .am-slot,.am-work .am-bars rect{animation:none}
  .am-work .am-bars rect{opacity:.55}
}

/* a group heading that is a person rather than a bucket */
.tdgroup-h.who{text-transform:none;letter-spacing:0;font-size:12.5px;font-weight:600;color:var(--txt)}
.tdgroup-h.who .avatar{margin-right:1px}

/* ---------- pods (the team assembler) ---------- */
.podwrap{width:100%;max-width:1180px;margin-inline:auto}
.pod-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(310px,1fr));gap:12px}
.pod-card{display:flex;flex-direction:column;gap:12px;text-align:left;padding:14px 15px 13px;
  border:1px solid var(--line);border-radius:12px;background:var(--bg-elev);
  transition:border-color .14s,transform .14s cubic-bezier(.2,.8,.3,1)}
.pod-card:hover{border-color:var(--line-hi);transform:translateY(-1px)}
.pod-h{display:flex;align-items:center;gap:9px;flex-wrap:wrap}
.pod-n{width:24px;height:24px;border-radius:7px;flex:none;display:grid;place-items:center;
  background:var(--bg-elev2);box-shadow:inset 0 0 0 1px var(--line);
  font-family:"Geist Mono",monospace;font-size:11px;font-weight:600;color:var(--txt-2)}
.pod-h b{font-size:14px;font-weight:600;letter-spacing:-.01em}
.pod-tag{font-size:9.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--txt-3);border:1px solid var(--line);border-radius:5px;padding:2px 6px}
.pod-note{font-size:11px;color:var(--txt-3)}
.pod-h .pod-note{width:100%}

.pod-work{display:flex;align-items:center;gap:10px;min-height:26px;padding:9px 0;
  border-top:1px solid var(--line-soft);border-bottom:1px solid var(--line-soft)}
.pod-icons{display:flex;gap:5px}
.pod-work-n{font-size:11.5px;color:var(--txt-3)}
.pod-work-n b{color:var(--txt);font-weight:600;font-family:"Geist Mono",monospace}
.pod-work-e{font-size:11.5px;color:#4d4d4d}

.pod-f{display:flex;align-items:center;gap:10px}
.pod-people{display:flex;align-items:center}
.pod-people .avatar{margin-right:-6px;box-shadow:0 0 0 2px var(--bg-elev)}
.pod-more{margin-left:10px;font-size:10.5px;color:var(--txt-3);font-family:"Geist Mono",monospace}
.pod-lead{margin-left:auto;font-size:11px;color:var(--txt-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pod-lead b{color:var(--txt-2);font-weight:500}
.pod-bell{display:inline-flex;align-items:center;gap:5px;flex:none;color:var(--txt-3);
  border:1px solid var(--line);border-radius:7px;padding:4px 8px;cursor:pointer}
.pod-bell:hover{border-color:var(--line-hi);color:var(--txt)}
.pod-bell.on{color:oklch(from #45d267 min(l, var(--ink-l)) c h);border-color:color-mix(in srgb,#45d267 34%,transparent)}
.pod-bell i{font-style:normal;font-size:10px;font-family:"Geist Mono",monospace}

/* the sheet */
.pod-sheet{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:81;
  width:min(760px,94vw);max-height:min(800px,90vh);display:flex;flex-direction:column;
  background:var(--bg-elev);border:1px solid var(--line);border-radius:14px;overflow:hidden;
  box-shadow:0 30px 90px rgb(0 0 0/calc(.72*var(--shade)))}
.pod-sheet .np-top .pod-note{margin-left:2px}
.pod-body{flex:1;min-height:0;overflow-y:auto;padding:16px 18px 26px}
.pod-mute{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;color:var(--txt-3);
  border:1px solid var(--line);border-radius:7px;padding:4px 10px}
.pod-mute:hover{border-color:var(--line-hi);color:var(--txt)}
.pod-mute.on{color:oklch(from #45d267 min(l, var(--ink-l)) c h);border-color:color-mix(in srgb,#45d267 34%,transparent)}

.pod-tier{margin-bottom:18px}
.pod-tier-h{display:flex;align-items:center;gap:8px;margin-bottom:6px;font-size:10px;font-weight:700;
  letter-spacing:.07em;text-transform:uppercase;color:var(--txt-3)}
.pod-tier-h span{font-family:"Geist Mono",monospace;font-weight:500;letter-spacing:0;text-transform:none}
.pod-row{display:flex;align-items:center;gap:10px;padding:7px 9px;border-radius:9px}
.pod-row:hover{background:var(--hover)}
.pod-row b{font-size:13px;font-weight:500}
.pod-tier-chip{font-size:9.5px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;
  border-radius:5px;padding:2px 7px;color:var(--txt-3);border:1px solid var(--line)}
.pod-tier-chip.lead{color:oklch(from #3291ff min(l, var(--ink-l)) c h);border-color:color-mix(in srgb,#3291ff 45%,transparent);
  background:color-mix(in srgb,#3291ff 12%,transparent)}
.pod-tier-chip.assistant{color:var(--txt-2)}
.pod-role{font-size:11.5px;color:var(--txt-3)}
.pod-load{margin-left:auto;font-size:10.5px;color:var(--txt-3);font-family:"Geist Mono",monospace}
.pod-hint{margin:0 0 16px;font-size:11.5px;line-height:1.55;color:var(--txt-3)}

.pod-trig{margin-bottom:18px}
.pod-trow{display:flex;align-items:center;gap:10px;padding:7px 9px;border-radius:9px;
  border:1px solid transparent}
.pod-trow:hover{background:var(--hover)}
.pod-trow.on{border-color:var(--line-soft);background:var(--bg-elev)}
.pod-dot{width:8px;height:8px;border-radius:50%;flex:none}
.pod-trig-n{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
.pod-trig-n b{font-size:12.5px;font-weight:500;color:var(--txt-2)}
.pod-trow.on .pod-trig-n b{color:var(--txt)}
.pod-trig-n span{font-size:10.5px;color:var(--txt-3)}
/* a switch, because a toggle that looks like a checkbox reads as a filter */
.pod-sw{width:32px;height:18px;border-radius:20px;flex:none;background:color-mix(in srgb,var(--line-hi) 72%,var(--bg));
  box-shadow:inset 0 0 0 1px var(--line);transition:background .14s;position:relative}
.pod-sw i{position:absolute;top:2px;left:2px;width:14px;height:14px;border-radius:50%;
  background:#8b8b96;transition:transform .16s cubic-bezier(.2,.8,.3,1),background .14s}
.pod-sw.on{background:color-mix(in srgb,#45d267 calc(100% - 58% * var(--dk)),#07070a)}
.pod-sw.on i{transform:translateX(14px);background:#eafaef}
.pod-cc{flex:none;width:150px}
.pod-cc select{font-size:12px}
.pod-cc select:disabled{color:var(--txt-3);cursor:default}
.pod-warn{color:oklch(from var(--st-qa) min(l, var(--ink-l)) c h);font-weight:500}

/* ---------- clients ---------- */
.clwrap{width:100%;max-width:1180px;margin-inline:auto}
.cl-new{align-self:center;margin-left:auto;padding:6px 12px;display:inline-flex;align-items:center;gap:6px}
.cl-sec{margin-bottom:26px}
.cl-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(268px,1fr));gap:10px}
.cl-card{display:flex;flex-direction:column;gap:12px;text-align:left;padding:14px;
  border:1px solid var(--line);border-radius:12px;background:var(--bg-elev);
  transition:border-color .14s,transform .14s cubic-bezier(.2,.8,.3,1)}
.cl-card:hover{border-color:var(--line-hi);transform:translateY(-1px)}
.cl-h{display:flex;align-items:center;gap:11px;min-width:0}
.cl-id{display:flex;flex-direction:column;gap:2px;min-width:0}
.cl-id b{font-size:13.5px;font-weight:600;letter-spacing:-.01em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cl-site{font-size:11px;color:var(--accent);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cl-site.none{color:#4d4d4d}
.cl-f{display:flex;align-items:center;gap:10px;padding-top:10px;border-top:1px solid var(--line-soft)}
.cl-n{font-size:11.5px;color:var(--txt-3)}
.cl-n b{color:var(--txt);font-weight:600;font-family:"Geist Mono",monospace}
.cl-n i{font-style:normal;color:var(--txt-3)}
.cl-pods{margin-left:auto;font-size:10.5px;color:var(--txt-3);font-family:"Geist Mono",monospace;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* the sheet */
.cl-sheet{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:81;
  width:min(680px,94vw);max-height:min(780px,90vh);display:flex;flex-direction:column;
  background:var(--bg-elev);border:1px solid var(--line);border-radius:14px;overflow:hidden;
  box-shadow:0 30px 90px rgb(0 0 0/calc(.72*var(--shade)))}
.cl-top{gap:12px}
.cl-title{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}
.cl-tabs{flex:none}
.cl-f2{margin-bottom:20px}
.cl-k{font-size:10px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;
  color:var(--txt-3);margin-bottom:8px}
.cl-a{font-size:13px;color:var(--accent)}
.cl-a:hover{text-decoration:underline}
.cl-none{font-size:12.5px;color:#4d4d4d}
.cl-mono{font-family:"Geist Mono",monospace;font-size:11.5px;color:var(--txt-3)}
.cl-contact{display:flex;align-items:center;gap:10px}
.cl-contact b{display:block;font-size:13px;font-weight:500}
.cl-contact i{display:block;font-style:normal;font-size:11px;color:var(--txt-3);margin-top:1px}
.cl-contact .cl-mono{margin-left:auto}
.cl-ini{width:28px;height:28px;border-radius:9px;flex:none;display:grid;place-items:center;
  background:var(--bg-elev2);box-shadow:inset 0 0 0 1px var(--line);font-size:12px;font-weight:600;color:var(--txt-2)}
.cl-slack{margin-top:8px;padding-left:38px}
.cl-code{font-family:"Geist Mono",monospace;font-size:12px;color:var(--txt-2);background:var(--bg-elev);
  border:1px solid var(--line);border-radius:8px;padding:8px 11px}
.cl-chip{display:inline-flex;align-items:center;gap:7px;font-size:12px;color:var(--txt-2);
  border:1px solid var(--line);border-radius:8px;padding:6px 11px}
.cl-chip:hover{border-color:var(--line-hi);color:var(--lit)}
.cl-launches{display:flex;flex-direction:column;gap:4px}
.cl-launch{display:flex;align-items:center;gap:10px;padding:7px 9px;border-radius:9px;text-align:left}
.cl-launch:hover{background:var(--hover)}
.cl-launch b{font-size:12.5px;font-weight:500}
.cl-launch span{font-size:11px;color:var(--txt-3)}
.cl-launch i{margin-left:auto;font-style:normal;font-size:11px;color:var(--txt-3);font-family:"Geist Mono",monospace}

.cl-linkrow{display:flex;align-items:center;gap:10px}
.cl-grow{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cl-linkrow .btn-primary,.cl-invite .btn-primary{align-self:auto;flex:none;padding:7px 13px;font-size:12.5px}
.cl-invite{display:flex;align-items:center;gap:10px;margin-bottom:10px}
.cl-people{display:flex;flex-direction:column;gap:4px}
.cl-person{display:flex;align-items:center;gap:10px;padding:6px 8px;border-radius:9px}
.cl-person:hover{background:var(--hover)}
.cl-person .cl-ini{width:22px;height:22px;border-radius:7px;font-size:10px}
.cl-when{font-size:10.5px;color:var(--txt-3);flex:none}
.cl-x{width:22px;height:22px;border-radius:6px;color:var(--txt-3);flex:none}
.cl-x:hover{background:var(--hover);color:var(--lit)}
.cl-log{display:flex;flex-direction:column;gap:5px}
.cl-logrow{display:flex;align-items:center;gap:8px;font-size:11.5px;color:var(--txt-3)}
.cl-logrow i{margin-left:auto;font-style:normal;font-family:"Geist Mono",monospace;font-size:10.5px}
.cl-mock{margin-top:22px;padding-top:14px;border-top:1px solid var(--line-soft)}

/* ---------- apps ---------- */
.appwrap{width:100%;max-width:1180px;margin-inline:auto}
.app-sec{margin-bottom:26px}

/**
 * **An app is a row.** It was a bordered card in a four-across grid —
 * mark, uppercase category badge, name, description, and a footer holding
 * three 26px icon buttons — and eleven bookmarks came to about nine hundred
 * pixels. A link with a name is the least card-shaped object in this
 * product; the grid was the last one left on a library page.
 *
 * The community list carries one extra column, because who published a
 * thing is the fact that makes it community rather than company. Everything
 * else about the row is `.pgrow`.
 */
.applist .approw{grid-template-columns:28px minmax(0,1fr) 148px 92px}
.applist.community .approw{grid-template-columns:28px minmax(0,1fr) 148px 146px 92px}
.approw{position:relative}

/* The row opens the app, but a `<button>` inside an `<a>` (or the reverse)
   is invalid and misbehaves. The title is the real link and its ::after is
   stretched over the row, so the whole row is the target, the keyboard gets
   one honest link, and the controls sit above it on their own layer. */
.approw-link{color:inherit;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.approw-link::after{content:"";position:absolute;inset:0;border-radius:inherit}
.approw:hover .approw-link{color:var(--lit)}
.approw-link:focus-visible{outline:none}
.approw-link:focus-visible::after{outline:2px solid var(--accent);outline-offset:-2px;border-radius:7px}

/* "Pinned" is a claim on one of the sidebar's scarce slots, so it says so in
   a word rather than only in the fill state of a 13px icon at the far end of
   the row. */
.approw-pin{flex:none;font-style:normal;font-size:9.5px;font-weight:600;letter-spacing:.05em;
  text-transform:uppercase;color:var(--accent);border:1px solid color-mix(in srgb,var(--accent) 34%,transparent);
  background:color-mix(in srgb,var(--accent) 11%,transparent);border-radius:5px;padding:1px 6px}

/* The category was an uppercase tinted badge — the same shouting micro-type
   the knowledge cards wore. A dot carries the colour and the word carries
   the meaning, which is the `.lstat` rule the List view already keeps. */
.approw-cat{display:flex;align-items:center;gap:7px;min-width:0;font-size:11.5px;color:var(--txt-3);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.approw-cat i{flex:none;width:6px;height:6px;border-radius:50%;background:var(--t);opacity:.85}

.app-acts{position:relative;display:flex;justify-content:flex-end;gap:2px}
.app-act{width:26px;height:26px;border-radius:7px;display:grid;place-items:center;color:var(--txt-3)}
.app-act:hover{background:var(--bg-elev2);color:var(--lit);box-shadow:inset 0 0 0 1px var(--line)}
.app-act.on{color:oklch(from var(--st-qa) min(l, var(--ink-l)) c h)}
.app-add{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;color:var(--txt-2);
  border:1px solid var(--line);border-radius:7px;padding:4px 10px;white-space:nowrap}
.app-add:hover{border-color:var(--accent);background:color-mix(in srgb,var(--accent) 12%,transparent);color:var(--lit)}
.app-add svg{width:11px;height:11px}
.kb-clear{margin-left:8px;color:var(--accent);font-size:12.5px}

/* the fallback tile, for an app with no site worth borrowing a favicon from */
.app-glyph{display:grid;place-items:center;flex:none;color:oklch(from var(--t) min(l, var(--ink-l)) c h);
  background:color-mix(in srgb,var(--t) 13%,transparent);
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--t) 26%,transparent)}

/* the editor */
.app-sheet{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:81;
  width:min(620px,94vw);max-height:min(800px,90vh);display:flex;flex-direction:column;
  background:var(--bg-elev);border:1px solid var(--line);border-radius:14px;overflow:hidden;
  box-shadow:0 30px 90px rgb(0 0 0/calc(.72*var(--shade)))}
.app-where{width:100%}
.app-where button{flex:1}
.app-cats{display:flex;flex-wrap:wrap;gap:5px}
.app-catbtn{border:1px solid var(--line);border-radius:7px;padding:5px 11px;font-size:12px;color:var(--txt-2)}
.app-catbtn:hover{border-color:var(--line-hi);color:var(--txt)}
.app-catbtn.on{color:var(--lit);border-color:color-mix(in srgb,var(--t) 55%,transparent);
  background:color-mix(in srgb,var(--t) 18%,transparent)}
.app-icons{display:grid;grid-template-columns:repeat(auto-fill,minmax(44px,1fr));gap:5px;margin-bottom:9px}
.app-ico{height:38px;border:1px solid var(--line);border-radius:8px;display:grid;place-items:center;
  color:var(--txt-2);background:var(--bg-elev)}
.app-ico:hover{border-color:var(--line-hi);color:var(--lit)}
.app-ico.on{border-color:var(--accent);background:color-mix(in srgb,var(--accent) 14%,transparent);color:var(--lit)}
.app-site{display:flex;align-items:center;gap:8px}
.app-using{display:flex;align-items:center;gap:8px;margin-top:9px}
.app-using button{color:var(--accent);font-size:11px}
.app-del{border-color:color-mix(in srgb,var(--st-blocked) 40%,transparent);color:oklch(from var(--st-blocked) min(l, var(--ink-l)) c h)}
.app-del:hover{border-color:var(--st-blocked);background:color-mix(in srgb,var(--st-blocked) 12%,transparent);color:var(--lit)}

/* pinned into the sidebar, above the launches */
.pinrow{display:flex;align-items:center;gap:10px;width:100%;padding:6px 8px;border-radius:var(--radius);
  color:var(--txt-2);font-size:13px}
.pinrow:hover{background:var(--hover);color:var(--txt)}
.pinrow .lico,.pinrow .app-glyph{width:18px;height:18px;border-radius:5px;flex:none}
.pinrow .app-glyph svg{width:10px;height:10px}
/* named, not `span` — AppMark renders a span too, and flex:1 on it stretched
   the mark into a bar across the row */
.pin-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pinrow i{font-style:normal;color:var(--txt-3);font-size:10px;opacity:0}
.pinrow:hover i{opacity:1}
/* a drawn mark for an in-house tool — the tile is the brand, not a favicon */
.app-mark{display:grid;place-items:center;flex:none;overflow:hidden;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.22),0 1px 3px -1px rgba(0,0,0,.6)}
.pinrow .app-mark{width:18px;height:18px;border-radius:5px}
.pinrow .app-mark svg{width:11px;height:11px}

/* the list's status: dot for the colour, sentence case for the word */
.lstat{display:inline-flex;align-items:center;gap:7px;white-space:nowrap;font-size:12px;
  color:var(--txt-2);border:1px solid color-mix(in srgb,var(--s) 26%,transparent);
  background:color-mix(in srgb,var(--s) 9%,transparent);border-radius:20px;padding:3px 10px 3px 8px}
.lstat i{width:7px;height:7px;border-radius:50%;background:var(--s);flex:none;
  box-shadow:0 0 0 2px color-mix(in srgb,var(--s) 18%,transparent)}
/* the same pill as a control: it brightens under the pointer and while its
   menu is open, which is all the affordance a thing already shaped like a
   chip needs */
.lstat-pick{display:inline-flex}
.lstat.lstat-btn{font-family:inherit;cursor:pointer;
  transition:border-color .12s,background .12s,color .12s}
.lstat.lstat-btn:hover,.lstat.lstat-btn.open{color:var(--txt);
  border-color:color-mix(in srgb,var(--s) 55%,transparent);
  background:color-mix(in srgb,var(--s) 16%,transparent)}
.lstat.lstat-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* ---------- users (performance) ---------- */
.uswrap{width:100%;max-width:1180px;margin-inline:auto}
.us-win{flex:none}
.us-card{border:1px solid var(--line);border-radius:12px;background:var(--bg-elev);overflow:hidden}
.us-card-h{display:flex;align-items:baseline;gap:10px;padding:13px 16px;border-bottom:1px solid var(--line)}
.us-card-h b{font-size:13.5px;font-weight:600}
.us-card-h span{font-size:11px;color:var(--txt-3)}
.us-tbl{border:none;border-radius:0}
.us-tbl table{font-size:13px}
.us-tbl th{padding:9px 16px;background:transparent;border-bottom:1px solid var(--line-soft);
  font-size:10px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--txt-3)}
.us-tbl td{padding:8px 16px;border-top:1px solid var(--line-soft)}
.us-tbl tbody tr:hover td{background:var(--hover)}
.us-th{text-align:right;cursor:pointer;user-select:none;white-space:nowrap}
.us-th:hover{color:var(--txt-2)}
.us-th.on{color:var(--txt)}
.us-th i{font-style:normal;margin-left:5px;font-size:9px}
/* name, role and team are text: they read from the left, and the arrow hangs after the word */
.us-th.txt{text-align:left}
.us-t{font-size:12.5px;color:var(--txt-2);white-space:nowrap}
.us-name{font-size:13px;font-weight:600;letter-spacing:-.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.us-pod{color:var(--txt-2);text-decoration:underline;text-decoration-color:transparent;text-underline-offset:3px;
  transition:color .12s,text-decoration-color .12s}
.us-pod:hover{color:var(--txt);text-decoration-color:var(--txt-3)}
.us-who{display:flex;align-items:center;gap:11px;min-width:0}
/* presence sits on the avatar, not in its own column — it is a property of
   the person, and a column for it would be nine tenths empty */
.us-av{position:relative;flex:none;display:block}
.us-av:after{content:"";position:absolute;right:-1px;bottom:-1px;width:9px;height:9px;border-radius:50%;
  background:var(--line-hi);box-shadow:0 0 0 2px var(--bg-elev)}
.us-av.on:after{background:#45d267}
.us-n{text-align:right;font-family:"Geist Mono",monospace;font-size:12.5px;color:var(--txt-2);white-space:nowrap}
.us-n.strong{color:var(--txt);font-weight:600}
.us-n b{font-weight:600}
.us-n i{font-style:normal;color:var(--txt-3);margin-left:5px;font-size:11px}
.us-note{display:flex;align-items:flex-start;gap:8px;margin:16px 2px 0;font-size:11px;
  line-height:1.55;color:var(--txt-3);max-width:76ch}
.us-note svg{flex:none;margin-top:1px}
.us-note b{color:var(--txt-2);font-weight:500}
/* ---------- users: accounts ---------- */
/* The one wide list on a People page: eight columns and four actions a row,
   so it takes the directory's width rather than the reading width. */
.uswrap.acc{max-width:1320px}
.acc-bar{flex-wrap:wrap}
.acc-total{margin-left:auto;font-size:11.5px;color:var(--txt-3);font-family:"Geist Mono",monospace;white-space:nowrap}
.acc-tbl{overflow-x:auto;background:var(--bg-elev)}
.acc-tbl table{min-width:1000px}
.acc-tbl th{padding:10px 12px;background:transparent;border-bottom:1px solid var(--line-soft);
  font-size:10px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--txt-3);white-space:nowrap}
.acc-tbl td{padding:9px 12px}
/* On a laptop the middle columns scroll and the actions stay: they are what
   the page is for, and a Revoke you have to scroll sideways to find is the
   directory's clipped-table problem again. Opaque, so rows pass under it,
   and its hover composites over the ground rather than replacing it. */
.acc-tbl th:last-child,.acc-tbl td:last-child{position:sticky;right:0;z-index:1;background:var(--bg-elev);
  box-shadow:-1px 0 0 var(--line-soft)}
.acc-tbl th.c,.acc-tbl td.c{text-align:center}
.acc-tbl tbody tr:hover td{background:var(--hover)}
.acc-tbl tbody tr:hover td:last-child{background:var(--bg-elev) linear-gradient(var(--hover),var(--hover))}
/* shut out: the person steps back, the actions that bring them back do not */
.acc-row.revoked td:not(:last-child){opacity:.5}
.acc-who{display:flex;align-items:center;gap:11px;min-width:0}
.acc-id{display:flex;flex-direction:column;gap:2px;min-width:0;max-width:230px}
.acc-n{display:flex;align-items:center;gap:6px;min-width:0}
.acc-n b{font-size:13px;font-weight:600;letter-spacing:-.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.acc-mail{font-size:11.5px;color:var(--txt-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* Manager and Cross-pod are facts about the account, on half the rows — so
   they are quiet, a hairline and a word, or the column is a wall of colour */
.acc-tag{flex:none;font-style:normal;font-size:9px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--txt-3);border:1px solid var(--line);border-radius:5px;padding:1px 5px;line-height:1.4}
.acc-tag.bad{color:oklch(from #f5405e min(l, var(--ink-l)) c h);border-color:color-mix(in srgb,#f5405e 40%,transparent)}
.acc-t{font-size:12.5px;color:var(--txt-2);white-space:nowrap}
.acc-divs{display:flex;gap:5px}
.acc-div{font-style:normal;font-size:11px;font-weight:500;color:var(--txt-2);padding:2px 7px;border-radius:5px;
  background:color-mix(in srgb,var(--tint) 6%,transparent)}
.acc-all{font-size:12px;color:var(--txt-3)}
.acc-pods{display:inline-flex;align-items:center;gap:6px}
.acc-more{font-style:normal;font-size:10.5px;font-weight:600;color:var(--txt-3);font-family:"Geist Mono",monospace;
  padding:1px 5px;border-radius:5px;background:color-mix(in srgb,var(--tint) 6%,transparent)}
.acc-ck{display:inline-grid;place-items:center;width:18px;height:18px;border-radius:50%;vertical-align:middle;
  background:color-mix(in srgb,var(--tint) 6%,transparent);color:var(--txt-3)}
.acc-ck i{width:7px;height:1.5px;border-radius:1px;background:currentColor}
.acc-ck.on{background:color-mix(in srgb,var(--st-done) 16%,transparent);color:oklch(from var(--st-done) min(l, var(--ink-l)) c h)}
.acc-when{font-size:11.5px;color:var(--txt-2);font-family:"Geist Mono",monospace;white-space:nowrap}
/* Four fixed slots, so Edit, Re-invite, View as and Revoke each sit in one
   column down the page however many a row has: right-aligned, a row with
   one button fewer shifted every other one sideways. */
.acc-acts{display:grid;grid-template-columns:42px 68px 60px 58px;gap:5px;justify-content:end;align-items:center}
.acc-btn{height:26px;width:100%;border:1px solid var(--line);border-radius:7px;background:var(--bg-elev);
  font-size:11.5px;font-weight:600;color:var(--txt-2);white-space:nowrap;transition:background .12s,border-color .12s,color .12s}
.acc-btn:hover:not(:disabled){border-color:var(--line-hi);background:var(--hover);color:var(--txt)}
.acc-btn:disabled{color:var(--txt-3);opacity:.6;cursor:default}
.acc-btn.go{background:var(--accent);border-color:var(--accent);color:#fff}
.acc-btn.go:hover:not(:disabled){background:color-mix(in srgb,var(--accent) 84%,#fff);border-color:transparent;color:#fff}
.acc-btn.bad{color:oklch(from #f5405e min(l, var(--ink-l)) c h);border-color:color-mix(in srgb,#f5405e 35%,transparent)}
.acc-btn.bad:hover:not(:disabled){background:color-mix(in srgb,#f5405e 10%,transparent);
  border-color:color-mix(in srgb,#f5405e 60%,transparent);color:oklch(from #f5405e min(l, var(--ink-l)) c h)}
.acc-clear{margin-left:10px;font-size:12px;color:var(--accent)}
.acc-clear:hover{text-decoration:underline}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
/* the person window, and EOD's reminders: the app sheet's shell, two fields
   to a row, a Picker that takes its row, toggle chips */
.acc-sheet{width:min(560px,94vw)}
.f2{display:grid;grid-template-columns:1fr 1fr;gap:14px}
/* the Picker wraps its trigger in an inline span; in a field it takes the row */
.app-sheet .pick{display:flex}
.fpick{display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;height:35px;padding:0 11px;
  background:var(--bg-elev);border:1px solid var(--line);border-radius:8px;font-size:13px;color:var(--txt)}
.fpick:hover{border-color:var(--line-hi)}
.fpick>svg{color:var(--txt-3)}
.acc-seg{display:flex;width:100%}
.acc-seg button{flex:1;justify-content:center}
.fchips{display:flex;flex-wrap:wrap;gap:6px}
.fchip{border:1px solid var(--line);border-radius:7px;padding:6px 11px;font-size:12px;color:var(--txt-2)}
.fchip:hover{border-color:var(--line-hi);color:var(--txt)}
.fchip.on{color:var(--lit);border-color:color-mix(in srgb,var(--accent) 55%,transparent);
  background:color-mix(in srgb,var(--accent) 14%,transparent)}
.acc-state{margin-top:0}
.acc-del{color:oklch(from #f5405e min(l, var(--ink-l)) c h);border-color:color-mix(in srgb,#f5405e 35%,transparent)}
.acc-del:hover{color:oklch(from #f5405e min(l, var(--ink-l)) c h);border-color:color-mix(in srgb,#f5405e 60%,transparent)}
@media (max-width:640px){.f2{grid-template-columns:1fr}}
/* ---------- EOD reminders (a manager's) ---------- */
/* the toolbar's own filter button, saying the schedule it holds; a green dot
   while reminders are on, the Kanban-live dot's meaning */
.eodr-btn{flex:none}
.eodr-btn .tbm-l{max-width:none}
.eodr-btn svg{color:var(--txt-3)}
.eodr-btn.live svg{color:var(--txt-2)}
.eodr-live{width:6px;height:6px;border-radius:50%;background:var(--live);flex:none}
.eodr-sheet{width:min(560px,94vw)}
.eodr-lead{margin:0 0 16px;font-size:12.5px;line-height:1.55;color:var(--txt-2)}
.eodr-master{display:flex;align-items:center;gap:12px;padding:12px 14px;margin-bottom:18px;
  border:1px solid var(--line);border-radius:10px;background:var(--bg)}
.eodr-master-t{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.eodr-master-t b{font-size:13px;font-weight:600;color:var(--txt)}
.eodr-master-t span{font-size:11.5px;color:var(--txt-3)}
/* switched off, the schedule is still there to set — it just reads as waiting */
.eodr-when.off{opacity:.55}
.eodr-k{display:flex;align-items:baseline;justify-content:space-between;gap:8px}
.eodr-custom{font-size:10.5px;font-weight:500;letter-spacing:0;text-transform:none;color:var(--accent)}
.eodr-custom:hover{text-decoration:underline}
.eodr-time{font-family:"Geist Mono",monospace;font-variant-numeric:tabular-nums}
.nt-in.bad,.nt-in.bad:focus{border-color:color-mix(in srgb,#f5405e 60%,transparent)}
.eodr-bad{color:oklch(from #f5405e min(l, var(--ink-l)) c h)}
.eodr-warn{color:oklch(from var(--st-qa) min(l, var(--ink-l)) c h)}
.eodr-who{margin:0;font-size:12.5px;line-height:1.55;color:var(--txt-2)}
.eodr-who b{color:var(--txt);font-weight:600}
.eodr-dm{display:flex;gap:10px;padding:11px 12px;border:1px solid var(--line);border-radius:10px;background:var(--bg)}
.eodr-dm-av{flex:none;width:26px;height:26px;border-radius:7px;display:grid;place-items:center;
  font-size:13px;font-weight:700;color:#fff;background:var(--accent)}
.eodr-dm-b{display:flex;flex-direction:column;gap:3px;min-width:0;font-size:12.5px;line-height:1.5;color:var(--txt-2)}
.eodr-dm-h{display:flex;align-items:baseline;gap:7px}
.eodr-dm-h b{font-size:12.5px;font-weight:600;color:var(--txt)}
.eodr-dm-h span{font-size:10.5px;color:var(--txt-3);font-family:"Geist Mono",monospace}
.eodr-note{margin-top:4px}
.eodr-state{font-size:11.5px;color:var(--txt-3)}
.eodr-state.dirty{color:oklch(from var(--st-qa) min(l, var(--ink-l)) c h)}
/* which team's day you are reading */
.eod-pods{display:inline-flex;flex-wrap:wrap;align-items:center;gap:2px;margin-left:auto;
  background:var(--bg-elev);border:1px solid var(--line);border-radius:9px;padding:2px}
.eod-pod{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;color:var(--txt-2);
  border:1px solid transparent;border-radius:6px;padding:4px 11px}
.eod-pod:not(.on):hover{background:var(--hover)}
.eod-pod b{font-weight:500;font-size:10.5px;color:var(--txt-3);font-family:"Geist Mono",monospace}
.eod-pod:hover{color:var(--txt)}
.eod-pod.on{background:var(--active);border-color:var(--line-hi);color:var(--lit)}
.eod-pod.on b{color:var(--txt-2)}

/* The end of the cut: a column, not a floating button, because the strip is
   the film in order and the next scene goes where the next scene goes. It
   stands the full height of the block — a button in the header row would
   leave four dead cells under it. */
.jaddcol{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;
  color:var(--txt-3);background:color-mix(in srgb,var(--tint) 1.2%,transparent);
  border-left:1px dashed var(--line);border-bottom:1px solid var(--line-soft)}
.jaddcol-i{display:grid;place-items:center;width:26px;height:26px;border-radius:50%;
  border:1px dashed var(--line);transition:background .12s,border-color .12s}
.jaddcol-t{font-size:10px;white-space:nowrap;writing-mode:vertical-rl;letter-spacing:.02em}
.jaddcol:hover{color:var(--lit);background:color-mix(in srgb,var(--accent) 7%,transparent);border-left-color:var(--accent)}
.jaddcol:hover .jaddcol-i{background:var(--accent);border-color:var(--accent);border-style:solid}

/* Terminology — a lookup, so it is a definition list and not a card grid:
   the term on the left in one narrow column you can run your eye down, the
   sentence beside it. Grouped under the same areas the pages use, because a
   word belongs where it is practised. */
.kb-terms{margin-top:16px}
.kb-tgrp{margin-top:18px}
.kb-tgrp h3{font-size:10.5px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;
  color:var(--txt-3);margin-bottom:6px}
.kb-tlist{border:1px solid var(--line);border-radius:10px;overflow:hidden;background:var(--bg-elev)}
.kb-term{display:grid;grid-template-columns:184px 1fr;gap:18px;padding:11px 14px;
  border-bottom:1px solid var(--line-soft)}
.kb-term:last-child{border-bottom:none}
.kb-term:hover{background:var(--hover)}
.kb-term dt{font-size:13px;font-weight:600;color:var(--txt);min-width:0}
.kb-term-a{display:block;margin-top:3px;font-size:11px;font-weight:400;color:var(--txt-3)}
.kb-term dd{font-size:12.5px;line-height:1.55;color:var(--txt-2);margin:0;min-width:0}
.kb-term-see{display:inline-flex;align-items:center;margin-left:7px;font-size:11.5px;
  color:var(--accent);border-bottom:1px solid transparent}
.kb-term-see::before{content:"→ ";margin-right:3px;color:var(--txt-3)}
.kb-term-see:hover{border-bottom-color:currentColor}
@media (max-width:760px){.kb-term{grid-template-columns:1fr;gap:5px}}

/* a tile that is a way in, not just a reading */
.wsr-go{cursor:pointer}
.wsr-go:hover{filter:brightness(1.3)}
.wsr-go:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* Adding where a version is reviewed. The section is always there, with or
   without a link: a version with nowhere to review it is a thing to fix, not
   a section to hide. No tool picker — the mark is derived from the URL, so
   pasting the link is the whole job. */
.tlink-add{display:inline-flex;align-items:center;gap:7px;font-size:12px;color:var(--txt-2);
  border:1px dashed var(--line);border-radius:8px;padding:6px 11px}
.tlink-add:hover{border-style:solid;border-color:var(--line-hi);color:var(--txt);background:var(--hover)}
.tlink-form{display:flex;flex-wrap:wrap;align-items:center;gap:7px}
.tlink-form input{flex:1;min-width:180px;background:var(--bg);border:1px solid var(--line);
  border-radius:8px;padding:7px 10px;font:inherit;font-size:12px;color:var(--txt);
  font-family:"Geist Mono",monospace}
.tlink-form input:focus{outline:none;border-color:var(--line-hi)}
.tlink-form .btn-primary{padding:6px 13px;font-size:12px;align-self:auto}
.tlink-form .btn-primary:disabled{opacity:.45;cursor:default}
.tlink-rm{color:oklch(from #f75f8f min(l, var(--ink-l)) c h)}

/* Home's queue carries both kinds, and the leading control is the tell:
   a note you can tick, a ticket showing the status it settled into. Same
   width for both so the titles still line up down the column. */
.hnext-tick{display:inline-flex;align-items:center;justify-content:center;flex:none;
  width:17px;height:17px;border-radius:5px;border:1px solid var(--line);
  color:transparent;background:var(--bg);cursor:pointer;transition:border-color .12s,color .12s,background .12s}
.hnext-tick:hover{border-color:#45d267;color:oklch(from #45d267 min(l, var(--ink-l)) c h);background:rgba(69,210,103,.1)}
.hnext-tick:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
/* the status word sits with the launch and the date, which is what it is:
   a fact about the row, not a control on it */
.hnext-sw{flex:none;font-size:11px;font-weight:500;margin-left:auto;white-space:nowrap}
.hnext-sw + .hnext-l{margin-left:14px}

/* Shared is the exception, so only it gets a marker — labelling the default
   on every row would be forty rows of "Private". */
.tdshared{display:inline-flex;align-items:center;gap:5px;flex:none;font-size:11px;color:var(--txt-3)}
.tdrow:hover .tdshared{color:var(--txt-2)}
/* private / shared, in the note sheet */
.tsheet-vis{margin-left:auto;padding:2px}
.tsheet-vis button{padding:4px 11px;font-size:11.5px}

/* Appearance — centred, because settings are not a thing you work beside */
.apmodal{position:fixed;z-index:120;top:50%;left:50%;transform:translate(-50%,-50%);
  width:min(560px,calc(100vw - 32px));max-height:min(80vh,680px);display:flex;flex-direction:column;
  background:var(--bg-elev);border:1px solid var(--line);border-radius:14px;
  box-shadow:0 30px 90px -20px rgb(0 0 0/calc(.8*var(--shade))),0 0 0 1px rgba(0,0,0,.4)}
.apmodal-top{display:flex;align-items:center;gap:10px;padding:14px 16px;
  border-bottom:1px solid var(--line-soft)}
.apmodal-top h2{margin:0;font-size:14px;font-weight:600;letter-spacing:-.01em}
.apmodal-top .ticket-x{margin-left:auto}
.apmodal-body{overflow-y:auto;padding:16px}

.apsec + .apsec{margin-top:22px;padding-top:20px;border-top:1px solid var(--line-soft)}
.apsec-h{display:flex;align-items:baseline;gap:10px;margin-bottom:11px}
.apsec-h b{font-size:12.5px;font-weight:600}
.apsec-h span{font-size:11.5px;color:var(--txt-3)}

.apthemes{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}
.apcard{display:flex;flex-direction:column;align-items:flex-start;gap:7px;padding:10px;
  text-align:left;border:1px solid var(--line);border-radius:11px;background:var(--bg);
  transition:border-color .12s,background .12s}
.apcard:hover{border-color:var(--line-hi)}
.apcard.on{border-color:var(--accent);background:color-mix(in srgb,var(--accent) 9%,transparent)}
.apcard-n{font-size:12.5px;font-weight:600;color:var(--txt)}
.apcard-d{font-size:10.5px;line-height:1.35;color:var(--txt-3)}

/* the little plate: a window, painted the way that theme would paint it */
.apw{position:relative;display:block;width:100%;height:48px;border-radius:7px;overflow:hidden;
  background:#0a0a0a;border:1px solid rgba(255,255,255,.1)}
.apw-bar{position:absolute;left:0;top:0;width:34%;height:100%;background:#000}
.apw-l1,.apw-l2{position:absolute;left:41%;height:4px;border-radius:2px;background:#2e2e34}
.apw-l1{top:14px;width:46%}
.apw-l2{top:25px;width:30%}
.apw.light{background:#fff;border-color:rgba(0,0,0,.14)}
.apw.light .apw-bar{background:#f4f0ea}
.apw.light .apw-l1,.apw.light .apw-l2{background:#d8d4cd}
/* system: half and half, split down the middle */
.apw.sys{background:linear-gradient(to right,#0a0a0a 0 50%,#fff 50% 100%)}
.apw.sys .apw-bar{background:#000}
.apw.sys .apw-l1{background:linear-gradient(to right,#2e2e34 0 30%,#d6d6dc 30% 100%)}
.apw.sys .apw-l2{background:#2e2e34}

.apnote{margin:11px 0 0;font-size:11.5px;line-height:1.5;color:var(--txt-3)}
.apnote b{color:var(--txt-2);font-weight:600}

.apsoon-tag{font-size:10px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;
  color:var(--txt-3);border:1px solid var(--line);border-radius:20px;padding:2px 8px}
.apsoon{display:flex;flex-direction:column;border:1px solid var(--line-soft);border-radius:10px;
  overflow:hidden;opacity:.62}
.apsoon-r{display:flex;align-items:center;gap:12px;padding:9px 12px;
  border-bottom:1px solid var(--line-soft)}
.apsoon-r:last-child{border-bottom:none}
.apsoon-k{flex:none;width:74px;font-size:12px;font-weight:500;color:var(--txt-2)}
.apsoon-d{flex:1;min-width:0;font-size:11px;color:var(--txt-3)}
.apsoon-v{flex:none;font-size:11.5px;color:var(--txt-3);font-family:"Geist Mono",monospace}
@media (max-width:620px){.apthemes{grid-template-columns:1fr}}

/* which project a queue row came from — five launches in one list and none
   of them named meant opening a ticket to find out whose it was */
.hnext-l{display:inline-flex;align-items:center;gap:6px;flex:none;max-width:190px;
  font-size:11px;color:var(--txt-3);margin-left:auto;padding-left:14px}
.hnext-ln{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.hnext-l .lico{width:14px;height:14px;font-size:7px}
.hnext-row:hover .hnext-l{color:var(--txt-2)}
/* shrinks, never grows: a long title ellipsises instead of pushing the
   status, project and date off the row, and a short one leaves the status
   pinned right by its own auto margin */
.hnext-t{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* which project, on the right of the Assignments header */
.hsec-proj{margin-left:auto;text-transform:none;letter-spacing:0;flex-wrap:wrap}
.hsec-proj button{gap:7px;padding:4px 10px;font-size:11.5px}
.hsec-proj b{font-weight:500;font-size:10px;color:var(--txt-3);font-family:"Geist Mono",monospace}
.hsec-proj button.on b{color:var(--txt-2)}
.hsec-proj .lico{width:15px;height:15px;font-size:7px;flex:none}
.hsec-proj-n{white-space:nowrap}

/* the rest of the projects */
.hsec-more{display:inline-flex;align-items:center;justify-content:center;min-width:26px;height:24px;
  padding:0 6px;border-radius:6px;color:var(--txt-3);font-size:14px;line-height:1}
.hsec-more:hover,.hsec-more.open{background:var(--hover);color:var(--txt)}
.hsec-proj .stadd-pop{left:auto;right:0}

/* Needs your review — the other half of the day: not what you owe, but what
   is stopped until you look. Flatter than the assignments list on purpose,
   so the two read as different things at a glance. */
.hsec-note{margin-left:10px;font-size:11px;font-weight:400;letter-spacing:0;
  text-transform:none;color:var(--txt-3)}
.hrev{display:flex;flex-direction:column;border:1px solid var(--line);border-radius:11px;
  overflow:hidden;background:var(--bg-elev)}
.hrev-row{display:flex;align-items:center;gap:12px;padding:9px 13px;text-align:left;
  border-bottom:1px solid var(--line-soft)}
.hrev-row:last-child{border-bottom:none}
.hrev-row:hover{background:var(--hover)}
/* which gate it is stuck at, in the lane's own colour */
.hrev-lane{flex:none;width:86px;font-size:10px;font-weight:600;letter-spacing:.03em;
  text-transform:uppercase}
.hrev-lane.design{color:oklch(from #8b6fe8 min(l, var(--ink-l)) c h)}
.hrev-lane.anim{color:oklch(from #29bc9b min(l, var(--ink-l)) c h)}
.hrev-lane.hand{color:oklch(from var(--st-qa) min(l, var(--ink-l)) c h)}
.hrev-t{flex:1;min-width:0;font-size:12.5px;color:var(--txt);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.hrev-scene{flex:none;font-size:11px;color:var(--txt-3);font-family:"Geist Mono",monospace}
.hrev-l{display:inline-flex;align-items:center;gap:6px;flex:none;max-width:170px;
  font-size:11px;color:var(--txt-3)}
.hrev-l .lico{width:14px;height:14px;font-size:7px}
.hrev-w{flex:none;width:86px;text-align:right;font-size:11px;color:var(--txt-3);
  font-family:"Geist Mono",monospace}
.hrev-w{font-variant-numeric:tabular-nums}
.hrev-more{margin:9px 2px 0;font-size:11.5px;color:var(--txt-3)}

/* The launch's own schedule — the Gantt's marks, evenly spaced. See Steps in
   Overview.jsx for why this is a stepper and not a scaled rail. */
.ovs-note{font-size:11px;font-weight:500}
/* The way into the editor from the launch's own page. It is the section-action
   pill (`.zone-cta`) rather than the chart's bare icon: on a row of twenty
   bars the icon has a row to belong to, and here it would be an 18px mark
   floating in the margin above a stepper, aligned with nothing. */
.overview-sub-h.ovs-h{display:flex;align-items:center;gap:6px}
.ovs-edit{font-size:11.5px;letter-spacing:0;text-transform:none;padding:4px 9px}
.ovs-edit svg{opacity:.75}
.ovs-edit.open{border-color:var(--line-hi);color:var(--txt);background:var(--bg-elev2)}
.ovs-edit.open svg{opacity:1}
/* ---------- the schedule on its own scale (Timeline, Overview.jsx) ----------
   Marks where their dates are; labels in lanes so none touch; today a line
   with the word above it; the overdue stretch red; undated marks listed
   under the rail rather than drawn somewhere invented. */
.ovs-next{margin-left:4px;text-transform:none;letter-spacing:0;font-weight:500;color:var(--txt-3)}
.ovs-next b{color:var(--txt-2);font-weight:600}
.tl{position:relative;margin:4px 0 0}
.tl-rail,.tl-past,.tl-over{position:absolute;top:30px;height:2px;border-radius:2px}
.tl-rail{background:var(--line)}
.tl-past{background:color-mix(in srgb,var(--tint) 32%,transparent)}
.tl-over{background:color-mix(in srgb,var(--st-blocked) 80%,transparent);height:3px;top:29.5px}
.tl-today{position:absolute;top:0;transform:translateX(-50%);font-size:9.5px;font-weight:700;
  letter-spacing:.08em;text-transform:uppercase;color:var(--txt-2);white-space:nowrap}
.tl-today::after{content:"";position:absolute;left:50%;top:16px;width:1px;height:24px;
  background:color-mix(in srgb,var(--tint) 55%,transparent);transform:translateX(-.5px)}
.tl-node{position:absolute;top:31px;z-index:1;display:grid;place-items:center;width:20px;height:20px;
  border-radius:50%;background:var(--bg-elev);transform:translate(-50%,-50%)}
.tl-node .gt-ms{position:static;margin:0;transform:none}
.tl-node .gt-ms.diamond{transform:rotate(45deg)}
.tl-m.next .tl-node{box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 30%,transparent)}
.tl-stem{position:absolute;top:40px;width:1px;background:var(--line-hi);transform:translateX(-.5px)}
.tl-label{position:absolute;display:flex;flex-direction:column;align-items:center;gap:2px;
  white-space:nowrap;text-align:center;cursor:default}
.tl-label.l{align-items:flex-start;text-align:left}
.tl-label.r{align-items:flex-end;text-align:right}
.tl-label b{font-size:12px;font-weight:600;letter-spacing:-.01em;color:var(--txt-2)}
.tl-label span{font-family:"Geist Mono",monospace;font-size:10.5px;color:var(--txt-3)}
.tl-m.done .tl-label b{color:var(--txt-3)}
.tl-m.next .tl-label b{color:var(--lit)}
.tl-m.next .tl-label span{color:var(--accent)}
.tl-undated{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:6px 0 0;
  font-size:11.5px;color:var(--txt-3)}

/* ---------- Jam: blocks ----------
 *
 * **The design team is being asked to think in chunks, so the board puts the
 * chunk above the scene.** A change that covers a run of scenes is not about
 * any one of them — it is about the run — so each lane gets a *band* whose
 * only job is holding bars that span columns, and reading down a column you
 * get "what is true of this chunk" before "what is true of this scene".
 *
 * The band is not always there. Nothing to span, no band; selecting scenes
 * raises the design band with the bar you are about to write already in it,
 * and a block in mid-drag raises every other lane's so there is somewhere to
 * drop it. The board changing height is the point, not the cost.
 */
.jband{position:relative;padding:7px 0;border-bottom:1px solid var(--line-soft);
  background:color-mix(in srgb,var(--tint) 2.2%,transparent);min-height:44px}
.jband.buffer{background:var(--well)}
.jband.over{background:color-mix(in srgb,var(--accent) 8%,transparent);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--accent) 35%,transparent)}
/* the inner grid repeats the outer column width with no gap, so a bar over
   scenes 3–5 is exactly as wide as scenes 3–5 — pixel maths would drift the
   first time anybody changes the column width */
.jband-in{display:grid;align-items:start;row-gap:5px}
/* the lane's label spans its band and its cells: one lane, one name */
.jgrid-k.tall{border-bottom:1px solid var(--line)}

.jbar{min-width:0;padding:0 9px}
.jbar.cont{display:flex;align-items:center}

/**
 * **A block bar is one line.**
 *
 * Every bar was the full stacked chip — title row, span, status pill, meta,
 * step bar — about eighty pixels each, and five changes shared across a run
 * of scenes made the band taller than the lane under it. A bar is at least
 * two columns wide by definition, so there is nowhere near enough vertical
 * pressure to justify stacking what fits side by side in five hundred
 * pixels. The detail was never the bar's job: it says which scenes, what
 * state, how far, and the ticket says the rest.
 */
/**
 * **Two lines, and the second one is the detail.**
 *
 * One line was right until a *scattered* span turned up: its lead segment
 * can be a single column, 248px, and the title, the owner, the numbers, the
 * status and the step bar do not fit in that. The title lost, which is the
 * one thing that cannot — the bar read as an avatar followed by a list of
 * numbers with no indication of what the change was.
 *
 * So **title and status on the first line**, the status hard right so it is
 * in the same place on every bar however long the title runs, and the scene
 * numbers, the attachments and the step bar underneath. The steps flex
 * rather than taking a fixed width, so they squeeze instead of pushing the
 * numbers off the end.
 */
.jband .jchg{flex-direction:row;flex-wrap:wrap;align-items:center;gap:2px 8px;padding:5px 8px}
/* basis 0, not auto: the title shrinks to whatever is left once the status
   has its place, instead of claiming its natural width and pushing the
   status onto a line of its own on a one-column segment */
.jband .jchg-r{order:0;flex:1 1 0;min-width:0;gap:7px}
.jband .jchg-st{order:1;flex:none;align-self:center;margin-left:auto}
.jband .jchg-f{order:2;display:flex;align-items:center;gap:9px;flex:1 1 100%;min-width:0}
.jband .jchg-span{flex:none;margin-top:0}
.jband .jchg-span b{font-family:"Geist Mono",monospace;font-size:10px;letter-spacing:.02em;
  color:var(--txt-2)}
.jband .jchg-m{flex:none}
.jband .jchg .ksubbar{flex:1 1 56px;min-width:40px;margin-top:0}

/**
 * **A carried-across segment is the same chip, faded.**
 *
 * It was the words `· same change ·` over a rule, then a stripped-down
 * ghost carrying only the title, and both made one change read as several
 * things — because the segments did not look like each other. They are the
 * same ticket, so they are the same chip.
 *
 * What makes it obviously not a second ticket is **value and saturation,
 * not shape**: a third of the strength, and `saturate(.25)` so the status
 * pills stop competing with the live ones beside them. Opacity alone left
 * a row of soft coloured pills that still read as things to act on; the
 * colour is what was doing that, so the colour is what goes. Dashed rather
 * than solid, and it comes up on hover because it is still the way into
 * the change.
 */
.jchg.ghosted{opacity:.34;border-style:dashed;background:none;
  filter:saturate(.25);transition:opacity .14s,filter .14s}
.jchg.ghosted:hover{opacity:.8;filter:saturate(.7);border-color:var(--line-hi)}
.jchg.ghosted .jchg-st{cursor:default}
.jchg-el{flex:none;display:grid;place-items:center;color:var(--txt-3)}


/* what the change is about to become, drawn where it will land */
.jbar.ghost{pointer-events:none}
.jbar.ghost .jghost{pointer-events:auto}
.jghost{display:flex;align-items:center;gap:8px;padding:6px 9px;border-radius:9px;
  border:1px dashed color-mix(in srgb,var(--accent) 60%,transparent);
  background:color-mix(in srgb,var(--accent) 9%,transparent);animation:jghost-p 2s ease-in-out infinite}
.jghost b{font-size:11px;font-weight:600;color:var(--lit);white-space:nowrap}
.jghost-go,.jghost-m{font-size:11px;white-space:nowrap;border-radius:6px;padding:3px 9px}
.jghost-go{background:var(--accent);color:#fff;font-weight:500}
.jghost-go:hover{filter:brightness(1.12)}
.jghost-m{border:1px solid var(--line-hi);color:var(--txt-2)}
.jghost-m:hover{border-color:var(--lit);color:var(--lit)}
.jghost-x{margin-left:auto;width:18px;height:18px;border-radius:50%;display:grid;place-items:center;
  font-size:13px;line-height:1;color:var(--txt-3)}
.jghost-x:hover{background:color-mix(in srgb,var(--tint) 10%,transparent);color:var(--lit)}
/* the same whisper the Gantt's pending plan uses: opacity only, because this
   is a board people read while it is on screen */
@keyframes jghost-p{0%,100%{opacity:1}50%{opacity:.74}}

/* Selecting is how a block gets written, so the scene name is the control. */
.jscene-n{font-size:12.5px;font-weight:600;letter-spacing:-.01em;border-radius:6px;padding:2px 6px;
  margin-left:-6px;color:inherit;transition:background .12s,color .12s,box-shadow .12s}
.jscene-n:hover{background:color-mix(in srgb,var(--tint) 7%,transparent);color:var(--lit)}
.jscene-n.picked{background:color-mix(in srgb,var(--accent) 24%,transparent);color:var(--lit);
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--accent) 60%,transparent)}

/* Width answers "which scenes" at a glance and nothing once you are reading
   the chip — and on the animation side it is a lie by omission, since what
   you hold is one part of something somebody wrote wider. */
.jchg-span{display:flex;align-items:center;gap:6px;margin-top:1px}
.jchg-span b{font-size:9.5px;font-weight:600;letter-spacing:.03em;color:var(--txt-3)}
.jchg-of{font-size:9px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;
  color:var(--accent);border:1px solid color-mix(in srgb,var(--accent) 36%,transparent);
  background:color-mix(in srgb,var(--accent) 12%,transparent);border-radius:5px;padding:1px 5px}
.jchg-of:hover{border-color:var(--accent);color:#fff;background:var(--accent)}

/* The split, asked before it happens: a board that turns one chip into three
   without saying so reads as a bug the first time and as untrustworthy after. */
.jask{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:81;width:min(480px,92vw);
  background:var(--bg-elev);border:1px solid var(--line);border-radius:14px;overflow:hidden;
  box-shadow:0 24px 70px rgb(0 0 0/calc(.6*var(--shade)))}
.jask-b{padding:16px 18px}
.jask-l{margin:0 0 14px;font-size:12.5px;line-height:1.6;color:var(--txt-2)}
.jask-l b{color:var(--txt);font-weight:600}
.jask-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:1px;
  border:1px solid var(--line);border-radius:10px;overflow:hidden;background:var(--bg)}
.jask-list li{display:flex;align-items:center;gap:11px;padding:9px 12px;background:var(--bg-elev2)}
.jask-n{flex:none;width:19px;height:19px;border-radius:6px;display:grid;place-items:center;
  font-family:"Geist Mono",monospace;font-size:10.5px;color:var(--txt-2);
  background:color-mix(in srgb,var(--tint) 5%,transparent);box-shadow:inset 0 0 0 1px var(--line)}
.jask-t{display:flex;flex-direction:column;gap:2px;min-width:0}
.jask-t b{font-size:12.5px;font-weight:600;color:var(--txt)}
.jask-t em{font-style:normal;font-family:"Geist Mono",monospace;font-size:10.5px;color:var(--txt-3);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.jask-go{display:flex;align-items:center;gap:11px;width:100%;text-align:left}
.jask-go:hover{color:var(--lit)}
.jask-go:hover .jask-t b{color:var(--lit)}
.jask-st{margin-left:auto;flex:none;font-size:10.5px;font-weight:600;white-space:nowrap}
.jask-list li.on{background:color-mix(in srgb,var(--accent) 12%,var(--bg-elev2))}
.jask-tick{flex:none;width:17px;height:17px;border-radius:5px;display:grid;place-items:center;
  font-size:10px;color:transparent;box-shadow:inset 0 0 0 1px var(--line-hi)}
.jask-tick.on{background:var(--accent);color:#fff;box-shadow:inset 0 0 0 1px var(--accent)}

/**
 * **A preview has to look unbuilt, not merely tinted.**
 *
 * The first pass reused the change chip's own parts — the title row, the
 * "1 of 3" pill — under a dashed border, and at a glance it read as a fourth
 * real change somebody had already filed. A tint is not a difference in
 * kind, and this is a difference in kind: none of it exists yet.
 *
 * So it is not a chip. It has no fill, no owner, no status pill and no step
 * bar — everything a chip carries *because work is happening* — and the line
 * that would have held them says **Lands here** instead. What is left reads
 * as a space held open in the list rather than as something in it, which is
 * exactly what it is.
 */
.jprev{display:flex;flex-direction:column;gap:4px;padding:8px 9px;border-radius:9px;
  border:1px dashed color-mix(in srgb,var(--accent) 50%,transparent);background:none;
  animation:jghost-p 2s ease-in-out infinite;pointer-events:none}
.jprev-h{display:flex;align-items:center;gap:5px;font-size:9px;font-weight:700;letter-spacing:.09em;
  text-transform:uppercase;color:var(--accent)}
.jprev-h svg{flex:none}
.jprev-h i{font-style:normal;letter-spacing:.06em;color:color-mix(in srgb,var(--accent) 66%,#8a8a94)}
.jprev-t{font-size:12px;line-height:1.35;color:var(--txt-2);overflow:hidden;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.jprev-m{font-family:"Geist Mono",monospace;font-size:9.5px;color:var(--txt-3);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* the lane under the cursor is the one being aimed at, so its outline firms
   up and stops breathing — you are no longer being told where it could go */
.jlane.over .jprev{border-color:var(--accent);animation:none;opacity:1;
  background:color-mix(in srgb,var(--accent) 7%,transparent)}

/**
 * **A block's ticket opens on a roster of its scenes.**
 *
 * It said "Scene 7" — the scene the record happens to be stored on — which
 * is true of the data and a lie about the work: one change over four scenes,
 * and the ticket named one of them. The roster is grouped by **Aspect file**
 * because that is the grouping the work divides on, so it doubles as the
 * answer to "what happens at the hand-off" without saying it twice.
 */
.tsec-n{margin-left:auto;font-size:10.5px;font-weight:500;letter-spacing:0;text-transform:none;
  color:var(--txt-3);font-family:"Geist Mono",monospace}
.tscn{display:flex;flex-direction:column;gap:1px;border:1px solid var(--line);border-radius:10px;
  overflow:hidden;background:var(--bg)}
.tscn-g{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:10px 14px;align-items:center;
  padding:9px 12px;background:var(--bg-elev2)}
.tscn-f{display:inline-flex;align-items:center;gap:7px;min-width:0;font-family:"Geist Mono",monospace;
  font-size:11px;color:var(--txt-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tscn-f:hover{color:var(--txt-2)}
.tscn-f svg,.tscn-f img,.tscn-f span{flex:none}
.tscn-l{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:5px;min-width:0}
/* a scene is a chip, the same object the roster on Team uses — a person and
   a scene are both "one of the things this covers" */
.tscn-s{display:inline-flex;align-items:baseline;gap:6px;padding:3px 9px;border-radius:20px;
  border:1px solid var(--line);background:var(--bg-elev)}
.tscn-s b{font-size:11.5px;font-weight:500;color:var(--txt);white-space:nowrap}
.tscn-s em{font-style:normal;font-family:"Geist Mono",monospace;font-size:10px;color:var(--txt-3)}
/* the scene the record is stored on — worth marking, not worth shouting */
.tscn-s.here{border-color:color-mix(in srgb,var(--accent) 45%,transparent);
  background:color-mix(in srgb,var(--accent) 10%,transparent)}
.tscn-note{margin:9px 0 0;font-size:11.5px;line-height:1.55;color:var(--txt-3)}
.tscn-note b{color:var(--txt-2);font-weight:600}

/* ---------- the production sheet: All launches, advanced ----------
 *
 * **The one place in this app that colours a whole cell.** Everywhere else a
 * status is a dot and a word (`.lstat`), because colour on its own makes
 * eight statuses the same shape. A sheet is different: it is a *scanning*
 * surface fourteen columns wide, read by running down a column looking for
 * the one that is the wrong colour, and the people who use it already read
 * it that way in Google Sheets. Matching that is not a lapse, it is the
 * idiom of the thing being ported.
 */
.pjtbl.adv{min-width:1680px}
.pjtbl.adv td,.pjtbl.adv th{white-space:nowrap}
/* **No padding override.** This used to shave a pixel off every row to fit
   more of them in, which also hit the band and group heads — a pod
   separator went from 27px to 37px and the two views stopped looking like
   one table. The switch changes which columns you see; nothing else. */

.pjpill{display:inline-block;max-width:100%;padding:3px 10px;border-radius:20px;
  font-size:11px;font-weight:600;letter-spacing:-.01em;line-height:1.45;
  color:oklch(from var(--t) var(--pj-l) calc(c * var(--pj-c)) h);
  background:color-mix(in srgb,var(--t) var(--pj-t),var(--pj-k));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.14);
  overflow:hidden;text-overflow:ellipsis}
/* Expected stage is context, not a verdict — it only earns full strength
   when it disagrees with the stage the launch is actually at. Lit on every
   row it would be fourteen columns of solid colour and nothing to scan for. */
.pjpill.soft{background:none;color:var(--txt-3);font-weight:500;
  box-shadow:inset 0 0 0 1px var(--line)}

.pj-who{display:inline-flex;align-items:center;gap:7px;font-size:12px;color:var(--txt-2);
  white-space:nowrap}
.pj-num{font-family:"Geist Mono",monospace;font-size:11.5px;color:var(--txt-2)}
/* **Quiet until you reach for them.** Sixty rows of accent-blue "Checklist"
   was the brightest thing on the page attached to the least important
   column; grey marks say a document is there without competing with the
   status pills that are the reason to open this view. */
.pj-docs{display:flex;align-items:center;gap:4px}
.pj-docs a{display:grid;place-items:center;width:24px;height:24px;border-radius:6px;
  color:var(--txt-3);transition:color .12s,background .12s}
.pj-docs a:hover{color:var(--accent);background:color-mix(in srgb,var(--accent) 13%,transparent)}
/* the slot is held on rows with no call, or the checklist mark shifts left
   and the column stops reading as a column */
.pj-docs-gap{width:24px;height:24px}

/* A sheet cell you can type into. It looks like a table until you reach for
   it — an outline on every cell would turn a scanning surface into a form. */
/* the cap is the column plus the 6px the negative margins hand back: at a
   plain 100% it resolved against a wrapper already sized to the button minus
   those margins, so every value lost 6px — "Design" read "Desi…" and
   "Nobody booked" broke onto two lines on the Overview */
.pjpick{max-width:calc(100% + 6px);text-align:left;border-radius:6px;padding:1px 3px;margin:-1px -3px}
.pjpick:hover,.pjpick.open{background:color-mix(in srgb,var(--tint) 6%,transparent);box-shadow:inset 0 0 0 1px var(--line-hi)}
.pjcell{display:inline-flex;align-items:center;max-width:100%}
.pjcell-in{border-radius:6px;padding:2px 5px;margin:-2px -5px;outline:none;min-width:34px;
  font-family:"Geist Mono",monospace;font-size:11.5px;color:var(--txt-2)}
.pjcell-in:hover{background:color-mix(in srgb,var(--tint) 6%,transparent);box-shadow:inset 0 0 0 1px var(--line-hi)}
.pjcell-in:focus{background:var(--bg-elev2);box-shadow:inset 0 0 0 1px var(--accent);color:var(--txt)}
.pjcell-in:empty::before{content:attr(data-ph);color:var(--txt-3);pointer-events:none}
/* a name, not a number: typed text takes the page's type, not the budget's mono */
.pjcell-in.txt{font-family:inherit;font-size:12.5px;color:var(--txt)}
.pjcell-in:empty:focus::before{opacity:.55}
/* **A typed value stops tracking what it was derived from**, so it says so.
   A field that silently stopped following its rule is the worst kind of
   stale — the dotted rule is the whole marking, and the menu carries the ↺. */
.pjcell.set,.pjpick.set .pjcell{text-decoration:underline dotted
  color-mix(in srgb,var(--accent) 70%,transparent);text-underline-offset:4px}

/* ---------- the launch sheet, on one launch's Overview ----------
 *
 * Every field the All-launches advanced table carries, grouped by **who asks
 * the question** rather than by the sheet's column order: ownership is who
 * to chase, schedule is where it is against where it should be, the shoot is
 * the one part with other people's calendars in it, links are the two
 * documents everything starts from. Column order in the real sheet is an
 * artefact of whoever added a column last, and nobody reads it left to right.
 */
/* label over value, not beside it: a label column wide enough for
   "Pre-launch checklist" leaves a hole beside every short one */
.ovf-k{font-size:10px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;color:var(--txt-3)}
.ovf-num{font-family:"Geist Mono",monospace;font-size:12px;color:var(--txt);
  display:inline-flex;align-items:baseline;gap:7px}
/* how far off the shoot is, in the weight the Overview stepper uses for the
   same fact — a date you cannot subtract from today in your head */
.ovf-in{font-style:normal;font-size:10.5px;color:var(--txt-3)}
.ovf-link{font-family:"Geist Mono",monospace;font-size:11px;color:var(--accent);
  min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  border-bottom:1px solid transparent}
.ovf-link:hover{border-bottom-color:currentColor}
/* the one sentence the pair of stages exists to produce */
.overview-sub-h .pjpill{margin-left:auto}

/* **Stage leads the launch sheet** — it is the only fact on that panel the
   schedule does not already hold, and the one you set. Everything under it
   is context for chasing somebody; this is the status. */
.swatch{width:14px;height:14px;border-radius:4px;flex:none}
/* the two owners, one to a line on the Overview, side by side in the table */
.ovowners{display:flex;flex-direction:column;align-items:flex-start;gap:4px}
.pjowners{display:inline-flex;align-items:center;gap:12px;white-space:nowrap}
.pjowners .pj-who{gap:6px}
/* the danger zone is the card's last line: said once, quietly, then the button */
.ovdanger{display:flex;align-items:center;gap:24px}
.ovdanger-t{min-width:0}
.ovdanger-t .ovf-k{color:oklch(from #f75f8f min(l, var(--ink-l)) c h)}
.ovdanger-t p{margin:5px 0 0;max-width:64ch;font-size:11.5px;line-height:1.5;color:var(--txt-3)}
.ovdanger-b{flex:none;margin-left:auto;padding:8px 14px;border-radius:8px;border:1px solid rgba(247,95,122,.4);
  background:rgba(247,95,122,.08);color:oklch(from #f75f8f min(l, var(--ink-l)) c h);font-size:12.5px;font-weight:600}
.ovdanger-b:hover{background:rgba(247,95,122,.16)}

/* ---------- the projects table is a grid in both views ----------
 *
 * Three things were wrong at thirteen columns and they compounded:
 * `.tblwrap` is `overflow:hidden`, so a 1680px table was **clipped** with no
 * scrollbar at all; the pills truncated to "G…" and "Confir…", which is a
 * coloured chip with the meaning taken out; and the table is sixty rows
 * long, so even with a scrollbar the horizontal bar would sit a screen and
 * a half below the rows being read.
 *
 * The fix is the Gantt's: a **grid that scrolls inside itself** — capped
 * height, sticky header, sticky first column, sticky band heads, and the
 * horizontal scrollbar at the bottom of the viewport rather than the bottom
 * of the data.
 *
 * **Both views get it, not just the wide one.** Sticky needs a scrollport,
 * and while `.tblwrap` was `overflow:hidden` in Normal there was nothing
 * for a band head to stick to — so making only the advanced view behave
 * would have been the two views drifting apart again, one row after being
 * brought back together. The switch changes which columns you see. That is
 * now the only thing it changes.
 */
.pjwrap .tblwrap{overflow:auto;max-height:calc(100vh - 230px);overscroll-behavior:contain}
/* **The directory is the page, so the table takes the page's height** — the
   Gantt's rule (`gttmode`). A capped `calc(100vh - 230px)` guessed at the
   chrome around it, reserved room for a footer that has since gone, and sat
   on the content's 60px of bottom padding besides, so the table stopped a
   hand's width above the window with nothing under it. In `pjmode` the page
   does not scroll: the toolbar and the heading keep their height, the table
   takes what is left and scrolls inside itself, and a short one still ends
   where its last row does. */
.content.pjmode{overflow:hidden;display:flex;flex-direction:column;padding-bottom:18px}
.content.pjmode .pjwrap{flex:1;min-height:0;display:flex;flex-direction:column}
.content.pjmode .pjwrap > *{flex:none}
.content.pjmode .pjwrap > .tblwrap{flex:0 1 auto;min-height:0;max-height:none}
.pjwrap .tblwrap::-webkit-scrollbar{height:11px;width:11px}
.pjwrap .tblwrap::-webkit-scrollbar-thumb{background:var(--line-hi);border-radius:6px;
  border:2px solid var(--bg-elev)}
.pjwrap .tblwrap::-webkit-scrollbar-thumb:hover{background:#4d4d59}
.pjwrap .tblwrap::-webkit-scrollbar-track{background:var(--bg-elev)}
.pjwrap .tblwrap::-webkit-scrollbar-corner{background:var(--bg-elev)}

/* the header follows you down.
   **One stacking order for everything that sticks**: the header (5, its
   first cell 6) over the pod band (4) over the pinned launch-name column (2)
   over the rest. The band and the name column were both 2, and at a tie the
   later element paints on top — so each row's name cell, scrolling up under
   the pinned band, painted over it and covered its label, and what stuck at
   the top of the table was a black box with some launch's name in it. */
.pjwrap .tblwrap .pjtbl thead th{position:sticky;top:0;z-index:5}

/**
 * **The pod head follows you down too**, parked directly under the column
 * header. Sixty rows in a capped scrollport means the band that says which
 * pod you are reading is off screen for most of the time you spend reading
 * it, which is the same complaint as losing the launch name when you scroll
 * across — you end up with a screen of values and nothing saying whose.
 *
 * `top` is the header's own height. The two grouping levels do **not** both
 * stick: `.pj-grp` (Ongoing / Not ongoing) is a divider you cross twice in
 * the whole table, and a second pinned bar would cost a row of height all
 * the way down to save a glance nobody needs.
 */
.pjwrap .tblwrap .pjtbl .pj-band td{position:sticky;top:30px;z-index:4}

/* **and the launch name follows you across** — scrolled right without it you
   are reading a row of values with no idea whose they are, which is the
   thing that makes a wide table useless rather than merely wide */
.pjwrap .tblwrap .pjtbl tbody tr.clk td:first-child,
.pjwrap .tblwrap .pjtbl thead th:first-child{position:sticky;left:0;z-index:2;
  background-color:var(--bg)}
.pjtbl.adv tbody tr.clk td:first-child,
.pjtbl.adv thead th:first-child{box-shadow:1px 0 0 var(--line)}
.pjwrap .tblwrap .pjtbl thead th:first-child{z-index:6;background-color:var(--bg-elev2)}
/* hover has to composite over the sticky cell's own ground rather than
   replace it, or the name column stops being opaque exactly when you point
   at it */
.pjwrap .tblwrap .pjtbl tbody tr.clk:hover td:first-child{
  background-image:linear-gradient(var(--hover),var(--hover))}

/* **The band label follows you across as well.** The cell still spans every
   column — it is the *content* that sticks, so the band's ground stays
   unbroken behind it. */
.pjwrap .tblwrap .pj-grp .pj-pin,
.pjwrap .tblwrap .pj-band button{position:sticky;left:12px;display:inline-flex;align-items:center;
  /* **`width:auto` is load-bearing.** The band button is `width:100%` of a
     cell spanning every column, and a sticky element already as wide as its
     containing block has no slack to shift within — it sat 102px off the
     left edge and the pod label was simply gone the moment you scrolled
     across. Shrink it to its content and sticky has somewhere to go. */
  width:auto}

/* **A pill never truncates.** These are one or two words — "Good", "No crew",
   "Confirmed" — and a chip reading "G…" is a colour with the meaning removed,
   which is precisely the failure the dot-plus-word rule exists to prevent
   everywhere else in the app. The column takes the width the word needs. */
.pjtbl.adv .pjpill{max-width:none;overflow:visible;text-overflow:clip}

/* **The band label follows you across too.** The launch name being pinned is
   no use if you have scrolled past the heading that says which pod you are
   looking at. The cell still spans every column — it is the *content* that
   sticks, so the band's ground stays unbroken behind it. */

/* ---------- live: who is on the board, and what they have open ----------
   Everybody signed in has a colour of their own (lib/live.js hands them out
   from presence, one per person, every tab of theirs alike), and the
   colour is identity, not state. That is why it is an outline and a
   name tag round a chip and never the chip's fill: the fill and the status
   pill already say what state the work is in, and a second meaning on the
   same surface would be two colours arguing. */
.guest{display:inline-grid;place-items:center;flex:none;border-radius:50%;background:var(--pc);
  color:#0a0a0a;font-weight:700;line-height:1;letter-spacing:0;box-shadow:0 0 0 2px var(--bg-elev)}

/* the pill: as small as it can be and still say who. Glass over the board
   rather than a solid slab, so the corner of the last scene is still there
   under it; the lit top edge is the one the enclosed tracks (.seg) wear. */
/* on the board the pill is a corner notch, like the zoom below it: flush
   with the top and right edges, rounded only on the corner facing the board
   (the Kanban's inline pill keeps its own shape) */
.jwho{position:absolute;top:0;right:0;z-index:4;display:flex;align-items:center;gap:7px;
  height:40px;padding:0 8px 0 13px;border-radius:0 0 0 14px;cursor:default;
  background:color-mix(in srgb,var(--glass) 84%,transparent);-webkit-backdrop-filter:blur(10px) saturate(1.3);backdrop-filter:blur(10px) saturate(1.3);
  border:1px solid color-mix(in srgb,var(--tint) 8%,transparent);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.06),0 8px 24px rgb(0 0 0/calc(.45*var(--shade)))}
/* the board is live: one dot, and a ring leaving it slowly — the socket is a
   thing happening now, which is what motion is kept for here */
.jwho-live{position:relative;flex:none;width:6px;height:6px;border-radius:50%;background:var(--live);
  box-shadow:0 0 6px color-mix(in srgb,var(--live) 65%,transparent)}
.jwho-live::after{content:'';position:absolute;inset:0;border-radius:50%;border:1px solid var(--live);
  animation:jlive 2.8s ease-out infinite}
@keyframes jlive{0%{transform:scale(1);opacity:.7}70%,100%{transform:scale(2.7);opacity:0}}
.jwho-av{display:flex;align-items:center}
.jwho-p{position:relative;display:grid;border-radius:50%;padding:0;transition:transform .14s cubic-bezier(.2,.8,.3,1)}
.jwho-av > * + *{margin-left:-6px}
.jwho-p .guest{box-shadow:0 0 0 2px var(--raise)}
/* somebody arriving pops into the stack; `backwards` so the pop lets go of
   the transform afterwards and the hover lift still works */
.jwho-av .jwho-p{animation:jwho-in .32s cubic-bezier(.2,.8,.3,1.3) backwards}
@keyframes jwho-in{from{transform:scale(.4);opacity:0}}
button.jwho-p:not(:disabled){cursor:pointer}
button.jwho-p:not(:disabled):hover{transform:translateY(-2px)}
button.jwho-p:disabled{cursor:default}
.jwho-av .jwho-p:hover{z-index:1}
.jwho-more{display:grid;place-items:center;width:22px;height:22px;border-radius:50%;flex:none;
  background:color-mix(in srgb,var(--line-hi) 68%,var(--bg));color:#a1a1a1;font-size:9.5px;font-weight:700;box-shadow:0 0 0 2px var(--raise)}
.jwho-sep{width:1px;height:14px;background:color-mix(in srgb,var(--tint) 10%,transparent);flex:none}
/* you: a ring in your own colour, drawn inside the pill's padding */
.jwho-p.you .guest{box-shadow:0 0 0 2px var(--raise),0 0 0 3.5px color-mix(in srgb,var(--pc) 80%,transparent)}
@media (prefers-reduced-motion:reduce){.jwho-live::after,.jwho-av .jwho-p{animation:none}}

/* everybody else's pointer. The arrow is their colour with a dark keyline so
   it holds on the pale chips and the black ground alike; the name tab hangs
   off the tip the way Figma's does, square corner to the arrow. A move is
   eased over less time than the next message takes to arrive, so it glides
   without trailing. */
.jcursors{position:absolute;left:0;top:0;width:0;height:0;z-index:60;pointer-events:none}
/* the glide lasts a little longer than cursor messages take to arrive, so a
   moving cursor never stops between two of them; JamView sets the pace off
   the send rate (`--cursor-ease`), and 80ms is the old socket's */
.jcur{position:absolute;left:0;top:0;transform-origin:0 0;transition:transform var(--cursor-ease,80ms) linear,opacity .5s}
.jcur-a{display:block;margin:-1.5px 0 0 -1.5px;filter:drop-shadow(0 1px 2px rgba(0,0,0,.55))}
.jcur-a path{fill:var(--pc);stroke:#0a0a0a;stroke-width:1.1;stroke-linejoin:round}
.jcur-n{position:absolute;left:12px;top:15px;display:inline-flex;align-items:center;gap:5px;
  background:var(--pc);color:#0a0a0a;font-size:11px;font-weight:600;
  line-height:1;padding:3px 7px 3px 3px;border-radius:2px 9px 9px 9px;white-space:nowrap;box-shadow:0 3px 10px rgb(0 0 0/calc(.35*var(--shade)))}
/* a face on the live layer: the photo, ringed in the person's colour */
.face{display:inline-grid;place-items:center;flex:none;border-radius:50%;box-shadow:0 0 0 1.5px var(--pc)}
.face .avatar{display:block}
.jcur-n .face{box-shadow:0 0 0 1px rgba(0,0,0,.35)}
.jcur-n.says b{display:inline-flex;align-items:center;gap:5px}
.jcur.idle{opacity:.38}

.jchg{position:relative}
.jchg.seen{border-color:var(--pc)}
/* the glow breathes on opacity alone, so the compositor carries it and a pan
   across a board with several open changes costs what it did before */
.jchg-ring{position:absolute;inset:-1px;border-radius:8px;pointer-events:none;
  box-shadow:0 0 0 1px var(--pc),0 0 0 4px color-mix(in srgb,var(--pc) 20%,transparent),
    0 0 22px 2px color-mix(in srgb,var(--pc) 38%,transparent);
  animation:jseen 2.6s ease-in-out infinite}
@keyframes jseen{0%,100%{opacity:1}50%{opacity:.45}}
/* the name sits on the top edge, straddling it — in the band's padding or
   the lane's gap, never over the chip's own title */
.jchg-who{position:absolute;top:-8px;right:10px;z-index:1;pointer-events:none;display:inline-flex;align-items:center;gap:4px;
  background:var(--pc);color:#0a0a0a;font-size:9px;font-weight:700;line-height:1;
  padding:2px 6px 2px 2px;border-radius:4px;white-space:nowrap;max-width:calc(100% - 20px);
  overflow:hidden;text-overflow:ellipsis;box-shadow:0 2px 8px rgb(0 0 0/calc(.45*var(--shade)))}
.jchg-flash{position:absolute;inset:-1px;border-radius:8px;pointer-events:none;
  background:color-mix(in srgb,var(--fc) 16%,transparent);box-shadow:0 0 0 1.5px var(--fc);
  animation:jflash 1.8s ease-out forwards}
@keyframes jflash{0%{opacity:0}10%{opacity:1}100%{opacity:0}}
@media (prefers-reduced-motion:reduce){
  .jchg-ring{animation:none}
  .jchg-flash{animation:none;opacity:.8}
}
/* above the Jam toolbar rather than on top of it */
.tv-toast.jtoast{bottom:98px;max-width:min(560px,86vw);text-align:center}

.ticket-here{display:inline-flex;align-items:center;gap:7px;font-size:11.5px;color:var(--txt-2);white-space:nowrap}
.ticket-here b{color:var(--txt);font-weight:600}
.ticket-here-av{display:flex}
.ticket-here-av .guest + .guest{margin-left:-5px}

/* ---------- sign in ----------
   One card on the black ground, the width of a form and no wider. Google's
   own button is the only door; the card's other two faces are a server that
   is not set up and a server that did not answer, each saying so in words
   and neither offering a way round. The mockup's door is the same card
   asking for a name (NameCard.jsx), with no Google button on it at all. */
.signin{min-height:100vh;display:grid;place-items:center;padding:24px 16px;background:var(--bg);
  background-image:radial-gradient(ellipse 60% 45% at 50% 0%,color-mix(in srgb,var(--accent) 9%,transparent),transparent 70%)}
.si-card{width:min(380px,100%);display:flex;flex-direction:column;padding:30px 28px 24px;
  background:var(--bg-elev);border:1px solid var(--line);border-radius:14px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.05),0 24px 70px rgba(0,0,0,.55)}
.si-mark{font-weight:600;letter-spacing:-.02em;font-size:15px;color:var(--txt);margin-bottom:26px}
.si-h{font-size:22px;font-weight:600;letter-spacing:-.02em;line-height:1.25;margin:0}
.si-sub{margin:6px 0 22px;font-size:13px;line-height:1.5;color:var(--txt-2)}
.si-notice{margin:-8px 0 16px;padding:8px 11px;border:1px solid var(--line);border-radius:8px;
  background:var(--bg);font-size:12.5px;color:var(--txt-2)}
/* Google draws its button into .si-gbtn, an iframe we cannot style. Until it
   does, a placeholder of the same pill holds its place, so the card does not
   jump when the script arrives — and while signing in the button steps
   aside for the line saying so, since a second click would only start a
   second attempt under the first. */
.si-gwrap{position:relative;min-height:44px;display:flex;align-items:center;justify-content:center}
.si-gbtn{width:100%;min-height:44px;display:flex;align-items:center;justify-content:center}
.si-gwait{position:absolute;inset:2px 0;border-radius:22px;border:1px solid var(--line);
  background:linear-gradient(90deg,var(--bg-elev2),rgba(255,255,255,.06),var(--bg-elev2));background-size:200% 100%;
  animation:si-wait 1.4s linear infinite}
@keyframes si-wait{to{background-position:-200% 0}}
.si-gwrap.busy .si-gbtn{visibility:hidden}
.si-going{position:absolute;inset:0;display:grid;place-items:center;font-size:13px;font-weight:500;color:var(--txt-2)}
.si-note{margin:10px 0 0;text-align:center;font-size:11.5px;color:var(--txt-3)}
.si-note b{color:var(--txt-2);font-weight:600}
/* a refusal reads as one, in the Blocked red, and says why in words */
.si-err{display:flex;align-items:center;flex-wrap:wrap;gap:8px 10px;margin:14px 0 0;padding:9px 11px;border-radius:8px;
  border:1px solid color-mix(in srgb,var(--st-blocked) 45%,transparent);
  background:color-mix(in srgb,var(--st-blocked) 10%,transparent);font-size:12.5px;line-height:1.45;color:var(--txt)}
.si-retry{margin-left:auto;padding:4px 9px;border:1px solid var(--line-hi);border-radius:7px;
  font-size:12px;font-weight:600;color:var(--txt)}
.si-retry:hover{background:var(--hover)}
.si-k{margin:0 0 7px;font-size:12px;font-weight:500;color:var(--txt-2)}
/* the missing settings, by name only — never a value */
.si-missing{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:6px}
.si-missing code{display:inline-block;padding:3px 8px;border:1px solid var(--line);border-radius:6px;background:var(--bg);
  font-family:'Geist Mono',monospace;font-size:12px;color:var(--txt)}
.si-go{height:38px;margin-top:5px;border-radius:8px;background:var(--accent);color:#fff;font-size:13.5px;font-weight:600}
.si-go:hover:not(:disabled){background:#1a7ef5}
.si-go:disabled{opacity:.7;cursor:progress}
.si-fine{margin:16px 0 0;font-size:11.5px;line-height:1.5;color:var(--txt-3)}
.si-fine code{font-family:'Geist Mono',monospace;font-size:11px;color:var(--txt-2)}
/* the mockup's one field, your name. Continue waits for it — not-allowed,
   not the progress cursor the other buttons wear while they try */
.si-name{display:flex;flex-direction:column;gap:7px;margin-bottom:6px}
.si-name .si-k{margin:0}
.si-in{height:38px;padding:0 12px;border-radius:8px;background:var(--bg);border:1px solid var(--line);
  color:var(--txt);font:inherit;font-size:13.5px;outline:none}
.si-in::placeholder{color:var(--txt-3)}
.si-in:focus{border-color:var(--accent);box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 20%,transparent)}
.si-form .si-go:disabled{opacity:.45;cursor:not-allowed}
@media (prefers-reduced-motion:reduce){.si-gwait{animation:none}}


/* cursor chat ("/"): the name tab grows into a speech bubble — same colour,
   same square corner to the arrow, the name shrinking to a caption over the
   line. Yours is an input in the same bubble, following your pointer. */
/* width:max-content, because the arrow it hangs off is zero pixels wide:
   left to shrink-to-fit, the bubble took its narrowest and broke after
   every word */
.jcur-n.says{display:flex;flex-direction:column;gap:3px;padding:6px 10px 8px;border-radius:2px 12px 12px 12px;
  width:max-content;max-width:260px;white-space:normal;transition:opacity .9s ease}
.jcur-n.says b{font-size:9.5px;font-weight:700;opacity:.62}
.jcur-t{font-size:13px;font-weight:500;line-height:1.3;overflow-wrap:anywhere}
.jcur-n.fading{opacity:0}
.jchat{position:absolute;left:0;top:0;z-index:6;padding:6px 10px;border-radius:2px 12px 12px 12px;
  background:var(--pc);box-shadow:0 6px 20px rgb(0 0 0/calc(.45*var(--shade)));animation:jchat-in .16s cubic-bezier(.2,.8,.3,1.2)}
@keyframes jchat-in{from{opacity:0;scale:.85}}
.jchat-in{background:none;border:none;outline:none;padding:0;color:#0a0a0a;font:inherit;font-size:13px;font-weight:500;
  max-width:280px}
.jchat-in::placeholder{color:rgba(10,10,10,.5)}
@media (prefers-reduced-motion:reduce){.jchat{animation:none}}

/* ---------- undecided: no dates anybody agreed to ----------
   The warning yellow is the sheet's own Warning flag, so a launch with no
   plan reads the same wherever it says so. A guessed milestone keeps its
   place in the order — it still says what comes next — but its node goes
   hollow and dashed, the silhouette of a date that has not been set. */
.undecided{display:inline-flex;align-items:center;gap:5px;color:oklch(from var(--warn) min(l, var(--ink-l)) c h);font-size:11.5px;font-weight:600;
  white-space:nowrap;letter-spacing:0;text-transform:none}
.undecided svg{flex:none}
.overview-sub-h .undecided{margin-left:10px}

/* ---------- the Kanban, live and draggable ----------
   The glow, name tag and flash are the Jam chip's own (.jchg-ring and
   friends) — the same fact gets the same mark on every board. */
.ktop{display:flex;align-items:flex-start;gap:10px;width:100%;flex:none}
.ktop .tbar{flex:1;min-width:0}
.jwho.inline{position:static;flex:none;margin-top:1px;box-shadow:none;background:var(--bg-elev);backdrop-filter:none}
.kcard{position:relative;cursor:grab}
.kcard:active{cursor:grabbing}
.kcard:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.kcard.seen{border-color:var(--pc)}
.kcard .jchg-ring,.kcard .jchg-flash{border-radius:10px}
/* the card you are carrying stays put, faded, until it lands — so the gap
   you took it from is still readable */
.kcard.lifted{opacity:.35}
/* while a card is in the air the columns it can go to say so, and the one
   under it lights in the accent, the way the Jam lanes do */
.kboard.dragging .kcol{transition:background .12s,box-shadow .12s}
.kcol.over{background:color-mix(in srgb,var(--accent) 7%,transparent);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--accent) 45%,transparent)}
.kcol.over .kempty{color:var(--accent)}

/* a line whose pointer has left the board: the bubble alone, where it was */
.jcur.off .jcur-n{left:0;top:0}

/* an undecided mark, shown only on the row being edited: the silhouette of
   a date that has not been set, dashed and hollow, waiting to be dragged */
.gt-ms.guessed{background:none!important;border-style:dashed;opacity:.7}

/* ---------- Home: somebody else's change, made visible ----------
   The row lights once in that person's colour (the Jam and Kanban flash,
   drawn as a row) and their name sits beside the new status for a few
   seconds, then goes — a note that something moved, not a badge to clear. */
.hnext-row,.hrev-row{position:relative}
.row-flash{position:absolute;inset:0;pointer-events:none;border-radius:inherit;
  background:color-mix(in srgb,var(--fc) 13%,transparent);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--fc) 70%,transparent);
  animation:jflash 1.8s ease-out forwards}
.row-by{flex:none;margin-left:auto;font-size:10.5px;font-weight:600;color:oklch(from var(--fc) min(l, var(--ink-l)) c h);white-space:nowrap;
  animation:rowby 4.2s ease forwards}
.row-by + .hnext-sw{margin-left:10px}
.hrev-row .row-by{margin-left:auto}
@keyframes rowby{0%{opacity:0;transform:translateX(-4px)}8%{opacity:1;transform:none}80%{opacity:1}100%{opacity:0}}
@media (prefers-reduced-motion:reduce){.row-flash{animation:none;opacity:.8}.row-by{animation:none}}

/* ---------- personal tasks ---------- */
/* the Personal mark: LaunchIcon's tile, a person where the favicon goes */
.pmark{color:#3b4049}
.pmark svg{display:block}

/* the one thing the Assignments section makes, at the end of its row */
.hsec-new{display:inline-flex;align-items:center;gap:6px;height:29px;padding:0 11px 0 9px;flex:none;
  border:1px solid var(--line);border-radius:9px;background:var(--bg-elev);color:var(--txt-2);
  font-size:11.5px;font-weight:500;text-transform:none;letter-spacing:0;
  transition:color .12s,border-color .12s,background .12s}
.hsec-new:hover{color:var(--txt);border-color:var(--line-hi);background:var(--bg-elev2)}
.hsec-new svg{width:11px;height:11px}
.hsec-h .hsec-new{margin-left:auto}
.hsec-h .hsec-proj + .hsec-new{margin-left:0}
.hnext-due.none{color:var(--txt-3);opacity:.75}
.ktag-personal{display:inline-flex;align-items:center;gap:5px}
.ktag-personal .lico{width:12px;height:12px}

/* The window: centred, not docked. It borrows the New-ticket form's body
   (.nt, its fields, its foot) and only changes where it sits and how wide
   it is, so the two forms cannot drift apart. */
.nt.ptask{top:50%;left:50%;right:auto;bottom:auto;transform:translate(-50%,-50%);
  width:min(600px,calc(100vw - 32px));max-height:min(780px,calc(100vh - 48px));
  border:1px solid var(--line);border-radius:12px;box-shadow:0 30px 90px rgb(0 0 0/calc(.65*var(--shade)));
  overflow:hidden;outline:none}
.ptask .nt-top{padding:12px 14px 12px 16px}
.ptask .nt-t{font-size:13px;font-weight:500;color:var(--txt-2);letter-spacing:0}
.ptask .crumb-sep{margin:0}
.pt-crumb{display:inline-flex;align-items:center;gap:8px;font-size:13px;font-weight:500;color:var(--txt)}
.pt-body{flex:1;min-height:0;overflow-y:auto;padding:16px 18px 22px;display:flex;flex-direction:column;gap:14px}
.pt-title{width:100%;background:none;border:none;outline:none;padding:0;
  font-family:inherit;font-size:19px;font-weight:600;letter-spacing:-.022em;color:var(--txt)}
.pt-title::placeholder{color:var(--txt-3)}

/* the properties as label | control rows, one column of labels */
.pt-props{display:grid;grid-template-columns:72px minmax(0,1fr);align-items:center;gap:11px 14px;
  padding:14px 0;border-top:1px solid var(--line-soft);border-bottom:1px solid var(--line-soft)}
.pt-props .nt-k{margin:0}
.pt-status{flex-wrap:wrap;justify-self:start}
.pt-status button{padding:4px 10px;font-size:12px;gap:6px}
.pt-status .dot{width:7px;height:7px;border-radius:50%;display:inline-block;flex:none}
.pt-due{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.pt-due input{background:var(--bg-elev);border:1px solid var(--line);border-radius:8px;padding:6px 10px;
  color:var(--txt);font-size:12.5px;font-family:inherit;outline:none}
.pt-due input:focus{border-color:var(--accent)}
.pt-when{font-size:11.5px;color:var(--txt-3);font-family:"Geist Mono",monospace}
.pt-when.late{color:oklch(from #f5405e min(l, var(--ink-l)) c h)}
.pt-effort{max-width:240px}
.pt-for{display:flex;align-items:center;gap:8px;flex-wrap:wrap;min-width:0}
.pt-note{font-size:11.5px;color:var(--txt-3)}

.pt-sec .nt-k{display:flex;align-items:baseline}
.pt-n{margin-left:8px;font-family:"Geist Mono",monospace;font-weight:500;letter-spacing:0;color:var(--txt-2)}
.pt-step{display:flex;align-items:center;gap:10px;padding:5px 8px;margin:0 -8px;border-radius:7px}
.pt-step:hover{background:var(--hover)}
.pt-chk{width:16px;height:16px;flex:none;border-radius:5px;border:1.5px solid var(--line-hi);
  display:grid;place-items:center;color:#fff;transition:background .12s,border-color .12s}
.pt-chk:hover{border-color:var(--txt-3)}
.pt-step.done .pt-chk{background:var(--accent);border-color:var(--accent)}
.pt-step-t{flex:1;min-width:0;font-size:13px;line-height:1.4;color:var(--txt)}
.pt-step.done .pt-step-t{color:var(--txt-3);text-decoration:line-through}
.pt-step .chx{color:var(--txt-3);padding:3px;opacity:0;transition:opacity .12s}
.pt-step:hover .chx,.pt-step .chx:focus-visible{opacity:1}
.pt-step .chx:hover{color:var(--lit)}
.pt-addstep{display:flex;align-items:center;gap:10px;padding:5px 8px;margin:0 -8px;color:var(--txt-3)}
.pt-addstep svg{width:12px;height:12px;flex:none;margin:0 2px}
.pt-addstep input{flex:1;min-width:0;background:none;border:none;outline:none;padding:2px 0;
  font-family:inherit;font-size:13px;color:var(--txt)}
.pt-addstep input::placeholder{color:var(--txt-3)}

.ptask .nt-foot{padding:11px 14px}
.pt-saved{margin-right:auto;font-size:11px;color:var(--txt-3)}
.pt-del + .pt-saved{margin-left:4px}
.pt-del{font-size:12px;font-weight:500;color:oklch(from #f5405e min(l, var(--ink-l)) c h);padding:6px 10px;border-radius:7px}
.pt-del:hover{background:rgba(245,64,94,.1)}

/* ---------- Home: supervising ---------- */
/* the review list's box, rows a little taller to seat the artifact */
/* the dimension switch sits right, just before the chips it decides */
.hsec-h .hsec-by{margin-left:auto;text-transform:none;letter-spacing:0;flex:none}
.hsec-by button{padding:4px 10px;font-size:11.5px}
.hsec-h .hsec-by + .hsec-watch{margin-left:0}
.hwatch{display:flex;flex-direction:column;border:1px solid var(--line);border-radius:11px;overflow:hidden}
.hwatch.open{max-height:52vh;overflow-y:auto}
.hwatch-row{position:relative;display:flex;align-items:center;gap:12px;min-height:44px;padding:5px 13px 5px 10px;
  text-align:left;border-bottom:1px solid var(--line-soft);transition:background .12s}
.hwatch-row:last-child{border-bottom:none}
.hwatch-row:hover{background:var(--hover)}
.hwatch-art{position:relative;flex:none;width:24px;height:32px}
.hwatch-t{flex:none;font-size:12.5px;font-weight:600;color:var(--txt);white-space:nowrap}
.hwatch-sum{flex:1;min-width:0;font-size:12px;color:var(--txt-3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.hwatch-row .hnext-sw{width:124px;text-align:right;margin-left:0}
.hwatch-row .row-by + .hnext-sw{width:auto;margin-left:10px}
.hwatch-row .hnext-l{margin-left:0}
.hwatch-who{flex:none;display:inline-flex;width:18px;justify-content:center}
.hwatch-row .hnext-l{width:120px;max-width:120px}
.hwatch-row .hnext-due{width:64px;justify-content:flex-end}
.hwatch-more{display:block;background:none;border:none;padding:0;cursor:pointer}
.hwatch-more:hover{color:var(--txt-2)}

/* ---------- Overview: the workstream columns ---------- */
/* **One row, as many columns as there are workstreams** (`--n`, set by the
   component) — never 4 + 1. `auto-fit` with a 148px floor was the first
   pass and it wrapped at exactly the widths people use: the Overview's main
   column is the viewport less ~640px, so five fitted only from ~1420px up and
   a 1280 or 1366 laptop got four and an orphan. Pinned, a column narrows
   instead, and each is its own container so it can shed the date and the
   tool's name when it does (the mark stays). Only at phone width does the row
   break, into pairs. Each column is the current version of one workstream;
   the button's ::after covers it, so the whole column is the target, and the
   file chip sits above on its own layer. */
.wscols{display:grid;grid-template-columns:repeat(var(--n,5),minmax(0,1fr));gap:10px}
@media (max-width:760px){.wscols{grid-template-columns:repeat(2,minmax(0,1fr))}}
.wscol{position:relative;display:flex;flex-direction:column;gap:7px;min-width:0;padding:12px 12px 11px;
  container:wscol/inline-size;
  border:1px solid var(--line);border-radius:10px;background:var(--bg-elev);transition:background .15s,border-color .15s}
/* only a column with something to open answers the pointer */
.wscol:not(.empty):hover{background:var(--bg-elev2);border-color:var(--line-hi)}
.wscol:has(.wscol-open:focus-visible){outline:2px solid var(--accent);outline-offset:2px}
.wscol-top{display:flex;align-items:flex-start;justify-content:space-between;gap:8px}
.wscol-art{position:relative;flex:none;width:28px;height:36px}
.wscol-art .amini{width:28px;height:36px}
/* not delivered yet: the workstream's own object, faded, up to full on hover */
.wscol.pending .amini{opacity:.42;transition:opacity .2s,transform .16s cubic-bezier(.2,.8,.3,1)}
.wscol.pending:hover .amini{opacity:1}
.wscol.empty .wscol-art{border:1.5px dashed var(--line-hi);border-radius:5px}
.wscol-who{display:inline-flex}
.wscol-open{display:block;text-align:left;padding:0;min-width:0;outline:none}
.wscol-open::after{content:"";position:absolute;inset:0;border-radius:inherit;cursor:pointer}
.wscol-t{display:block;font-size:13px;font-weight:600;letter-spacing:-.01em;color:var(--txt);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.wscol-st{display:inline-flex;align-items:flex-start;gap:6px;font-size:11.5px;line-height:1.3;color:var(--txt-2)}
.wscol-st i{margin-top:4px}
.wscol-st i{width:7px;height:7px;border-radius:50%;background:var(--s);flex:none;
  box-shadow:0 0 0 2px color-mix(in srgb,var(--s) 18%,transparent)}
.wscol-foot{display:flex;align-items:center;justify-content:space-between;gap:6px;margin-top:auto;padding-top:2px;min-width:0}
.wscol-foot .lasset{position:relative;z-index:1;min-width:0;max-width:100%;overflow:hidden}
.lasset-n{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* a narrow column keeps the file's mark and drops its name and the date */
@container wscol (max-width:128px){
  .wscol .lasset-n,.wscol-date{display:none}
  .wscol .lasset{padding:0 6px}
}
.wscol-date{font-size:10.5px;color:var(--txt-3);font-family:"Geist Mono",monospace;white-space:nowrap}
.wscol-none{font-size:11px;color:var(--txt-3)}

/* ---------- due dates: a date, or Undecided ---------- */
.ltbl td.ldue{font-family:"Geist Mono",monospace;font-size:11.5px;color:var(--txt-2);white-space:nowrap}
.ltbl td.ldue.late{color:oklch(from #f5405e min(l, var(--ink-l)) c h)}
.ltbl td.ldue .undecided{font-family:inherit;font-size:11px}
.kdue .undecided,.km-due .undecided,.hnext-due .undecided,.stk-due .undecided{font-size:10.5px;gap:4px}
.kdue .undecided svg,.km-due .undecided svg,.hnext-due .undecided svg,.stk-due .undecided svg{width:11px;height:11px}
.hnext-due.none{opacity:1}
.tf-duebox{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.tf-duepick{display:inline-flex;align-items:center;gap:6px}
.tf-duepick input{background:var(--bg-elev);border:1px solid var(--line);border-radius:7px;padding:3px 7px;
  color:var(--txt);font-size:11.5px;font-family:inherit;outline:none}
.tf-duepick input:focus{border-color:var(--accent)}
.tf-duepick input::-webkit-calendar-picker-indicator{filter:invert(.6);cursor:pointer}

/* ---------- an empty database (EmptyWorkspace.jsx) ---------- */
.empty-ws{min-height:100vh;display:grid;place-items:center;padding:24px 16px;background:var(--bg)}
.empty-ws-card{width:min(440px,100%);padding:28px 26px 24px;border:1px solid var(--line);border-radius:12px;background:var(--bg-elev)}
.empty-ws-mark{font-size:13px;font-weight:700;letter-spacing:-.02em;color:var(--txt);margin-bottom:22px}
.empty-ws h1{margin:0 0 10px;font-size:18px;font-weight:600;letter-spacing:-.02em;color:var(--txt)}
.empty-ws p{margin:0 0 14px;font-size:13px;line-height:1.55;color:var(--txt-2)}
.empty-ws pre{margin:0 0 14px;padding:10px 12px;border:1px solid var(--line);border-radius:8px;background:var(--bg);
  font-family:'Geist Mono',monospace;font-size:12.5px;color:var(--txt)}
.empty-ws code{font-family:'Geist Mono',monospace;font-size:12px;color:var(--txt)}
.empty-ws .empty-ws-then{font-size:12px;color:var(--txt-3)}

/* ---------- time off ----------
   The library shape (masthead, one track, rows) because it is a shelf of
   requests; each list sets only its own columns. Status is the dot and the
   word, from STATUS_COLORS (pending is QA's amber, approved Done's green,
   declined Blocked's red). */
.towrap{max-width:1180px;margin:0 auto}
.to-group{margin-top:22px}
.to-group:first-of-type{margin-top:0}
.pglist + .to-group{margin-top:22px}
.to-group h2{display:flex;align-items:baseline;gap:8px;margin:0 0 8px;font-size:10.5px;font-weight:700;
  letter-spacing:.07em;text-transform:uppercase;color:var(--txt-3)}
.to-group h2 span{font-family:"Geist Mono",monospace;font-weight:500;letter-spacing:0;color:var(--txt-2)}
.tolist.past .torow{opacity:.62}
.tolist.past .torow:hover{opacity:1}
.torow{cursor:default}
.torow.mine{grid-template-columns:minmax(170px,210px) 108px minmax(0,1fr) 104px 84px}
.torow.ask{grid-template-columns:minmax(180px,220px) minmax(150px,190px) 100px minmax(0,1fr) 172px}
.torow.out{grid-template-columns:minmax(200px,260px) minmax(150px,190px) 100px minmax(0,1fr) 104px}
.to-when{display:flex;flex-direction:column;gap:1px;min-width:0}
.to-when b{font-size:13px;font-weight:600;letter-spacing:-.01em;color:var(--txt);white-space:nowrap}
.to-when span{font-size:11.5px;color:var(--txt-3)}
.to-kind{font-size:12.5px;color:var(--txt-2)}
.to-note{display:flex;flex-direction:column;gap:3px;min-width:0;font-size:12.5px;line-height:1.45;color:var(--txt-2)}
.to-note b{color:var(--txt);font-weight:600}
/* somebody else on the pod already out then — the thing a manager would
   otherwise go and look up before saying yes */
.to-clash{font-style:normal;font-size:11.5px;color:oklch(from var(--st-qa) min(l, var(--ink-l)) c h)}
.to-st{display:inline-flex;align-items:center;gap:7px;font-size:12.5px;color:var(--txt-2);white-space:nowrap}
.to-st i{width:7px;height:7px;border-radius:50%;flex:none}
.to-who{display:flex;align-items:center;gap:10px;min-width:0}
.to-who > span{display:flex;flex-direction:column;min-width:0}
.to-who b{font-size:13px;font-weight:600;color:var(--txt);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.to-who > span > span{font-size:11.5px;color:var(--txt-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.to-act{display:flex;justify-content:flex-end;gap:6px}
.to-btn{height:28px;padding:0 11px;border-radius:7px;border:1px solid var(--line);font-size:12px;font-weight:500;
  color:var(--txt-2);transition:background .12s,border-color .12s,color .12s}
.to-btn:hover{border-color:var(--line-hi);color:var(--txt);background:var(--hover)}
.to-btn.go{background:var(--btn);border-color:var(--btn);color:var(--btn-ink)}
.to-btn.go:hover{background:var(--btn-hi);border-color:var(--btn-hi);color:var(--btn-ink)}
.to-btn.no{background:color-mix(in srgb,var(--st-blocked) 16%,transparent);
  border-color:color-mix(in srgb,var(--st-blocked) 45%,transparent);color:var(--lit)}
/* Decline waits for its reason: dimmed, still showing why on hover */
.to-btn:disabled{opacity:.45;cursor:default}
.to-btn.quiet{border-color:transparent;color:var(--txt-3)}
.to-btn.quiet:hover{border-color:var(--line);color:var(--txt)}
/* a no comes with a reason, typed on the row it answers */
.torow.deciding{background:var(--bg-elev2)}
.to-decline{grid-column:1/-1;display:flex;align-items:center;gap:8px}
.to-decline input{flex:1;min-width:0;height:30px;padding:0 10px;border-radius:7px;background:var(--bg);
  border:1px solid var(--line);color:var(--txt);font:inherit;font-size:12.5px;font-weight:400;outline:none}
.to-decline input:focus{border-color:color-mix(in srgb,var(--st-blocked) 60%,var(--line))}
/* the request window is the personal-task window's shell (.nt.ptask) */
.toreq .pt-props{grid-template-columns:64px minmax(0,1fr)}
.to-ta{width:100%;min-height:52px;resize:vertical;padding:8px 10px;border-radius:8px;background:var(--bg-elev);
  border:1px solid var(--line);color:var(--txt);font:inherit;font-size:12.5px;line-height:1.5;outline:none}
.to-ta::placeholder{color:var(--txt-3)}
.to-ta:focus{border-color:var(--accent)}
.to-half{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--txt-2);cursor:pointer}
.to-half input{accent-color:var(--accent)}
.to-sum{display:flex;flex-direction:column;gap:6px;padding:12px 14px;border-radius:10px;
  background:var(--bg-elev);border:1px solid var(--line-soft)}
.to-sum-n{display:flex;align-items:baseline;gap:10px}
.to-sum-n b{font-size:18px;font-weight:600;letter-spacing:-.02em;color:var(--txt)}
.to-sum-n span{font-size:12px;color:var(--txt-3)}
.to-sum p{margin:0;font-size:12.5px;line-height:1.5;color:var(--txt-2)}
.to-sum p b{color:var(--txt);font-weight:600}
.to-sum p.warn,.to-sum p.to-clash{color:oklch(from var(--st-qa) min(l, var(--ink-l)) c h)}
.to-sum p.to-problem{color:oklch(from var(--st-blocked) min(l, var(--ink-l)) c h)}
@media (max-width:900px){
  .torow.mine{grid-template-columns:minmax(0,1fr) 96px 84px}
  .torow.out{grid-template-columns:minmax(0,1fr) minmax(0,1fr) 96px}
  .torow.ask{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
  .torow .to-kind,.torow.mine .to-note,.torow.out .to-note{display:none}
}

/* ---------- the launch bell's menu (NotifyMenu.jsx) ----------
   Three levels, loudest first, each one line on what it means; the groups
   only under Everything, the one level with anything to trim. */
.nmenu{position:absolute;top:calc(100% + 8px);left:-10px;z-index:60;width:340px;padding:12px;
  background:var(--raise);border:1px solid var(--line);border-radius:12px;
  box-shadow:0 18px 44px rgb(0 0 0/calc(.55*var(--shade)));cursor:default}
.nmenu-h{display:flex;align-items:baseline;gap:8px;margin:0 2px 10px}
.nmenu-h b{font-size:13px;font-weight:600;color:var(--txt)}
.nmenu-h span{font-size:11.5px;color:var(--txt-3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.nmenu-levels{display:flex;flex-direction:column;gap:2px}
.nmenu-l{display:flex;align-items:flex-start;gap:10px;width:100%;padding:8px 9px;border-radius:8px;text-align:left}
.nmenu-l:hover{background:var(--hover)}
.nmenu-l.on{background:color-mix(in srgb,var(--accent) 12%,transparent)}
.nmenu-radio{flex:none;width:15px;height:15px;margin-top:1px;border-radius:50%;border:1.5px solid var(--line-hi)}
.nmenu-l.on .nmenu-radio{border-color:var(--accent);box-shadow:inset 0 0 0 3px var(--bg-elev2);background:var(--accent)}
.nmenu-lt{display:flex;flex-direction:column;gap:2px;min-width:0}
.nmenu-lt b{display:flex;align-items:center;gap:7px;font-size:12.5px;font-weight:600;color:var(--txt)}
.nmenu-lt b em{font-style:normal;font-size:9.5px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;
  padding:1px 5px;border-radius:4px;color:var(--txt-3);box-shadow:inset 0 0 0 1px var(--line)}
.nmenu-lt > span{font-size:11.5px;line-height:1.45;color:var(--txt-3)}
.nmenu-groups{display:flex;flex-direction:column;gap:1px;margin-top:8px;padding-top:10px;border-top:1px solid var(--line-soft)}
.nmenu-k{margin:0 9px 5px;font-size:10px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--txt-3)}
.nmenu-g{display:flex;align-items:flex-start;gap:10px;padding:6px 9px;border-radius:8px;cursor:pointer}
.nmenu-g:hover{background:var(--hover)}
.nmenu-g input{flex:none;margin:2px 0 0;accent-color:var(--accent)}
.nmenu-g:not(.on) .nmenu-lt b{color:var(--txt-2)}
.nmenu-foot{margin:10px 2px 0;padding-top:10px;border-top:1px solid var(--line-soft);
  font-size:11px;line-height:1.5;color:var(--txt-3)}
/* the centre says whose list it is */
.ncen-foot{margin:0;padding:9px 14px 11px;border-top:1px solid var(--line-soft);font-size:11px;line-height:1.5;color:var(--txt-3)}

/* ---------- Jam: commands, the toolbar's second group (JamCommands.jsx) ----------
   The confirm is one line and two buttons above the button that asked. */
.jtb-cmd{position:relative;display:flex}
.jtb:disabled{opacity:.4;cursor:default}
.jtb:disabled:hover{background:none;color:var(--txt-3)}
.jcmd-pop{position:absolute;bottom:calc(100% + 12px);left:50%;transform:translateX(-50%);width:236px;
  padding:10px 11px;text-align:left;background:var(--raise);border:1px solid var(--line);border-radius:10px;
  box-shadow:0 14px 34px rgb(0 0 0/calc(.55*var(--shade)))}
.jcmd-pop p{margin:0;font-size:11.5px;line-height:1.45;color:var(--txt-2)}
.jcmd-pop p b{color:var(--txt);font-weight:600}
.jcmd-f{display:flex;justify-content:flex-end;gap:6px;margin-top:9px}
.jcmd-no,.jcmd-yes{height:26px;padding:0 10px;border-radius:6px;font-size:11.5px;font-weight:500}
.jcmd-no{color:var(--txt-3)}
.jcmd-no:hover{color:var(--txt);background:var(--hover)}
.jcmd-yes{background:var(--btn);color:var(--btn-ink)}
.jcmd-yes:hover{background:var(--btn-hi)}

/* ---------- the calendar (DatePicker.jsx) ----------
   The one date input: the value is the trigger, the month is portalled.
   Monday first; today ringed; the chosen day in the accent; other dates that
   matter to this one as a dot under their day. */
.dp-trigger{display:inline-flex;align-items:center;text-align:left;font:inherit;color:inherit}
.dp{position:fixed;z-index:210;padding:10px;background:var(--raise);border:1px solid var(--line);
  border-radius:12px;box-shadow:0 18px 44px rgb(0 0 0/calc(.55*var(--shade)))}
.dp,.dp *{text-transform:none;letter-spacing:normal}
.dp-h{display:flex;align-items:center;justify-content:space-between;margin:0 0 8px}
.dp-h b{font-size:13px;font-weight:600;color:var(--txt)}
.dp-nav{width:26px;height:26px;border-radius:7px;display:grid;place-items:center;font-size:17px;line-height:1;color:var(--txt-2)}
.dp-nav:hover{background:var(--hover);color:var(--txt)}
.dp-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}
.dp-w{height:22px;display:grid;place-items:center;font-size:10px;font-weight:600;color:var(--txt-3)}
.dp-w.we{opacity:.6}
.dp-d{position:relative;height:32px;border-radius:7px;display:grid;place-items:center;font-size:12px;
  font-variant-numeric:tabular-nums;color:var(--txt);outline:none}
.dp-d:hover{background:var(--hover)}
.dp-d:focus-visible{box-shadow:inset 0 0 0 1.5px var(--accent)}
.dp-d.we{color:var(--txt-2)}
.dp-d.out{color:var(--txt-3);opacity:.45}
.dp-d.today{box-shadow:inset 0 0 0 1px var(--line-hi);font-weight:700}
.dp-d.sel{background:var(--accent);color:#fff;font-weight:600}
.dp-d.sel.today{box-shadow:none}
.dp-mk{position:absolute;bottom:4px;left:50%;width:4px;height:4px;margin-left:-2px;border-radius:50%;background:var(--st-qa)}
.dp-d.sel .dp-mk{background:#fff}
.dp-f{display:flex;align-items:center;gap:6px;margin-top:9px;padding-top:9px;border-top:1px solid var(--line-soft)}
.dp-sel{flex:1;min-width:0;font-size:11.5px;color:var(--txt-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dp-sel b{color:var(--txt);font-weight:600}
.dp-btn{height:26px;padding:0 9px;border-radius:6px;font-size:11.5px;color:var(--txt-2);border:1px solid var(--line)}
.dp-btn:hover{border-color:var(--line-hi);color:var(--txt)}

/* ---------- the launch sheet: one properties sheet (Prop, Overview.jsx) ----------
   Sentence-case labels in one column, values in the next, a hairline between
   rows; two columns — the project's facts, then the shoot and its papers. */
.ovprops{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 44px}
.ovcol{margin:0;display:flex;flex-direction:column;min-width:0}
.ovp{display:grid;grid-template-columns:136px minmax(0,1fr);align-items:center;gap:14px;min-height:40px;
  padding:6px 0;border-bottom:1px solid var(--line-soft)}
.ovp:last-child{border-bottom:none}
.ovp.top{align-items:start}
.ovp.top dt{padding-top:2px}
.ovp dt{font-size:12px;color:var(--txt-3)}
.ovp dd{margin:0;min-width:0;display:flex;align-items:center;flex-wrap:wrap;gap:6px 8px;font-size:13px;color:var(--txt)}
.ovp .ovf-link{min-width:0;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ovp .ovon button{font-size:11.5px;padding:3px 10px}
.ovon-reset{font-size:11px;color:var(--txt-3);border-radius:5px;padding:2px 5px}
.ovon-reset:hover{color:var(--txt);background:var(--hover)}
@media (max-width:900px){.ovprops{grid-template-columns:1fr}}


/* ---------- Jam: the notch (Notch in JamView.jsx) ----------
   Hangs from the canvas's top edge: flat on top, rounded below, the same
   glass as the toolbars; the versions are ways into their tickets and the
   stage is a picker. */
.jnotch{position:absolute;top:-1px;left:50%;transform:translateX(-50%);z-index:4;display:flex;align-items:center;
  gap:4px;padding:5px 6px 6px;background:var(--glass);border:1px solid var(--line);border-top:none;
  border-radius:0 0 14px 14px;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
  box-shadow:0 10px 28px rgb(0 0 0/calc(.45*var(--shade)))}
.jn-v{display:inline-flex;align-items:baseline;gap:6px;height:28px;padding:0 10px;border-radius:8px;align-items:center}
.jn-v span{font-size:11px;color:var(--txt-3)}
.jn-v b{font-family:"Geist Mono",monospace;font-size:12px;font-weight:600;color:var(--txt)}
.jn-v:hover{background:var(--hover)}
.jn-sep{width:1px;height:16px;background:var(--line);flex:none}
.jn-part{display:inline-flex;align-items:center;gap:2px}
.jn-stage{display:inline-flex;align-items:center;gap:7px;height:26px;padding:0 10px;border-radius:20px;
  font-size:11.5px;font-weight:600;color:var(--txt);border:1px solid var(--line);background:var(--bg-elev)}
.jn-stage:hover,.jn-stage.open{border-color:var(--line-hi);background:var(--bg-elev2)}
.jn-stage i{width:7px;height:7px;border-radius:50%;flex:none}

/* ---------- Jam: the bottom notch ----------
   The top notch's twin, flush with the bottom edge: the panels you open,
   a divider, then the one control that makes real work. */
.jnotch-b{top:auto;bottom:-1px;border-top:1px solid var(--line);border-bottom:none;border-radius:14px 14px 0 0;
  padding:5px 6px 6px}
.jn-t{position:relative;display:inline-flex;align-items:center;gap:7px;height:28px;padding:0 10px;border-radius:8px;
  font-size:12px;font-weight:500;color:var(--txt-3)}
.jn-t svg{flex:none}
.jn-t:hover{background:var(--hover);color:var(--txt)}
.jn-t.on{background:var(--active);color:var(--lit)}
.jn-t:disabled{opacity:.4;cursor:default}
.jn-t:disabled:hover{background:none;color:var(--txt-3)}
.jn-dot{width:6px;height:6px;border-radius:50%;background:var(--accent);flex:none}
.jn-n{min-width:15px;padding:0 5px;border-radius:20px;background:var(--accent);color:#fff;
  font-size:9.5px;font-weight:700;text-align:center}
.jn-act{color:var(--txt)}
.jn-act > svg{color:var(--accent)}
.jn-cap{font-size:11px;font-weight:400;color:var(--txt-3)}

/* List: the workstream's tasks come after its deliverables, under a hairline
   the width of every other line — brighter, not thicker (a 2px rule read
   heavier than the table's own outline) */
.ltbl tr.first-task > td{border-top:1px solid var(--line-hi)}

/* ═══════════════════════════════════════════════════════════════════════════
   PART II · STUDIO ADDITIONS — authoring (from the Learning Map editor)
   Nothing here redefines a Part I rule; every selector is new.
   ═══════════════════════════════════════════════════════════════════════════ */
/* Tokens Parts II and III add to Part I's (ShownRoom keeps these hues in JS) */
:root{
  --st-todo:#8f8f8f;--st-progress:#3291ff;--st-review:#a07bf0;--st-revision:#f75f8f;
  --ease:cubic-bezier(.2,.8,.3,1);--t-fast:.12s;--t-mid:.16s;
  --stage-w:880px;--rail-w:300px;--ltop-h:54px;
}

/* A count beside a heading or a group; "ready" as a dot and a word */
.chk-n{font-family:"Geist Mono",ui-monospace,monospace;font-size:11px;color:var(--txt-3)}
.ready-w{display:inline-flex;align-items:center;gap:7px;font-size:12px;color:var(--txt-2)}
.ready-w i{width:7px;height:7px;border-radius:50%;background:var(--st-done)}
/* A check the app ticks, not you: dashed until it is done */
.tdcheck.auto{cursor:default;border-style:dashed}
.tdcheck.auto.on{border-style:solid}
/* A small dashed kind label: a different kind of item in the same order */
.chip.dashed{border:1px dashed var(--line-hi);color:var(--txt-3)}

/* Ordered groups: a numbered container of ordered rows (a pillar of modules,
   a stage of tasks). The number column says the order; rows carry the work. */
.mcard{display:grid;grid-template-columns:52px minmax(0,1fr);border:1px solid var(--line);border-radius:12px;background:var(--bg-elev);margin-bottom:12px;overflow:hidden}
.mcard-n{display:flex;justify-content:center;padding-top:16px;font-family:"Geist Mono",monospace;font-size:20px;font-weight:600;color:var(--txt-2);border-right:1px solid var(--line-soft);background:var(--bg-elev2)}
.mcard.ready .mcard-n{color:var(--st-done)}
.mcard-b{padding:14px 16px 12px;min-width:0}
.mcard-h{display:flex;align-items:center;gap:10px;min-width:0}
.mcard-t{font-size:15px;font-weight:600;letter-spacing:-.015em;color:var(--txt);text-align:left;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mcard-t:hover{text-decoration:underline;text-decoration-color:var(--line-hi);text-underline-offset:3px}
.mcard-tools{margin-left:auto;display:flex;align-items:center;gap:2px;flex:none}
.mcard-d{margin:3px 0 0;font-size:12.5px;color:var(--txt-3);line-height:1.45}
.mcard-adds{display:flex;flex-wrap:wrap;gap:8px}
.mods{margin:12px 0 10px;border:1px solid var(--line-soft);border-radius:9px;overflow:hidden}
.mrow{display:grid;grid-template-columns:38px minmax(0,1fr) auto;align-items:center;gap:12px;padding:9px 12px;border-bottom:1px solid var(--line-soft);text-align:left}
.mrow:last-child{border-bottom:none}
.mrow.clk{cursor:pointer}
.mrow.clk:hover{background:var(--hover)}
.mrow-n{font-family:"Geist Mono",monospace;font-size:12px;color:var(--txt-3)}
.mrow.ready .mrow-n{color:var(--st-done)}
.mrow-b{display:flex;flex-direction:column;gap:3px;min-width:0}
.mrow-t{font-size:13.5px;font-weight:500;color:var(--txt);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mrow-s{display:flex;align-items:center;gap:7px;min-width:0;font-size:11.5px;color:var(--txt-3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mrow.empty{display:block;color:var(--txt-3);font-size:12.5px}
/* a different kind of item in the same order (a filler page): unnumbered, sunk, tagged */
.mrow.filler{background:var(--well)}
.mrow.filler .mrow-n{display:grid;place-items:center;width:22px;height:22px;border-radius:6px;border:1px dashed var(--line-hi);color:var(--txt-3)}
.mrow.filler .mrow-t{color:var(--txt-2)}
/* a different kind of group in the same order (a quiz between pillars) */
.mcard.alt{border-style:dashed}
.mcard.alt .mcard-n{color:var(--txt-3);padding-top:15px}
.madd{display:flex;align-items:center;justify-content:center;gap:7px;width:100%;padding:14px;border:1px dashed var(--line);border-radius:12px;font-size:13px;color:var(--txt-2)}
.madd:hover{border-style:solid;border-color:var(--line-hi);color:var(--txt);background:var(--hover)}
.madd-row{display:grid;grid-template-columns:minmax(0,2fr) minmax(0,1fr);gap:10px}

/* checks: what "ready" is made of, one row each */
.checks{border:1px solid var(--line);border-radius:11px;overflow:hidden}
.crow{display:grid;grid-template-columns:20px minmax(0,1fr);gap:10px;padding:11px 14px;border-bottom:1px solid var(--line-soft);align-items:start}
.crow:last-child{border-bottom:none}
.crow-t{font-size:13px;font-weight:500;color:var(--txt);display:flex;align-items:center;gap:8px;flex-wrap:wrap;min-height:18px}
.crow-t .req{font-size:10px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;color:var(--txt-3)}
.crow-s{font-size:12px;color:var(--txt-3);margin-top:4px;line-height:1.5}
.crow-c{margin-top:8px;display:flex;flex-direction:column;gap:7px}
.ordrow{display:flex;align-items:center;gap:8px;padding:7px 10px;border-bottom:1px solid var(--line-soft);font-size:12.5px}
.ordrow:last-child{border-bottom:none}
.ordrow .n{font-family:"Geist Mono",monospace;font-size:11px;color:var(--txt-3);width:34px;flex:none}
.ordrow .t{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--txt);text-align:left}

/* "What learners see": the words a Stage page will show, edited in Studio as a
   labelled block of their own, never mixed with internal fields */
.ctext{margin:0 0 18px;padding:13px 14px 14px;border:1px solid var(--line);border-radius:12px;background:var(--bg-elev)}
.ctext-h{display:flex;align-items:baseline;gap:8px;margin-bottom:12px;font-size:10.5px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--txt-2)}
.ctext-h span{font-size:11.5px;font-weight:400;letter-spacing:0;text-transform:none;color:var(--txt-3)}
.ctext .nt-k{margin-top:12px}
.ctext .nt-k:first-of-type{margin-top:0}
.ctext .miss{color:oklch(from var(--warn) min(l, var(--ink-l)) c h)}
.nt-in.ctext-in{font-size:16px;font-weight:600;letter-spacing:-.015em;padding:8px 10px}
.nt-in.ctext-area{min-height:76px;line-height:1.55}

/* The question editor: tick every right answer */
.qeds{display:flex;flex-direction:column;gap:10px;margin-bottom:10px}
.qed{border:1px solid var(--line);border-radius:12px;background:var(--bg-elev);padding:12px}
.qed-h{display:flex;align-items:flex-start;gap:8px}
.qed-n{flex:none;width:22px;padding-top:8px;font-size:11.5px;color:var(--txt-3);text-align:center;font-family:"Geist Mono",monospace}
.nt-in.qed-q{flex:1;min-height:38px;line-height:1.45;font-weight:500}
.qed-opts{display:flex;flex-direction:column;gap:6px;margin:10px 0 0 30px}
.qed-o{display:flex;align-items:center;gap:8px}
.qed-o .tdcheck{margin:0}
.qed-o .nt-in{flex:1;padding:6px 9px}
.qed-o.on .nt-in{border-color:color-mix(in srgb,var(--st-done) 45%,var(--line))}
.qed-f{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:10px 0 0 30px;font-size:11.5px;color:var(--txt-3)}

@media (max-width:900px){.mcard{grid-template-columns:40px minmax(0,1fr)}}


/* ═══════════════════════════════════════════════════════════════════════════
   PART III · STAGE — what employees take and read
   Flat on purpose: no gradients, glows or coloured shadows, with one exception,
   the cover's backdrop (.lglow), which is painted by a canvas (DESIGN.md).
   ════════════════════════════════════════════════════════════════════════ */
.learn{height:100%;display:flex;flex-direction:column;background:var(--bg);color:var(--txt)}

/* Buttons for Stage: bigger, with an arrow that nudges */
.lbtn{display:inline-flex;align-items:center;justify-content:center;gap:8px;height:36px;padding:0 14px;border-radius:9px;font-size:13px;font-weight:600;letter-spacing:-.005em;white-space:nowrap;
  transition:transform .25s var(--ease),background .15s,border-color .15s,color .15s}
.lbtn svg{transition:transform .3s var(--ease)}
.lbtn.primary{background:var(--btn);color:var(--btn-ink)}
.lbtn.primary:hover:not(:disabled){background:var(--btn-hi);transform:translateY(-1px)}
.lbtn.primary:hover:not(:disabled) svg{transform:translateX(3px)}
.lbtn.primary:active:not(:disabled){transform:translateY(0) scale(.985)}
.lbtn.ghost{border:1px solid var(--line);background:var(--bg-elev);color:var(--txt-2);font-weight:500}
.lbtn.ghost:hover{border-color:var(--line-hi);color:var(--txt)}
.lbtn.sm{height:30px;padding:0 10px;font-size:12px;border-radius:8px;gap:6px}
.lbtn.lg{height:46px;padding:0 20px 0 22px;font-size:14px;border-radius:12px}
.lbtn:disabled{opacity:.4;cursor:default}

/* Top bar: brand / where you are · progress · share. A 1px progress line on its edge. */
.ltop{height:var(--ltop-h);flex:none;display:flex;align-items:center;gap:6px;padding:0 14px 0 16px;border-bottom:1px solid var(--line);position:relative;z-index:30;background:var(--bg)}
.ltop-brand{display:flex;align-items:center;line-height:0;padding:6px;border-radius:7px;flex:none}
.ltop-brand:hover{background:var(--hover)}
.ltop .wordmark{height:15px}
.ltop-sep{width:1px;height:20px;background:var(--line-hi);transform:rotate(18deg);margin:0 6px;flex:none}
.ltop-course{display:flex;align-items:baseline;gap:8px;min-width:0;padding:6px 9px;border-radius:7px}
.ltop-course:hover{background:var(--hover)}
.ltop-cn{font-size:13.5px;font-weight:600;letter-spacing:-.012em;color:var(--txt);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ltop-ck{font-size:11.5px;color:var(--txt-3);flex:none}
.ltop-r{margin-left:auto;display:flex;align-items:center;gap:6px;flex:none}
.lprog{display:inline-flex;align-items:center;gap:8px;margin-right:8px;font:500 12px/1 "Geist Mono",ui-monospace,monospace;color:var(--txt-3)}
.lprog b{color:var(--txt);font-weight:500}
.lic{width:30px;height:30px;border-radius:8px;display:grid;place-items:center;color:var(--txt-3);transition:color .15s,background .15s}
.lic:hover{background:var(--hover);color:var(--txt)}
.lic-outline{display:none}
.ltop-bar{position:absolute;left:0;right:0;bottom:-1px;height:1px;pointer-events:none}
.ltop-bar i{display:block;height:1px;width:0;background:var(--accent);transition:width .9s var(--ease)}
/* a progress ring: set --c (circumference) and stroke-dashoffset inline */
.lring{transform:rotate(-90deg);flex:none;overflow:visible}
.lring-t{fill:none;stroke:var(--line-hi);stroke-width:2.2}
.lring-f{fill:none;stroke:var(--st-done);stroke-width:2.2;stroke-linecap:round}

/* Body: the outline on the left, the stage on the right */
.lbody{flex:1;min-height:0;display:flex}
.lrail{width:var(--rail-w);flex:none;overflow-y:auto;border-right:1px solid var(--line);background:var(--bg-side);padding:16px 10px 32px;scrollbar-width:thin}
.learn.is-cover .lrail,.learn.is-cover .lic-outline{display:none}
.lrail-scrim{display:none}
.lrail-h{display:flex;align-items:center;justify-content:space-between;padding:4px 10px 12px;font-size:10.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--txt-3)}
.lrail-h .mono{font-weight:500;letter-spacing:0;text-transform:none;font-size:11px;color:var(--txt-2)}
.lrail-list{position:relative}
/* one highlight that glides to where you are (JS sets transform + height) */
.lrail-ind{position:absolute;left:0;right:0;top:0;height:0;opacity:0;border-radius:9px;pointer-events:none;background:var(--sel);box-shadow:inset 0 0 0 1px var(--line);
  transition:transform .5s var(--ease),height .5s var(--ease),opacity .25s}
.lrail-ind::before{content:"";position:absolute;left:-1px;top:9px;bottom:9px;width:2px;border-radius:2px;background:var(--accent)}
.lr-grp{margin-bottom:8px}
.lr-p,.lr-m,.lr-q{position:relative;z-index:1;display:flex;align-items:center;gap:10px;width:100%;text-align:left;border-radius:9px;transition:color .2s,background .2s}
.lr-p{padding:9px 10px;font-size:13px;font-weight:600;letter-spacing:-.01em;color:var(--txt)}
.lr-pn{width:22px;height:22px;flex:none;border-radius:7px;display:grid;place-items:center;font:600 11px/1 "Geist Mono",ui-monospace,monospace;color:var(--txt-2);background:var(--bg-elev2);border:1px solid var(--line);transition:background .3s,border-color .3s,color .3s}
.lr-pn svg{width:11px;height:11px}
.lr-p.done .lr-pn{background:var(--st-done);border-color:transparent;color:#04120a}
.lr-pt{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lr-pc{font-size:10.5px;color:var(--txt-3);font-family:"Geist Mono",monospace}
.lr-m{padding:7px 10px 7px 13px;font-size:12.5px;color:var(--txt-2)}
/* the thread between steps, broken around each tick, green where it is done */
.lr-m::before,.lr-m::after{content:"";position:absolute;left:21px;width:1px;height:calc(50% - 10px);background:var(--line);transition:background .4s}
.lr-m::before{top:0}
.lr-m::after{bottom:0}
.lr-p+.lr-m::before,.lr-m:last-child::after{display:none}
.lr-m.done::after,.lr-m.done+.lr-m::before{background:color-mix(in srgb,var(--st-done) 55%,var(--line))}
.lr-p:not(.on):hover,.lr-m:not(.on):hover,.lr-q:not(.on):hover{background:var(--hover);color:var(--txt)}
.lr-p.on,.lr-m.on,.lr-q.on{color:var(--lit)}
.lr-mn{font-size:10.5px;color:var(--txt-3);width:24px;flex:none;font-family:"Geist Mono",monospace}
.lr-mt{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lr-ck{width:16px;height:16px;flex:none;border-radius:50%;border:1.5px solid var(--line-hi);display:grid;place-items:center;color:#04120a;transition:background .3s,border-color .3s}
.lr-ck svg{width:9px;height:9px}
.on>.lr-ck{border-color:var(--accent)}
.done>.lr-ck{background:var(--st-done);border-color:var(--st-done)}
.pop>.lr-ck,.pop>.lr-qi{animation:l-pop .55s var(--ease)}
.pop>.lr-ck .lcheck-p{stroke-dasharray:24;animation:l-draw .5s .1s var(--ease) both}
/* a quiet page in the path (a filler page): a dot on the thread, no tick */
.lr-fd{width:16px;height:16px;flex:none;display:grid;place-items:center}
.lr-fd::before{content:"";width:5px;height:5px;border-radius:50%;background:var(--line-hi)}
.lr-f.on .lr-fd::before{background:var(--accent)}
.lr-f .lr-mt{color:var(--txt-3)}
.lr-f.on .lr-mt{color:var(--lit)}
/* a check in the path (a quiz) */
.lr-q{margin:4px 0 10px;padding:10px;font-size:13px;font-weight:600;color:var(--txt-2);border-top:1px solid var(--line-soft);border-radius:0 0 9px 9px}
.lr-q.on{border-radius:9px}
.lr-qi{width:22px;height:22px;flex:none;border-radius:7px;display:grid;place-items:center;border:1px dashed var(--line-hi);color:var(--txt-3)}
.lr-qi svg{width:12px;height:12px}
.lr-q.done .lr-qi,.lr-qi.done{background:var(--st-done);border:1px solid var(--st-done);color:#04120a}

/* The stage: one step at a time, a reading column */
.lmain{flex:1;min-width:0;overflow-y:auto;overflow-x:hidden;display:flex;flex-direction:column;scrollbar-gutter:stable}
.lstage{position:relative;width:100%;max-width:var(--stage-w);margin:0 auto;padding:48px 44px 64px;flex:1 0 auto}
/* each step rises a few pixels into place as one piece, whichever way you went */
.lstage.l-enter{animation:l-up .55s var(--ease) both}
.lkick{display:flex;align-items:center;gap:10px;min-height:28px;margin-bottom:14px;font-size:12.5px;color:var(--txt-3)}
.lkick-p{color:var(--txt-2);font-weight:500;border-radius:6px;transition:color .15s}
.lkick-p:hover{color:var(--lit)}
.lkick-n::before{content:"";display:inline-block;width:3px;height:3px;border-radius:50%;background:var(--txt-3);margin:0 10px 3px 0;vertical-align:middle}
.lh{margin:0;font-size:clamp(27px,3.1vw,36px);font-weight:600;letter-spacing:-.038em;line-height:1.08;color:var(--lit);text-wrap:balance}
.llead{margin:14px 0 0;max-width:62ch;font-size:15.5px;line-height:1.62;color:var(--txt-2);text-wrap:pretty}
.lprose{margin-top:20px;max-width:64ch}
.lprose p{margin:0 0 16px;font-size:16px;line-height:1.72;color:var(--txt-2);text-wrap:pretty}
.lblock{margin-top:32px}
.lblock-h{display:flex;align-items:center;gap:10px;margin-bottom:10px;font-size:10.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--txt-3)}
.lblock-h .mono{font-weight:500;letter-spacing:0;color:var(--txt-2)}
.ldraft{flex:none;font-size:10px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;padding:2px 7px;border-radius:999px;border:1px solid color-mix(in srgb,var(--warn) 45%,var(--line));color:oklch(from var(--warn) min(l, var(--ink-l)) c h)}
/* mark a step done yourself */
.ldone{margin-left:auto;flex:none;white-space:nowrap;display:inline-flex;align-items:center;gap:8px;height:28px;padding:0 11px 0 7px;border:1px solid var(--line);border-radius:999px;font-size:12px;font-weight:500;color:var(--txt-2);transition:color .2s,border-color .2s}
.ldone:hover{border-color:var(--line-hi);color:var(--txt)}
.ldone.on{border-color:color-mix(in srgb,var(--st-done) 45%,var(--line));color:oklch(from var(--st-done) min(l, var(--ink-l)) c h)}

/* Media that plays here (a video): a quiet frame that pulses while it loads */
.lframe{position:relative;width:100%;aspect-ratio:16/9;border-radius:14px;overflow:hidden;background:var(--well);border:1px solid var(--line)}
.lframe iframe,.lframe video{position:absolute;inset:0;width:100%;height:100%;border:0;transition:opacity .8s var(--ease)}
.lframe.loading{animation:l-pulse 1.8s ease-in-out infinite}
.lframe.loading iframe{opacity:0}

/* Everything else is a tidy link: what it is, and where it opens. Documents
   and decks are never previewed inline (private files show a sign-in instead). */
.llinks{display:flex;flex-direction:column;gap:8px}
.llink,.lsoon{display:flex;align-items:center;gap:12px;min-height:48px;padding:8px 14px 8px 8px;border:1px solid var(--line);border-radius:12px;background:var(--bg-elev);font-size:13.5px}
.llink{color:var(--txt-3);transition:border-color .2s,background .2s}
.llink:hover{border-color:var(--line-hi);background:var(--bg-elev2)}
.llink>svg{flex:none;transition:transform .3s var(--ease),color .15s}
.llink:hover>svg{transform:translate(2px,-2px);color:var(--txt)}
.llink-ic{width:32px;height:32px;flex:none;border-radius:8px;display:grid;place-items:center;background:var(--bg-elev2);border:1px solid var(--line);color:var(--txt-2)}
.llink-t{min-width:0;flex:0 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:600;letter-spacing:-.01em;color:var(--txt)}
.llink-app{margin-left:auto;flex:none;font-size:12px;color:var(--txt-3)}
/* something that is not there yet says so, the same size as what will be */
.lsoon{border-style:dashed;background:none}
.lsoon .llink-ic{color:var(--txt-3)}
.lsoon .llink-t{color:var(--txt-2)}
.lsoon-b{min-width:0;font-size:12.5px;color:var(--txt-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.lsoon-tag{margin-left:auto;flex:none;font-size:9.5px;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--txt-3);border:1px solid var(--line);border-radius:999px;padding:3px 8px}

/* Previous / Next, pinned to the bottom of the stage, frosted */
.lnav-slot{position:sticky;bottom:0;z-index:10}
.lnav-slot:empty{display:none}
.lnav{display:grid;grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);align-items:center;gap:16px;padding:12px max(24px,calc((100% - var(--stage-w)) / 2 + 44px));
  border-top:1px solid var(--line);background:color-mix(in srgb,var(--bg) 88%,transparent);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px)}
.lnav-b{display:flex;flex-direction:column;gap:3px;min-width:0;padding:8px 12px;border-radius:11px;text-align:left;transition:background .2s,transform .25s var(--ease)}
.lnav-b.prev{justify-self:start;margin-left:-12px}
.lnav-b.prev:hover{background:var(--hover)}
.lnav-b.prev:hover svg{transform:translateX(-3px)}
.lnav-b.next{justify-self:end;text-align:right;align-items:flex-end;padding:9px 16px;background:var(--btn);color:var(--btn-ink)}
.lnav-b.next:hover{background:var(--btn-hi);transform:translateY(-1px)}
.lnav-b.next:hover svg{transform:translateX(3px)}
.lnav-b.next:active{transform:scale(.985)}
.lnav-b.end{background:none;color:var(--txt-3);border:1px dashed var(--line)}
.lnav-k{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;font-weight:600;color:var(--txt-3)}
.lnav-k svg{transition:transform .3s var(--ease)}
.lnav-b.next .lnav-k{color:inherit;opacity:.68}
.lnav-t{max-width:100%;font-size:13.5px;font-weight:600;letter-spacing:-.01em;color:var(--txt);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lnav-b.next .lnav-t{color:inherit}
.lnav-b.end .lnav-t{color:var(--txt-3);font-weight:500}
.lnav-pos{font-size:11px;color:var(--txt-3);font-family:"Geist Mono",monospace}

/* The cover: what it is, how big it is, one way in, then the whole path */
.lstage.lcover{max-width:800px;padding-top:76px}
.learn.is-cover .lstage{z-index:1}
.lcover-k{font-size:11.5px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--txt-3)}
.lcover-h{margin:14px 0 0;font-size:clamp(38px,5.4vw,58px);font-weight:600;letter-spacing:-.05em;line-height:1;color:var(--lit);text-wrap:balance}
.lcover-p{margin:18px 0 0;max-width:56ch;font-size:16.5px;line-height:1.6;color:var(--txt-2);text-wrap:pretty}
.lcover-meta{display:flex;flex-wrap:wrap;align-items:center;gap:8px 24px;margin-top:24px;font-size:13px;color:var(--txt-3)}
.lcover-meta b{font-family:"Geist Mono",ui-monospace,monospace;font-weight:500;color:var(--txt);margin-right:5px}
.lcover-cta{display:flex;align-items:center;flex-wrap:wrap;gap:14px 20px;margin-top:32px}
.lcover-resume{font-size:12.5px;color:var(--txt-3)}
.lcover-resume b{color:var(--txt-2);font-weight:500}
.lout{list-style:none;margin:56px 0 0;padding:0;display:flex;flex-direction:column;gap:10px}
.lout-p{border:1px solid var(--line);border-radius:16px;background:var(--bg-elev);overflow:hidden;transition:border-color .25s}
.lout-p:hover{border-color:var(--line-hi)}
.lout-p.alt{border-style:solid}
.lout-h{display:grid;grid-template-columns:46px minmax(0,1fr) auto;align-items:center;gap:14px;width:100%;padding:18px 20px;text-align:left}
.lout-n{font-size:13px;font-weight:600;color:var(--txt-3);display:flex;align-items:center;font-family:"Geist Mono",monospace}
.lout-tb{display:flex;flex-direction:column;gap:4px;min-width:0}
.lout-t{font-size:15.5px;font-weight:600;letter-spacing:-.018em;color:var(--txt);transition:color .15s}
.lout-h:hover .lout-t{color:var(--lit)}
.lout-d{font-size:12.5px;line-height:1.5;color:var(--txt-3)}
.lout-c{font-size:11px;color:var(--txt-3);white-space:nowrap;font-family:"Geist Mono",monospace}
.lout-ms{border-top:1px solid var(--line-soft);padding:6px 10px 10px 70px;display:flex;flex-direction:column}
.lout-m{display:flex;align-items:center;gap:11px;width:100%;padding:7px 10px;border-radius:9px;font-size:13px;color:var(--txt-2);text-align:left;transition:background .15s,color .15s}
.lout-m:hover{background:var(--hover);color:var(--txt)}
.lout-m .mono{font-size:11px;color:var(--txt-3);width:26px;flex:none}

/* The cover's backdrop: the reference gradient, breathing. A canvas painted at a
   tenth of the window's size (paintGlow in DESIGN.md) under a still layer of grain.
   Cards on it stay solid so every word reads the same over black, blue or ice. */
.lglow,.lgrain{position:fixed;left:0;right:0;top:var(--ltop-h);bottom:0;width:100%;height:calc(100% - var(--ltop-h));pointer-events:none;z-index:0}
.lglow{display:block;animation:l-fade 1.6s var(--ease) both}
.lgrain{opacity:.1;animation:l-fade 1.6s var(--ease) both;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .5 0 0 0 0 .5 0 0 0 0 .5 0 0 0 1.4 -.2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");background-size:180px 180px}

/* A section opener (a pillar): an outline numeral, then the words */
.lpill-hero{display:flex;align-items:flex-start;gap:24px}
.lpill-num{flex:none;font-size:64px;font-weight:500;letter-spacing:-.07em;line-height:.86;color:transparent;-webkit-text-stroke:1.2px color-mix(in srgb,var(--txt) 34%,transparent);user-select:none;font-family:"Geist Mono",monospace}
.lpill-tb{min-width:0;padding-top:2px}
.lmods{border:1px solid var(--line);border-radius:14px;background:var(--bg-elev);overflow:hidden}
.lmods-r{display:flex;align-items:center;gap:12px;width:100%;padding:13px 16px;border-bottom:1px solid var(--line-soft);text-align:left;font-size:13.5px;color:var(--txt);transition:background .15s}
.lmods-r:last-child{border-bottom:none}
.lmods-r:hover{background:var(--hover)}
.lmods-r>svg{margin-left:auto;flex:none;color:var(--txt-3);transition:transform .3s var(--ease),color .15s}
.lmods-r:hover>svg{transform:translateX(3px);color:var(--txt)}
.lmods-n{font-size:11.5px;color:var(--txt-3);width:28px;flex:none;font-family:"Geist Mono",monospace}
.lmods-t{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:500}

/* A quiz: one card per question; one right answer is a radio (round mark),
   several are checkboxes (square mark) under "Select all that apply" */
.lquiz-badge{display:inline-flex;align-items:center;gap:7px;height:27px;padding:0 11px 0 9px;border:1px solid var(--line);border-radius:999px;background:var(--bg-elev);font-size:12px;font-weight:600;color:var(--txt-2)}
.lqz{display:flex;flex-direction:column;gap:14px;margin-top:30px}
.lqz-q{padding:18px 18px 16px;border:1px solid var(--line);border-radius:14px;background:var(--bg-elev);transition:border-color .3s}
.lqz-q.right{border-color:color-mix(in srgb,var(--st-done) 45%,var(--line))}
.lqz-q.wrong{border-color:color-mix(in srgb,var(--st-blocked) 45%,var(--line))}
.lqz-h{display:flex;align-items:baseline;gap:12px}
.lqz-n{flex:none;font-size:12px;color:var(--txt-3);font-family:"Geist Mono",monospace}
.lqz-t{flex:1;min-width:0;font-size:15px;font-weight:600;letter-spacing:-.012em;line-height:1.45;color:var(--txt)}
.lqz-v{flex:none;font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase}
.lqz-q.right .lqz-v{color:oklch(from var(--st-done) min(l, var(--ink-l)) c h)}
.lqz-q.wrong .lqz-v{color:oklch(from var(--st-blocked) min(l, var(--ink-l)) c h)}
.lqz-hint{margin:6px 0 0 24px;font-size:12px;color:var(--txt-3)}
.lqz-os{display:flex;flex-direction:column;gap:6px;margin:14px 0 0 24px}
.lqz-o{display:flex;align-items:center;gap:11px;width:100%;min-height:40px;padding:8px 12px;border:1px solid var(--line);border-radius:10px;text-align:left;font-size:13.5px;color:var(--txt-2);transition:border-color .2s,background .2s,color .2s}
.lqz-o:hover:not([aria-disabled]){border-color:var(--line-hi);color:var(--txt)}
.lqz-o.on{border-color:var(--accent);color:var(--txt);background:var(--sel)}
.lqz-o[aria-disabled]{cursor:default}
.lqz-o.ok{border-color:color-mix(in srgb,var(--st-done) 55%,var(--line));color:var(--txt);background:none}
.lqz-o.bad{border-color:color-mix(in srgb,var(--st-blocked) 55%,var(--line));background:none}
.lqz-o.dim{opacity:.55}
.lqz-mark{width:18px;height:18px;flex:none;border-radius:50%;border:1.5px solid var(--line-hi);display:grid;place-items:center;color:#fff;transition:background .2s,border-color .2s}
.lqz-mark.sq{border-radius:5px}
.lqz-mark svg{width:11px;height:11px}
.lqz-o.on .lqz-mark{background:var(--accent);border-color:var(--accent)}
.lqz-o.ok .lqz-mark{background:var(--st-done);border-color:var(--st-done);color:#04120a}
.lqz-o.bad .lqz-mark{background:var(--st-blocked);border-color:var(--st-blocked)}
.lqz-f{display:flex;align-items:center;flex-wrap:wrap;gap:12px 16px;margin-top:22px}
.lqz-count{font-size:12px;color:var(--txt-3);font-family:"Geist Mono",monospace}
.lqz-score{display:inline-flex;align-items:center;gap:10px;font-size:14px;color:var(--txt-2)}
.lqz-score b{color:var(--txt);font-weight:600}
/* a quiz that is not written yet: two faded question shapes and "Coming soon" */
.lquiz-mock{position:relative;margin-top:34px;display:grid;gap:12px}
.lq-card{display:grid;gap:9px;padding:18px;border:1px solid var(--line);border-radius:16px;background:var(--bg-elev);opacity:calc(.7 - var(--i,0) * .35)}
.lq-card i{display:block;height:9px;border-radius:5px;background:color-mix(in srgb,var(--txt) 9%,var(--bg-elev2))}
.lquiz-veil{position:absolute;inset:0;display:grid;place-items:center}
.lquiz-veil .lsoon-tag{margin:0;font-size:10.5px;padding:6px 13px;color:var(--txt-2);border-color:var(--line-hi);background:var(--bg)}

.lempty{margin:auto;max-width:420px;padding:40px 20px;text-align:center;display:flex;flex-direction:column;align-items:center;gap:12px}
.lempty h1{margin:0;font-size:22px;font-weight:600;letter-spacing:-.025em}
.lempty p{margin:0 0 6px;color:var(--txt-3);font-size:13.5px;line-height:1.55}

@keyframes l-up{from{opacity:0;transform:translate3d(0,8px,0)}}
@keyframes l-fade{from{opacity:0}}
@keyframes l-pulse{50%{background-color:var(--bg-elev2)}}
@keyframes l-pop{0%{transform:scale(.55)}55%{transform:scale(1.18)}100%{transform:scale(1)}}
@keyframes l-draw{from{stroke-dashoffset:24}to{stroke-dashoffset:0}}
@keyframes l-ring{from{stroke-dashoffset:var(--c)}}
.lstage.l-enter .lring-f{animation:l-ring 1.1s .2s var(--ease) both}

@media (max-width:900px){
  .ltop{gap:2px;padding:0 8px 0 10px}
  .ltop-ck,.ltop-sep{display:none}
  .ltop .wordmark{height:13px}
  .lic-outline{display:grid}
  .lrail{position:fixed;top:var(--ltop-h);bottom:0;left:0;z-index:41;width:min(320px,86vw);transform:translateX(-102%);transition:transform .38s var(--ease)}
  .learn.outline-open .lrail{transform:none}
  .lrail-scrim{display:block;position:fixed;inset:var(--ltop-h) 0 0;z-index:40;background:rgb(0 0 0/calc(.55*var(--shade)));opacity:0;pointer-events:none;transition:opacity .3s}
  .learn.outline-open .lrail-scrim{opacity:1;pointer-events:auto}
  .lstage{padding:30px 18px 44px}
  .lstage.lcover{padding-top:44px}
  .lkick-n{display:none}
  .lpill-hero{gap:16px}
  .lpill-num{font-size:44px}
  .lnav{grid-template-columns:auto minmax(0,1fr);padding:10px 14px;gap:10px}
  .lnav-pos,.lnav-b.prev .lnav-t{display:none}
  .lnav-b.prev{margin-left:0}
  .lout-ms{padding-left:18px}
  .lout-h{grid-template-columns:34px minmax(0,1fr);padding:16px}
  .lout-c,.llink-app,.lsoon-b{display:none}
}

/* Stage's motion goes with reduced motion: every rise, glide, pop and fill */
@media (prefers-reduced-motion:reduce){
  .learn *,.learn *::before,.learn *::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}
}
