/* ═══════════════════════════════════════════════════════════════════════════
   V3 PRIMITIVES — the shared component layer (src/components/*), for BOTH
   V3 surfaces.
   ───────────────────────────────────────────────────────────────────────────
   These are NOT screen styles. Every V3 screen composes them; no screen may
   restyle them or invent a near-duplicate. If a screen needs something these
   can't express, add a primitive here and record the rule in
   md/design/v3/system.md — that is the only way the system stays one system.

   One foundation, two surfaces (design/v3/README.md): the dashboard
   (web/app-v3, light) and the marketing landing (web/landing-v3, dark noir) link
   this same file, so a primitive exists exactly once. Consume it AFTER
   tokens.css:

       @import "/design/fonts.css";
       @import "/design/v3/tokens.css";
       @import "/design/v3/primitives.css";

   Colour never appears as a literal below: it is always a token, and it always
   arrives through a TONE class (positive | mild | negative | unknown | neutral),
   so [data-theme="noir"] re-skins every chart and pill for free.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ─── Tone: the colour language, in one place ─────────────────────────────── */
.v3-tone-positive { color: var(--positive); }
.v3-tone-mild     { color: var(--green-300); }
.v3-tone-negative { color: var(--negative); }
.v3-tone-unknown  { color: var(--text-faint); }

/* The one rendering of "we don't know". Never a 0, never an empty cell. */
.v3-unknown { color: var(--text-faint); font-size: var(--text-caption); }

/* ─── Panel ──────────────────────────────────────────────────────────────── */
.v3-panel.flush { padding: 0; }
.v3-panel-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 14px; }
.v3-panel.flush .v3-panel-head { padding: 16px 18px 12px; margin-bottom: 0; }
.v3-panel-head h3 { font-size: var(--text-h3); font-weight: var(--weight-bold); margin: 0 0 2px; }
.v3-panel-head .hint { color: var(--text-faint); font-size: var(--text-caption); }
.v3-split { display: grid; grid-template-columns: 1.5fr 1fr; gap: 16px; align-items: start; }

/* The unit note — a number carries its unit once, in the header, not in a caption. */
.v3-unit { font-size: var(--text-micro); color: var(--text-faint); white-space: nowrap; }
.v3-unit b { font-family: var(--font-mono); font-weight: 500; color: var(--text-muted);
  background: var(--surface-page); border: 1px solid var(--border); border-radius: 3px; padding: 1px 5px; }

/* ─── StatStrip ──────────────────────────────────────────────────────────── */
.v3-stats { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 1px; background: var(--border);
  border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; margin-bottom: 16px; }
.v3-stats .cell { background: var(--surface); padding: 14px 18px; }
.v3-stats .cell.invert { background: var(--surface-invert); color: var(--text-invert); }
.v3-stats .k { font-size: var(--text-micro); font-weight: var(--weight-bold); letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase; color: var(--text-faint); }
.v3-stats .cell.invert .k { color: var(--text-invert-muted); }
.v3-stats .v { font-family: var(--font-display); font-size: 26px; font-weight: var(--weight-semibold); margin: 5px 0 2px; }
.v3-stats .v small { font-size: 14px; font-weight: 400; color: var(--text-faint); }
.v3-stats .v .sm { display: inline-block; font-size: 15px; padding-top: 5px; }
.v3-stats .cell.invert .v { text-shadow: var(--glow-invert); }   /* glow is earned: hero cell only */
.v3-stats .cell.invert .v small { color: var(--text-invert-muted); }
.v3-stats .s { font-size: var(--text-caption); color: var(--text-muted); }
.v3-stats .cell.invert .s { color: var(--text-invert-muted); }

/* ─── Toolbar ────────────────────────────────────────────────────────────── */
.v3-toolbar { display: flex; align-items: center; gap: 9px; margin-bottom: 14px; }
.v3-toolbar .spacer { flex: 1; }
.v3-label { font-size: var(--text-caption); font-weight: var(--weight-semibold); color: var(--text-faint); }
.v3-select { font: inherit; font-size: var(--text-caption); font-weight: var(--weight-semibold); padding: 7px 10px;
  border-radius: var(--radius); border: 1px solid var(--border); background: var(--surface); color: var(--text); cursor: pointer; }
