/* zena-tokens.css: the Zena colour and type roles (r9 spec as corrected by the r9 critique, 2026-11-09).
   Palash, 11:20 PM ET 2026-11-08: "the most important thing is the colour differentiation for users to follow exactly
   what they need". One token per role, defined here only and linked FIRST in index.html and landing.html, so every
   later sheet reads the same roles. Rules (docs/news-key-card-rules.md W2 amendment):
   - two inks only: title and body. Section labels use title ink; meta uses body ink and is set apart by position.
   - one ground: cards are the ground, separated by a 1px hairline and 16px of space, never a lighter shade.
   - the category kicker above a title is the one coloured word on a card. Category hue otherwise appears only on the
     2px top rule, the dot and an active chip underline: never body text, titles, prices, buttons, backgrounds, whole-card
     borders or tints.
   - small change figures are body ink with a green/red triangle mark; purple is the Zena estimate figure only.
   Dark is the default; light follows the pattern index.html uses: the prefers-color-scheme:light media query guarded by
   :root:not([data-theme=dark]), and :root[data-theme=light]. Contrast is WCAG 2.x against --z-surface. */
:root{
  --z-title:#f4f6fa;           /* 18.2:1 titles, headlines, card and section titles */
  --z-body:#b9bfc8;            /* 10.7:1 descriptions, reasons, figure labels, meta */
  --z-section:var(--z-title);  /* critique C1: two inks only */
  --z-meta:var(--z-body);      /* critique C1: meta is set apart by position, not a grey */
  --z-surface:#080b10;         /* the ground */
  --z-raised:var(--z-surface); /* critique C2: one ground */
  --z-hairline:#232a35;
  --z-hairline-strong:#3a4452;
  --z-up:#00c805;              /*  8.7:1 */
  --z-down:#ff5000;            /*  6.0:1 */
  --z-live:#ff3b30;            /*  5.6:1 the live dot only */
  --z-estimate:#b18cff;        /*  7.6:1 the Zena estimate figure ONLY */
  --cat-finance:#5fa8ff;       /*  8.0:1 blue */
  --cat-crypto:#ff9f45;        /*  9.0:1 amber (critique C6) */
  --cat-sports:#2fd0bc;        /* 10.2:1 teal */
  --cat-politics:#ff9ad5;      /*  9.5:1 rose (critique C6) */
  --cat-entertainment:#e3d454; /* 13.0:1 lemon */
  --cat-world:#8fdcff;         /* 13.0:1 sky; Climate and Science file under World */
  --cat-perps:var(--cat-crypto); /* critique C6: perps are crypto perpetuals */
  --cat:var(--z-title);        /* resolved per element by [data-zcat] below */
  --zt-page:650 32px/38px var(--sans);
  --zt-story:650 26px/32px var(--sans);
  --zt-section:650 20px/26px var(--sans);
  --zt-card:600 16px/22px var(--sans);
  --zt-body:400 15px/23px var(--sans);
  --zt-small:400 13px/18px var(--sans);
  --zt-figure:650 28px/32px var(--sans);
  --zt-figure-hero:650 40px/44px var(--sans);
  --z-kicker-weight:600;
}
@media (max-width:600px){:root{
  --zt-page:650 27px/33px var(--sans);
  --zt-story:650 22px/28px var(--sans);
  --zt-section:650 18px/24px var(--sans);
  --zt-card:600 15px/21px var(--sans);
  --zt-body:400 14px/21px var(--sans);
  --zt-small:400 12px/16px var(--sans);
  --zt-figure:650 24px/28px var(--sans);
  --zt-figure-hero:650 32px/36px var(--sans);
}}
/* the landing page is dark only (landing.html color-scheme:dark), so a light system preference never repaints its inks */
@media (prefers-color-scheme:light){:root:not([data-theme=dark]):not([data-news-view]):not(:has(>body[data-zena-surface=landing])){
  --z-title:#14161a; --z-body:#3d4148;
  --z-surface:#f6f5f1; --z-hairline:#e3e0d8; --z-hairline-strong:#bdb8ad;
  --z-up:#0b6e33; --z-down:#b81c29; --z-live:#c8102e; --z-estimate:#6d28d9;
  --cat-finance:#1d5fb8; --cat-crypto:#7a3d00; --cat-sports:#0b6f63; --cat-politics:#b0306a;
  --cat-entertainment:#6b6300; --cat-world:#0f6688;
}}
:root[data-theme=light]:not([data-news-view]){   /* News and the terminal pages stay dark on every device (visual spec); one source of truth for their inks */
  --z-title:#14161a; --z-body:#3d4148;
  --z-surface:#f6f5f1; --z-hairline:#e3e0d8; --z-hairline-strong:#bdb8ad;
  --z-up:#0b6e33; --z-down:#b81c29; --z-live:#c8102e; --z-estimate:#6d28d9;
  --cat-finance:#1d5fb8; --cat-crypto:#7a3d00; --cat-sports:#0b6f63; --cat-politics:#b0306a;
  --cat-entertainment:#6b6300; --cat-world:#0f6688;
}
/* One attribute resolves the hue. Renderers stamp data-zcat with the code's own category keys (econ, crypto, sport,
   pol, culture, world, climate, perps); the existing data-category / data-zc-category hooks map to the same tokens. */
