
.v16-root{
  --ground:#bcbec4; --paper:#eaebee; --card:#ffffff; --tint:#f2f3f6;
  --ink:#0d1b2a; --ink-soft:#55606d; --ink-faint:#8d9099;
  --line:#dcdee4; --night:#07182d; --night-2:#102b49; --cream:#fdf7ea;
  --glow:#ff8f1f; --glow-soft:#ffb763; --glow-text:#8f4a00; --slate:#9db6cc;
  --good:#009966; --good-base:#00bc7d; --good-fill:rgba(0,188,125,.10); --good-line:rgba(0,188,125,.30);
  --bad:#ee343b; --bad-fill:rgba(238,52,59,.10); --bad-line:rgba(238,52,59,.30);
}
.v16-root *{box-sizing:border-box}
/* the mockup's body rule, scoped to the port root */
.v16-root{margin:0;color:var(--ink);font-family:"Inter",system-ui,sans-serif;font-size:16px;line-height:1.5;
  -webkit-font-smoothing:antialiased;min-height:100vh;
  /* padding, not child margins: a child top margin would collapse through this
     wrapper and expose the app's dark page background as a bar above the
     ground (seen live 2026-09-01) */
  padding:20px;
  background:
    radial-gradient(1100px 460px at 15% -8%, rgba(255,255,255,.55), transparent 60%),
    radial-gradient(900px 620px at 108% 40%, rgba(13,27,42,.07), transparent 55%),
    var(--ground)}
.v16-root .mono{font-family:"DM Mono",monospace}
/* headings name the family too: app/globals.css paints h1-h6 in the interior
   face with an element rule, which beats what they would inherit from
   .v16-root. GATE: __tests__/v16-heading-font.test.ts */
.v16-root h1,.v16-root h2,.v16-root h3,.v16-root h4,.v16-root h5,.v16-root h6{font-family:"Inter",system-ui,sans-serif}

/* the frame is the near-full-screen card: a small even inset on every side
   (founder direction 2026-09-01), not the mockup's 1240px artboard cap */
.v16-root .app{width:100%;margin:0;display:flex;align-items:stretch;
  background:var(--paper);border:1px solid rgba(13,27,42,.14);border-radius:30px;overflow:hidden;
  box-shadow:0 2px 4px rgba(13,27,42,.06),0 34px 80px -22px rgba(13,27,42,.3);min-height:calc(100vh - 40px)}
@media(max-width:920px){.v16-root{padding:0}.v16-root .app{border-radius:0;min-height:100vh}.v16-root .sb{display:none}}

/* ————— sidebar (approved component 01) ————— */
/* sticky within the viewport: on any page taller than the screen the pinned
   Upgrade/Help/Settings rows and the profile card used to scroll away below the
   fold (Home only escaped it by fitting one screen; found 2026-09-02 building
   the Plans and Help rooms). overflow-x stays hidden for the fold-to-rail. */
.v16-root .sb{background:var(--card);border-right:1px solid var(--line);padding:18px 12px 14px;display:flex;flex-direction:column;gap:1px;
  width:248px;max-width:248px;min-width:0;flex:none;transition:max-width .32s cubic-bezier(.3,.8,.3,1);overflow:hidden;position:sticky;top:20px;align-self:flex-start;max-height:calc(100vh - 40px);overflow-y:auto}
.v16-root .app.rail .sb{max-width:66px}
.v16-root .sb .lb{transition:opacity .18s ease, transform .22s cubic-bezier(.3,.8,.3,1);white-space:nowrap}
.v16-root .app.rail .sb .lb{opacity:0;transform:translateX(-8px);pointer-events:none}
.v16-root .app.rail .sb .grp{opacity:0;transition:opacity .15s}
.v16-root .sb .grp{transition:opacity .2s .1s;white-space:nowrap}
.v16-root .app.rail .sb a{gap:0}
.v16-root .app.rail .sb .badge,.v16-root .app.rail .sb .count{opacity:0;transition:opacity .15s}
.v16-root .sb .badge,.v16-root .sb .count{transition:opacity .2s .12s}
.v16-root .app.rail .sb .search .lb{display:none}
.v16-root .app.rail .sb .search{justify-content:center;padding:8px 0}
.v16-root .app.rail .sb .logo .wm{opacity:0;transform:translateX(-8px);width:0;overflow:hidden}
/* in the rail the logo row stacks: mark on top, the toggle right under it —
   the way back out must never be clipped away */
.v16-root .app.rail .sb .logo{flex-direction:column;align-items:center;gap:10px;padding:6px 0 14px}
.v16-root .app.rail .sb .fold{margin-left:0}
/* Base logo-row layout — the mockup rule the port lost (found live 2026-09-01:
   without flex the collapse button falls out of the row into the text flow
   and effectively disappears). Values verbatim from the mockup. */
.v16-root .sb .logo{display:flex;align-items:center;gap:9px;padding:6px 10px 14px;
  transition:padding .3s cubic-bezier(.3,.8,.3,1)}
/* the mark links home; it lays out exactly like the bare images did */
.v16-root .sb .logo .home{display:flex;align-items:center;gap:9px;color:inherit;text-decoration:none;border-radius:8px}
.v16-root .sb .logo .home:focus-visible{outline:2px solid var(--glow);outline-offset:2px}
/* 34px: the founder asked for the wordmark 30% larger than the mockup's 26 (2026-09-03) */
.v16-root .sb .logo .wm{height:34px;width:auto;display:block;
  transition:opacity .18s, transform .22s cubic-bezier(.3,.8,.3,1)}
/* the propeller mark exists only in the rail, where the wordmark cannot fit */
.v16-root .sb .logo .prop{display:none;width:34px;height:34px}
.v16-root .app.rail .sb .logo .prop{display:block}
/* Visible at rest, not only on hover — the faint bare glyph was invisible on
   the glass live (founder, 2026-09-01), so the toggle wears a bordered chip. */
.v16-root .sb .fold{cursor:pointer;border:1px solid var(--line);background:var(--tint);
  width:28px;height:28px;display:grid;place-items:center;padding:0;border-radius:8px;
  transition:transform .3s cubic-bezier(.3,.8,.3,1), background .15s}