.v3-segmented { display: flex; background: var(--surface-page); border: 1px solid var(--border);
  border-radius: var(--radius-pill); padding: 2px; }
.v3-segmented button { font: inherit; font-size: var(--text-caption); font-weight: var(--weight-semibold);
  padding: 5px 11px; border-radius: var(--radius-pill); border: 0; background: none; color: var(--text-muted); cursor: pointer; }
.v3-segmented button.on { background: var(--emphasis); color: var(--on-emphasis); }

/* ─── Pills, tags, flags ─────────────────────────────────────────────────── */
.v3-pill { display: inline-flex; align-items: center; gap: 6px; font-size: var(--text-micro);
  font-weight: var(--weight-semibold); padding: 3px 9px; border-radius: var(--radius-pill); white-space: nowrap; }
.v3-pill .dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.v3-pill.positive { background: var(--positive-soft); color: var(--positive-ink); }
.v3-pill.positive .dot { background: var(--positive); }
.v3-pill.mild { background: var(--positive-faint); color: var(--positive-ink); }
.v3-pill.mild .dot { background: var(--green-300); }
.v3-pill.negative { background: var(--negative-soft); color: var(--negative-ink); }
.v3-pill.negative .dot { background: var(--negative); }
/* unknown is NOT a standing — dashed, colourless, and it says so in words */
.v3-pill.unknown { background: transparent; color: var(--text-faint); border: 1px dashed var(--n-300); }
.v3-pill.unknown .dot { display: none; }
.v3-pill.neutral { background: var(--emphasis); color: var(--on-emphasis); }
.v3-pill.neutral .dot { display: none; }

.v3-tag { font-size: var(--text-micro); font-weight: var(--weight-semibold); padding: 2px 7px;
  border-radius: var(--radius-pill); background: var(--surface-page); color: var(--text-muted);
  border: 1px solid var(--border); white-space: nowrap; }
.v3-flag { font-size: var(--text-micro); font-weight: var(--weight-bold); padding: 2px 7px;
  border-radius: var(--radius-pill); background: var(--emphasis); color: var(--on-emphasis); white-space: nowrap; }
.v3-dimtag { font-size: var(--text-micro); font-weight: var(--weight-semibold); padding: 2px 7px;
  border-radius: var(--radius-pill); border: 1px solid; background: var(--surface); white-space: nowrap; }

/* ─── Table (column track inherited from --cols, set once on .v3-table) ───── */
.v3-table { display: block; }
.v3-thead, .v3-trow { display: grid; grid-template-columns: var(--cols); align-items: center; gap: 13px; }
.v3-thead { padding: 10px 18px; background: var(--surface-page);
  border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); }
.v3-thead div { font-size: var(--text-micro); font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-eyebrow); text-transform: uppercase; color: var(--text-faint); }
.v3-trow { padding: 11px 18px; border-bottom: 1px solid var(--border); }
.v3-trow.indent { padding-left: 38px; }
.v3-trow.click { cursor: pointer; }
.v3-trow.click:hover { background: var(--surface-page); }
/* below the demand cut: present and readable, visibly not in the working set */
.v3-trow.faded { opacity: .55; }

/* the prompt cell — the text plus its quiet second line */
.cell-prompt .t { font-size: var(--text-sm); }
.cell-prompt.inline { display: flex; align-items: center; gap: 8px; }
.cell-prompt .m { display: flex; gap: 7px; margin-top: 4px; align-items: center; }
.cell-prompt .sub { font-size: var(--text-micro); color: var(--text-faint); }
.cell-dims { display: flex; gap: 5px; flex-wrap: wrap; }
.cell-move { display: flex; align-items: center; gap: 8px; }

/* ─── Group + ShareBar ───────────────────────────────────────────────────── */
.v3-group .head { display: flex; align-items: center; gap: 12px; padding: 11px 18px; cursor: pointer;
  border-bottom: 1px solid var(--border); user-select: none; }