:is([data-zcat=econ],[data-category=econ],[data-zc-category=econ]){--cat:var(--cat-finance)}
:is([data-zcat=crypto],[data-category=crypto],[data-zc-category=crypto]){--cat:var(--cat-crypto)}
:is([data-zcat=sport],[data-category=sport],[data-zc-category=sport]){--cat:var(--cat-sports)}
:is([data-zcat=pol],[data-category=pol],[data-zc-category=pol]){--cat:var(--cat-politics)}
:is([data-zcat=culture],[data-category=culture],[data-zc-category=culture]){--cat:var(--cat-entertainment)}
:is([data-zcat=world],[data-zcat=climate],[data-category=world],[data-category=climate],[data-zc-category=world],[data-zc-category=climate]){--cat:var(--cat-world)}
:is([data-zcat=perps],[data-category=perps],[data-zc-category=perps]){--cat:var(--cat-perps)}
/* the permitted uses, as shared utilities */
.z-kicker{font:var(--zt-small);font-weight:var(--z-kicker-weight);color:var(--cat)}
.z-cat-rule{box-shadow:inset 0 2px 0 var(--cat)}
.z-cat-dot{display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--cat);flex:none}
.z-cat-chip[aria-selected=true],.z-cat-chip[aria-pressed=true],.z-cat-chip.on{color:var(--z-title);box-shadow:inset 0 -2px 0 var(--cat)}
.z-chg{font:var(--zt-small);font-weight:600;color:var(--z-body)}
.z-chg::before{content:'';display:inline-block;margin-right:4px;border:4px solid transparent;vertical-align:1px}
.z-chg[data-dir=up]::before{border-bottom:6px solid var(--z-up);border-top:0}
.z-chg[data-dir=down]::before{border-top:6px solid var(--z-down);border-bottom:0}
.z-chg[data-dir=flat]::before{display:none}
.z-figure{font:var(--zt-figure);font-variant-numeric:tabular-nums}
.z-figure-hero{font:var(--zt-figure-hero);font-variant-numeric:tabular-nums}
/* Secondary text roles (r14, 2026-11-09). Palash, 3:15 AM ET: "the gray text pass is literally for everything on our site
   ... a lot of the gray text currently has to be there, it can be presented in such a better form." These extend the two
   inks above (they add no ink): every secondary line is body ink at the small step (13/18, 12/16 on phones), and its job is
   carried by position, grouping and the separator, never by a third grey, opacity, a size under 12px, tracked capitals or
   a weight under 400. Rules: docs/news-key-card-rules.md, "Secondary text system". Light values resolve through the light
   blocks above (body #3d4148, title #14161a, hairline-strong #bdb8ad); nothing here names a colour of its own.
   - label    names one value; above it (2px) or left of it (8px), one line, never wraps, at most three words
   - value    the thing labelled; title ink, card step, tabular figures
   - meta     the one provenance line per item: source, time, then context; parts are child elements and the separator
              is drawn here, never typed into a string (W2 still holds for words: no written interpunct)
   - source   a meta line that opens with "Source:" and sits in the card foot or under its graphic, never among the facts
   - caption  a meta line attached to a graphic (4px under its plot, aligned to the plot's left edge)
   - axis     tick and end labels; the one role drawn at 12/16 at every size (scanned, not read)
   - note     one short phrase that qualifies a value ("inside spread 83-86¢"); at most 12 words, no full stop
   - status   a state word led by a 6px dot (live, paused, closed); no box, no pill
   - empty    a slot with nothing to show: a card-step title plus one body line, in the slot's final geometry
   - legal    the page's one disclaimer paragraph, in the footer only; in-product caveats sit behind .z-tip
   - tip      the "?" disclosure after a label (the .lrnq pattern); long forms live in its popover, never on the card
   - change   the existing .z-chg takes its window as a second part (<b>4.5¢</b> <span>24h</span>), so the window is never lost */