.v16-root .sb .fold:hover{background:#e4e6ea;color:var(--ink)}
.v16-root .app.rail .sb .fold{transform:rotate(180deg)}
.v16-root .app.rail .pf-trigger .who{opacity:0;pointer-events:none;width:0;min-width:0;flex:none;overflow:hidden}
.v16-root .app.rail .pf .bend{opacity:0;pointer-events:none}
.v16-root .pf-trigger .who,.v16-root .pf .bend{transition:opacity .18s}
.v16-root .app.rail .pf-trigger{padding:6px;justify-content:center;gap:0}
/* rail hover preview: a floating label pill beside the icon (beui pattern) */
.v16-root .rail-tip{position:fixed;z-index:200;background:var(--night);color:var(--cream);
  font-size:12.5px;font-weight:500;padding:7px 13px;border-radius:9px;white-space:nowrap;
  box-shadow:0 3px 8px rgba(13,27,42,.25),0 12px 28px -8px rgba(13,27,42,.35);
  pointer-events:none;opacity:0;transform:translateX(-4px);
  transition:opacity .14s ease, transform .18s cubic-bezier(.3,.8,.3,1)}
.v16-root .rail-tip.on{opacity:1;transform:none}
.v16-root .rail-tip .n{color:var(--glow-soft);margin-left:7px;font-variant-numeric:tabular-nums}
@media (prefers-reduced-motion: reduce){.v16-root .sb,.v16-root .sb .lb,.v16-root .sb .logo .wm,.v16-root .sb .fold,.v16-root .sb .grp,.v16-root .rail-tip{transition:none}}
.v16-root .sb .logo{display:flex;align-items:center;gap:9px;padding:6px 10px 14px}
.v16-root .sb .fold{margin-left:auto;color:var(--ink-soft)}
.v16-root .sb .search{display:flex;align-items:center;gap:8px;background:var(--tint);border:1px solid var(--line);
  border-radius:10px;padding:8px 12px;margin:0 0 12px;color:var(--ink-faint);font-size:13px}
.v16-root .sb a{display:flex;align-items:center;gap:11px;padding:8px 10px;border-radius:9px;text-decoration:none;
  color:var(--ink-soft);font-size:13.5px;font-weight:500}
.v16-root .sb a:hover{background:var(--tint);color:var(--ink)}
.v16-root .sb a.on{background:var(--night);color:var(--cream)}
.v16-root .sb a svg{width:16px;height:16px;flex:none;stroke:currentColor;fill:none;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;opacity:.85}
.v16-root .sb .grp{font-family:"DM Mono",monospace;font-size:9.5px;letter-spacing:.2em;text-transform:uppercase;color:var(--ink-faint);padding:13px 10px 5px}
.v16-root .sb .badge{margin-left:auto;font-family:"DM Mono",monospace;font-size:10.5px;font-variant-numeric:tabular-nums;
  background:var(--glow);color:#26140a;border-radius:6px;padding:1px 7px;font-weight:500}
.v16-root .sb .spacer{flex:1}
/* profile dropdown — ported from the founder-picked KokonutUI reference */
.v16-root .pf{position:relative;margin-top:10px}
.v16-root .pf-trigger{display:flex;align-items:center;gap:12px;width:100%;text-align:left;font-family:inherit;
  padding:10px 12px;border:1px solid var(--line);border-radius:14px;background:var(--card);cursor:pointer;
  transition:border-color .18s, background .18s, box-shadow .18s}
.v16-root .pf-trigger:hover{border-color:#c9ccd4;background:var(--tint);box-shadow:0 1px 3px rgba(13,27,42,.06)}
.v16-root .pf-trigger:focus-visible{outline:2px solid var(--glow);outline-offset:2px}
.v16-root .pf-trigger .who{flex:1;min-width:0}
.v16-root .pf-trigger .who b{display:block;font-size:13px;font-weight:600;letter-spacing:-.01em;line-height:1.2}
.v16-root .pf-trigger .who span{display:block;font-size:11px;color:var(--ink-faint);line-height:1.3;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.v16-root .pf-trigger .av{width:36px;height:36px;border-radius:50%;padding:2px;flex:none;
  background:conic-gradient(from 210deg, var(--glow), var(--night) 55%, var(--glow-soft))}
.v16-root .pf-trigger .av i{display:flex;align-items:center;justify-content:center;width:100%;height:100%;
  border-radius:50%;background:var(--night);color:var(--cream);font-style:normal;font-weight:600;font-size:13px;
  letter-spacing:.01em;line-height:1;border:2px solid var(--card);position:relative}
.v16-root .pf-trigger .av i img{width:100%;height:100%;border-radius:50%;object-fit:cover;display:block}
.v16-root .pf-trigger .av i::after{content:"";position:absolute;right:-2px;bottom:-2px;width:9px;height:9px;border-radius:50%;
  background:var(--good);border:2px solid var(--card)}
.v16-root .pf .bend{position:absolute;right:-2px;top:50%;transform:translateY(-50%);color:var(--ink-faint);
  opacity:.6;transition:opacity .18s, color .18s}
.v16-root .pf:hover .bend{opacity:1}
.v16-root .pf.open .bend{opacity:1;color:var(--glow-text)}
.v16-root .pf-menu{position:absolute;left:0;right:0;bottom:calc(100% + 8px);background:rgba(255,255,255,.96);
  border:1px solid var(--line);border-radius:16px;padding:8px;backdrop-filter:blur(8px);
  box-shadow:0 4px 10px rgba(13,27,42,.06),0 24px 50px -12px rgba(13,27,42,.25);
  opacity:0;transform:translateY(6px) scale(.97);transform-origin:bottom center;pointer-events:none;
  transition:opacity .18s cubic-bezier(.2,.7,.2,1), transform .18s cubic-bezier(.2,.7,.2,1)}
.v16-root .pf.open .pf-menu{opacity:1;transform:none;pointer-events:auto}
.v16-root .pf-menu a,.v16-root .pf-menu button{display:flex;align-items:center;gap:11px;padding:10px 11px;border-radius:11px;border:1px solid transparent;
  text-decoration:none;color:var(--ink-soft);font-size:13px;font-weight:500;transition:background .15s,border-color .15s}
.v16-root .pf-menu button{width:100%;text-align:left;background:none;font-family:inherit;cursor:pointer}
.v16-root .pf-menu a:hover,.v16-root .pf-menu button:hover{background:var(--tint);border-color:var(--line);color:var(--ink)}
.v16-root .pf-menu a svg,.v16-root .pf-menu button svg{width:15px;height:15px;flex:none;stroke:currentColor;fill:none;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;opacity:.8}
.v16-root .pf-menu a .val{margin-left:auto;font-family:"DM Mono",monospace;font-size:10.5px;letter-spacing:.1em;color:var(--glow-text)}
.v16-root .pf-menu .sep{height:1px;background:var(--line);margin:7px 4px}
.v16-root .pf-menu button.out{color:#9c3b2e}
.v16-root .pf-menu button.out:hover{background:rgba(156,59,46,.07);border-color:rgba(156,59,46,.2)}
@media (prefers-reduced-motion: reduce){.v16-root .pf-menu{transition:none}}

/* ————— page ————— */
/* overflow:clip — the ambient .bgjet sits at right:-4% and used to push the
   document 18px wider than the viewport (a sideways scroll on Home, found
   2026-09-02 while building the Course rooms); clip, not hidden, so the page
   never becomes a scroll container of its own */
.v16-root .page{flex:1;padding:36px 44px 44px;min-width:0;display:flex;flex-direction:column;position:relative;overflow:clip}
.v16-root .bgjet{position:absolute;right:-4%;top:-30px;width:58%;max-width:700px;opacity:.12;
  pointer-events:none;user-select:none;z-index:0}
.v16-root .page > *:not(.bgjet){position:relative;z-index:1}
@media(max-width:920px){.v16-root .page{padding:26px 18px 90px}}

/* ═══ Glass dock (founder-picked direction C, 2026-09-01) ═══
   The sidebar is a floating frosted panel; the page is its own floating
   card; the silver world shows through the seam between them. */
.v16-root .app{background:transparent;border:0;box-shadow:none;overflow:visible;gap:16px}
.v16-root .sb{border-radius:22px;border:1px solid rgba(255,255,255,.65);
  background:rgba(255,255,255,.62);backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);
  box-shadow:0 2px 6px rgba(13,27,42,.08), 0 24px 60px -18px rgba(13,27,42,.35);
  overflow:hidden}
.v16-root .page{background:var(--paper);border-radius:22px;border:1px solid rgba(13,27,42,.12);
  box-shadow:0 2px 4px rgba(13,27,42,.06), 0 24px 60px -18px rgba(13,27,42,.3)}
.v16-root .sb a:hover{background:rgba(255,255,255,.78)}
/* The tapped row while its room is still on the way. Same paint as hover, so
   nothing new is drawn and nothing moves; it is the dock saying "heard you"
   for the beat before the room's loading ghost takes over. A row that is
   already the lit room keeps its night pill: .on is written after this. */
.v16-root .sb a[data-pending]{background:rgba(255,255,255,.78);color:var(--ink)}
.v16-root .sb a.on{background:var(--night);color:var(--cream)}
.v16-root .sb .search{background:rgba(255,255,255,.55);border-color:rgba(13,27,42,.08)}
.v16-root .pf-trigger{background:rgba(255,255,255,.6);border-color:rgba(255,255,255,.7)}
@media(max-width:920px){.v16-root .app{gap:0}}
/* addendum, forced: under 920px the sidebar is gone and the page IS the screen,
   so the floating-card chrome would draw a hairline and a radius against the
   viewport edge. The mockup never drew a phone layout; the r1 edge-to-edge
   phone frame is kept. Desktop, the approved composition, is untouched. */
@media(max-width:920px){.v16-root .page{border-radius:0;border:0;box-shadow:none}}

/* ————— addendum (NOT in the mockup) —————
   The mockup hides the sidebar under 920px and puts nothing in its place, which
   strands phone users with no navigation and no way to sign out. This bar uses
   only the mockup's own tokens, chrome and icon set: logo left, Review badge and
   the same profile control right. It is invisible at 921px and above, so the
   approved desktop composition is untouched. */
.v16-root .topbar{display:none}
@media(max-width:920px){
  /* full-bleed: cancels the page's own 26px/18px padding so the bar reaches
     both edges the way the sidebar reaches the frame edge on desktop */
  .v16-root .topbar{display:flex;align-items:center;gap:12px;
    background:var(--card);border-bottom:1px solid var(--line);padding:10px 14px;
    margin:-26px -18px 18px}
  /* Written against .page > .topbar, not .topbar, on purpose. The page block
     above gives every direct child of .page position:relative and z-index:1
     through .v16-root .page > *:not(.bgjet), which is one class heavier than
     a bare .v16-root .topbar: the bar's own position and stacking were being
     overruled, so it sat at the same z-index as the stat cards and lost the
     tie to them on DOM order. With the menu open the cards painted straight
     over it (founder, phone, 2026-09-03). Same specificity, declared later,
     so this one wins, and the bar owns a layer of its own above the page. */
  .v16-root .page > .topbar{position:sticky;top:0;z-index:30}
  /* and an opaque ground under the menu: the desktop dock floats the menu over
     the silver world, where .96 white reads as glass; on the phone it floats
     over the page's own cards, where the same value let a card's number show
     through the rows. */
  .v16-root .topbar .pf-menu{background:var(--card);backdrop-filter:none;-webkit-backdrop-filter:none}
  .v16-root .topbar .logo{display:flex;align-items:center}
  .v16-root .topbar .logo .wm{height:18px;width:auto;display:block}
  .v16-root .topbar .tb-right{margin-left:auto;display:flex;align-items:center;gap:10px}
  .v16-root .topbar a.tb-review{display:flex;align-items:center;gap:7px;text-decoration:none;
    color:var(--ink-soft);font-size:13px;font-weight:500;padding:6px 10px;border-radius:9px}
  .v16-root .topbar a.tb-review:hover{background:var(--tint);color:var(--ink)}
  .v16-root .topbar a.tb-review svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;opacity:.85}
  .v16-root .topbar .badge{font-family:"DM Mono",monospace;font-size:10.5px;font-variant-numeric:tabular-nums;
    background:var(--glow);color:#26140a;border-radius:6px;padding:1px 7px;font-weight:500}
  /* the same profile control, anchored to the right and opening downward */
  .v16-root .topbar .pf{margin-top:0;width:210px}
  .v16-root .topbar .pf .bend{display:none}
  .v16-root .topbar .pf-trigger{padding:6px 8px;border-radius:12px}
  .v16-root .topbar .pf-trigger .av{width:28px;height:28px}
  .v16-root .topbar .pf-trigger .av i{font-size:11px}
  .v16-root .topbar .pf-menu{bottom:auto;top:calc(100% + 8px);transform-origin:top center;
    transform:translateY(-6px) scale(.97)}
  .v16-root .topbar .pf.open .pf-menu{transform:none}
}
/* addendum, forced: the mockup declares .sb{display:none} inside its 920px
   media query BEFORE the .sb{display:flex} base rule. Media queries add no
   specificity, so the later base rule wins and the sidebar stays on screen at
   phone width, stacked above the page. The mockup's intent is not in doubt
   (the grid collapses to one column at the same breakpoint), so the identical
   declaration is repeated here, after the base rule, where it takes effect.
   No value is changed. */
@media(max-width:920px){.v16-root .sb{display:none}}
@media(max-width:520px){
  .v16-root .topbar .pf{width:auto}
  .v16-root .topbar .pf-trigger .who{display:none}
  .v16-root .topbar .pf-menu{left:auto;right:0;width:230px}
}

/* ————— the signed-out dock (2026-09-02) —————
   Where the profile card stands for a student, a visitor gets the kit's own
   card (.card.tight: 16 / 20, radius 22) carrying one primary button and one
   quiet link. Only the values the card itself cannot own are written here: the
   column, the 10 between the two controls and the 10 that sets the card off
   from the row above it, both the profile card's own numbers. The quiet link
   keeps the card's left edge: centring is opt in by name in this design and is
   for an empty state, a gate or a confirmation (brand-kit 9.4).
   In the rail the card keeps the button and nothing else, so its padding drops
   to 8 and the button gives up its side padding; the label folds away the way
   every dock label does. Nothing above is re-declared. */
.v16-root .sb .signin{display:flex;flex-direction:column;align-items:stretch;gap:10px;margin-top:10px}
.v16-root .sb .signin .btn{width:100%}
.v16-root .app.rail .sb .signin{padding:8px;gap:0}
.v16-root .app.rail .sb .signin .link{display:none}
.v16-root .app.rail .sb .signin .btn{padding:0}
.v16-root .app.rail .sb .signin .btn .lb{display:none}
@media(max-width:920px){
  /* the phone bar's own pair: the quiet link reads as a link beside the button,
     and under 520px the button is the whole offer */
  .v16-root .topbar .tb-signup{white-space:nowrap}
  .v16-root .topbar .btn{flex:none;white-space:nowrap}
}
@media(max-width:520px){.v16-root .topbar .tb-signup{display:none}}
/* ————— the phone dock (NOT in the mockup, 2026-09-03) —————
   The approved mockup hides the sidebar under 920px and draws nothing in its
   place, yet it reserves 90px at the foot of the phone page (its own
   .page{padding:26px 18px 90px}, written into the canon as "the phone page's
   bottom inset"). The reserve was there and the bar that belongs in it was
   not, so a signed-in student on a phone had no way out of the room they were
   in (founder, 2026-09-03). This dock fills that reserve with the app's ONE
   nav list: same items, same icons, same lit-row rule as the desktop dock, so
   it is a second surface for one navigation and never a second navigation.

   It is a sibling of the page card, not a child, so it stands in a stacking
   context of its own and no page content can paint over it.

   The row does NOT scroll sideways. It carries the five rooms flagged
   phoneDock in shell/nav.tsx, evenly spaced, plus More, which opens the sheet
   below holding the rest of the list. The founder made that call after the
   first version shipped a sideways-scrolling row: a student should never have
   to swipe a bar to find out what the app contains (2026-09-03). */
.v16-root .pdock{display:none}
@media(max-width:920px){
  .v16-root .pdock{position:fixed;left:0;right:0;bottom:0;z-index:40;
    display:flex;align-items:stretch;gap:2px;
    background:var(--card);border-top:1px solid var(--line);
    padding:6px 8px calc(6px + env(safe-area-inset-bottom))}
  /* Six equal columns. flex-basis 0 with min-width 0 is what makes them equal
     rather than content-sized, so "Mock tests" cannot buy width from "Home". */
  .v16-root .pdock a,.v16-root .pdock .pmore-btn{position:relative;flex:1 1 0;min-width:0;
    display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;
    padding:6px 2px;border-radius:12px;text-decoration:none;border:0;background:none;
    font:inherit;cursor:pointer;
    color:var(--ink-soft);font-size:10px;font-weight:500;line-height:1.2;white-space:nowrap}
  .v16-root .pdock .lb{max-width:100%;overflow:hidden;text-overflow:ellipsis}
  .v16-root .pdock a svg,.v16-root .pdock .pmore-btn svg{width:18px;height:18px;flex:none;
    stroke:currentColor;fill:none;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;opacity:.85}
  .v16-root .pdock a.on,.v16-root .pdock .pmore-btn.on{background:var(--night);color:var(--cream)}
  .v16-root .pdock a.on svg,.v16-root .pdock .pmore-btn.on svg{opacity:1}
  /* The tapped row, before the room arrives. A phone has no hover state, so
     this IS the acknowledgement; it borrows the desktop dock's hover tint
     rather than adding a spinner or any mark of its own. */
  .v16-root .pdock a[data-pending]{background:var(--tint);color:var(--ink)}
  .v16-root .pdock a[data-pending] svg{opacity:1}
  .v16-root .pdock .badge{position:absolute;top:2px;right:8px;
    font-family:"DM Mono",monospace;font-size:9.5px;font-variant-numeric:tabular-nums;
    background:var(--glow);color:#26140a;border-radius:6px;padding:0 4px;font-weight:500}

  /* The More sheet. A child of the dock, positioned at bottom:100% of it, so
     it sits on the dock's true top edge without anyone writing the dock's
     height down as a number that would then drift. */
  .v16-root .pmore-scrim{position:fixed;inset:0;z-index:38}
  .v16-root .pmore{position:absolute;left:0;right:0;bottom:100%;z-index:39;
    background:var(--card);border:1px solid var(--line);border-bottom:0;
    border-radius:22px 22px 0 0;padding:8px 8px 12px;
    display:flex;flex-direction:column;gap:2px;
    box-shadow:0 -12px 32px rgba(13,27,42,.14)}
  .v16-root .pmore .pmore-row{position:relative;flex:none;min-width:0;
    display:flex;flex-direction:row;align-items:center;justify-content:flex-start;gap:12px;
    padding:10px 12px;border-radius:12px;text-decoration:none;
    color:var(--ink-soft);font-size:13px;font-weight:500;line-height:1.2;white-space:nowrap}
  .v16-root .pmore .pmore-row svg{width:18px;height:18px;flex:none;
    stroke:currentColor;fill:none;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;opacity:.85}
  .v16-root .pmore .pmore-row.on{background:var(--night);color:var(--cream)}
  .v16-root .pmore .pmore-row.on svg{opacity:1}
  .v16-root .pmore .pmore-row .badge{position:static;margin-left:auto}
}

/* header */
.v16-root .hd .kick{font-size:13.5px;font-weight:500;color:var(--ink-faint);margin:0}
.v16-root .hd h1{font-weight:600;font-size:26px;letter-spacing:-.025em;line-height:1.15;margin:4px 0 0}
.v16-root .hd h1 b{font-weight:600}
.v16-root .stats{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:22px}
@media(max-width:760px){.v16-root .stats{grid-template-columns:1fr;gap:10px}}
.v16-root .inst{background:var(--card);border:1px solid var(--line);border-radius:14px;
  box-shadow:0 1px 2px rgba(13,27,42,.05);padding:16px 20px;display:flex;align-items:center;gap:14px}
.v16-root .inst .itile{width:38px;height:38px;border-radius:12px;flex:none;
  background:linear-gradient(135deg,#1d3d61,var(--night));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.12), 0 1px 2px rgba(13,27,42,.18);
  display:flex;align-items:center;justify-content:center;color:#fdf7ea}
.v16-root .inst .itile svg{width:19px;height:19px;stroke:currentColor;fill:none;stroke-width:2.1;stroke-linecap:round;stroke-linejoin:round}
.v16-root .inst .l{font-size:12.5px;font-weight:500;color:var(--ink-faint);line-height:1.3}
.v16-root .inst .v{font-size:20px;font-weight:600;font-variant-numeric:tabular-nums;line-height:1.2;letter-spacing:-.02em}
.v16-root .inst .v small{font-size:12.5px;font-weight:500;color:var(--ink-faint)}

/* ————— tonight's flight: the hero continue card ————— */
.v16-root .hero{margin-top:16px;background:
  radial-gradient(700px 300px at 85% -30%, rgba(157,182,204,.16), transparent 60%),
  var(--night);
  color:var(--cream);border-radius:24px;padding:28px 32px;position:relative;overflow:hidden;
  display:flex;gap:28px;align-items:center;justify-content:space-between}
@media(max-width:760px){.v16-root .hero{flex-direction:column;align-items:stretch;padding:24px 22px;gap:18px}}
.v16-root .hero .k2{display:flex;align-items:center;gap:10px;margin:0 0 2px}
.v16-root .hero .k2 .chip{font-size:11px;font-weight:600;letter-spacing:.02em;padding:4px 11px;border-radius:999px;
  background:rgba(255,143,31,.16);color:var(--glow-soft)}
.v16-root .hero .k2 span:last-child{font-size:13px;font-weight:500;color:var(--slate)}
.v16-root .hero h2{font-weight:300;font-size:clamp(22px,2.8vw,30px);letter-spacing:-.03em;margin:8px 0 0;color:var(--cream);line-height:1.15}
.v16-root .hero h2 b{font-weight:600}
.v16-root .hero .sub{color:var(--slate);font-size:14px;margin:8px 0 0;max-width:52ch}
.v16-root .hero .go{flex:none}
@media(max-width:760px){.v16-root .hero .go .btn{width:100%}}

.v16-root .btn{display:inline-flex;align-items:center;justify-content:center;gap:9px;min-height:46px;padding:0 28px;
  border-radius:999px;border:1px solid transparent;font-weight:500;font-size:15px;font-family:inherit;cursor:pointer;
  transition:transform .14s,box-shadow .14s,background .14s;text-decoration:none}
.v16-root .btn-primary{background:var(--glow);color:#26140a}
.v16-root .btn-primary:hover{background:#ffa03c;transform:translateY(-1px);box-shadow:0 3px 6px rgba(160,70,0,.3),0 16px 36px rgba(255,143,31,.5)}
.v16-root .btn-quiet{background:var(--card);color:var(--ink);border-color:var(--line)}
.v16-root .btn-quiet:hover{border-color:var(--ink-faint);box-shadow:0 2px 4px rgba(13,27,42,.08)}
/* a button that carries a glyph draws it at the dock's own size. Without this
   a bare <svg viewBox> falls back to the 300x150 replaced-element default and
   blows the button open; the dock's sign-in button only escaped it because
   the dock's own icon rule happens to catch it, and the phone bar's did not
   (found looking at the signed-out phone bar, 2026-09-02). */
.v16-root .btn svg{width:16px;height:16px;flex:none;stroke:currentColor;fill:none;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
.v16-root .link{font-size:13.5px;color:var(--ink-faint);text-decoration:none}
.v16-root .link:hover{color:var(--ink)}

/* ————— below deck: two columns ————— */
.v16-root .deck{display:grid;grid-template-columns:1.6fr 1fr;gap:16px;margin-top:16px;flex:1;align-items:start}
@media(max-width:920px){.v16-root .deck{grid-template-columns:1fr}}
.v16-root .panel{background:var(--card);border:1px solid var(--line);border-radius:14px;
  box-shadow:0 1px 2px rgba(13,27,42,.05);overflow:hidden}
.v16-root .panel .ph{display:flex;align-items:center;gap:12px;padding:18px 22px;border-bottom:1px solid var(--tint)}
.v16-root .panel .ph .tt h3{font-size:15.5px;font-weight:600;letter-spacing:-.01em;margin:0}
.v16-root .panel .ph .tt p{margin:2px 0 0;font-size:12.5px;color:var(--ink-faint)}
.v16-root .panel .ph .all{margin-left:auto}
.v16-root .panel .pc-body{padding:6px 22px 10px}

/* subject rows with mini routes */
.v16-root .srow{display:grid;grid-template-columns:38px 176px 1fr auto 14px;gap:16px;align-items:center;
  padding:14px 0;border-top:1px solid var(--tint);text-decoration:none;color:var(--ink)}
.v16-root .srow:first-of-type{border-top:none}
.v16-root .srow .ico{width:38px;height:38px;border-radius:12px;flex:none;
  background:linear-gradient(135deg,#1d3d61,var(--night));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.12), 0 1px 2px rgba(13,27,42,.18);
  display:flex;align-items:center;justify-content:center;color:#fdf7ea}
.v16-root .srow .ico svg{width:18px;height:18px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.v16-root .srow .nm{font-size:14px;font-weight:500;line-height:1.25}
.v16-root .srow .nm small{display:block;font-weight:400;font-size:12px;color:var(--ink-faint);margin-top:2px}
.v16-root .srow .bar{height:7px;border-radius:999px;background:var(--tint);overflow:hidden}
.v16-root .srow .bar i{display:block;height:100%;border-radius:999px;background:var(--glow)}
.v16-root .srow .pc{font-size:13px;color:var(--ink-faint);font-variant-numeric:tabular-nums;text-align:right;min-width:44px}
.v16-root .srow .pc b{color:var(--ink);font-weight:600;font-size:14px}
.v16-root .srow .chev{color:var(--ink-faint);transition:transform .15s}
.v16-root .srow:hover .chev{transform:translateX(2px);color:var(--ink)}
.v16-root .srow:hover .nm{color:var(--ink)}
@media(max-width:560px){.v16-root .srow{grid-template-columns:38px 1fr auto 14px}.v16-root .srow .bar{display:none}}

/* right column stack */
.v16-root .stack{display:flex;flex-direction:column;gap:16px}
.v16-root .stat-card{background:var(--card);border:1px solid var(--line);border-radius:14px;
  box-shadow:0 1px 2px rgba(13,27,42,.05);padding:20px 22px}
.v16-root .stat-card .srt{display:flex;align-items:center;gap:12px}
.v16-root .stat-card .tile{width:40px;height:40px;border-radius:13px;display:flex;align-items:center;justify-content:center;flex:none;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.25), 0 1px 3px rgba(13,27,42,.2);color:#fff}
.v16-root .stat-card .tile.amber{background:linear-gradient(135deg,#ffb763,var(--glow));color:#26140a}
.v16-root .stat-card .tile.navy{background:linear-gradient(135deg,#1d3d61,var(--night));color:#fdf7ea}
.v16-root .stat-card .tile svg{width:20px;height:20px;stroke:currentColor;fill:none;stroke-width:2.1;stroke-linecap:round;stroke-linejoin:round}
.v16-root .stat-card .srt .lbl{font-size:13px;font-weight:500;color:var(--ink-faint)}
.v16-root .stat-card .big{font-size:30px;font-weight:600;letter-spacing:-.02em;line-height:1.1;margin-top:12px;font-variant-numeric:tabular-nums}
.v16-root .stat-card .big .pill{display:inline-block;font-size:11.5px;font-weight:600;vertical-align:4px;margin-left:8px;
  border-radius:999px;padding:3px 9px;background:rgba(255,143,31,.14);color:var(--glow-text)}
.v16-root .stat-card .big .pill.ok{background:var(--good-fill);color:var(--good)}
.v16-root .stat-card p{margin:6px 0 0;font-size:13px;color:var(--ink-soft);max-width:34ch}
.v16-root .stat-card .foot{margin-top:14px;padding-top:14px;border-top:1px solid var(--tint);display:flex;align-items:center}

/* reveal */
.v16-root .rv{opacity:0;transform:translateY(14px);animation:v16rv .7s cubic-bezier(.2,.7,.2,1) forwards}
.v16-root .rv.d1{animation-delay:.07s}.v16-root .rv.d2{animation-delay:.14s}.v16-root .rv.d3{animation-delay:.24s}.v16-root .rv.d4{animation-delay:.34s}
@keyframes v16rv{to{opacity:1;transform:none}}
@media (prefers-reduced-motion: reduce){.v16-root .rv{animation:none;opacity:1;transform:none}}

/* ═══ Soft islands (founder-picked card direction A, 2026-09-01) ═══
   Borders dissolve; cards are paper islands on the silver ground, held by
   layered shadow, radius matched to the dock (22). Values verbatim from the
   approved mockup (.v16-port/dashboard-home-approved-r3.html). */
.v16-root .inst,.v16-root .panel,.v16-root .stat-card{border:0;border-radius:22px;
  box-shadow:0 1px 2px rgba(13,27,42,.05), 0 10px 30px -12px rgba(13,27,42,.18);
  transition:box-shadow .18s, transform .18s}
.v16-root .inst:hover,.v16-root .stat-card:hover{box-shadow:0 2px 4px rgba(13,27,42,.06), 0 16px 40px -12px rgba(13,27,42,.24);
  transform:translateY(-1px)}
.v16-root .panel .ph{border-bottom:0;padding-bottom:8px}
.v16-root .srow{border-top:1px solid rgba(13,27,42,.04)}
.v16-root .stat-card .foot{border-top:1px solid rgba(13,27,42,.05)}
.v16-root .hero{border-radius:22px;box-shadow:0 2px 6px rgba(13,27,42,.15), 0 22px 50px -16px rgba(7,24,45,.5)}
@media (prefers-reduced-motion: reduce){.v16-root .inst,.v16-root .stat-card{transition:none}}
/* ---- chip on a light surface + chip-line (founder, 2026-09-02, landing try-card) ---- */
.v16-root .chip{font-size:11px;font-weight:600;letter-spacing:.02em;padding:4px 11px;border-radius:999px;
  background:rgba(255,143,31,.16);color:var(--glow-soft)}
.v16-root .chip.light{color:var(--glow-text)}
.v16-root .chip-line{display:flex;align-items:center;gap:10px;margin:0}
.v16-root .chip-line span:last-child{font-size:13px;font-weight:500;color:var(--slate)}
.v16-root .chip-line.light span:last-child{color:var(--ink-soft)}
/* ---- count line: weighted number, plain label, amber point (landing subject cards) ---- */
.v16-root .count-line{display:flex;align-items:center;gap:8px;font-size:13px;font-weight:300;color:var(--ink-soft);margin:0;white-space:nowrap}
.v16-root .count-line b{font-weight:500;color:var(--ink);font-variant-numeric:tabular-nums}
.v16-root .count-line i{width:5px;height:5px;border-radius:50%;background:var(--glow);flex:none}
.v16-root .count-line.night{color:var(--slate)}
.v16-root .count-line.night b{color:var(--cream)}

/* SPACING CANON (brand-kit 9.4, founder 2026-09-02: "fix the padding, the
   alignment and maintain uniformity"). Every value below is the approved
   dashboard's own, lifted out of the one page that already had it so a room
   inherits the rhythm instead of improvising it. Nothing here changes what
   Home renders: Home uses none of these class names, and the two button sizes
   restate the values it already writes inline.

   The audit that produced it measured thirteen review rooms against Home and
   found three header gaps (16 / 20 / 22), two form-control heights (44 / 46),
   two segmented-control shapes and two generic list rows, because two crews
   invented the same parts twice. A room that needs a part the kit lacks adds
   it HERE. */

/* the page header's one sentence of context (brand-kit 9.2 rule 5): the same
   register as a panel header's description, on a readable measure */
.v16-root .hd .lead{margin:8px 0 0;font-size:14px;font-weight:400;line-height:1.45;
  color:var(--ink-soft);max-width:62ch}

/* the section stack. Home spaces its sections with a margin-top on each one
   (22 under the header, then 16, 16); a room that wraps its sections in this
   gets the identical rhythm from one place and cannot drift. The margin reset
   lets .stats, .hero and .deck keep their own rule outside the stack. */
.v16-root .sections{display:flex;flex-direction:column;gap:16px;flex:1;min-width:0}
/* !important, on purpose (rollout crews 2026-09-02): a room's own rule of the
   same specificity declared later, say ".v16-root .card{margin-top:16px}",
   used to beat this reset on the tie and double the gap. The stack's gap is the
   only rhythm between sections, so nothing may re-add a margin here, whatever
   its order or weight. GATE: __tests__/v16-kit-parts.test.tsx */
.v16-root .sections > *{margin-top:0!important}
.v16-root .hd + .sections{margin-top:22px}

/* the plain card: the stat card's chrome with none of its anatomy, and the
   only three paddings a card is allowed. Tight is the reading card's, default
   the stat card's, roomy the night band's. */
.v16-root .card{background:var(--card);border-radius:22px;padding:20px 22px;
  box-shadow:0 1px 2px rgba(13,27,42,.05), 0 10px 30px -12px rgba(13,27,42,.18)}
.v16-root .card.tight{padding:16px 20px}
.v16-root .card.roomy{padding:28px 32px}

/* the generic list row: a subject row's metrics without its five fixed
   columns, for the rows that carry a fact or a control instead of a bar */
.v16-root .lrow{display:flex;align-items:center;gap:16px;padding:14px 0;
  border-top:1px solid rgba(13,27,42,.04);text-decoration:none;color:var(--ink)}
.v16-root .lrow:first-of-type{border-top:none}
.v16-root .lrow .rt{margin-left:auto;flex:none}

/* the action row. Right-aligned on desktop, gap taken from the panel header's
   own control gap; under 760px it stacks full width, which is what the night
   band already does with its one button at the same breakpoint. */
.v16-root .actions{display:flex;align-items:center;justify-content:flex-end;gap:12px;flex-wrap:wrap}
.v16-root .actions.start{justify-content:flex-start}
@media(max-width:760px){
  .v16-root .actions{flex-direction:column;align-items:stretch}
  .v16-root .actions > .btn{width:100%}
}

/* the two button sizes, no third. Home writes the compact one inline on the
   Review card; this is the same 38 / 0 18 / 13.5 as a class so a room stops
   inventing 36, 40 and 44. */
.v16-root .btn.sm{min-height:38px;padding:0 18px;font-size:13.5px}
.v16-root .btn.wide{width:100%}
/* a control that cannot be pressed says so: the kit had no disabled state, so
   the runner's Reset chapter looked identical whether or not there was
   anything to clear. Hover is cancelled with it, on both tones. */
.v16-root .btn:disabled{opacity:.42;cursor:default}
.v16-root .btn:disabled:hover{background:var(--card);border-color:var(--line);transform:none;box-shadow:none}
.v16-root .btn-primary:disabled:hover{background:var(--glow)}

/* centred text is for an empty state, a gate and a confirmation. An app room
   is left aligned everywhere else, so centring is opt-in and named. */
.v16-root .centred{text-align:center}

/* KIT PARTS, ROUND 2 (2026-09-02). The two rollout crews that brought the
   thirteen review rooms onto the canon each listed the same missing parts, and
   each had faked them locally with different numbers. They are designed once
   here, on the scale, and every room inherits them. Still only new class names:
   nothing below re-targets a selector the soft islands painted. */

/* the form field: label above, control, optional hint below. One height, the
   full button's 46, so a field and the button beside it share a baseline. One
   radius, 12: the corner the kit already gives its 38px tiles (.ico, .itile)
   and the phone profile trigger, between the dock row's 9 and the profile
   card's 14. A control is deliberately NOT a pill: the pill is the button's
   shape, and a student should see where they type apart from where they tap.
   The utility rooms' local 10 belonged to the dock's search box, a 34px
   control, and is too tight a corner on 46. */
.v16-root .field{display:flex;flex-direction:column;gap:6px;min-width:0}
.v16-root .field .fl{font-size:13px;font-weight:500;color:var(--ink-soft);margin:0}
.v16-root .field input,.v16-root .field select,.v16-root .field textarea{width:100%;min-height:46px;padding:0 16px;
  border-radius:12px;border:1px solid var(--line);background:var(--card);color:var(--ink);
  font-family:inherit;font-size:15px;line-height:1.4;outline:none;transition:border-color .14s,box-shadow .14s}
.v16-root .field textarea{padding:12px 16px;min-height:92px;resize:vertical}
.v16-root .field input::placeholder,.v16-root .field textarea::placeholder{color:var(--ink-faint)}
.v16-root .field input:hover,.v16-root .field select:hover,.v16-root .field textarea:hover{border-color:var(--ink-faint)}
.v16-root .field input:focus-visible,.v16-root .field select:focus-visible,.v16-root .field textarea:focus-visible{
  border-color:var(--glow);box-shadow:0 0 0 3px rgba(255,143,31,.22)}
.v16-root .field .fh{font-size:12.5px;line-height:1.4;color:var(--ink-faint);margin:0}
.v16-root .field.bad input,.v16-root .field.bad select,.v16-root .field.bad textarea{border-color:var(--bad)}
.v16-root .field.bad .fh{color:var(--bad)}

/* the segmented control: the small button's 38 / 0 18 / 13.5 in a row, in the
   dashboard's own chip language (the pill, radius 999, like every chip, pill
   and button on Home) with the dock's night-on-cream for the chosen one. The
   4px well is the only spacing that is the control's own; the chosen pill sits
   inside it the way the night pill sits inside the dock. */
.v16-root .segmented{display:inline-flex;align-items:center;flex-wrap:wrap;gap:4px;padding:4px;max-width:100%;
  border-radius:999px;background:var(--tint)}
.v16-root .segmented button{min-height:38px;padding:0 18px;font-size:13.5px;font-weight:500;font-family:inherit;
  border-radius:999px;border:0;background:transparent;color:var(--ink-soft);cursor:pointer;
  transition:background .14s,color .14s}
.v16-root .segmented button:hover{color:var(--ink);background:rgba(255,255,255,.7)}
.v16-root .segmented button.on{background:var(--night);color:var(--cream)}
.v16-root .segmented button:focus-visible{outline:2px solid var(--glow);outline-offset:2px}

/* the lit row: a featured row tints without insetting. The tint bleeds 12
   outward on both sides and the same 12 of side padding brings the content
   back, so the row's text keeps exactly its siblings' left edge (Cadet and
   Flight computer had faked this with an inline tint plus an inset, which
   walked their rows out of line). The hairlines on its two edges give way to
   the tint so the block reads as one shape. */
.v16-root .lrow.lit,.v16-root .srow.lit{background:var(--tint);border-radius:12px;margin:0 -12px;
  padding-left:12px;padding-right:12px;border-top-color:transparent}
.v16-root .lrow.lit + .lrow,.v16-root .srow.lit + .srow{border-top-color:transparent}

/* the caption: one muted line tied to the block above it, 12 below the block
   and flush with its left edge, replacing the sims rooms' local .cap */
.v16-root .caption{margin:12px 0 0;font-size:12.5px;line-height:1.4;color:var(--ink-faint);max-width:62ch}

/* the plain column: a 16-gapped column with nothing else attached, for a wide
   deck column of exam rows. .stack stays the narrow right-hand side's; a room
   with a wide column of rows takes this instead of borrowing .sections. */
.v16-root .col{display:flex;flex-direction:column;gap:16px;min-width:0}

/* the in-panel action row: an .actions row that closes a panel takes the
   panel's own 22 side padding, 8 down from the body's 10 (18 between the last
   row and the buttons, the header's own top) and 22 to the panel's edge. */
.v16-root .panel .pc-actions{padding:8px 22px 22px}

/* THE QUESTION RUNNER (2026-09-04). The parts the founder-approved practice
   runner mockup draws (.v16-port/rooms/practice-runner.html, pick B: one card
   per question). Only new class names: nothing here re-targets a selector an
   earlier block painted, and the one shared name it touches, .card, is reached
   through the runner's own .qlist so no other room's card moves. Values are
   the mockup's own, verbatim. */

/* the page header, when a room hangs its actions off the right of the title
   block. Opt in by name so every other room's header is untouched. */
.v16-root .hd.split{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;flex-wrap:wrap}
.v16-root .hd.split .right{display:flex;align-items:center;gap:12px;flex:none}
.v16-root .hd.split .count-line{margin-top:8px}
/* On a phone the right cluster already drops below the title, and its
   controls do not shrink, so they wrap among themselves rather than pushing
   the page sideways. Nothing moves at a width where they still fit. */
@media(max-width:560px){.v16-root .hd.split .right{flex:1 1 100%;flex-wrap:wrap;row-gap:10px}}

/* the header switch (.v16-port/rooms/practice-revision.html, founder pick B
   "toggle", 2026-09-05). A page-level on/off that changes what the room shows
   rather than doing anything, so it is a checkbox wearing a track, not a
   button. Values are the mockup's own, verbatim. */
.v16-root .hd .right .swx{display:flex;align-items:center;gap:10px;font-size:13.5px;font-weight:500;color:var(--ink-soft);cursor:pointer;user-select:none}
.v16-root .swx input{position:absolute;opacity:0;width:0;height:0}
.v16-root .swx .track{width:44px;height:26px;border-radius:999px;background:var(--tint);border:1px solid var(--line);position:relative;flex:none;transition:background .16s,border-color .16s}
.v16-root .swx .track::after{content:"";position:absolute;top:2px;left:2px;width:20px;height:20px;border-radius:50%;background:var(--card);
  box-shadow:0 1px 2px rgba(13,27,42,.25);transition:transform .18s cubic-bezier(.3,.8,.3,1)}
.v16-root .swx input:checked + .track{background:var(--night);border-color:var(--night)}
.v16-root .swx input:checked + .track::after{transform:translateX(18px)}
.v16-root .swx input:focus-visible + .track{outline:2px solid var(--glow);outline-offset:2px}

/* one card per question, in a 16-gapped column. A marked card lifts, so a
   student scrolling back can see at a glance which ones they have done. */
.v16-root .qlist{display:flex;flex-direction:column;gap:16px}
.v16-root .qlist .card{padding:22px 24px}
.v16-root .qlist .card:has(.q.marked){box-shadow:0 1px 2px rgba(13,27,42,.05), 0 10px 30px -12px rgba(13,27,42,.10)}

/* the foot of a chapter that is still arriving. A long chapter reaches the
   room a window at a time, so this quiet line sits under the last card until
   the next one lands, and is absent entirely once they all have. */
.v16-root .qmore{display:flex;justify-content:center;padding:18px 0;font-size:13.5px;color:var(--ink-faint)}
.v16-root .qmore p{margin:0}

/* the question block */
.v16-root .q{display:flex;flex-direction:column;gap:14px}
.v16-root .q .qk{font-size:12.5px;font-weight:500;color:var(--ink-faint);margin:0;display:flex;align-items:center;gap:10px}
.v16-root .q .qk .done{margin-left:auto;font-size:12px;font-weight:500}
.v16-root .q .qk .done.ok{color:var(--good)}
.v16-root .q .qk .done.no{color:var(--bad)}
.v16-root .q .qt{margin:0;font-size:16px;font-weight:500;line-height:1.45;max-width:66ch;text-wrap:pretty}
.v16-root .q .qt p{margin:0}
.v16-root .q .qt p + p{margin-top:8px}
.v16-root .q .qfig{max-width:520px;width:100%;height:auto;border-radius:12px;border:1px solid var(--line)}
/* a pipe table inside the stem. Some questions print their givens as a table
   and the markdown renderer emits a real one, so the kit paints it: hairline
   rows on the day surface, and a wrapper that scrolls a wide table inside the
   card rather than widening the page. */
.v16-root .q .qt .qtable{overflow-x:auto;border:1px solid var(--line);border-radius:12px;margin:12px 0}
.v16-root .q .qt table{width:100%;border-collapse:collapse;font-size:13.5px;font-variant-numeric:tabular-nums}
.v16-root .q .qt th{padding:8px 12px;font-weight:600;color:var(--ink);background:var(--tint);text-align:left}
.v16-root .q .qt td{padding:8px 12px;text-align:left;border-top:1px solid var(--line)}

/* the answer table (components/ui/AviationTable, surface="v16"): the question's
   own table when its cells are what the student fills in. Same day card as the
   question it sits in, and the cells are the kit's field control at a compact
   height. */
.v16-root .atable{border:1px solid var(--line);border-radius:12px;background:var(--card);overflow:hidden;margin:12px 0}
.v16-root .atable .atable-title{padding:8px 12px;font-size:13px;font-weight:600;color:var(--ink);background:var(--tint);border-bottom:1px solid var(--line)}
.v16-root .atable .atable-scroll{overflow-x:auto}
.v16-root .atable table{width:100%;border-collapse:collapse;font-size:13.5px;font-variant-numeric:tabular-nums}
/* left aligned like every other table in the app: an app room reads from one
   left edge, and centring is opt in by name (canon 9.4). The legacy cockpit
   table centred its cells; tabular figures keep the columns lined up without
   it. */
.v16-root .atable th{padding:8px 12px;font-weight:600;color:var(--ink);background:var(--tint);text-align:left}
.v16-root .atable td{padding:8px 12px;text-align:left;color:var(--ink-soft);white-space:pre-wrap;border-top:1px solid var(--line)}
.v16-root .atable input{min-width:64px;min-height:34px;width:100%;padding:0 10px;border-radius:8px;border:1px solid var(--line);
  background:var(--card);color:var(--ink);font-family:inherit;font-size:13.5px;outline:none;
  transition:border-color .14s,box-shadow .14s}
.v16-root .atable input:hover{border-color:var(--ink-faint)}
.v16-root .atable input:focus-visible{border-color:var(--glow);box-shadow:0 0 0 3px rgba(255,143,31,.22)}
.v16-root .atable input.atable-inline{display:inline-block;width:72px;min-width:44px;margin:0 6px;vertical-align:middle}

.v16-root .opts{display:flex;flex-direction:column;gap:8px}
.v16-root .opt{display:flex;align-items:center;gap:14px;text-align:left;width:100%;
  padding:10px 14px 10px 10px;border-radius:12px;border:1px solid var(--line);background:var(--card);
  color:var(--ink);font:inherit;font-size:14.5px;line-height:1.4;cursor:pointer;transition:border-color .14s,background .14s}
.v16-root .opt:hover{border-color:var(--ink-faint);background:var(--tint)}
/* An option that has been tapped and whose grade has not come back yet. Same
   declarations as :hover above — the mockup's one touched state, reused, not a
   second appearance invented for waiting. */
.v16-root .opt[aria-pressed="true"]{border-color:var(--ink-faint);background:var(--tint)}
.v16-root .opt:focus-visible{outline:2px solid var(--glow);outline-offset:2px}
.v16-root .opt i{width:30px;height:30px;border-radius:10px;flex:none;display:grid;place-items:center;
  background:var(--tint);color:var(--ink-soft);font-style:normal;font-size:12.5px;font-weight:600}
.v16-root .q.marked .opt{cursor:default}
.v16-root .q.marked .opt:hover{border-color:var(--line);background:var(--card)}
.v16-root .opt.good{background:var(--good-fill);border-color:var(--good-line)}
.v16-root .opt.good i{background:var(--good);color:#fff}
.v16-root .opt.bad{background:var(--bad-fill);border-color:var(--bad-line)}
.v16-root .opt.bad i{background:var(--bad);color:#fff}

/* a typed answer: the kit field beside the small primary button */
.v16-root .num{display:flex;align-items:flex-end;gap:10px;max-width:420px}
.v16-root .num .field{flex:1}
.v16-root .num .field input{min-height:38px;font-size:14.5px}
.v16-root .parts{display:flex;flex-direction:column;gap:12px;max-width:420px}
/* the button under a stack of sub-part fields is the numeric row's button, at
   its own width on the left, not a full-width bar. */
.v16-root .parts > .btn{align-self:flex-start}

/* the answer line: one sentence of result, then the way into the working */
.v16-root .ans{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin:0;font-size:14px}
.v16-root .ans b{font-weight:600}
.v16-root .ans.ok b{color:var(--good)}
.v16-root .ans.no b{color:var(--bad)}
.v16-root .ans .btn{margin-left:auto}
/* a second control on the same line sits beside the first, not at the other
   end of it: only the leading button takes the free space. */
.v16-root .ans .btn ~ .btn{margin-left:0}
/* the revision answer line: a statement, not a verdict. The value is green
   because it is the right answer, but nothing about the line says the student
   got it, because nothing was marked. */
.v16-root .ans.rev{color:var(--ink-soft)}
.v16-root .ans.rev b{color:var(--good);font-weight:600}

/* the working: teaching sits on the sky panel (founder pick E, "sky deeper",
   2026-09-04). The navy night panel it replaces was not readable enough; the
   night surface is now reserved for the one flight card and the exam readout.
   Values are the frozen mockup's .work.sky2 rules, verbatim. */
.v16-root .work{background:linear-gradient(180deg,rgba(157,182,204,.30),rgba(157,182,204,.16));
  border:1px solid rgba(79,128,158,.40);
  color:var(--ink);border-radius:22px;padding:22px 24px;
  box-shadow:none;display:flex;flex-direction:column;gap:14px}
.v16-root .work p{margin:0;font-size:14.5px;line-height:1.55;color:var(--ink);max-width:66ch}
.v16-root .work .whead{display:flex;align-items:center;gap:10px;margin:0 0 2px}
.v16-root .work .whead .chip{font-size:11px;font-weight:600;letter-spacing:.02em;padding:4px 11px;
  border-radius:999px;background:var(--night);color:var(--cream)}
.v16-root .work .whead span:last-child{font-size:13px;font-weight:500;color:#1d3d61}
.v16-root .work .terms{display:flex;flex-wrap:wrap;gap:8px}
.v16-root .work .term{font-size:12px;font-weight:500;padding:5px 11px;border-radius:999px;
  background:var(--card);border:1px solid rgba(157,182,204,.6);color:var(--ink-soft)}
.v16-root .work .term b{color:var(--night-2);font-weight:600;margin-right:6px}
.v16-root .work .step{display:grid;grid-template-columns:28px 1fr;gap:12px;align-items:start}
.v16-root .work .step i{width:28px;height:28px;border-radius:9px;display:grid;place-items:center;font-style:normal;
  font-size:12.5px;font-weight:600;background:linear-gradient(135deg,#1d3d61,var(--night));color:#fdf7ea}
.v16-root .work .step h4{margin:0 0 3px;font-size:14px;font-weight:600;color:var(--night-2)}
.v16-root .work .eq{font-family:"DM Mono",monospace;font-size:14px;line-height:1.7;color:var(--ink);
  background:var(--card);border:1px solid rgba(157,182,204,.6);border-radius:12px;padding:12px 16px;white-space:pre}
.v16-root .work ul{margin:0;padding-left:20px;font-size:14.5px;line-height:1.6;color:var(--ink)}
.v16-root .work .final{display:flex;align-items:center;gap:10px;padding-top:12px;
  border-top:1px solid rgba(79,128,158,.30);font-size:14px;color:#1d3d61}
.v16-root .work .final b{color:var(--night-2);font-weight:600;font-size:17px}
/* KaTeX draws the equation as spans, which the mockup's typed-working well
   sets in white-space:pre. Rendered math takes the same well, wrapping
   normally, and inherits the well's ink. */
.v16-root .work .eq.math{white-space:normal;color:var(--ink)}
.v16-root .work .eq.math .katex{color:var(--ink)}
.v16-root .work table{width:100%;border-collapse:collapse;font-size:14px;color:var(--ink);
  background:var(--card);border:1px solid rgba(157,182,204,.6);border-radius:12px;overflow:hidden}
.v16-root .work th,.v16-root .work td{padding:8px 12px;text-align:left;border-bottom:1px solid rgba(157,182,204,.6)}
.v16-root .work th{color:var(--night-2);font-weight:600}
.v16-root .work .fig img{display:block;width:100%;max-width:520px;height:auto;border-radius:12px;
  background:var(--card);border:1px solid rgba(157,182,204,.6)}
.v16-root .work .fig svg{background:var(--card);border:1px solid rgba(157,182,204,.6)}
.v16-root .work .fig text{fill:var(--ink)}
.v16-root .work .wa{display:flex;gap:10px;justify-content:flex-end;flex-wrap:wrap}
.v16-root .work .btn-quiet{background:var(--card);color:var(--ink);border-color:rgba(157,182,204,.7)}
.v16-root .work .btn-quiet:hover{border-color:rgba(79,128,158,.7);box-shadow:none}

/* the floating tool pill: one control, pinned, above the page and under the
   dock's own sheets (dock 40, More sheet 39, rail tip 200). Values are the
   approved CX3 popup probe's minimised pill, verbatim. */
.v16-root .floatpill{position:fixed;right:20px;bottom:20px;z-index:50;
  display:inline-flex;align-items:center;gap:10px;min-height:46px;padding:0 20px 0 16px;
  border-radius:999px;border:0;background:var(--night);color:var(--cream);
  font:inherit;font-weight:500;font-size:14px;cursor:pointer;
  box-shadow:0 10px 30px -12px rgba(13,27,42,.5)}
.v16-root .floatpill svg{width:18px;height:18px;flex:none;fill:none;
  stroke:var(--glow);stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.v16-root .floatpill:focus-visible{outline:2px solid var(--glow);outline-offset:2px}
/* under 920px the phone dock owns the bottom edge, so the pill sits above it
   and above the device's own home indicator. */
@media(max-width:920px){
  .v16-root .floatpill{right:16px;bottom:calc(76px + env(safe-area-inset-bottom))}
}

/* THE GATE (2026-09-04). The system pages: the 404, the two error boundaries,
   the sign-in error, the account on hold and the phone step. All six are the
   same card, from the founder-approved mockup
   (.v16-port/rooms/system-pages.html), and its values are that mockup's own.

   Two contexts. .gatewrap centres the card in a signed-in room, inside the
   page card. .bare is the signed-out composition: the wordmark above the
   card, both centred on the silver ground with no dock at all.

   The one selector that is not the mockup's verbatim is the field: the mockup
   writes .field.left because its own markup is a bare <label>, and the kit
   renders the field through the Field primitive, which carries no room class.
   Inside a gate there is only ever the one field, so it is reached by name.
   Same declarations, same rendering. */
.v16-root .gatewrap{flex:1;display:flex;align-items:center;justify-content:center;min-height:calc(100vh - 160px)}
.v16-root .gate{max-width:520px;width:100%;display:flex;flex-direction:column;align-items:center;gap:12px}
.v16-root .gate .mark{width:44px;height:44px;margin-bottom:4px}
.v16-root .gate .mark svg{width:100%;height:100%}
.v16-root .gate .ro{margin:0;font-size:13px;letter-spacing:.1em;color:var(--ink-faint)}
.v16-root .gate h2{margin:0;font-size:26px;font-weight:600;letter-spacing:-.025em;line-height:1.15;text-wrap:balance}
.v16-root .gate .lead{margin:0;font-size:14px;line-height:1.45;color:var(--ink-soft);max-width:44ch}
.v16-root .gate .ref{margin:0;font-size:12.5px;color:var(--ink-faint)}
.v16-root .gate .ref .mono{color:var(--ink-soft)}
.v16-root .gate .actions.centre{justify-content:center;margin-top:10px}
.v16-root .gate .field{width:100%;max-width:360px;text-align:left;margin-top:6px}
.v16-root .bare{min-height:calc(100vh - 40px);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:28px}
.v16-root .bare .wm{height:34px;width:auto}
@media(max-width:920px){.v16-root .gatewrap{min-height:60vh}}

/* THE EXAM RUNNER (2026-09-04). The mock paper while it is being sat, from the
   founder-approved mockup (.v16-port/rooms/mock-runner.html, founder pick F
   "instrument"). Its values are that mockup's own.

   These are the kit's, not the mocks room's, because a timed paper is not only
   the mocks room: the header that carries a clock, the question column, the
   bottom sheet that holds the whole paper and the confirm dialog that guards
   an irreversible submit are all shapes the RTR exam and the cadet battery
   will want.

   The design is the quiet one. The founder looked at a desk layout with a
   side column first and found it busy, so there is no side column and no
   notes: one header line carrying the paper, its clock and the way out, one
   question under it, and the whole paper behind a floating pill.

   Two selectors are not the mockup's verbatim. The mockup writes .qcard for
   the question card because its markup is hand-written; the kit renders that
   card through the QuestionCard primitive, whose class is .card, so inside
   .exam it is reached by that name. Same element, same declarations, same
   rendering. And .pal button centres its number with place-items rather than
   leaving it to the browser: the founder saw the numbers in the answered tiles
   sitting against the left edge. */
.v16-root .examcol{max-width:760px;margin:0 auto;width:100%}
.v16-root .examcol.wide{max-width:860px}
/* A fixed overlay reserves the space it covers (audit 2026-09-10, H1).
   At maximum scroll on a 375px screen the exam room's own last control, the
   Previous / Flag / Next row, sat underneath the floating palette pill and the
   phone dock, so a tap on Next hit the pill and a student could not leave
   question one by the obvious control. Nothing about the pill moves: its
   corner, its inset and its size stay the mockup's verbatim. The column
   reserves the pill's footprint instead, so the action row is always ABOVE the
   pill's band and the counter is never on the action line.

   --float-foot is the pill's top edge measured from the bottom of the
   viewport: its own inset plus its 46px height. --page-foot is what
   shell/styles.ts already reserves at the foot of .page (44px, 90px on a
   phone), so the column adds only the difference plus one gap and never pads
   twice for the same pixels. */
.v16-root .examcol{--float-foot:66px;--page-foot:44px;--float-gap:16px;
  padding-bottom:max(0px,calc(var(--float-foot) + var(--float-gap) - var(--page-foot)))}
@media(max-width:920px){
  .v16-root .examcol{--float-foot:calc(122px + env(safe-area-inset-bottom));--page-foot:90px}
}
/* An Air Navigation paper floats a second pill, the flight computer, one step
   above the palette (.floatpill.above), so the room says so and the column
   reserves that taller footprint instead. */
.v16-root .examcol.twofloats{--float-foot:122px}
@media(max-width:920px){
  .v16-root .examcol.twofloats{--float-foot:calc(178px + env(safe-area-inset-bottom))}
}
/* the instrument header: what the paper is on the left, what the clock and the
   paper say on the right, in one navy readout beside the way out. */
.v16-root .inst-hd{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:22px}
.v16-root .inst-hd .kick{margin:0;font-size:14px;color:var(--ink-soft)}
.v16-root .inst-hd h1{margin:2px 0 0;font-size:22px;font-weight:600;letter-spacing:-.02em}
.v16-root .inst-hd .right{display:flex;align-items:center;gap:12px;flex:none}
.v16-root .readout{display:flex;align-items:center;gap:10px;background:var(--night);color:var(--cream);border-radius:12px;padding:7px 12px;box-shadow:0 2px 6px rgba(13,27,42,.15), 0 12px 30px -14px rgba(7,24,45,.5)}
.v16-root .readout .l{font-size:10.5px;color:var(--slate);font-weight:500;line-height:1.2}
.v16-root .readout .t{font-family:"DM Mono",monospace;font-size:19px;font-weight:500;letter-spacing:-.02em;color:var(--glow-soft);font-variant-numeric:tabular-nums;line-height:1.1}
/* Under five minutes the readout's clock steps up to the full amber. The
   mockup drew only the resting state; the warn state is the kit's own --glow,
   one step brighter than the soft amber beside it, so the change is legible on
   navy without introducing a colour the palette does not have. */
.v16-root .readout .t.warn{color:var(--glow)}
.v16-root .readout .sep{width:1px;height:22px;background:rgba(255,255,255,.12)}
.v16-root .readout .n{font-family:"DM Mono",monospace;font-size:15px;color:var(--cream);font-variant-numeric:tabular-nums}
.v16-root .readout .n small{font-size:12px;color:var(--slate)}
.v16-root .exam{display:grid;gap:16px;align-items:start}
.v16-root .exam.f{grid-template-columns:1fr}
.v16-root .exam .card{padding:22px 24px}
.v16-root .exam.f .card .qk{margin-bottom:2px}
.v16-root .exam.f .card .qt{font-size:17px;line-height:1.5}
.v16-root .exam.f .opts{gap:10px;margin-top:6px}
.v16-root .exam.f .opt{font-size:15px;padding:12px 16px 12px 12px}
/* the option key as an instrument tile, the same navy gradient squircle the
   kit gives every other tile; picked, it turns amber. */
.v16-root .exam.f .opt i{background:linear-gradient(135deg,#1d3d61,var(--night));color:#fdf7ea;box-shadow:inset 0 1px 0 rgba(255,255,255,.12), 0 1px 2px rgba(13,27,42,.18)}
.v16-root .exam.f .opt.picked{border-color:var(--glow);background:rgba(255,143,31,.08)}
.v16-root .exam.f .opt.picked i{background:linear-gradient(135deg,#ffb763,var(--glow));color:#26140a}
.v16-root .nav{display:flex;align-items:center;gap:12px;margin-top:18px}
.v16-root .nav .sp{flex:1}
.v16-root .nav .btn{white-space:nowrap}
/* the runner's one line of plain text (a save that did not land, or the paper
   being handed over) sits between the card and the controls. */
.v16-root .exam.f .ans{margin-top:14px}
.v16-root .flag{display:inline-flex;align-items:center;gap:8px}
.v16-root .flag .lb-s{display:none}
.v16-root .flag.on{border-color:var(--glow);background:rgba(255,143,31,.14);color:var(--glow-text)}
.v16-root .flag svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.v16-root .flag.on svg{fill:var(--glow);stroke:var(--glow)}
/* the paper at a glance, which in this layout lives only in the sheet */
.v16-root .pal{display:grid;grid-template-columns:repeat(7,1fr);gap:5px;margin-top:14px}
.v16-root .pal button{position:relative;height:28px;border-radius:8px;border:1px solid var(--line);background:var(--card);color:var(--ink-soft);font:inherit;font-size:12px;font-weight:500;font-variant-numeric:tabular-nums;cursor:pointer;padding:0;display:grid;place-items:center;line-height:1}
.v16-root .pal button.ans{background:var(--night);border-color:var(--night);color:var(--cream)}
.v16-root .pal button.flg{border-color:var(--glow);color:var(--glow-text);background:rgba(255,143,31,.10)}
.v16-root .pal button.ans.flg{background:var(--night);border-color:var(--glow);color:var(--cream)}
.v16-root .pal button.ans.flg::after{content:"";position:absolute;top:3px;right:3px;width:5px;height:5px;border-radius:50%;background:var(--glow)}
.v16-root .pal button.cur{outline:2px solid var(--glow);outline-offset:2px}
.v16-root .pal button:focus-visible{outline:2px solid var(--glow);outline-offset:2px}
.v16-root .legend{display:flex;flex-wrap:wrap;gap:10px 14px;margin:14px 0 0;font-size:12.5px;color:var(--ink-faint)}
.v16-root .legend span{display:inline-flex;align-items:center;gap:6px}
.v16-root .legend i{width:12px;height:12px;border-radius:4px;border:1px solid var(--line);background:var(--card)}
.v16-root .legend i.ans{background:var(--night);border-color:var(--night)}
.v16-root .legend i.flg{border-color:var(--glow);background:rgba(255,143,31,.10)}
/* the palette sheet: the whole paper, at every width */
.v16-root .sheet{position:fixed;inset:0;z-index:70;display:flex;align-items:flex-end;justify-content:center;background:rgba(7,24,45,.35)}
.v16-root .sheet .card{width:min(560px,100%);border-radius:22px 22px 0 0;max-height:80vh;overflow:auto}
.v16-root .sheet .ph{display:flex;align-items:center;gap:12px;margin-bottom:4px}
.v16-root .sheet .ph h3{margin:0;font-size:15.5px;font-weight:600}
.v16-root .sheet .ph .cnt{font-size:13px;color:var(--ink-soft)}
.v16-root .sheet .ph .x{margin-left:auto}
.v16-root .sheet .btn.wide{margin-top:14px}
/* the submit confirmation: a paper cannot be unsubmitted */
.v16-root .confirm{position:fixed;inset:0;z-index:80;display:flex;align-items:center;justify-content:center;background:rgba(7,24,45,.45);padding:20px}
.v16-root .confirm .card{max-width:440px;width:100%}
.v16-root .confirm h3{margin:0 0 6px;font-size:20px;font-weight:600;letter-spacing:-.02em}
.v16-root .confirm p{margin:0;font-size:14px;color:var(--ink-soft);line-height:1.45}
.v16-root .confirm .actions{margin-top:18px}
/* Under 920px the header wraps to two rows, so the paper's name keeps its own
   line and the readout and Submit share the one under it, and the flag button
   drops to its short label so the three controls never wrap. */
@media(max-width:920px){
  .v16-root .inst-hd{flex-wrap:wrap}
  .v16-root .inst-hd .right{flex:1 1 100%;justify-content:space-between}
  .v16-root .nav{gap:10px}
  .v16-root .nav .flag .lb{display:none}
  .v16-root .nav .flag .lb-s{display:inline}
}
/* An Air Navigation paper has two floating controls: the palette, which is the
   paper's whole navigation and keeps the mockup's own corner, and the flight
   computer, which steps 56px up so neither ever covers the other. On a phone
   both clear the dock and the device's home indicator. */
.v16-root .floatpill.above{bottom:76px}
@media(max-width:920px){
  .v16-root .floatpill.above{bottom:calc(132px + env(safe-area-inset-bottom))}
}

/* ---------------------------------------------------------------------------
   THE APP-WIDE OVERLAYS (2026-09-04). The toast layer, the offline strip and
   the flight-computer window are mounted by the app layout, outside any room,
   and portalled to the body. They are wrapped in .v16-root so the tokens
   resolve; .v16-overlay then takes back the three things the root rule does to
   a PAGE (its padding, its silver ground and its full-viewport height), which
   an overlay must not inherit, and it is display:contents so it adds no box
   of its own to whatever it was mounted in.

   Nothing above this point declares any of these names, so the block adds to
   the cascade without joining it.
--------------------------------------------------------------------------- */
.v16-root.v16-overlay{display:contents;padding:0;background:none;min-height:0}

/* the toast: one paper card, a tone dot and the sentence. Bottom centre, and
   on a phone above the dock, by the same offset rule the floating pill uses. */
.v16-root .v16-toasts{position:fixed;bottom:20px;right:20px;z-index:90;
  display:flex;flex-direction:column;align-items:flex-end;gap:10px;pointer-events:none}
.v16-root .v16-toast{pointer-events:auto;display:flex;align-items:center;gap:10px;
  max-width:min(420px,calc(100vw - 32px));padding:11px 12px 11px 14px;
  background:var(--card);border:1px solid var(--line);border-radius:14px;
  box-shadow:0 1px 2px rgba(13,27,42,.05), 0 10px 30px -12px rgba(13,27,42,.18);
  font-family:"Inter",system-ui,sans-serif;font-size:13.5px;line-height:1.45;color:var(--ink)}
.v16-root .v16-toast i{width:5px;height:5px;border-radius:50%;flex:none;background:var(--glow)}
.v16-root .v16-toast.good i{background:var(--good)}
.v16-root .v16-toast.bad i{background:var(--bad)}
.v16-root .v16-toast span{flex:1;min-width:0}
.v16-root .v16-toast button{flex:none;width:24px;height:24px;border:0;border-radius:999px;
  background:none;color:var(--ink-faint);cursor:pointer;display:grid;place-items:center;font:inherit}
.v16-root .v16-toast button:hover{background:var(--tint);color:var(--ink)}
.v16-root .v16-toast button svg{width:13px;height:13px;fill:none;stroke:currentColor;
  stroke-width:2;stroke-linecap:round}
.v16-root .v16-toast button:focus-visible{outline:2px solid var(--glow);outline-offset:2px}
@media(max-width:920px){
  .v16-root .v16-toasts{left:16px;right:16px;align-items:center;
    bottom:calc(76px + env(safe-area-inset-bottom))}
  .v16-root .v16-toast{width:100%}
}
@media(prefers-reduced-motion:no-preference){
  .v16-root .v16-toast{animation:v16-toast-in .18s ease-out}
  @keyframes v16-toast-in{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
}

/* the offline strip: the chip line on a paper strip, sticky at the top of
   whatever it is mounted in. */
.v16-root .v16-offline{position:sticky;top:0;z-index:45;display:flex;align-items:center;gap:9px;
  margin:14px 24px 0;padding:10px 16px;background:var(--card);border:1px solid var(--line);
  border-radius:14px;box-shadow:0 1px 2px rgba(13,27,42,.05);
  font-family:"Inter",system-ui,sans-serif;font-size:13.5px;line-height:1.45;color:var(--ink)}
.v16-root .v16-offline i{width:5px;height:5px;border-radius:50%;flex:none;background:var(--bad)}

/* THE FLIGHT-COMPUTER WINDOW. Values are the approved CX-3 popup probe's own,
   moved here from components/tools/cx3-popup.css so the window is drawn from
   the kit like every other part. The frame keeps a definite 460x620: their
   build measures its viewport once at load, so a frame that resizes renders
   the tool squashed. */
.v16-root .v16-cx3-open{display:flex;align-items:center;gap:6px;min-height:44px;padding:0 2px;
  border:0;background:none;color:var(--ink-soft);font:inherit;font-size:12.5px;font-weight:600;
  white-space:nowrap;cursor:pointer}
.v16-root .v16-cx3-open:hover{color:var(--ink)}
.v16-root .v16-cx3-open svg{width:14px;height:14px;stroke:currentColor;stroke-width:2;fill:none;
  stroke-linecap:round}
.v16-root .v16-cx3{position:fixed;left:max(20px, calc(100vw - 500px));top:80px;width:460px;
  background:var(--card);border-radius:22px;
  box-shadow:0 1px 2px rgba(13,27,42,.08), 0 24px 60px -18px rgba(13,27,42,.45);
  overflow:hidden;z-index:60;display:none;touch-action:none;color:var(--ink)}
.v16-root .v16-cx3.is-open{display:block}
.v16-root .v16-cx3.is-dragging{box-shadow:0 1px 2px rgba(13,27,42,.1), 0 34px 80px -18px rgba(13,27,42,.55)}
.v16-root .v16-cx3-bar{display:flex;align-items:center;gap:12px;padding:10px 12px 10px 18px;
  background:var(--night);color:var(--cream);cursor:grab;user-select:none}
.v16-root .v16-cx3-bar:active{cursor:grabbing}
.v16-root .v16-cx3-title{flex:1;display:flex;align-items:center;gap:10px;font-size:13px;
  font-weight:600;letter-spacing:.02em}
.v16-root .v16-cx3-grip{width:18px;height:10px;border-radius:2px;opacity:.6;
  background:repeating-linear-gradient(90deg, var(--slate) 0 2px, transparent 2px 4px)}
.v16-root .v16-cx3-btn{width:32px;height:32px;border-radius:999px;border:0;
  background:rgba(255,255,255,.08);color:var(--cream);cursor:pointer;display:grid;place-items:center;
  font:inherit}
.v16-root .v16-cx3-btn:hover{background:rgba(255,255,255,.16)}
.v16-root .v16-cx3-btn svg{width:14px;height:14px;stroke:currentColor;stroke-width:2;fill:none;
  stroke-linecap:round}
.v16-root .v16-cx3-frame{position:relative;width:460px;height:620px;background:var(--tint)}
.v16-root .v16-cx3-frame iframe{display:block;width:100%;height:100%;border:0}
.v16-root .v16-cx3-note{position:absolute;inset:0;margin:0;display:grid;place-items:center;padding:24px;
  font-size:13px;color:var(--ink-faint);pointer-events:none}
.v16-root .v16-cx3-foot{display:flex;justify-content:flex-end;align-items:center;padding:8px 18px;
  font-size:12px;white-space:nowrap;color:var(--ink-faint);background:var(--card);
  border-top:1px solid var(--tint)}
.v16-root .v16-cx3-foot a{color:var(--ink-soft)}
.v16-root .v16-cx3-open:focus-visible,.v16-root .v16-cx3-btn:focus-visible{
  outline:2px solid var(--glow);outline-offset:2px}
@media(max-width:640px){
  .v16-root .v16-cx3{left:0 !important;right:0;top:auto !important;bottom:0;width:100%;
    border-radius:22px 22px 0 0;max-height:92vh}
  .v16-root .v16-cx3-bar{cursor:default}
  .v16-root .v16-cx3-open{min-height:32px}
  .v16-root .v16-cx3-frame{width:100%;height:min(620px, calc(92vh - 92px))}
  .v16-root .v16-cx3-frame iframe{width:460px;height:620px;transform-origin:0 0}
}
@media(prefers-reduced-motion:no-preference){
  .v16-root .v16-cx3.is-open{animation:v16-cx3-in .18s ease-out}
  @keyframes v16-cx3-in{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
}

/* the term-definition popover, on the sky panel. Same element the two legacy
   surfaces draw with their own classes; here it is paper, kit ink and Inter. */
.v16-root .v16-termpop{position:fixed;z-index:50;width:280px;max-width:calc(100vw - 24px);
  padding:10px 12px;background:var(--card);border:1px solid var(--line);border-radius:12px;
  box-shadow:0 1px 2px rgba(13,27,42,.05), 0 10px 30px -12px rgba(13,27,42,.30);
  font-family:"Inter",system-ui,sans-serif;font-size:13.5px;line-height:1.45;color:var(--ink);
  text-align:left;white-space:normal;font-weight:400}
.v16-root .v16-termpop b{display:block;margin-bottom:3px;font-size:12px;font-weight:600;
  color:var(--night-2)}
.v16-root .v16-termpop span{display:block;color:var(--ink-soft)}

/* THE CONTENTS LIST (2026-09-05). The founder-picked chapter room, look A
   "Resume first": one card holding every lesson of the chapter in order, the
   modules reduced to quiet dividers inside it, and two calm assessment rows
   under it. Values are the approved mockup's own
   (.v16-port/rooms/course-chapter-approved.html), appended here in the order
   the mockup wrote them, after the kit rules they lean on.

   Only new class names, with three deliberate exceptions the mockup itself
   draws: the number, name and chevron cells inside .lrow, the lit lesson row
   (a taller tint than the generic one, because the row carries two lines), and
   the count line inside the night band. None of the three reaches a room that
   does not draw a contents list. */
.v16-root .card.lessons{padding:10px 22px 14px}
.v16-root .lrow.lesson{gap:14px;padding:13px 0}
.v16-root .lrow .num{flex:none;width:26px;text-align:right;
  font-family:"DM Mono",monospace;font-size:13px;font-variant-numeric:tabular-nums;
  color:var(--ink-faint);font-weight:400}
.v16-root .lrow .num.now{color:var(--ink);font-weight:500}
.v16-root .lrow .nm{font-size:14.5px;font-weight:500;line-height:1.3;min-width:0}
.v16-root .lrow .nm small{display:block;font-weight:400;font-size:12.5px;
  color:var(--ink-faint);margin-top:3px;line-height:1.4}
.v16-root .lrow .chev{color:var(--ink-faint);flex:none;display:flex;align-items:center}
.v16-root .lrow .chev svg{width:14px;height:14px;stroke-width:1.8}
.v16-root .lrow:hover .chev{color:var(--ink)}
.v16-root .lrow.lesson:hover{background:rgba(13,27,42,.02)}
.v16-root .st{font-size:12.5px;color:var(--ink-faint);white-space:nowrap;
  display:inline-flex;align-items:center;gap:6px}
.v16-root .st.now{color:var(--glow-text);font-weight:500}
.v16-root .st.now i{width:6px;height:6px;border-radius:50%;background:var(--glow);flex:none}
.v16-root .gdiv{font-size:12.5px;font-weight:500;color:var(--ink-faint);
  padding:20px 0 4px;border-top:1px solid rgba(13,27,42,.06);margin-top:8px}
.v16-root .card.lessons > .gdiv:first-child{border-top:0;margin-top:0;padding-top:10px}
.v16-root .lrow.lesson.lit{background:var(--tint);border-radius:14px;
  margin:6px -14px;padding:14px;border-top-color:transparent}
.v16-root .lrow.lesson.lit + .lrow{border-top-color:transparent}

/* the assessment row: the chapter's checkpoint and its placement check, each a
   night tile, a name, a sentence and one small quiet control */
.v16-root .lrow.arow{gap:14px;padding:16px 0}
.v16-root .atile{flex:none;width:36px;height:36px;border-radius:11px;background:var(--night);
  color:var(--cream);display:flex;align-items:center;justify-content:center}
.v16-root .atile svg{width:17px;height:17px;fill:none;stroke:currentColor;stroke-width:1.8;
  stroke-linecap:round;stroke-linejoin:round}
.v16-root .arow .nm{font-size:14.5px;font-weight:500}

/* the next chapter row that ends the page */
.v16-root a.card.nextch{display:flex;align-items:center;gap:14px;text-decoration:none}
.v16-root .nextch .nm{font-size:14px;font-weight:500}
.v16-root .nextch .nm small{display:block;font-weight:400;font-size:12.5px;color:var(--ink-faint);margin-top:3px}
.v16-root .nextch .chev{margin-left:auto;color:var(--ink-faint);flex:none}

/* a stat card that carries a sentence where the figure would be: with no
   .big above it the sentence takes the number's own top margin. Approved on
   the dashboard's Refer a friend card (probe tab 2, 2026-09-06). */
.v16-root .stat-card.refcard p{margin:12px 0 0}

/* the night band's own count line sits 14 under the sentence above it */
.v16-root .hero .count-line{margin-top:14px}

/* on a phone the list keeps its rhythm and gives back its side padding */
@media(max-width:760px){
  .v16-root .card.lessons{padding:8px 16px 12px}
  .v16-root .lrow.lesson{gap:12px}
  .v16-root .lrow .nm{font-size:14px}
  .v16-root .st{font-size:12px}
  .v16-root .lrow.lesson.lit{margin:6px -10px;padding:14px 10px}
}

/* the trail above a page's header (components/v16/primitives/crumb.tsx).
   It was declared five times over, identically, in the blog, catalog, compare
   and shared-cost sheets; it is one block here. Class based, never
   element qualified, so the nav the kit draws is styled as the p was. */
.v16-root .crumb{display:flex;flex-wrap:wrap;align-items:center;gap:7px;margin:0 0 14px;
  font-size:12.5px;color:var(--ink-faint)}
.v16-root .crumb a{color:var(--ink-soft);text-decoration:none}
.v16-root .crumb a:hover{color:var(--ink);text-decoration:underline;text-underline-offset:2px}
.v16-root .crumb i{font-style:normal;opacity:.5}
.v16-root .crumb b{font-weight:500;color:var(--ink)}

/* the section boundary marker (components/v16/primitives/eyebrow.tsx). The
   same six rules were declared in the blog, catalog and guide-stepper sheets
   and again, with an 18px margin, in the directory and cost sheets. The base
   is here; the 18px margin and the phone label wrap stay in the sheets that
   picked them, after this block, exactly where they were. */
.v16-root .eyebrow{display:flex;align-items:center;gap:10px;margin:0 0 12px}
.v16-root .eyebrow i{width:16px;height:5px;border-radius:999px;background:var(--glow);flex:none}
.v16-root .eyebrow span{font-family:"DM Mono",ui-monospace,monospace;font-size:11px;
  letter-spacing:.14em;text-transform:uppercase;color:var(--ink-faint);white-space:nowrap}
.v16-root .eyebrow em{font-style:normal;margin-left:auto;font-size:12.5px;color:var(--ink-faint);
  font-weight:400;text-align:right}
@media(max-width:560px){.v16-root .eyebrow em{display:none}}

/* the key-facts row (components/v16/primitives/facts-strip.tsx). The same
   rules were declared in the blog, guide-stepper and hub sheets. The hub's
   .worked .facts-strip two-column override stays in that sheet, after this
   block, where it was. */
.v16-root .facts-strip{display:grid;grid-template-columns:repeat(4,1fr);gap:12px}
@media(max-width:900px){.v16-root .facts-strip{grid-template-columns:repeat(2,1fr)}}
@media(max-width:420px){.v16-root .facts-strip{grid-template-columns:1fr}}
.v16-root .facts-strip.three{grid-template-columns:repeat(3,1fr)}
@media(max-width:900px){.v16-root .facts-strip.three{grid-template-columns:repeat(2,1fr)}}
@media(max-width:420px){.v16-root .facts-strip.three{grid-template-columns:1fr}}
.v16-root .fact{background:var(--card);border-radius:16px;padding:16px 16px 15px;
  box-shadow:0 1px 2px rgba(13,27,42,.05), 0 10px 30px -14px rgba(13,27,42,.16)}
.v16-root .fact .d{width:6px;height:6px;border-radius:50%;background:var(--glow);display:block;
  margin-bottom:10px}
.v16-root .fact b{display:block;font-size:14px;font-weight:600;letter-spacing:-.01em;line-height:1.25}
.v16-root .fact span{display:block;margin-top:6px;font-size:12.5px;line-height:1.5;color:var(--ink-soft)}

/* the night band that closes a public page
   (components/v16/primitives/practice-cta.tsx). The guides, cost and directory
   sheets each declared it. The cost and directory sheets keep their own
   margin-top:4px, after this block, where it was. */
.v16-root .cta{background:linear-gradient(160deg,#102b49,var(--night));border-radius:22px;
  padding:26px 30px;color:var(--cream);display:flex;gap:22px;align-items:center;
  justify-content:space-between;flex-wrap:wrap;
  box-shadow:0 2px 6px rgba(13,27,42,.15), 0 22px 50px -16px rgba(7,24,45,.5)}
.v16-root .cta h3{font-size:20px;font-weight:600;letter-spacing:-.02em;margin:0;color:var(--cream)}
.v16-root .cta p{margin:8px 0 0;font-size:13.5px;color:var(--slate);max-width:52ch}
.v16-root .cta .acts{display:flex;gap:10px;flex-wrap:wrap}
@media(max-width:640px){
  .v16-root .cta{padding:22px 20px;flex-direction:column;align-items:stretch}
  .v16-root .cta .acts{flex-direction:column}
  .v16-root .cta .btn{width:100%}
}
.v16-root .cta .btn-quiet{background:rgba(255,255,255,.08);color:var(--cream);
  border-color:rgba(157,182,204,.35)}

/* the onward rows, two up on a wide screen, and the quiet line that closes the
   page (components/v16/primitives/onward.tsx). Declared in the blog, catalog,
   compare and guide-stepper sheets. The blog's own second-row rule for its
   .srow rows stays in that sheet, after this block, where it was. */
@media(min-width:900px){
  .v16-root .lrows2{display:grid;grid-template-columns:1fr 1fr;column-gap:28px}
  .v16-root .lrows2 .lrow:nth-child(2){border-top:0}
}
.v16-root .endline{font-size:13.5px;color:var(--ink-soft);text-align:center;padding:6px 0 0}
.v16-root .endline a{color:var(--ink);text-decoration:underline;text-underline-offset:2px}

/* the night worked-solution stage (drawn by the catalog account module and by
   the comparison pages). The same rules were declared in both sheets; the SVG
   text classes each room's drawing uses stay in the sheet that sizes them. */
.v16-root .stage{background:linear-gradient(162deg,#0e2c4c,var(--night));border-radius:22px;
  padding:16px 16px 14px;color:var(--cream);min-width:0;
  box-shadow:0 2px 6px rgba(13,27,42,.18), 0 26px 60px -20px rgba(7,24,45,.6)}
.v16-root .stage .sbar{display:flex;align-items:center;gap:10px;padding:2px 4px 12px}
.v16-root .stage .sbar .lb{font-family:"DM Mono",ui-monospace,monospace;font-size:10px;
  letter-spacing:.16em;text-transform:uppercase;color:var(--slate)}
.v16-root .stage .tabs{margin-left:auto;display:flex;gap:5px;background:rgba(255,255,255,.06);
  border-radius:999px;padding:3px;flex-wrap:wrap;justify-content:flex-end}
.v16-root .stage .tabs span{font-family:"DM Mono",ui-monospace,monospace;font-size:9.5px;
  letter-spacing:.1em;text-transform:uppercase;padding:5px 10px;border-radius:999px;color:var(--slate)}
.v16-root .stage .tabs span.on{background:var(--glow);color:#26140a}
@media(max-width:560px){
  .v16-root .stage .sbar{flex-wrap:wrap;gap:10px 8px}
  .v16-root .stage .tabs{margin-left:0;width:100%;justify-content:flex-start;flex-wrap:nowrap}
  .v16-root .stage .tabs span{padding:5px 9px;font-size:9.5px;letter-spacing:.08em}}
.v16-root .stage .canvas{border-radius:16px;background:rgba(3,12,24,.55);
  border:1px solid rgba(157,182,204,.16);overflow:hidden}
.v16-root .stage .canvas svg{display:block;width:100%;height:auto}
.v16-root .stage .cap{display:flex;gap:11px;align-items:flex-start;padding:14px 6px 4px}
.v16-root .stage .cap i{width:5px;height:5px;border-radius:50%;background:var(--glow);flex:none;
  margin-top:7px;box-shadow:0 0 0 4px rgba(255,143,31,.18)}
.v16-root .stage .cap p{margin:0;font-size:13.5px;line-height:1.5;color:var(--cream);max-width:52ch}
.v16-root .stage .scrub{display:flex;align-items:center;gap:10px;padding:10px 6px 2px}
.v16-root .stage .scrub .tk{flex:1;height:4px;border-radius:999px;background:rgba(157,182,204,.24);
  position:relative;overflow:hidden}
.v16-root .stage .scrub .tk i{position:absolute;left:0;top:0;bottom:0;width:58%;border-radius:999px;
  background:var(--glow)}
.v16-root .stage .scrub .st{font-family:"DM Mono",ui-monospace,monospace;font-size:10px;
  letter-spacing:.12em;text-transform:uppercase;color:var(--slate);white-space:nowrap}
.v16-root .stage .dots{display:flex;gap:5px}
.v16-root .stage .dots i{width:6px;height:6px;border-radius:50%;background:rgba(157,182,204,.35)}
.v16-root .stage .dots i.on{background:var(--glow)}

/* the drawn admit card (components/v16/primitives/admit-glyphs.tsx and the two
   rooms that build a card on it). The blog article header and the past-paper
   hero declared these rules identically; each keeps only its own last slot,
   the article's .art and the hub's .bars, after this block. */
.v16-root .admit{position:relative;border-radius:20px;overflow:hidden;color:var(--cream);
  background:linear-gradient(155deg,#123655,var(--night));padding:20px 22px 18px 30px;
  box-shadow:0 2px 6px rgba(13,27,42,.16), 0 26px 60px -20px rgba(7,24,45,.55)}
@media(min-width:820px){.v16-root .admit{padding:26px 30px 24px 40px}}
.v16-root .admit .perf{position:absolute;left:0;top:0;bottom:0;width:16px}
.v16-root .admit .perf svg{width:16px;height:100%;display:block}
.v16-root .admit .glow{position:absolute;right:-70px;top:-90px;width:250px;height:250px;border-radius:50%;
  background:radial-gradient(circle,rgba(255,143,31,.22),transparent 65%);pointer-events:none}
.v16-root .admit .arow{display:flex;align-items:flex-start;justify-content:space-between;gap:14px;
  position:relative;z-index:1}
.v16-root .admit .org{font-family:"DM Mono",ui-monospace,monospace;font-size:9.5px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--slate);line-height:1.7;margin:0}
.v16-root .admit .org b{display:block;color:var(--glow-soft);font-weight:500}
.v16-root .admit .stamp{flex:none;width:56px;height:56px}
.v16-root .admit .stamp svg{width:100%;height:100%;display:block}
@media(max-width:400px){.v16-root .admit .stamp{width:46px;height:46px}}
.v16-root .admit .ttl{font-size:26px;font-weight:400;letter-spacing:-.02em;
  line-height:1.1;margin:16px 0 0;color:var(--cream);position:relative;z-index:1}
@media(min-width:820px){.v16-root .admit .ttl{font-size:34px}}
.v16-root .admit .fields{display:grid;grid-template-columns:1fr 1fr;gap:14px 20px;margin-top:18px;
  position:relative;z-index:1}
.v16-root .admit .fields div{min-width:0}
.v16-root .admit .fields span{display:block;font-family:"DM Mono",ui-monospace,monospace;font-size:9.5px;
  letter-spacing:.14em;text-transform:uppercase;color:var(--slate);margin-bottom:5px}
.v16-root .admit .fields b{display:block;font-size:14px;font-weight:500;line-height:1.3;color:var(--cream)}
.v16-root .admit .fields b.mn{font-family:"DM Mono",ui-monospace,monospace;letter-spacing:.06em}
.v16-root .admit .pills{display:flex;flex-wrap:wrap;gap:7px;margin-top:20px;padding-top:16px;
  border-top:1px solid rgba(157,182,204,.24);position:relative;z-index:1}
.v16-root .admit .pills span{font-family:"DM Mono",ui-monospace,monospace;font-size:10px;letter-spacing:.1em;
  text-transform:uppercase;padding:5px 11px;border-radius:999px;background:rgba(253,247,234,.09);
  color:var(--cream);border:1px solid rgba(157,182,204,.26)}
.v16-root .admit .pills span.amb{background:var(--glow);color:#26140a;border-color:transparent;font-weight:500}

/* The parts three rooms each wrote for themselves, marked in their sheets as
   KIT GAPS. They were byte-identical in components/cadet-v16/styles.ts,
   components/mocks-v16/styles.ts and components/rtr-v16/styles.ts, which is
   three authors saying the kit was missing a primitive.

   GAP 2  .srow.meta  a list row whose right side is a fact, not a progress bar
                     (its re-collapse inside a narrow .stack column stays in
                     the three rooms: the kit forbids a row collapse attached
                     to the plain column, GATE __tests__/v16-kit-parts.test.tsx)
   GAP 12 .meter      a score out of a maximum, outside a row
   GAP 6  .empty      a panel with no rows at all

   NOT MOVED, deliberately: .steps, because four founder-picked designs share
   that class name (the guides sheet's numbered procedure, the directory's chip
   row, the tools list and this checklist) and the kit is read first, so the
   checklist's flex-direction would reach the directory's row; and the
   button.srow reset, because the kit's row is a link and the three rooms that
   draw it as a button each keep their own reset; every one of them now leaves
   the row's border-top alone, so the ruled rows survive (2026-09-11). */
.v16-root .srow.meta{grid-template-columns:38px 1fr auto 14px}
.v16-root .srow.meta .rt{display:flex;align-items:center;gap:10px;justify-content:flex-end;
  font-size:13px;color:var(--ink-soft);white-space:nowrap}
.v16-root .srow.meta .rt b{font-weight:600;color:var(--ink);font-variant-numeric:tabular-nums;font-size:14px}
.v16-root .srow.meta .rt .dim{color:var(--ink-faint)}
@media(max-width:560px){.v16-root .srow.meta{grid-template-columns:38px 1fr 14px;row-gap:6px}
  .v16-root .srow.meta .nm{grid-column:2;grid-row:1}
  .v16-root .srow.meta .chev{grid-column:3;grid-row:1}
  .v16-root .srow.meta .rt{grid-column:2/4;grid-row:2;justify-content:flex-start}}

.v16-root .meter{height:7px;border-radius:999px;background:var(--tint);overflow:hidden;margin-top:10px}
.v16-root .meter i{display:block;height:100%;border-radius:999px;background:var(--glow)}
.v16-root .meter.ok i{background:var(--good)}
.v16-root .mrow{display:flex;align-items:baseline;gap:10px}
.v16-root .mrow .mn{font-size:13.5px;font-weight:500}
.v16-root .mrow .mv{margin-left:auto;font-size:13px;color:var(--ink-soft);font-variant-numeric:tabular-nums}
.v16-root .mrow .mv b{color:var(--ink);font-weight:600}

.v16-root .empty{padding:22px 4px 26px;text-align:center}
.v16-root .empty .eg{width:44px;height:44px;border-radius:14px;background:var(--tint);color:var(--ink-faint);
  display:inline-flex;align-items:center;justify-content:center;margin:0 auto 12px}
.v16-root .empty .eg svg{width:21px;height:21px;stroke:currentColor;fill:none;stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round}
.v16-root .empty p{margin:0;font-size:13.5px;color:var(--ink-soft);max-width:38ch;
  margin-left:auto;margin-right:auto;line-height:1.55}

/* the compact FAQ (components/v16/primitives/faq.tsx). Declared identically in
   the blog and directory sheets. */
.v16-root details.qa{border-radius:14px;background:var(--tint);padding:0;overflow:hidden}
.v16-root details.qa + details.qa{margin-top:8px}
.v16-root details.qa summary{list-style:none;cursor:pointer;display:flex;gap:12px;align-items:center;
  padding:14px 16px;font-size:13.5px;font-weight:600;line-height:1.4}
.v16-root details.qa summary::-webkit-details-marker{display:none}
.v16-root details.qa summary .pm{margin-left:auto;flex:none;width:20px;height:20px;border-radius:6px;
  background:var(--card);border:1px solid var(--line);color:var(--ink-faint);display:flex;
  align-items:center;justify-content:center;font-size:14px;line-height:1}
.v16-root details.qa[open] summary .pm{color:var(--glow-text);background:rgba(255,143,31,.16);
  border-color:transparent}
.v16-root details.qa summary .pm::before{content:"+"}
.v16-root details.qa[open] summary .pm::before{content:"\2212"}
.v16-root details.qa p{margin:0;padding:0 16px 16px;font-size:13px;line-height:1.65;color:var(--ink-soft)}

/* THE TEACHING PLATE, FULL SCREEN (2026-09-10). A student on a phone reported
   that the plate inside a worked solution could not be opened, and its labels
   are unreadable at inline size. Tapping it now lifts the SAME protected image
   onto a night scrim, fitted to the viewport.

   No new visual vocabulary: the scrim is the confirm dialog's, one step
   deeper because the plate is the only thing that should be lit; the stage is
   the paper card the working already draws a figure on; and the control is the
   flight-computer window's round night button, at a 40px tap target. The
   caption keeps the slate the night surfaces use for a quiet line.

   The stage takes touch-action:pinch-zoom, so the browser owns the pinch and
   a one-finger drag reaches the pan in diagram-lightbox.tsx. */
/* The corner glyph is chrome, not a teaching drawing, so it opts out of the
   figure's own rule above: .work .fig svg gives an inline diagram a paper card
   and a hairline, which drew a white box behind a 16px mark (seen live
   2026-09-10). */
.v16-root .work .fig .lb-open svg{background:none;border:0}
.v16-root .v16-lightbox{position:fixed;inset:0;z-index:96;display:flex;align-items:center;
  justify-content:center;padding:16px;background:rgba(7,24,45,.93);overscroll-behavior:contain}
.v16-root .v16-lightbox .lb-frame{display:flex;flex-direction:column;align-items:center;gap:12px;
  width:100%;max-width:min(1100px,100%);outline:none}
/* The stage takes the whole lit area rather than the fitted image's own box,
   so a zoomed plate fills the screen instead of being clipped back into a
   thumbnail-sized window (seen live 2026-09-10). The paper frame belongs to
   the IMAGE for the same reason: an empty stage would otherwise paint a white
   rectangle over the whole viewport. */
.v16-root .v16-lightbox .lb-stage{display:flex;align-items:center;justify-content:center;
  width:100%;height:calc(100vh - 140px);overflow:hidden;touch-action:pinch-zoom;cursor:zoom-in}
.v16-root .v16-lightbox .lb-stage.zoomed{cursor:grab}
.v16-root .v16-lightbox .lb-stage.dragging{cursor:grabbing}
.v16-root .v16-lightbox .lb-stage img{display:block;width:auto;height:auto;
  max-width:100%;max-height:100%;border-radius:14px;
  background:var(--card);border:1px solid rgba(157,182,204,.6);
  transform-origin:center center;user-select:none;-webkit-user-select:none;-webkit-user-drag:none}
/* The caption is centred by the frame's own flex axis, not by text-align: the
   spacing canon keeps centred TEXT for empty states, gates and closing links,
   and a wrapped caption reads better from one left edge anyway. */
.v16-root .v16-lightbox .lb-cap{margin:0;max-width:min(680px,100%);
  font-size:13px;line-height:1.5;color:var(--slate)}
.v16-root .v16-lightbox .lb-x{position:fixed;top:16px;right:16px;width:40px;height:40px;
  border:0;border-radius:999px;background:rgba(255,255,255,.10);color:var(--cream);
  cursor:pointer;display:grid;place-items:center;font:inherit}
.v16-root .v16-lightbox .lb-x:hover{background:rgba(255,255,255,.20)}
.v16-root .v16-lightbox .lb-x svg{width:16px;height:16px}
.v16-root .v16-lightbox .lb-x:focus-visible{outline:2px solid var(--glow);outline-offset:2px}
@media(max-width:920px){
  .v16-root .v16-lightbox{padding:12px}
  .v16-root .v16-lightbox .lb-stage{height:calc(100vh - 152px)}
}
@media(prefers-reduced-motion:no-preference){
  .v16-root .v16-lightbox{animation:v16-lightbox-in .16s ease-out}
  @keyframes v16-lightbox-in{from{opacity:0}to{opacity:1}}
}