.v3-group .head:hover { background: var(--surface-page); }
.v3-group .caret { color: var(--text-faint); font-size: 10px; transition: transform .18s var(--ease-standard); }
.v3-group.open .caret { transform: rotate(90deg); }
.v3-group .name { font-weight: var(--weight-semibold); font-size: var(--text-body); }
.v3-group .meta { font-size: var(--text-caption); color: var(--text-faint); }
.v3-group .summary { margin-left: auto; display: flex; align-items: center; gap: 10px; }
.v3-group .summary .pc { font-family: var(--font-mono); font-size: var(--text-caption); color: var(--text-muted); }

.v3-share { display: flex; width: 104px; height: 7px; border-radius: var(--radius-pill);
  overflow: hidden; background: var(--surface-sunken); }
.v3-share i.positive { background: var(--positive); }
.v3-share i.mild     { background: var(--green-300); }
.v3-share i.negative { background: var(--negative); }
.v3-share i.unknown  { background: var(--n-300); }

/* ─── BulletTrack — rank as a picture ────────────────────────────────────── */
.v3-bullet { display: flex; align-items: center; gap: 8px; }
.v3-bullet .track { flex: 1; display: flex; gap: 2px; }
.v3-bullet .track i { flex: 1; height: 14px; border-radius: 2px; background: var(--surface-sunken); }
.v3-bullet .track i.lead { background: var(--n-300); }
.v3-bullet .track i.you.positive { background: var(--positive); }
.v3-bullet .track i.you.mild     { background: var(--green-300); }
.v3-bullet .track i.you.negative { background: var(--negative); }
.v3-bullet .track i.you.unknown  { background: var(--n-300); }
.v3-bullet .label { font-family: var(--font-display); font-size: 14px;
  font-weight: var(--weight-semibold); white-space: nowrap; }
.v3-bullet .label small { font-size: 10px; font-weight: 400; color: var(--text-faint); }

/* ─── Sparkline + Delta (.v3-delta lives in tokens.css) ──────────────────── */
.v3-sparkline { width: 52px; height: 18px; }
.v3-sparkline path { fill: none; stroke: var(--n-400); stroke-width: 1.5; }
.v3-delta { font-family: var(--font-mono); font-size: var(--text-micro); }

/* ─── StackedArea + Legend ───────────────────────────────────────────────── */
.v3-area { width: 100%; height: 168px; }
.v3-area .grid { stroke: var(--border); stroke-dasharray: 3 4; }
.v3-area .axis { font-size: 10px; fill: var(--text-faint); }
.v3-area .band.positive { fill: var(--positive); fill-opacity: .9; }
.v3-area .band.mild     { fill: var(--green-300); fill-opacity: .9; }
.v3-area .band.negative { fill: var(--negative); fill-opacity: .8; }
.v3-area .band.unknown  { fill: var(--n-300); fill-opacity: .7; }

.v3-legend { display: flex; gap: 16px; margin-top: 10px; font-size: var(--text-micro); color: var(--text-muted); }
.v3-legend span { display: inline-flex; align-items: center; gap: 6px; }
.v3-legend em { width: 10px; height: 10px; border-radius: 3px; display: block; }
.v3-legend em.positive { background: var(--positive); }
.v3-legend em.mild     { background: var(--green-300); }
.v3-legend em.negative { background: var(--negative); }
.v3-legend em.unknown  { background: var(--n-300); }

/* ─── Donut — hover does the work; the hole is the label ─────────────────── */
.v3-donut { display: flex; align-items: center; gap: 32px; flex-wrap: wrap; margin-top: 8px; }
.v3-donut .ring { position: relative; width: 190px; height: 190px; flex: none; display: grid; place-items: center; }
.v3-donut .ring svg { width: 190px; height: 190px; }
.v3-donut .ring circle { cursor: pointer; transition: stroke-width .14s var(--ease-standard), opacity .14s; }
.v3-donut .hole { position: absolute; text-align: center; pointer-events: none; max-width: 118px; }
.v3-donut .hole .t { font-size: var(--text-caption); font-weight: var(--weight-semibold); line-height: 1.25; }
.v3-donut .hole .p { font-family: var(--font-display); font-size: 24px; font-weight: var(--weight-semibold); margin-top: 2px; }
.v3-donut .hole .s { font-size: var(--text-micro); color: var(--text-faint); }
.v3-donut .keys { display: grid; grid-template-columns: repeat(2, minmax(190px, 1fr)); gap: 1px 22px; flex: 1; }
.v3-donut .key { display: flex; align-items: center; gap: 9px; padding: 5px 7px; border-radius: 6px;
  cursor: pointer; font-size: var(--text-caption); }