:root{
  --z-sep:"\00b7";              /* the meta separator; one place to change it */
  --z-sep-space:.45em;          /* room either side of the separator */
  --zt-axis:400 12px/16px var(--sans);
  --z-gap-label:2px;            /* a label above its value */
  --z-gap-inline:8px;           /* a label left of its value */
  --z-gap-meta:4px;             /* a title to its meta line */
  --z-gap-caption:4px;          /* a graphic to its caption or axis row */
  --z-gap-block:12px;           /* a secondary line to the next block */
}
.z-label,.z-meta,.z-source,.z-caption,.z-note,.z-status,.z-empty>span,.z-legal{font:var(--zt-small,400 13px/18px var(--sans,system-ui));color:var(--z-body,#b9bfc8);letter-spacing:0;text-transform:none;font-style:normal}
.z-label{white-space:nowrap}
.z-value{font:var(--zt-card,600 16px/22px var(--sans,system-ui));color:var(--z-title,#f4f6fa);font-variant-numeric:tabular-nums;white-space:nowrap}
.z-pair{display:flex;flex-direction:column;gap:var(--z-gap-label,2px);min-width:0}
.z-pair.z-inline{flex-direction:row;align-items:baseline;gap:var(--z-gap-inline,8px)}
/* meta, source and caption: one line of parts. A part never breaks inside; on a phone the line may wrap once, at a part,
   and the separator stays with the part before it, so no line starts with one. A part marked .z-drop leaves on phones. */
.z-meta,.z-source,.z-caption{display:flex;flex-wrap:wrap;align-items:baseline;min-width:0;font-variant-numeric:tabular-nums}
.z-meta>*,.z-source>*,.z-caption>*,.z-chg>*{white-space:nowrap}
.z-meta>:not(:last-child)::after,.z-source>:not(:last-child)::after,.z-caption>:not(:last-child)::after,.z-chg>:not(:last-child)::after{content:var(--z-sep,"\00b7");margin:0 var(--z-sep-space,.45em);color:var(--z-body,#b9bfc8)}
@supports (content:"x" / ""){.z-meta>:not(:last-child)::after,.z-source>:not(:last-child)::after,.z-caption>:not(:last-child)::after,.z-chg>:not(:last-child)::after{content:var(--z-sep,"\00b7") / ""}}
.z-meta{margin-top:var(--z-gap-meta,4px)}
.z-caption{margin-top:var(--z-gap-caption,4px)}
.z-axis{font:var(--zt-axis,400 12px/16px var(--sans,system-ui));color:var(--z-body,#b9bfc8);font-variant-numeric:tabular-nums;white-space:nowrap;letter-spacing:0}
svg text.z-axis,svg .z-axis text,svg text.z-caption{fill:var(--z-body,#b9bfc8);font:var(--zt-axis,400 12px/16px var(--sans,system-ui))}
.z-note{max-width:40ch}
.z-status{display:inline-flex;align-items:center;gap:6px;white-space:nowrap}
.z-status::before{content:'';width:6px;height:6px;border-radius:50%;flex:none;background:var(--z-status-dot,var(--z-hairline-strong,#3a4452))}
.z-status[data-state=live]{--z-status-dot:var(--z-live,#ff3b30)}
.z-status[data-state=up]{--z-status-dot:var(--z-up,#00c805)}
.z-status[data-state=down],.z-status[data-state=paused]{--z-status-dot:var(--z-down,#ff5000)}
.z-empty{display:grid;align-content:center;justify-items:start;gap:var(--z-gap-meta,4px)}
.z-empty>b,.z-empty>strong{font:var(--zt-card,600 16px/22px var(--sans,system-ui));color:var(--z-title,#f4f6fa)}
.z-empty>span{max-width:48ch}
.z-legal{max-width:72ch;text-wrap:pretty}
.z-tip{display:inline-grid;place-items:center;width:16px;height:16px;margin-left:4px;border:1px solid var(--z-hairline-strong,#3a4452);border-radius:50%;background:none;padding:0;font:600 12px/1 var(--sans,system-ui);color:var(--z-body,#b9bfc8);cursor:help;vertical-align:1px}
.z-tip:is(:hover,:focus-visible,[aria-expanded=true]){color:var(--z-title,#f4f6fa);border-color:var(--z-body,#b9bfc8)}
.z-tip-pop{max-width:44ch;padding:10px 12px;border:1px solid var(--z-hairline-strong,#3a4452);background:var(--z-surface,#080b10);font:var(--zt-small,400 13px/18px var(--sans,system-ui));color:var(--z-body,#b9bfc8)}
.z-tip-pop b{color:var(--z-title,#f4f6fa);font-weight:600}
@media (max-width:600px){
  .z-meta>.z-drop,.z-source>.z-drop,.z-caption>.z-drop{display:none}
  :is(.z-meta,.z-source,.z-caption)>:nth-last-child(1 of :not(.z-drop))::after{content:none}
  .z-pair.z-inline{flex-direction:column;gap:var(--z-gap-label,2px)}
}