.v3-donut .key:hover, .v3-donut .key.on { background: var(--surface-page); }
.v3-donut .key em { width: 10px; height: 10px; border-radius: 3px; display: block; flex: none; }
.v3-donut .key .n { flex: 1; color: var(--text-muted); }
.v3-donut .key .q { color: var(--text-faint); font-size: var(--text-micro); }
.v3-donut .key b { font-family: var(--font-mono); font-size: var(--text-caption); }

/* ─── Meter — provenance on its face: solid = measured, striped = estimated ─ */
.v3-meter { display: flex; align-items: center; gap: 8px; }
.v3-meter .bar { flex: 1; min-width: 30px; height: 8px; border-radius: var(--radius-pill);
  background: var(--surface-sunken); overflow: hidden; }
.v3-meter .bar i { display: block; height: 100%; border-radius: var(--radius-pill); background: var(--emphasis); }
.v3-meter .bar i.estimated {
  background: repeating-linear-gradient(45deg, var(--n-800) 0 3px, var(--n-400) 3px 6px); }
.v3-meter .value { font-family: var(--font-mono); font-size: var(--text-caption); color: var(--text-muted); width: 36px; }

/* ─── RankList — the bar IS the chart. You are black (identity), not green. ── */
.v3-rank { display: flex; align-items: center; gap: 10px; padding: 7px 0; font-size: var(--text-caption);
  border-bottom: 1px solid var(--border); }
.v3-rank:last-child { border-bottom: 0; }
.v3-rank .name { width: 130px; color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v3-rank.me .name { color: var(--text); font-weight: var(--weight-semibold); }
.v3-rank .bar { flex: 1; height: 7px; border-radius: var(--radius-pill); background: var(--surface-sunken); overflow: hidden; }
.v3-rank .bar i { display: block; height: 100%; background: var(--n-300); border-radius: var(--radius-pill); }
.v3-rank.me .bar i { background: var(--emphasis); }
.v3-rank .count { width: 24px; text-align: right; font-family: var(--font-mono); font-size: 10px; color: var(--text-muted); }

/* ─── Timeline — a day we didn't run is a GAP, never a zero ──────────────── */
.v3-timeline { display: flex; gap: 3px; align-items: flex-end; height: 44px; }
.v3-timeline i { flex: 1; border-radius: 2px; }
.v3-timeline i.positive { background: var(--positive); height: 100%; }
.v3-timeline i.mild     { background: var(--green-300); height: 62%; }
.v3-timeline i.negative { background: var(--negative); height: 28%; }
.v3-timeline i.gap      { background: var(--n-100); height: 10%; }

/* ─── SidePanel — detail without leaving the page ────────────────────────── */
.v3-scrim { position: fixed; inset: 0; background: rgba(0,0,0,.26); z-index: var(--z-overlay);
  animation: v3-fade .22s var(--ease-out); }
.v3-drawer { position: fixed; top: 0; right: 0; width: 500px; max-width: 94vw; height: 100vh;
  background: var(--surface); border-left: 1px solid var(--border); box-shadow: var(--shadow-lg);
  z-index: var(--z-modal); overflow-y: auto; animation: v3-slide .28s var(--ease-standard); }
@keyframes v3-fade { from { opacity: 0; } }
@keyframes v3-slide { from { transform: translateX(100%); } }
.v3-drawer .head { position: sticky; top: 0; background: var(--surface); border-bottom: 1px solid var(--border);
  padding: 17px 20px 14px; z-index: 2; }
.v3-drawer .close { position: absolute; top: 14px; right: 15px; width: 29px; height: 29px; border-radius: 8px;
  border: 0; background: none; color: var(--text-faint); cursor: pointer; font-size: 15px; }
.v3-drawer .close:hover { background: var(--surface-page); color: var(--text); }
.v3-drawer .eyebrow { font-size: var(--text-micro); font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-eyebrow); text-transform: uppercase; color: var(--text-faint); }
.v3-drawer h2 { font-family: var(--font-display); font-size: 19px; font-weight: var(--weight-semibold);
  margin: 6px 40px 0 0; line-height: 1.3; }
.v3-drawer .body { padding: 18px 20px 60px; }
.v3-drawer .v3-stats { grid-template-columns: 1fr 1fr; }
.v3-drawer .v3-stats .v { font-size: 23px; }

.v3-section { margin-bottom: 22px; }
.v3-section h4 { font-size: var(--text-sm); font-weight: var(--weight-bold); margin: 0 0 10px;
  display: flex; justify-content: space-between; }
.v3-section h4 span { font-weight: 400; font-size: var(--text-micro); color: var(--text-faint); }

/* ─── Callout — the one finding worth a sentence, on the special black ────── */
.v3-callout { border-radius: var(--radius-lg); padding: 15px 17px; margin-bottom: 22px; }
.v3-callout .t { font-size: var(--text-sm); font-weight: var(--weight-semibold); margin-bottom: 4px; }
.v3-callout .d { font-size: var(--text-caption); color: var(--text-invert-muted); line-height: 1.5; }

/* ─── Small shared bits ──────────────────────────────────────────────────── */
.v3-listrow { display: flex; align-items: center; gap: 10px; padding: 10px 13px; border: 1px solid var(--border);
  border-radius: var(--radius); margin-bottom: 7px; font-size: var(--text-sm); font-weight: var(--weight-semibold); }
.v3-listrow.soon { opacity: .55; }
.v3-listrow .s { margin-left: auto; font-size: var(--text-micro); font-weight: 400; color: var(--text-faint); }

.v3-mover { display: flex; align-items: center; gap: 11px; padding: 8px 0; cursor: pointer;
  border-bottom: 1px solid var(--border); }
.v3-mover:last-child { border-bottom: 0; }
.v3-mover:hover .t { color: var(--text); }
.v3-mover .v3-delta { width: 30px; }
.v3-mover .t { flex: 1; font-size: var(--text-sm); color: var(--text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.v3-empty { padding: 26px 18px; text-align: center; color: var(--text-faint); font-size: var(--text-sm); }

/* ── Ring · the one noir hero per screen (system.md §3, §6) ─────────────────
   The card opts into [data-theme="noir"], so every colour below is a semantic
   token that re-points itself. Nothing here names a hue. */
.v3-hero { display: grid; grid-template-columns: 168px 1fr; gap: 28px; align-items: center;
  background: var(--surface-page); border-radius: var(--radius-xl); padding: 24px 26px;
  margin-bottom: 16px; box-shadow: var(--shadow-lg); position: relative; overflow: hidden;
  /* data-theme="noir" re-points the tokens; re-apply color so the text actually
     uses the noir near-white instead of inheriting the light-mode ink from body. */
  color: var(--text); }
.v3-hero::before { content: ""; position: absolute; left: -40px; top: -60px; width: 320px; height: 320px;
  background: radial-gradient(circle, rgba(255,255,255,.10) 0%, transparent 65%); pointer-events: none; }
.v3-hero .ring { position: relative; display: grid; place-items: center; }
.v3-hero .ring svg { width: 148px; height: 148px; filter: drop-shadow(0 0 14px rgba(255,255,255,.42)); }
.v3-hero .ring .track { stroke: var(--border-strong); }
.v3-hero .ring .arc { stroke: var(--emphasis); }
.v3-hero .ring .mid { position: absolute; text-align: center; pointer-events: none; }
.v3-hero .ring .mid .big { font-family: var(--font-display); font-size: 36px; font-weight: var(--weight-semibold);
  line-height: 1; text-shadow: var(--glow-invert); }
.v3-hero .ring .mid .cap { font-size: var(--text-micro); color: var(--text-faint); margin-top: 5px; }
.v3-hero .say .line { font-family: var(--font-display); font-size: 23px; font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight); line-height: 1.35; max-width: 34ch; text-wrap: balance; }
/* the silver sheen — the landing's highlight material, earned here by the hero */
.v3-hero .say .line b { background: var(--silver-sheen); -webkit-background-clip: text; background-clip: text;
  color: transparent; filter: drop-shadow(var(--silver-glow)); }
.v3-hero .say .sub { font-size: var(--text-sm); color: var(--text-muted); margin-top: 9px; max-width: 62ch; }
@media (max-width: 820px) { .v3-hero { grid-template-columns: 1fr; } }

/* ── Heatmap · where two facts intersect (system.md §3) ─────────────────────
   Depth = volume on a neutral ramp (set inline from the data). No hue: volume
   is not good or bad. Only the earned glow is coloured. */
.v3-heatmap { overflow-x: auto; padding: 2px 18px 18px; }
.v3-heatmap table { border-collapse: separate; border-spacing: 3px; }
.v3-heatmap th { padding: 0 0 7px; font-size: var(--text-micro); font-weight: var(--weight-semibold);
  color: var(--text-muted); white-space: nowrap; cursor: pointer; }
.v3-heatmap th span { padding: 4px 6px; border-radius: 5px; display: block; }
.v3-heatmap th:hover span, .v3-heatmap th.hl span { color: var(--text); background: var(--surface-page); }
.v3-heatmap td.rh { font-size: var(--text-caption); font-weight: var(--weight-semibold); color: var(--text-muted);
  padding: 0 11px 0 5px; white-space: nowrap; cursor: pointer; border-radius: 6px; }
.v3-heatmap td.rh:hover, .v3-heatmap td.rh.hl { background: var(--surface-page); color: var(--text); }
.v3-heatmap td.rh.mine { color: var(--text); }   /* you are identity, not a judgment */
.v3-heatmap td.rh .sw { display: inline-block; width: 9px; height: 9px; border-radius: 3px;
  margin-right: 7px; vertical-align: middle; }
.v3-heatmap .cell { width: 78px; height: 38px; border-radius: 6px; display: grid; place-items: center;
  font-family: var(--font-mono); font-size: 11px; cursor: pointer; border: 1px solid transparent;
  transition: transform .1s var(--ease-standard); }
.v3-heatmap .cell:hover { transform: scale(1.07); border-color: var(--emphasis); box-shadow: var(--shadow-md); }
.v3-heatmap .cell.hl { border-color: var(--border-strong); }
.v3-heatmap .cell.blind { box-shadow: 0 0 0 1.5px var(--negative), 0 0 14px color-mix(in srgb, var(--negative) 38%, transparent); }
.v3-heatmap .legend { display: flex; gap: 18px; align-items: center; flex-wrap: wrap;
  margin-top: 12px; font-size: var(--text-micro); color: var(--text-muted); }
.v3-heatmap .legend i { display: inline-block; vertical-align: middle; margin-right: 7px;
  width: 40px; height: 12px; border-radius: 3px; }
.v3-heatmap .legend .ramp i { background: linear-gradient(90deg, var(--n-100), var(--n-800)); }
.v3-heatmap .legend .blind i { width: 14px; background: var(--negative-faint);
  box-shadow: 0 0 0 1.5px var(--negative); }

/* ── Site, SourceTag, NameList, Quote, ExternalLink · the cited-source marks ── */
.v3-site { display: flex; align-items: center; gap: 9px; min-width: 0; }
.v3-site .sw { width: 10px; height: 10px; border-radius: 3px; flex: none; }
.v3-site .d { font-size: var(--text-sm); font-weight: var(--weight-semibold);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v3-namelist { font-size: var(--text-caption); color: var(--text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Evidence, quoted as evidence — the answer fragment a source backed. */
.v3-quote { margin: 0; border-left: 2px solid var(--border-strong); padding-left: 12px;
  font-size: var(--text-sm); line-height: var(--leading-normal); color: var(--text); }
.v3-quote cite { display: block; margin-top: 6px; font-style: normal;
  font-size: var(--text-micro); color: var(--text-faint); }
.v3-extlink { font-size: var(--text-caption); color: var(--text-muted); word-break: break-all; }
.v3-extlink:hover { color: var(--text); }

/* PanelRow · an item in a drawer section, optionally a doorway of its own. */
.v3-row .t { flex: 1; min-width: 0; }
.v3-row .t em { display: block; font-style: normal; font-size: var(--text-micro);
  color: var(--text-faint); margin-top: 2px; }
.v3-row.click { cursor: pointer; border-radius: 6px; }
.v3-row.click:hover { background: var(--surface-page); }

/* RankList · a row may carry a TONE when its bar means good/bad. Only tone.ts
   decides what green is; the caller never names a colour. */
.v3-rank.click { cursor: pointer; }
.v3-rank.click:hover .name { color: var(--text); }
.v3-rank .bar i.positive { background: var(--positive); }
.v3-rank .bar i.mild { background: var(--green-300); }
.v3-rank .bar i.negative { background: var(--negative); }
.v3-rank .bar i.unknown { background: var(--n-300); }

/* The rank number in a table row (shared with Prompts). */
.v3-table .v3-trow .n { font-family: var(--font-mono); font-size: var(--text-caption); color: var(--text-faint); }


/* ═══════════════════════════════════════════════════════════════════════════
   Shared marks — button, input, wordmark, tick, mono, eyebrow
   ───────────────────────────────────────────────────────────────────────────
   These began life in web/landing-v3/v3.css. The onboarding seam (login,
   signup, the wizard) uses the same marks inside the app, so they live here —
   the one copy both surfaces already load — rather than being forked into
   web/app-v3/src/styles.css. Moved 2026-07-26 with three fixes the second
   surface forced:
     · --silver-glow is noir-only, so :hover falls back to --shadow-md on light
     · ::placeholder was hard-coded to the noir ink; now it is per-theme
     · a focus ring and a :disabled state, because a form can now be submitted
   ═══════════════════════════════════════════════════════════════════════════ */

.l-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  font: inherit; font-weight: 700;
  border: 0; border-radius: var(--radius-pill);
  background: var(--emphasis); color: var(--on-emphasis);
  cursor: pointer; white-space: nowrap;
}
.l-btn:hover { background: var(--emphasis-hover); box-shadow: var(--silver-glow, var(--shadow-md)); color: var(--on-emphasis); }
.l-btn:disabled { opacity: .4; cursor: default; box-shadow: none; }

.l-btn-ghost {
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--border-strong); border-radius: var(--radius-pill);
  color: var(--text); background: none;
  font: inherit; font-weight: 700; cursor: pointer;
}
.l-btn-ghost:hover { background: var(--surface-hover); }
.l-btn-ghost:disabled { opacity: .4; cursor: default; }

.l-input {
  font: inherit; font-weight: 600;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface-sunken); color: var(--text);
  width: 100%; padding: 11px 13px; font-size: 14px;
}
.l-input:focus { outline: 2px solid var(--focus-ring); outline-offset: -1px; }
.l-input.pill {
  border-radius: var(--radius-pill);
  border-color: var(--border-strong);
  background: var(--surface);
}

::placeholder { color: var(--text-faint); }
[data-theme="noir"] ::placeholder { color: rgba(246, 246, 247, .38); }

.l-mono {
  font-family: var(--font-mono);
  font-size: 11px; letter-spacing: .05em;
  color: var(--text-faint);
}

.l-eyebrow {
  font-size: 11px; font-weight: 700;
  letter-spacing: var(--tracking-eyebrow); text-transform: uppercase;
  color: var(--text-faint);
}

/* The wordmark is a mask so it inherits the page's ink — one asset, any tone.
   The url is relative to THIS file (design/v3/), not to the page. */
.l-wordmark {
  display: inline-block;
  background: var(--text);
  mask: url("../assets/cite0-wordmark.svg") no-repeat center / contain;
  -webkit-mask: url("../assets/cite0-wordmark.svg") no-repeat center / contain;
}
.l-wordmark.nav  { width: 92px; height: 30px; }
.l-wordmark.rail { width: 72px; height: 24px; }
.l-wordmark.foot { width: 74px; height: 24px; background: var(--text-faint); }

.l-tick {
  width: 13px; height: 13px; border-radius: 3px;
  background: var(--positive); color: #0a0a0b;
  font-size: 9px; font-weight: 800;
  display: flex; align-items: center; justify-content: center; flex: none;
}
.l-tick.empty { background: none; border: 1px solid var(--border-strong); }
.l-tick.round { border-radius: 50%; width: 16px; height: 16px; font-size: 9px; }
.l-tick.badge {
  position: absolute; top: -8px; right: -8px;
  width: 19px; height: 19px; border-radius: 50%; font-size: 10px;
}

/* ─── Journey — stages that depend on each other ──────────────────────────── */
/* A dependency chain, not a stepper and not a filter bar. The separator is a
   chevron because the order is the meaning: each stage only matters if the one
   before it passed. `idle` is a stage nothing ran in — dashed, because a
   border we drew solid would read as a stage that finished. */
.v3-journey { display: flex; align-items: stretch; gap: 6px; margin-bottom: 16px; }
.v3-jstage { flex: 1 1 0; min-width: 0; text-align: left; font: inherit; color: var(--text);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg);
  padding: 12px 13px; cursor: pointer; transition: border-color .15s var(--ease-standard), box-shadow .15s var(--ease-standard); }
.v3-jstage:hover { border-color: var(--border-strong); }
.v3-jstage.on { border-color: var(--emphasis); box-shadow: var(--shadow-md); }
.v3-jstage.idle { border-style: dashed; }
.v3-jstage .top { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 9px; }
.v3-jstage .rank { font-size: var(--text-micro); font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-eyebrow); text-transform: uppercase; color: var(--text-faint); }
.v3-jstage .name { font-weight: var(--weight-semibold); font-size: var(--text-body); }
.v3-jstage .q { color: var(--text-muted); font-size: var(--text-caption); margin: 2px 0 10px; }
.v3-jstage .v3-share { width: 100%; }
.v3-jstage .checks { font-size: var(--text-caption); color: var(--text-faint); margin-top: 7px; }
.v3-jsep { align-self: center; color: var(--text-faint); font-size: 15px; flex: none; }

/* ─── ScoreHistory — a sparse series with incomparable segments ───────────── */
/* A hollow point was scored under superseded weights, and the line does not
   join it: two numbers from different exams are not a trend. Same rule as a
   no-data gap, applied to a different kind of gap. */
.v3-scorehist svg { width: 100%; height: auto; overflow: visible; }
.v3-scorehist .grid { stroke: var(--border); stroke-width: 1; stroke-dasharray: 2 4; }
.v3-scorehist .axis { stroke: var(--border); stroke-width: 1; }
.v3-scorehist .line { fill: none; stroke: var(--emphasis); stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round; }
.v3-scorehist .pt { fill: var(--emphasis); }
.v3-scorehist .pt.old { fill: var(--surface); stroke: var(--n-400); stroke-width: 1.5; }
.v3-scorehist .val { font-family: var(--font-mono); font-size: 9px; fill: var(--text-muted); text-anchor: middle; }
.v3-scorehist .date { font-size: 9px; fill: var(--text-faint); text-anchor: middle; }
.v3-scorehist .tick { font-family: var(--font-mono); font-size: 9px; fill: var(--text-faint); }
.v3-scorehist .note { font-size: var(--text-caption); color: var(--text-faint); margin-top: 8px; }

/* ─── CodeBlock — something to take away ──────────────────────────────────── */
.v3-code { border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }
.v3-code .bar { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 7px 10px; background: var(--surface-page); border-bottom: 1px solid var(--border); }
.v3-code .lbl { font-size: var(--text-caption); font-weight: var(--weight-semibold); color: var(--text-muted); }
.v3-code .copy { font: inherit; font-size: var(--text-caption); font-weight: var(--weight-semibold);
  background: var(--emphasis); color: var(--on-emphasis); border: 0; border-radius: var(--radius-sm);
  padding: 4px 10px; cursor: pointer; }
.v3-code pre { margin: 0; padding: 11px 12px; max-height: 260px; overflow: auto;
  font-family: var(--font-mono); font-size: 12px; line-height: 1.55; white-space: pre-wrap; word-break: break-word; }
.v3-code .hint { padding: 8px 12px 10px; font-size: var(--text-caption); color: var(--text-muted);
  border-top: 1px solid var(--border); background: var(--surface-page); }
