/* ════════════════════════════════════════════════════════════════
   toca.io · additions to the shared site.css (paper throughout)
   Same tokens, nav, bands, certs, chips, footer as toca.health and
   toca.legal. This file adds only what the parent needs.
   ════════════════════════════════════════════════════════════════ */

/* Wide Barlow 600, the parent site's heading cut (the sector sites and /legal set theirs in Barlow Condensed). Self-hosted,
   Latin subset as site.css's faces, from Google Fonts' own file (SIL Open Font License); it used to load from Google
   (Mat, 11 Nov 2026). gen.py's FONTS preloads it. */
@font-face { font-family:'Barlow'; font-style:normal; font-weight:600; font-display:swap;
  src:url(../assets/fonts/barlow-600.woff2) format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; }

body.io {
  --font-display: "Barlow", "Barlow Condensed", "Arial Narrow", sans-serif;
  --font-figure:  "Barlow Condensed", "Arial Narrow", sans-serif;
  --bbs-black: #0e0d0c;
}
.io h2 { letter-spacing: -.015em; }
body.io :is(h1, h2) { text-wrap: balance; }   /* even lines: the home headline left "on." alone on a third line at 1440px (11 Nov 2026) */

/* ── Placeholders: anything in brackets is undecided copy ────────── */
.ph { color: var(--color-muted); }
.ph::before { content: "["; } .ph::after { content: "]"; }

/* ── Family strip ────────────────────────────────────────────────── */
/* ── Layout system: one content column ───────────────────────────────
   Every piece of content shares one left edge. The column is .band-narrow
   (site.css: margin auto; max-width raised here) inside an outer element that
   carries the page gutter as padding plus any full-width rule or background.
   Chrome (family strip, header, subnav, proof bar, footer) follows the same
   pattern: layout lives on the inner .band-narrow, borders on the outer. The
   strip and the header are the exception on wide screens: they run to the page
   margins, as toca.legal's nav does (9 Nov 2026). */
.io { --col-max: 80rem; }
.io .band-narrow { max-width: var(--col-max); }
.io .nav { display: block; }
.io .nav > .band-narrow { display: flex; justify-content: space-between; align-items: center; gap: var(--space-lg); }
/* The frame (Mat, 9 Nov 2026, after fin.ai): up to 1920px wide the strip and nav run to the page margins, as toca.legal's
   nav does; past 1920 they stop growing and centre, like everything else. Backgrounds (tints, the legal film) always run
   to the screen edges: only content is framed, so a dark band never ends in a hard edge either side. */
:root { --frame: 120rem; --frame-pad: max(var(--page-gutter), calc(50% - var(--frame) / 2 + var(--page-gutter))); }
.io .family > .band-narrow, .io .nav > .band-narrow, .io .foot > .band-narrow { max-width: calc(var(--frame) - 2 * var(--page-gutter)); }   /* the footer shares the nav's edges */
.io .page-head--grain { --grain-opacity: .1; }   /* the Spectral hero's static, from toca.legal at .04, barely showed on toca.io's paper (Mat, 9 Nov 2026) */
.io .foot > .band-narrow { display: block; }
.io .mt-lg { margin-top: var(--space-lg); }
.io .mt-xl { margin-top: var(--space-xl); }
.io .mt-2xl { margin-top: var(--space-2xl); }
.io .support--wide { max-width: 60ch; }
.io .consent { display: flex; gap: var(--space-sm); align-items: flex-start; font-size: var(--text-sm); color: var(--color-muted); font-family: var(--font-body); text-transform: none; letter-spacing: normal; }   /* a sentence, not a field label: the form's labels are mono caps */
.io .consent .tlink { font-size: inherit; }
.io .consent input { width: auto; margin-top: .3rem; }

.family {
  padding: 0 var(--page-gutter);
  font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: .04em;
  border-bottom: var(--rule-hair) solid var(--color-rule); color: var(--color-muted);
}
.family > .band-narrow { display: flex; justify-content: space-between; align-items: center; gap: var(--space-md); min-height: 2.1rem; }
.family ul { display: flex; gap: var(--space-lg); margin: 0; padding: 0; list-style: none; }
.family a { color: inherit; text-decoration: none; padding: .4rem 0; }
.family a:hover, .family a[aria-current] { color: var(--color-ink); }
.family .nerd { background: none; border: 0; padding: .3rem .5rem; margin: 0; cursor: pointer; font: inherit; color: var(--color-muted); border-radius: 4px; }
.family .nerd:hover { color: var(--color-ink); background: var(--color-paper-2); }
/* the dark mode switch (js/theme.js), in the strip beside >_ since 10 Nov 2026: dark is the default, so it no longer floats */
.family-tools { display: flex; align-items: center; gap: .25rem; }
.family .theme-toggle { display: inline-flex; align-items: center; gap: .45rem; margin: 0; padding: .3rem .5rem; background: none; border: 0; border-radius: 4px; color: var(--color-muted); font: inherit; cursor: pointer; }
.family .theme-toggle[hidden] { display: none; }
.family .theme-toggle:hover { color: var(--color-ink); background: var(--color-paper-2); }
.theme-toggle svg { flex: none; }
.theme-toggle .tt-track { position: relative; flex: none; width: 1.6rem; height: .9rem; border-radius: 999px; background: var(--color-rule); transition: background-color .2s ease; }
.theme-toggle .tt-track::after { content: ""; position: absolute; top: .12rem; left: .12rem; width: .66rem; height: .66rem; border-radius: 50%; background: var(--color-paper-3); box-shadow: 0 1px 2px rgba(0,0,0,.25); transition: transform .2s var(--ease-out); }
.theme-toggle[aria-checked="true"] .tt-track { background: var(--color-accent-solid); }
.theme-toggle[aria-checked="true"] .tt-track::after { transform: translateX(.7rem); background: #fff; }
@media (max-width: 40rem) { .theme-toggle .tt-label { display: none; } }   /* phones: the moon and the switch say enough */
@media (prefers-reduced-motion: reduce) { .theme-toggle .tt-track, .theme-toggle .tt-track::after { transition: none; } }

/* ── The announcement bar, above everything (ANNOUNCE in gen.py; Mat, 10 Nov 2026, after fin.ai) ──
   One release at a time, on every toca.io page. The × (js/site.js) hides it and remembers the release; the inline
   script in the bar's markup adds .announce-off before it is drawn. Phones get the lead and the link only. */
.announce { position: relative; background: #2b2117; color: #faf7f1; padding: 0 var(--page-gutter); font-size: var(--text-sm); line-height: 1.35; }
.announce-off .announce { display: none; }
.announce-in { display: flex; justify-content: center; align-items: center; gap: .5rem .9rem; min-height: 2.6rem; margin: 0; padding: .45rem 2.75rem; flex-wrap: wrap; text-align: center; }
.announce-tag { flex: none; font-family: var(--font-mono); font-size: var(--text-xs); font-weight: 500; letter-spacing: .08em; text-transform: uppercase; color: #fff; background: var(--color-accent-solid); padding: .2rem .45rem; border-radius: 4px; }
.announce-link { color: inherit; text-decoration: none; }
.announce-link b { font-weight: 600; }
.announce-link .rest { color: rgba(250,247,241,.78); }
.announce-link .cta { margin-left: .5rem; font-weight: 500; border-bottom: 1px solid rgba(250,247,241,.45); white-space: nowrap; }
.announce-link:hover .cta { border-bottom-color: var(--color-accent); }
.announce :focus-visible { outline-color: #fdfbff; }
.announce-x { position: absolute; right: calc(var(--page-gutter) - .6rem); top: 50%; transform: translateY(-50%); width: 2.2rem; height: 2.2rem; display: grid; place-items: center; padding: 0; background: none; border: 0; border-radius: 50%; color: rgba(250,247,241,.7); font-size: 1.25rem; line-height: 1; cursor: pointer; }
.announce-x[hidden] { display: none; }
.announce-x:hover { color: #fff; background: rgba(250,247,241,.08); }
@media (max-width: 40rem) {
  .announce-in { justify-content: flex-start; padding-left: 0; text-align: left; }
  .announce-link .rest { display: none; }
  .announce-link .cta { margin-left: .35rem; }
}

/* ── Nav dropdown (Platform) ─────────────────────────────────────── */
.nav-links .has-menu { position: relative; display: flex; align-items: center; }   /* its link is laid out like the plain links beside it, so the two dropdowns sit on the same line */
.nav-links .has-menu > a::after { content: ""; display: inline-block; width: .4em; height: .4em; margin-left: .4em; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: translateY(-.2em) rotate(45deg); }
.menu {
  position: absolute; top: 100%; left: -1rem; min-width: 15rem; margin: 0; padding: .5rem 0; list-style: none;
  background: var(--color-paper-3); border: var(--rule-hair) solid var(--color-rule); border-radius: 10px;
  box-shadow: 0 12px 30px -12px rgba(43,33,23,.25);
  opacity: 0; visibility: hidden; transform: translateY(6px); transition: opacity 120ms, transform 120ms, visibility 0s 120ms;
}
.has-menu:hover .menu, .has-menu:focus-within .menu { opacity: 1; visibility: visible; transform: none; transition-delay: 0s; }
.menu li a { display: block; padding: .45rem 1rem; border: 0; font-weight: 400; color: var(--color-ink-2); }
.menu li a:hover { background: var(--color-paper-2); color: var(--color-ink); }
.menu li.sep { border-top: var(--rule-hair) solid var(--color-rule); margin: .4rem 0; }
.menu li small { display: block; font-family: var(--font-mono); font-size: var(--text-xs); color: var(--color-muted); margin-top: .1rem; }
/* ── The header comes back when you scroll up (Mat, 10 Nov 2026; js/site.js) ──
   The nav row is sticky; reading down the page slides it away, any scroll up brings it back, so Talk to us is one flick
   away without anything else floating. The announcement bar and the strip scroll away as normal. At the top of the page
   it sits in place. html.nav-shown is set while it covers the top, so things that stick under it (the platform page's
   stage) can step down by --nav-h. The law-firm pages are untouched: the rules say body.io > .nav, and their nav sits in a .io wrapper on body.legal (a bare .io > .nav caught it, 10 Nov 2026). */
body.io > .nav { position: sticky; top: 0; background: var(--color-paper); transition: transform .28s var(--ease-out), box-shadow .28s ease; }
body.io > .nav.nav--hidden { transform: translateY(-100%); }
html.nav-stuck body.io > .nav:not(.nav--hidden) { box-shadow: 0 12px 30px -20px rgba(2,4,12,.45); }
html.nav-shown .io-tx-stick { top: calc(var(--nav-h, 0px) + 1rem); }
.io-tx-stick { transition: top .28s var(--ease-out); }
@media (prefers-reduced-motion: reduce) { body.io > .nav, .io-tx-stick { transition: none; } }
@media (max-width: 64rem) { html.nav-shown .io-tx-stick { top: var(--nav-h, 0px); } }   /* phones: flush under the header, as it is flush with the top */
@media (max-width: 64rem) { .nav-links .has-menu { display: block; } .menu { position: static; opacity: 1; visibility: visible; transform: none; box-shadow: none; border: 0; padding-left: 1rem; } .nav-links .has-menu > a::after { display: none; } }
/* The open phone menu hangs from its right edge (site.css), so anything wider than the screen ran off the left: the dropdown
   descriptions kept site.css's nowrap and "payroll, accounting, charities and immigration" made the panel 451px on a 375px
   phone. They wrap now, and the panel never runs past the page gutters (9 Nov 2026). */
@media (max-width: 64rem) { .io .nav-links { max-width: calc(100% - 2 * var(--page-gutter)); } .io .nav-links .menu a { white-space: normal; } }
/* The open phone menu is about 800px tall and the header that holds it is sticky, so it never scrolled: on an iPhone 15
   News and Company sat below the screen, on an iPhone SE everything after Sectors, on a phone held sideways half the
   menu. It scrolls inside itself now, never past the bottom of the screen (js/site.js keeps --menu-room at the height
   left under the header), and short screens drop the dropdowns' one-line descriptions (11 Nov 2026). */
@media (max-width: 64rem) { .io .nav-links { max-height: var(--menu-room, calc(100svh - 7rem)); overflow-y: auto; overscroll-behavior: contain; } }
@media (max-width: 64rem) and (max-height: 40rem) { .io .nav-links .menu li small { display: none; } }
/* A phone on its side has 375 to 440px of height, and the header took 97 of them: it slims to 61 (11 Nov 2026). */
@media (max-height: 30rem) { .io .nav { padding-block: calc(var(--space-xs) + env(safe-area-inset-top, 0px)) var(--space-xs); } }

/* ── Hero: paper, no film. Headline, lede, ledger, the mark mosaic ── */
.hero-ledger { position: relative; overflow: hidden; padding: var(--space-3xl) var(--page-gutter) var(--space-2xl); }
.hero-ledger canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; z-index: 0; transition: opacity 120ms linear; }
.hero-ledger .band-narrow, .hero-ledger .hero-copy { position: relative; z-index: 1; }
/* copy and ledger share the content column; the mosaic mark hangs off the column's right edge (js/hero-mosaic.js) */
.hero-ledger .hero-copy { max-width: 48rem; }
.hero-ledger h1 { font-family: var(--font-display); font-weight: 600; font-size: var(--text-display); line-height: .98; letter-spacing: -.025em; margin: 0; max-width: 24ch; }
.hero-ledger h1 br { display: none; }
@media (min-width: 70rem) { .hero-ledger h1 br { display: inline; } }
.hero-ledger .hero-copy > p.support { font-size: var(--text-md); line-height: 1.45; max-width: 52ch; margin: var(--space-lg) 0 0; color: var(--color-ink-2); }
/* :where(body:not(.legal)) keeps a rule off the law-firm pages, which keep toca.legal's look, without changing its weight here */
:where(body:not(.legal)) .hero-links { display: flex; flex-wrap: wrap; gap: var(--space-sm) var(--space-lg); margin-top: var(--space-xl); align-items: center; }
:where(body:not(.legal)) .page-head .hero-links { margin-top: var(--space-xl); }   /* site.css's .page-head .hero-links (8px, toca.health's) outranked the line above: inner page heads now match the homepage (Mat, 10 Nov 2026) */

.ledger { list-style: none; margin: var(--space-2xl) 0 0; padding: 0; border-top: var(--rule-hair) solid var(--color-rule); }
.ledger li {
  display: grid; grid-template-columns: max-content minmax(0, 1fr) minmax(11rem, 17rem);
  gap: var(--space-md) var(--space-xl); align-items: baseline;
  padding: var(--space-lg) 0; border-bottom: var(--rule-hair) solid var(--color-rule);
}
:where(body:not(.legal)) .fig { font-family: var(--font-figure); font-weight: 600; font-size: clamp(3.4rem, 7vw, 7.5rem); line-height: .85; letter-spacing: -.01em; color: var(--color-ink); font-variant-numeric: tabular-nums; white-space: nowrap; }
:where(body:not(.legal)) .fig small { font-size: .38em; font-weight: 500; letter-spacing: 0; color: var(--color-muted); margin-left: .2em; }
.ledger .claim { margin: 0; font-size: var(--text-md); line-height: 1.4; max-width: 34ch; color: var(--color-ink-2); }
.ledger .claim b { color: var(--color-ink); font-weight: 500; }
.ledger .claim-n { display: inline-block; font-family: var(--font-figure); font-weight: 600; font-size: 1.4em; line-height: 1; letter-spacing: -.01em; color: var(--color-ink); font-variant-numeric: tabular-nums; text-align: right; vertical-align: -.05em; }
.ledger.is-live li.claimed .claim-n { animation: claim-pop 420ms var(--ease-out); }
@keyframes claim-pop { 0% { transform: scale(1); } 35% { transform: scale(1.08); } 100% { transform: scale(1); } }
.source { margin: 0; font-family: var(--font-mono); font-size: var(--text-xs); line-height: 1.5; color: var(--color-muted); }
.ledger .source { align-self: end; }
.ledger li { grid-template-columns: max-content minmax(0, 1fr); }   /* source lines removed by Mat, 9 Sept */
@media (max-width: 64rem) { .ledger li { grid-template-columns: max-content minmax(0, 1fr); } .ledger .source { grid-column: 2; } }
@media (max-width: 40rem) { .ledger li { grid-template-columns: 1fr; gap: .5rem; } .ledger .source { grid-column: 1; } :where(body:not(.legal)) .fig { font-size: clamp(3rem, 14vw, 4.6rem); } }

/* Build 02, counting up (js/ledger-count.js). The authored markup is the
   finished state; these rules only bite once the script adds .is-live,
   so no JavaScript and reduced motion both read the page as written. */
.ledger .fig-n { display: inline-block; text-align: right; }
.ledger.is-live .fig, .ledger.is-live .claim, .ledger.is-live .source { opacity: 0; }
.ledger.is-live .fig { transform: translateY(.3em); transition: opacity 600ms var(--ease-out), transform 600ms var(--ease-out); }
.ledger.is-live .fig small { opacity: 0; transition: opacity 360ms var(--ease-out); }
.ledger.is-live .claim { transform: translateY(6px); transition: opacity 500ms var(--ease-out) 160ms, transform 500ms var(--ease-out) 160ms; }
.ledger.is-live .source { transition: opacity 200ms linear; }
.ledger.is-live li.in .fig, .ledger.is-live li.in .claim { opacity: 1; transform: none; }
.ledger.is-live li.unit .fig small, .ledger.is-live li.counted .fig small { opacity: 1; }
.ledger.is-live li.counted .source { opacity: 1; }

/* ── Proof bar · the unified single-colour marks, as on toca.legal ──
   site.css lays .proof-bar out as a lozenge-centred grid built for the
   health marks; these marks are normalised by ink area already, so the
   legal site's flex row is used instead. Sizes are inline on each img and
   come from the legal build; copy them with the file. Organisations with
   no mark yet render as text in the same row (data-mark names the file
   expected in assets/img/logos/). */
:where(body:not(.legal)) .proof-bar--logos { display: block; padding: var(--space-lg) var(--page-gutter); border-top: var(--rule-hair) solid var(--color-rule); border-bottom: var(--rule-hair) solid var(--color-rule); }
:where(body:not(.legal)) .proof-bar--logos p { flex: 1 0 100%; margin: 0; order: 0; font-family: var(--font-mono); font-size: var(--text-xs); font-weight: 500; letter-spacing: .14em; text-transform: uppercase; color: var(--color-muted); }
:where(body:not(.legal)) .proof-bar--logos img.logo { order: 2; display: block !important; flex: 0 0 auto; height: auto !important; width: auto; transform: none !important; opacity: .6; transition: opacity .25s; }
:where(body:not(.legal)) .proof-bar--logos .firm { order: 2; flex: 0 0 auto; font-family: var(--font-display); font-weight: 600; font-size: clamp(1rem, 1.4vw + .4rem, 1.35rem); line-height: 1; color: var(--color-muted); opacity: .75; white-space: nowrap; transition: opacity .25s; }
:where(body:not(.legal)) .proof-bar--logos:hover img.logo, :where(body:not(.legal)) .proof-bar--logos:hover .firm { opacity: .42; }
:where(body:not(.legal)) .proof-bar--logos img.logo:hover, :where(body:not(.legal)) .proof-bar--logos .firm:hover { opacity: 1; }

/* ── Section heads ───────────────────────────────────────────────── */
.io-head { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); gap: var(--space-lg) var(--space-3xl); align-items: end; margin-bottom: var(--space-2xl); }
.io-head h2, .io-head h1 { font-family: var(--font-display); font-weight: 600; font-size: clamp(1.9rem, 3vw + .5rem, 3.1rem); line-height: 1.04; margin: 0; max-width: 22ch; }
.io-head .support { margin: 0; max-width: 56ch; }
@media (max-width: 64rem) { .io-head { grid-template-columns: 1fr; } }

/* ── Dossier ─────────────────────────────────────────────────────── */
.dossier { border-top: var(--rule-hair) solid var(--color-rule); }
.entry { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--space-xl) var(--space-3xl); padding: var(--space-2xl) 0; border-bottom: var(--rule-hair) solid var(--color-rule); }
.entry h3 { font-family: var(--font-display); font-weight: 600; font-size: clamp(1.7rem, 2.6vw + .4rem, 2.6rem); line-height: 1.06; margin: 0; max-width: 18ch; }
.entry .kicker { margin-bottom: var(--space-sm); }
.entry .support { margin: var(--space-lg) 0 0; max-width: 46ch; }
.entry .tlink { display: inline-block; margin-top: var(--space-lg); }
.entry-figs { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(8.5rem, 100%), 1fr)); gap: var(--space-lg) var(--space-md); margin-top: var(--space-xl); max-width: 32rem; }
.entry-figs div { display: flex; flex-direction: column; gap: .3rem; }
.entry-figs .fig { font-size: clamp(2.2rem, 3.2vw, 3.2rem); }
.entry-figs .source { max-width: 20ch; }
.entry-body { display: flex; flex-direction: column; gap: var(--space-lg); }

/* Build 03, England footprint (js/england-footprint.js). Map from
   tools/build_footprint_map.py, inlined by gen.py. The markup is the
   finished state; the .is-live rules hide and then reveal. */
.footprint { display: grid; grid-template-columns: minmax(0, 7fr) minmax(11rem, 5fr); gap: var(--space-lg) var(--space-xl); align-items: start; margin: 0; padding: var(--space-lg) 0 var(--space-md); border-top: var(--rule-hair) solid var(--color-rule); border-bottom: var(--rule-hair) solid var(--color-rule); }
.footprint .fp-map { display: block; width: 100%; height: auto; max-height: 34rem; }
.footprint .fp-land { fill: var(--color-paper-2); stroke: var(--color-muted); stroke-width: .8; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.footprint .fp-foot { fill: var(--color-accent); stroke: var(--color-paper); stroke-width: .8; vector-effect: non-scaling-stroke; transform-box: fill-box; transform-origin: center; }
.footprint .fp-side { display: flex; flex-direction: column; gap: var(--space-md); }
.footprint .fp-counter { display: flex; flex-direction: column; gap: .3rem; margin: 0; }
.footprint .fp-counter .fig { font-size: clamp(2.6rem, 4.6vw, 4.4rem); }
.footprint .fp-counter .fig-n { display: inline-block; text-align: right; }
.footprint .fp-list { list-style: none; margin: 0; padding: 0; border-top: var(--rule-hair) solid var(--color-rule); }
.footprint .fp-list li { display: flex; align-items: baseline; gap: .6rem; padding: .45rem 0; border-bottom: var(--rule-hair) solid var(--color-rule); font-family: var(--font-mono); font-size: var(--text-xs); line-height: 1.4; color: var(--color-ink-2); }
.footprint .fp-list li::before { content: ""; flex: none; width: .55em; height: .55em; background: var(--color-accent); border-radius: 1px; align-self: center; }
.footprint .fp-note { margin: 0; }
.footprint.is-live .fp-land { opacity: 0; transition: opacity 500ms var(--ease-out); }
.footprint.is-live.in .fp-land { opacity: 1; }
.footprint.is-live .fp-foot { opacity: 0; transform: scale(.85); transition: opacity 320ms var(--ease-out), transform 480ms var(--ease-out); }
.footprint.is-live .fp-foot.on { opacity: 1; transform: none; }
.footprint.is-live .fp-list li { opacity: 0; transform: translateY(-.4rem); transition: opacity 300ms var(--ease-out), transform 360ms var(--ease-out); }
.footprint.is-live .fp-list li.on { opacity: 1; transform: none; }
.footprint.is-live .fp-note { opacity: 0; transition: opacity 400ms linear; }
.footprint.is-live.done .fp-note { opacity: 1; }
@media (max-width: 40rem) { .footprint { grid-template-columns: 1fr; } .footprint .fp-map { max-height: 24rem; } }
.built { display: flex; flex-wrap: wrap; gap: .5rem 1.5rem; margin: 0; font-size: var(--text-sm); color: var(--color-muted); }
.built b { color: var(--color-ink); font-weight: 500; }
.built span::before { content: ""; display: inline-block; width: .42rem; height: .42rem; border-radius: 50%; background: var(--color-accent); margin-right: .5rem; vertical-align: .1em; }
@media (max-width: 64rem) { .entry { grid-template-columns: minmax(0, 1fr); } }

/* ── Products and enabling layers ────────────────────────────────── */
.plat-wrap { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3xl); align-items: start; }
.plat-notes { display: flex; flex-direction: column; gap: var(--space-lg); }
.plat-notes .chip { align-self: flex-start; }
.io-products { display: flex; flex-direction: column; gap: var(--space-md); margin: 0; padding: 0; list-style: none; }
.io-product { display: grid; grid-template-columns: minmax(0,1fr); gap: .5rem; padding: var(--space-lg); background: var(--color-paper-3); border: var(--rule-hair) solid var(--color-rule); border-radius: 10px; transition: transform var(--dur-short) var(--ease-out), border-color var(--dur-short); }
.io-product:hover { transform: translateX(6px); border-color: var(--color-muted); }
.io-product--lead { border: 1.5px solid var(--color-accent); }
.io-product .name { font-family: var(--font-display); font-weight: 600; font-size: var(--text-md); color: var(--color-ink); }
.io-product .lang { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--color-muted); margin-left: .75rem; }
.io-product .what { margin: 0; color: var(--color-ink-2); font-size: var(--text-sm); max-width: 50ch; line-height: 1.5; }
.cap-label { font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: .1em; text-transform: uppercase; color: var(--color-muted); margin: var(--space-lg) 0 var(--space-sm); }
.capabilities { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-md); margin: 0; padding: 0; list-style: none; }
.cap { padding: var(--space-md) var(--space-lg); background: var(--color-paper-2); border: var(--rule-hair) solid var(--color-rule); border-radius: 10px; }
.cap .name { font-family: var(--font-display); font-weight: 600; font-size: var(--text-base); color: var(--color-ink); }
.cap .what { margin: .3rem 0 0; color: var(--color-ink-2); font-size: var(--text-sm); max-width: 40ch; line-height: 1.5; }
.io .stat-strip b { font-family: var(--font-figure); font-weight: 600; font-size: clamp(2.2rem, 3.4vw, 3.2rem); letter-spacing: -.01em; }
.io .stat-strip { border-top: var(--rule-hair) solid var(--color-rule); padding-top: var(--space-lg); }
@media (max-width: 60rem) { .plat-wrap { grid-template-columns: 1fr; } .capabilities { grid-template-columns: 1fr; } }
/* above tablet the platform section is meant to sit in one viewport: two-line leads on the cards (the full copy is on the platform and product pages), tighter cards */
@media (min-width: 60.01rem) { #platform .io-head { grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); } .io-product { padding: var(--space-md) var(--space-lg); } .io-products { gap: var(--space-sm); } .io-product .what, .cap .what { max-width: none; } .cap { padding: var(--space-md); } .cap-label { margin-top: var(--space-md); } .plat-wrap { gap: var(--space-2xl); } #platform.band { padding-top: var(--space-xl); padding-bottom: var(--space-xl); } #platform .io-head { margin-bottom: var(--space-lg); } }

/* ── Family tiles ────────────────────────────────────────────────── */
.family-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-md); margin-top: var(--space-2xl); }
.tile { display: flex; flex-direction: column; gap: var(--space-md); padding: var(--space-xl) var(--space-lg) var(--space-lg); border-radius: 10px; min-height: 17rem; text-decoration: none; color: var(--color-ink); background: var(--color-paper-3); border: var(--rule-hair) solid var(--color-rule); transition: transform var(--dur-short) var(--ease-out); }
.tile:hover { transform: translateY(-4px); }
.tile--here { border: 1.5px solid var(--color-accent); }
.tile .wordmark { font-size: 1.1rem; }
.tile p { margin: 0; font-size: var(--text-sm); line-height: 1.5; max-width: 34ch; color: var(--color-ink-2); }
.tile .tile-foot { margin-top: auto; font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: .04em; color: var(--color-muted); }
.family-more { margin: var(--space-lg) 0 0; display: flex; flex-wrap: wrap; gap: .5rem 1.25rem; font-size: var(--text-sm); color: var(--color-muted); align-items: baseline; }
.family-more b { color: var(--color-ink); font-weight: 500; }
@media (max-width: 64rem) { .family-grid { grid-template-columns: 1fr; } .tile { min-height: 0; } }

/* ── Partner rows, built-on ──────────────────────────────────────── */
.partner-rows { margin: 0; border-top: var(--rule-hair) solid var(--color-rule); }
.partner-rows > div { display: grid; grid-template-columns: minmax(8rem, 12rem) minmax(0, 1fr); gap: var(--space-sm) var(--space-xl); padding: var(--space-lg) 0; border-bottom: var(--rule-hair) solid var(--color-rule); align-items: baseline; }
.partner-rows dt { font-family: var(--font-display); font-weight: 600; font-size: var(--text-md); }
.partner-rows dd { margin: 0; }
/* Phones: the name sits above its description. Side by side, the description had a 120px column, and a long link that
   would not wrap ("The network security case study", the Cyber Essentials Plus source) pushed it off the right of the
   screen, where html's overflow clip cut the text off (11 Nov 2026). */
.partner-rows dd .tlink { white-space: normal; }
@media (max-width: 40rem) { .partner-rows > div { grid-template-columns: minmax(0, 1fr); gap: var(--space-xs); } }
.partner-rows dd p { margin: 0; color: var(--color-ink-2); max-width: 54ch; }
.partner-rows dd .source { margin-top: .35rem; }
/* Power Platform page: Microsoft's side beside Toca's, row by row (10 Nov 2026) */
.vs-rows dd { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-md) var(--space-xl); }
.vs-rows .vs-who { display: block; margin-bottom: var(--space-2xs); font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: .12em; text-transform: uppercase; color: var(--color-muted); }
.vs-rows .vs-who--toca { color: var(--color-accent-text); }
@media (max-width: 48rem) { .vs-rows > div { grid-template-columns: 1fr; } .vs-rows dd { grid-template-columns: 1fr; } }
.built-on { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--space-3xl); align-items: start; }
.built-on h2 { font-family: var(--font-display); font-weight: 600; font-size: clamp(1.9rem, 3vw + .5rem, 3rem); line-height: 1.04; margin: 0 0 var(--space-lg); max-width: 14ch; }
@media (max-width: 64rem) { .built-on { grid-template-columns: 1fr; } }

/* ── Company tree ────────────────────────────────────────────────── */
.tree { list-style: none; margin: 0; padding: 0; border-top: var(--rule-hair) solid var(--color-rule); }
.tree > li { display: grid; grid-template-columns: minmax(10rem, 16rem) 1fr; gap: var(--space-md) var(--space-3xl); padding: var(--space-xl) 0; border-bottom: var(--rule-hair) solid var(--color-rule); }
.tree .tier { font-family: var(--font-figure); font-weight: 600; font-size: 1.1rem; letter-spacing: .01em; color: var(--color-accent-text); }
.tree .tier small { display: block; font-family: var(--font-body); font-weight: 400; font-size: var(--text-sm); color: var(--color-muted); margin-top: .35rem; max-width: 26ch; letter-spacing: 0; }
.tree ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-md); }
.tree ul li { display: grid; grid-template-columns: minmax(8rem, 12rem) 1fr; gap: 1rem; padding-left: var(--space-lg); border-left: 2px solid var(--color-rule); }
.tree ul li b { font-family: var(--font-display); font-weight: 600; font-size: var(--text-md); color: var(--color-ink); }
.tree ul li b small { display: block; font-family: var(--font-mono); font-weight: 400; font-size: var(--text-xs); color: var(--color-muted); margin-top: .2rem; }
.tree ul li p { margin: 0; color: var(--color-ink-2); max-width: 54ch; font-size: var(--text-base); }
.tree ul li.is-site { border-left-color: var(--color-accent); }
@media (max-width: 64rem) { .tree > li, .tree ul li { grid-template-columns: 1fr; } }

/* ── Product page bits ───────────────────────────────────────────── */
:where(body:not(.legal)) .page-head { padding: var(--space-3xl) var(--page-gutter) var(--space-xl); }
:where(body:not(.legal)) .page-head h1 { font-family: var(--font-display); font-weight: 600; font-size: clamp(2.4rem, 4.2vw + .6rem, 4.6rem); line-height: 1; letter-spacing: -.02em; margin: 0; max-width: 18ch; }   /* the kicker above carries the --space-sm gap, as in .io-head and .entry */
:where(body:not(.legal)) .page-head .support { font-size: var(--text-md); line-height: 1.45; max-width: 56ch; margin: var(--space-lg) 0 0; color: var(--color-ink-2); }
.duo-io { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--space-2xl) var(--space-3xl); align-items: start; }
.duo-io + .duo-io { margin-top: var(--space-2xl); padding-top: var(--space-2xl); border-top: var(--rule-hair) solid var(--color-rule); }
.duo-io h2 { font-family: var(--font-display); font-weight: 600; font-size: clamp(1.6rem, 2.4vw + .4rem, 2.4rem); line-height: 1.08; margin: 0; max-width: 18ch; }
.duo-io .support { margin: var(--space-md) 0 0; max-width: 46ch; }
.pointlist { margin: var(--space-lg) 0 0; padding: 0; list-style: none; display: grid; gap: .6rem; max-width: 46ch; }
.pointlist li { padding-left: 1.1rem; position: relative; color: var(--color-ink-2); }
.pointlist li::before { content: ""; position: absolute; left: 0; top: .6em; width: .42rem; height: .42rem; border-radius: 50%; background: var(--color-accent); }
@media (max-width: 64rem) { .duo-io { grid-template-columns: 1fr; } }

.subnav { padding: var(--space-md) var(--page-gutter); border-bottom: var(--rule-hair) solid var(--color-rule); font-size: var(--text-sm); }
.subnav > .band-narrow { display: flex; flex-wrap: wrap; gap: var(--space-xs) var(--space-lg); }
.subnav a { color: var(--color-ink-2); text-decoration: none; padding: .3rem 0; border-bottom: 1px solid transparent; }
.subnav a[aria-current] { color: var(--color-ink); border-bottom-color: var(--color-accent); }
.subnav a:hover { color: var(--color-ink); }
.subnav .lbl { font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: .1em; text-transform: uppercase; color: var(--color-muted); margin-right: .5rem; align-self: center; }

/* ── Placeholders: animation slots and tour flips ────────────────── */
.anim-slot { position: relative; border: 1px dashed color-mix(in srgb, var(--color-accent) 55%, transparent); border-radius: 10px; background: repeating-linear-gradient(-45deg, transparent 0 14px, color-mix(in srgb, var(--color-accent) 10%, transparent) 14px 15px); min-height: 18rem; padding: 2.4rem 1rem 1rem; display: flex; flex-direction: column; justify-content: flex-end; gap: .5rem; }
.anim-slot::before { content: "Animation build " attr(data-slot) "  ·  ANIMATION-PROPOSALS.md"; position: absolute; top: .9rem; left: 1rem; font-family: var(--font-mono); font-size: var(--text-xs); color: var(--color-accent-text); }
.anim-slot p { margin: 0; font-family: var(--font-mono); font-size: var(--text-xs); line-height: 1.55; max-width: 60ch; color: var(--color-muted); }
.anim-slot strong { font-weight: 500; color: var(--color-ink); }
.anim-slot--tall { min-height: 26rem; }
.anim-slot--note { min-height: 0; justify-content: flex-start; }
.tour-flip { display: flex; justify-content: space-between; align-items: center; gap: 1rem; margin-top: .6rem; padding: .6rem .9rem; border: 1px dashed var(--color-rule); border-radius: 8px; font-family: var(--font-mono); font-size: var(--text-xs); color: var(--color-muted); }
.tour-flip .chip { font-size: var(--text-xs); padding: .35rem .7rem; }

/* Smallest text anywhere on toca.io is --text-xs (12.8px): nothing smaller (WCAG review, 10 Nov 2026). */

/* ── Back to top ─────────────────────────────────────────────────── */
.totop { position: fixed; left: 1.25rem; bottom: 1.25rem; z-index: 60; width: 2.75rem; height: 2.75rem; display: grid; place-items: center; padding: 0; background: var(--color-paper-3); color: var(--color-ink); border: var(--rule-hair) solid var(--color-rule); border-radius: 50%; cursor: pointer; box-shadow: 0 10px 30px -12px rgba(43,33,23,.45); opacity: 0; transform: translateY(.6rem); pointer-events: none; transition: opacity .25s ease, transform .25s ease, background-color .15s ease; }
.totop.is-on { opacity: 1; transform: none; pointer-events: auto; }
.totop:hover { background: var(--color-ink); color: var(--color-paper-3); }
.totop[hidden] { display: none; }
@media (prefers-reduced-motion: reduce) { .totop { transition: none; } }

/* ── Concierge launcher and panel (mock) ─────────────────────────── */
.cx-launch { position: fixed; right: 1.25rem; bottom: 1.25rem; z-index: 60; display: inline-flex; align-items: center; gap: .5rem; padding: .7rem 1rem; background: var(--color-ink); color: var(--color-paper-3); border: 0; border-radius: 999px; font: 500 var(--text-sm) var(--font-body); cursor: pointer; box-shadow: 0 10px 30px -10px rgba(43,33,23,.45); }
.cx-launch .dot { width: .5rem; height: .5rem; border-radius: 50%; background: var(--color-accent); }
.cx { position: fixed; right: 1.25rem; bottom: 4.5rem; z-index: 60; width: min(24rem, calc(100vw - 2.5rem)); background: var(--color-paper-3); border: var(--rule-hair) solid var(--color-rule); border-radius: 14px; box-shadow: 0 24px 60px -20px rgba(43,33,23,.35); display: none; flex-direction: column; overflow: hidden; }
.cx.open { display: flex; }
/* Short screens (a phone on its side): the panel ran off the top of the screen, its Close with it, and the header covered
   its middle. It stops short of the top and sits over the header; the conversation and the small print scroll inside
   it (11 Nov 2026). The docked panel keeps its own height and z-index. */
.cx:not(.docked) { max-height: calc(100svh - 5.75rem); z-index: calc(var(--z-sticky) + 2); }
.cx:not(.docked) .cx-log { min-height: 5rem; }
.cx:not(.docked) .cx-foot { flex: 0 1 auto; min-height: 2.6rem; overflow-y: auto; }
.cx-head { display: flex; justify-content: space-between; align-items: center; padding: .8rem 1rem; border-bottom: var(--rule-hair) solid var(--color-rule); font: 500 var(--text-sm) var(--font-body); }
.cx-head button { background: none; border: 0; font: inherit; color: var(--color-muted); cursor: pointer; }
.cx-log { padding: 1rem; display: grid; gap: .75rem; font-size: var(--text-sm); max-height: 20rem; overflow: auto; }
.cx-log .me { justify-self: end; background: var(--color-paper-2); padding: .5rem .8rem; border-radius: 12px 12px 2px 12px; max-width: 85%; }
.cx-log .ai { background: var(--color-paper); border: var(--rule-hair) solid var(--color-rule); padding: .6rem .8rem; border-radius: 12px 12px 12px 2px; max-width: 90%; color: var(--color-ink-2); }
.cx-log .ai .act { display: inline-block; margin-top: .4rem; font-family: var(--font-mono); font-size: var(--text-xs); color: var(--color-accent-text); }
.cx-in { display: flex; gap: .5rem; padding: .75rem; border-top: var(--rule-hair) solid var(--color-rule); }
.cx-in input { flex: 1; padding: .6rem .8rem; border: var(--rule-hair) solid var(--color-rule); border-radius: 8px; background: var(--color-paper); font: inherit; }
.cx-foot { padding: .5rem 1rem .7rem; font-family: var(--font-mono); font-size: var(--text-xs); color: var(--color-muted); line-height: 1.45; }
.cx-foot a { color: inherit; }
.bot-field { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }   /* Netlify's honeypot */
.cx-trap { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }
.cx-in button[disabled] { opacity: .5; cursor: wait; }
.cx-log .cx-wait { color: var(--color-muted); font-style: italic; }
.cx-log .cx-err { border-color: var(--color-accent); }
.cx-log .ai .act { margin-right: .8rem; }
.cx-log .ai button.act { background: none; border: 0; padding: 0; cursor: pointer; text-decoration: underline; text-underline-offset: .2em; }
.cx-log .ai a.act { text-decoration: underline; text-underline-offset: .2em; }
.cx-article { display: grid; grid-template-columns: 5.5rem 1fr; gap: .8rem; padding: .6rem; border: var(--rule-hair) solid var(--color-rule); border-radius: 10px; background: var(--color-paper); text-decoration: none; color: inherit; max-width: 100%; }
.cx-article:hover { border-color: var(--color-accent); }
.cx-article img { width: 5.5rem; height: 5.5rem; object-fit: cover; border-radius: 6px; display: block; }
.cx-article-body { display: grid; gap: .25rem; font-size: var(--text-xs); color: var(--color-ink-2); min-width: 0; }
.cx-article-body b { font-weight: 500; color: var(--color-ink); font-size: var(--text-sm); line-height: 1.3; }
.cx-article-tag { font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: .08em; text-transform: uppercase; color: var(--color-accent-text); }
.cx-article .act { margin: .2rem 0 0; }
.cx-lead { display: grid; gap: .5rem; }
.cx-lead p { margin: 0; }
.cx-lead label { display: grid; gap: .2rem; font-size: var(--text-xs); color: var(--color-muted); }
.cx-lead input, .cx-lead textarea { padding: .45rem .6rem; border: var(--rule-hair) solid var(--color-rule); border-radius: 6px; background: var(--color-paper); font: inherit; font-size: var(--text-sm); color: var(--color-ink); }
.cx-lead textarea { min-height: 4rem; resize: vertical; }
.cx-lead .cx-consent { display: flex; gap: .5rem; align-items: center; color: var(--color-ink-2); }
.cx-lead-actions { display: flex; gap: 1rem; align-items: center; margin-top: .3rem; }
.cx-lead .chip { font-size: var(--text-xs); padding: .4rem .8rem; }
.cx-target { outline: 2px solid var(--color-accent); outline-offset: 10px; border-radius: 6px; transition: outline-color .8s ease; }
@media (prefers-reduced-motion: reduce) { .cx-target { transition: none; } }

/* ── Ami's starter buttons and the tour (AMI in gen.py, js/concierge.js; Mat, 10 Nov 2026) ──
   Buttons sit under the line they answer. Touring, the panel is a small card: progress, where you are, a line or
   two, Back and Next; the chat and its input hide until Ask about this. */
.cx-chips { display: flex; flex-wrap: wrap; gap: .4rem; margin-top: -.3rem; }
.cx-chip { display: inline-flex; align-items: center; padding: .42rem .75rem; border: var(--rule-hair) solid var(--color-rule); border-radius: 999px; background: var(--color-paper); color: var(--color-ink); font: 500 var(--text-xs) / 1.25 var(--font-body); text-align: left; text-decoration: none; cursor: pointer; transition: border-color .15s ease, background-color .15s ease; }
.cx-chip:hover { border-color: var(--color-accent); }
.cx-chip--lead { background: var(--color-accent-solid); border-color: var(--color-accent-solid); color: #fff; }
.cx-chip--lead:hover { background: var(--color-accent-deep); border-color: var(--color-accent-deep); }
.cx-head { gap: .75rem; }
.cx-head > span { flex: 1; }
.cx-head .cx-head-tour { color: var(--color-accent-text); }
.cx.touring .cx-head-tour, .cx.docked .cx-head-tour { display: none; }
.cx-tour { display: none; }
.cx.touring .cx-tour { display: grid; gap: .6rem; padding: 1rem 1rem .95rem; }
.cx.touring .cx-log, .cx.touring .cx-in, .cx.touring .cx-foot { display: none; }
.cx-tour-progress { display: flex; gap: 4px; }
.cx-tour-progress i { flex: 1; height: 3px; border-radius: 2px; background: var(--color-rule); }
.cx-tour-progress i.on { background: var(--color-accent); }
.cx-tour-step { margin: .2rem 0 0; font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: .04em; color: var(--color-muted); }
.cx-tour-step b { font-weight: 500; color: var(--color-accent-text); }
.cx-tour-text { margin: 0; font-size: var(--text-sm); line-height: 1.5; color: var(--color-ink-2); }
.cx-tour .cx-chip { justify-self: start; }
.cx-tour-bar { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .9rem; margin-top: .2rem; }
.cx-tour-next { order: 2; padding: .5rem .9rem; border: 0; border-radius: 999px; background: var(--color-accent-solid); color: #fff; font: 500 var(--text-sm) var(--font-body); cursor: pointer; }
.cx-tour-next:hover { background: var(--color-accent-deep); }
.cx-tour-back, .cx-tour-ask { padding: .3rem 0; border: 0; background: none; color: var(--color-muted); font: 500 var(--text-xs) var(--font-body); cursor: pointer; }
.cx-tour-back { order: 1; }
.cx-tour-ask { order: 3; margin-left: auto; text-decoration: underline; text-underline-offset: .2em; }
.cx-tour-back:hover, .cx-tour-ask:hover { color: var(--color-ink); }
@media (max-width: 40rem) { .cx-tour-what { display: none; } .cx.touring .cx-tour { padding: .85rem .9rem .8rem; } }   /* phones: Back, Next and Ask on one line */
@media (prefers-reduced-motion: reduce) { .cx-chip { transition: none; } }

/* ── Fill it in with Ami (contact page, on trial: Mat, 9 Nov 2026; js/concierge.js) ──
   The invite sits on top of the form; docked, the panel covers invite and form in the page flow (absolute in .cx-dock,
   so it scrolls with the page and a phone keyboard simply scrolls to the input). The form keeps its space underneath. */
.cx-dock { position: relative; }
.cx-invite { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: .6rem 1rem; margin: 0 0 var(--space-lg); padding: .7rem .7rem .7rem 1rem; border: var(--rule-hair) solid var(--color-rule); border-radius: 10px; background: var(--color-paper-3); font-size: var(--text-sm); line-height: 1.45; color: var(--color-ink-2); }
.cx-invite[hidden] { display: none; }
.cx-invite .chip { min-height: 2.5rem; padding: .45rem 1rem; }
.cx-invite .dot { width: .5rem; height: .5rem; border-radius: 50%; background: var(--color-accent); }
.cx-dock.is-docked > :not(.cx) { visibility: hidden; }
.cx.docked { position: absolute; inset: 0; width: auto; min-height: 26rem; z-index: 2; box-shadow: 0 18px 50px -24px rgba(43,33,23,.35); }
.cx.docked .cx-log { flex: 1; max-height: none; min-height: 0; align-content: start; }
.cx.docked .cx-head span { color: var(--color-ink); }
.cx.docked .cx-head button { white-space: nowrap; }
body.cx-docked .cx-launch { visibility: hidden; }
/* phones and tablets: the panel takes the form's place in the page, one screen tall, rather than covering a form taller than the screen */
@media (max-width: 64rem) {
  body.cx-docked .totop { visibility: hidden; }
  .cx-dock.is-docked > :not(.cx) { display: none; }
  .cx.docked { position: relative; inset: auto; height: calc(100svh - 3rem); min-height: 22rem; max-height: 42rem; }
}

/* ── The Toca BBS ─────────────────────────────────────────────────
   Black, light grey text, CGA cyan borders, CGA yellow hotkeys, Toca pink
   for the logo and figures. 80 columns; on narrow screens it scrolls
   sideways rather than reflowing the box drawing. Web437 IBM VGA when the
   font is present, Geist Mono otherwise. */
.bbs { position: fixed; inset: 0; z-index: 1000; background: var(--bbs-black); color: #c9c9c9; font: 14px/1.2 "Web437 IBM VGA 8x16", Menlo, Consolas, "DejaVu Sans Mono", "Liberation Mono", monospace;  /* needs box-drawing glyphs, which Geist Mono lacks */ display: none; flex-direction: column; }
.bbs.open { display: flex; }
.bbs.beep { animation: bbs-beep 120ms steps(1) 1; }
@keyframes bbs-beep { 0% { background: #2a2a2a; } 100% { background: var(--bbs-black); } }
.bbs-screen { flex: 1; min-height: 0; overflow: auto; padding: 2rem clamp(1rem, 4vw, 3rem) 1rem; }
.bbs-out { margin: 0; white-space: pre; font: inherit; min-width: 82ch; }
.bbs-line { display: flex; align-items: baseline; min-width: 82ch; padding-top: .25rem; }
.bbs-prompt { white-space: pre; }
.bbs-in { flex: 1; background: none; border: 0; outline: 0; color: #fff; font: inherit; caret-color: #c9c9c9; padding: 0; text-transform: uppercase; }
.bbs-in::selection { background: #c9c9c9; color: #000; }
.bbs .cy { color: #55ffff; } .bbs .ye { color: #ffff55; } .bbs .pk { color: #e91e63; } .bbs .gr { color: #55ff55; } .bbs .dim { color: #7a7a7a; }
.bbs .wh { color: #fff; } .bbs .hl { background: #e91e63; color: #fff; }   /* [B] a claim's bold part; [P] the lit layer, the selected row */
.bbs .blk { display: inline-block; line-height: 1; vertical-align: middle; } .bbs .side { display: inline-block; vertical-align: middle; }   /* [B] block art set solid, its words beside it */
.bbs .bbs-link { color: #55ffff; text-decoration: underline; text-underline-offset: .15em; }
.bbs .bbs-link:hover { color: #ffff55; }
.bbs .cur { display: inline-block; min-width: .6em; background: #c9c9c9; color: #000; animation: blink 1s steps(1) infinite; }
@keyframes blink { 50% { background: transparent; color: #c9c9c9; } }
/* Bamboozle! teletext: the seven fastext colours on black */
.bbs .tt { display: inline-block; background: #000; }
.bbs .ttk { color: #000; } .bbs .ttr { color: #f00; } .bbs .ttg { color: #0f0; } .bbs .tty { color: #ff0; } .bbs .ttb { color: #2af; } .bbs .ttw { color: #fff; } .bbs .ttc { color: #0ff; } .bbs .ttm { color: #f0f; }
.bbs .bas-screen { display: block; line-height: 1; background: #000; width: 80ch; margin: .3rem 0; }
.bbs .bas-canvas { display: block; image-rendering: pixelated; }   /* js/basic.js draws the screen here; sized in the script */
.bbs-chips { display: none; gap: .4rem; flex-wrap: wrap; padding: .6rem 1rem 1rem; border-top: 1px solid #333; background: var(--bbs-black); }
.bbs-chips button { background: #222; color: #ffff55; border: 1px solid #444; border-radius: 4px; padding: .5rem .8rem; font: inherit; min-width: 2.6rem; }
@media (pointer: coarse) { .bbs-chips { display: flex; } }
@media (prefers-reduced-motion: reduce) { .bbs .bbs-link { color: #55ffff; text-decoration: underline; text-underline-offset: .15em; }
.bbs .bbs-link:hover { color: #ffff55; }
.bbs .cur { animation: none; } .bbs.beep { animation: none; } }
.bbs-exit { position: fixed; z-index: 1001; top: 1rem; right: 1rem; padding: .5rem .9rem; background: #ffff55; color: #0e0d0c; border: 0; border-radius: 4px; font: 600 13px "Geist Mono", ui-monospace, monospace; cursor: pointer; }
/* after a SCREEN 1 program the board steps aside so its drawing on the homepage shows (js/bbs.js peek) */
.bbs.open.peek { display: none; }
.bbs-peekbar { position: fixed; left: 50%; bottom: 1.25rem; transform: translateX(-50%); z-index: 1001; display: flex; flex-wrap: wrap; align-items: center; gap: .6rem .9rem; width: max-content; max-width: calc(100vw - 2rem); padding: .6rem .7rem .6rem 1rem; background: var(--bbs-black); color: #c9c9c9; border: 1px solid #55ffff; border-radius: 4px; font: 13px/1.35 "Geist Mono", ui-monospace, monospace; box-shadow: 0 14px 34px -14px rgba(0,0,0,.65); }
.bbs-peekbar[hidden] { display: none; }
.bbs-peekbar button { padding: .45rem .8rem; border: 0; border-radius: 4px; font: 600 13px "Geist Mono", ui-monospace, monospace; cursor: pointer; }
.bbs-peekbar .go { background: #ffff55; color: #0e0d0c; }
.bbs-peekbar .alt { background: none; color: #55ffff; text-decoration: underline; text-underline-offset: .2em; padding-inline: .2rem; }

/* ── Video placeholder (mock: thumbnail linking out; real build uses a click-to-load embed) ── */
.video { margin: 0; display: grid; gap: .6rem; }
.video--wide { max-width: 48rem; }
.video figcaption a.source { color: var(--color-muted); text-decoration: underline; text-decoration-color: var(--color-rule); text-underline-offset: .2em; }
.video figcaption a.source:hover { color: var(--color-accent-text); text-decoration-color: currentColor; }
.video-frame { position: relative; display: block; aspect-ratio: 16 / 9; overflow: hidden; border-radius: 10px; background: var(--color-paper-2); border: var(--rule-hair) solid var(--color-rule); }
.video-frame img { width: 100%; height: 100%; object-fit: cover; display: block; filter: saturate(.9); }
.video-play { position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%); padding: .55rem 1.1rem; border-radius: 999px; background: var(--color-accent-solid); color: var(--color-accent-ink); font: 600 var(--text-sm) var(--font-display); letter-spacing: .01em; }
.video figcaption { display: grid; gap: .15rem; font-size: var(--text-sm); }
.video figcaption b { font-weight: 500; color: var(--color-ink); }
.film-frame { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; border-radius: 10px; background: #252f3f; object-fit: cover; }

/* ── Content notes for the next dev round. Remove before launch. ── */
.cnote { margin: .75rem 0 0; padding: .7rem .9rem; border-left: 3px solid var(--color-ink); background: var(--color-paper-3); font-family: var(--font-mono); font-size: var(--text-xs); line-height: 1.55; color: var(--color-ink-2); max-width: 70ch; border-radius: 0 6px 6px 0; }
.cnote b { display: block; font-weight: 500; color: var(--color-accent-text); margin-bottom: .2rem; }
.cnote[data-pass="3"] { border-left-color: var(--color-accent); }

/* ── News ── */
.news-filters { display: flex; flex-wrap: wrap; gap: .4rem; margin: var(--space-lg) 0 0; }
.news-filters a { font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: .04em; padding: .35rem .7rem; border: var(--rule-hair) solid var(--color-rule); border-radius: 999px; text-decoration: none; color: var(--color-ink-2); }
.news-filters a:hover, .news-filters a[aria-current] { border-color: var(--color-ink); color: var(--color-ink); }
.news-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-lg) var(--space-md); }
.news-item { display: grid; gap: .5rem; text-decoration: none; color: inherit; }
.news-item img { width: 100%; aspect-ratio: 16 / 10; object-fit: cover; border-radius: 8px; border: var(--rule-hair) solid var(--color-rule); background: var(--color-paper-2); }
.news-item .meta { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--color-muted); display: flex; gap: .75rem; }
.news-item .meta .tag { color: var(--color-accent-text); }
.news-item h3 { font-family: var(--font-display); font-weight: 600; font-size: var(--text-md); line-height: 1.15; margin: 0; }
.news-item p { margin: 0; font-size: var(--text-sm); color: var(--color-ink-2); line-height: 1.45; }
.news-item:hover h3 { text-decoration: underline; text-decoration-color: var(--color-accent); text-underline-offset: .2em; }
.news-year { font-family: var(--font-figure); font-weight: 600; font-size: 1.1rem; color: var(--color-accent-text); margin: var(--space-2xl) 0 var(--space-md); padding-top: var(--space-lg); border-top: var(--rule-hair) solid var(--color-rule); }
.news-year:first-child { margin-top: 0; border-top: 0; padding-top: 0; }
@media (max-width: 64rem) { .news-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 40rem) { .news-grid { grid-template-columns: 1fr; } }

/* ── Pull quote inside an entry ── */
.pull { margin: 0; padding: 0 0 0 var(--space-md); border-left: 2px solid var(--color-accent); }
.pull p { margin: 0; font-family: var(--font-display); font-weight: 600; font-size: var(--text-md); line-height: 1.25; color: var(--color-ink); max-width: 40ch; }
.pull footer { margin-top: .5rem; font-size: var(--text-sm); color: var(--color-muted); max-width: 52ch; line-height: 1.45; }
@media (max-width: 40rem) { .anim-slot::before { content: "Build " attr(data-slot); } .anim-slot { padding-top: 2rem; } }

/* ── Partners page: a partner's testimonial (quote, photo, name, their logo) ── */
.io-quote { margin: 0; }
.io-quote blockquote { margin: 0; position: relative; padding-top: 3rem; }
.io-quote blockquote::before { content: "\201C"; position: absolute; top: -1.1rem; left: -.2rem; font-family: Georgia, "Times New Roman", serif; font-weight: 700; font-size: 7rem; line-height: 1; color: var(--color-accent); }
.io-quote blockquote p { margin: 0; font-family: var(--font-display); font-weight: 600; font-size: clamp(1.35rem, 1.1vw + .95rem, 1.8rem); line-height: 1.22; color: var(--color-ink); max-width: 28ch; }
.io-quote figcaption { display: flex; align-items: center; gap: var(--space-md); margin-top: var(--space-lg); }
.io-quote-photo { width: 92px; height: 92px; border-radius: 50%; object-fit: cover; flex: none; }
.io-quote-who { display: grid; justify-items: start; gap: .1rem; font-size: var(--text-sm); color: var(--color-muted); padding-left: var(--space-md); border-left: 2px solid var(--color-accent); }
.io-quote-who b { font-weight: 600; font-size: var(--text-base); color: var(--color-ink); }
.io-quote-logo { width: 104px; height: auto; margin-top: .45rem; }
.io-quote-more { display: inline-block; margin-top: var(--space-lg); }

/* ── Platform page: the transaction as spine ── */
.io-tx { display: grid; grid-template-columns: minmax(0, 6fr) minmax(0, 6fr); gap: var(--space-2xl); align-items: start; }
.io-tx-stick { position: sticky; top: 5.5rem; }
.io-chapters { display: grid; gap: 0; padding-bottom: var(--space-3xl); }   /* keeps the stage pinned through the last chapter */
.io-chapter { padding: var(--space-2xl) 0; border-top: var(--rule-hair) solid var(--color-rule); }
.io-chapter:first-child { border-top: 0; padding-top: 0; }
.io-stamp { display: flex; align-items: baseline; gap: .75rem; font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: .06em; color: var(--color-muted); margin-bottom: var(--space-sm); }
.io-stamp b { font-family: var(--font-figure); font-weight: 600; font-size: 1.25rem; letter-spacing: 0; color: var(--color-accent-text); }
.io-chapter h2 { font-family: var(--font-display); font-weight: 600; font-size: clamp(1.6rem, 2.3vw + .4rem, 2.3rem); line-height: 1.08; margin: 0; max-width: 20ch; }
.io-chapter .io-claim { font-family: var(--font-display); font-weight: 600; font-size: var(--text-md); line-height: 1.3; color: var(--color-ink); margin: var(--space-md) 0 0; max-width: 40ch; }
.io-chapter .support { margin: var(--space-md) 0 0; max-width: 52ch; }
.io-chapter .tlink { display: inline-block; margin-top: var(--space-md); }
@media (max-width: 64rem) { .io-tx { grid-template-columns: 1fr; gap: var(--space-lg); } .io-tx-stick { top: 0; z-index: 2; background: var(--color-paper); padding: var(--space-sm) 0 var(--space-md); box-shadow: 0 14px 14px -14px rgba(43,33,23,.25); } }
/* A phone on its side: one column made the pinned stage 650 to 700px tall on a 375 to 440px screen, so it covered every
   chapter and none could be read. Short landscape screens keep the desktop's two columns, where the stage fits beside
   the text (11 Nov 2026). */
@media (max-width: 64rem) and (max-height: 32rem) and (orientation: landscape) {
  .io-tx { grid-template-columns: minmax(0, 6fr) minmax(0, 6fr); gap: var(--space-xl); }
  .io-tx-stick { top: .5rem; background: none; box-shadow: none; padding: 0; }
  html.nav-shown .io-tx-stick { top: calc(var(--nav-h, 0px) + .5rem); }
}
/* The end of the section, and landing on a chapter from a link (Platform > TDK in the nav, the subnav), 11 Nov 2026.
   js/site.js sets --tx-stick-h, the stage's height; --tx-room is the space above the pinned stage.
   - The TDK chapter is the last. js/tx-stage.js finishes a chapter's build when its bottom reaches mid-screen, but the
     section ended 6rem after it, and the stage (690px, pinned 88px down) began to leave long before that: the build
     always finished with the stage half off the top, and landing on #tdk put it there at once. --tx-tail, the space
     after the last chapter, now runs until the build has finished with the stage still whole, and a short dwell.
   - Two columns: the last chapter is at least tall enough that landing on it leaves the stage whole.
   - One column (phones, iPads upright): every chapter landed with its heading behind the pinned stage; each now
     lands just under it. */
.io-tx { --tx-room: calc(var(--nav-h, 6rem) + 1rem); --tx-tail: max(var(--space-3xl), calc(var(--tx-room) + var(--tx-stick-h, 0px) - 50vh + 4rem)); }
.io-chapters { padding-bottom: var(--tx-tail); }
.io-chapter:last-child { min-height: calc(var(--tx-room) + var(--tx-stick-h, 0px) - var(--tx-tail)); }
@media (max-width: 64rem) { .io-tx { --tx-room: 0px; } .io-chapter:last-child { min-height: 0; } .io-chapter { scroll-margin-top: var(--tx-stick-h, 0px); } }
@media (max-width: 64rem) and (max-height: 32rem) and (orientation: landscape) {
  .io-tx { --tx-room: calc(var(--nav-h, 4rem) + .5rem); }
  .io-chapter { scroll-margin-top: 0; }
  .io-chapter:last-child { min-height: calc(var(--tx-room) + var(--tx-stick-h, 0px) - var(--tx-tail)); }
}

/* ── Build P1: one transaction, the Prodigy stage (platform page, js/tx-stage.js) ──
   The stage is a crop of one 1920x1080 scene holding five studio screens (assets/img/prodigy-transaction.svg,
   built by tools/prodigy_transaction.py). Scroll picks the screen and the crop; [data-step] elements come on
   in order. Authored state: the accept screen, fully lit. */
.tx-stage { margin: 0; position: relative; }
.tx-frame { position: relative; aspect-ratio: 20 / 21; border: var(--rule-hair) solid var(--color-rule); border-radius: 10px; overflow: hidden; background: #fff; box-shadow: 0 24px 60px -30px rgba(43,33,23,.35); }
.tx-frame svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.tx-stage figcaption { margin-top: var(--space-sm); min-height: 2.6em; }
#tx .mono { font-family: var(--font-mono); }
#tx .screen { opacity: 0; transition: opacity .55s var(--ease-out); }
#tx .screen.active { opacity: 1; }
#tx .row { opacity: 0; transition: opacity .4s var(--ease-out); }
#tx .row.on { opacity: 1; }
#tx .node { opacity: .45; transition: opacity .4s var(--ease-out); }
#tx .node.run, #tx .node.done { opacity: 1; }
#tx .node .st-run, #tx .node .st-done { display: none; }
#tx .node.run .st-run { display: block; }
#tx .node.done .st-done { display: block; }
#tx .arrow line, #tx .arrow path { transition: stroke .4s var(--ease-out); }
#tx .arrow.lit line, #tx .arrow.lit path { stroke: #17a89b; }
#tx .endnode { opacity: .35; transition: opacity .4s var(--ease-out); }
#tx .endnode.on { opacity: 1; }
/* the studio's Run button and side-panel items are clickable once the script is up (a small egg) */
#tx { pointer-events: none; }
#tx.is-live .screen.active .hit { pointer-events: all; cursor: pointer; }
#tx.is-live .screen.active .hit[data-hit="edit-code"] { cursor: text; }
#tx #tdk-code.hidden { opacity: 0; }
/* the TDK screen's code, editable: a transparent textarea over a highlighted mirror, placed by js/tx-stage.js over the code lines of the current crop */
.tx-editor { position: absolute; font-family: var(--font-mono); }
.tx-editor .tx-hl, .tx-editor textarea.tx-ta { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; padding: 0; border: 0; border-radius: 0; box-shadow: none; background: transparent; font: inherit; line-height: inherit; white-space: pre; overflow: hidden; tab-size: 4; }
.tx-editor .tx-hl { color: #1f2933; pointer-events: none; }
.tx-editor .tx-hl .k { color: #6d3fc8; } .tx-editor .tx-hl .t { color: #12897e; } .tx-editor .tx-hl .s { color: #1fa971; } .tx-editor .tx-hl .c { color: #9aa3af; font-style: italic; } .tx-editor .tx-hl .p { color: #6b7280; }
.tx-editor textarea.tx-ta { color: transparent; caret-color: #1f2933; resize: none; outline: none; -webkit-text-fill-color: transparent; }
.tx-editor textarea.tx-ta::selection { background: rgba(232,23,93,.25); }
#tx .fly { display: none; }
#tx .fly.open { display: block; }
.tx-toast { position: absolute; left: 1rem; bottom: 1rem; max-width: calc(100% - 2rem); padding: .55rem .85rem; background: var(--color-ink); color: var(--color-paper-3); font-family: var(--font-mono); font-size: var(--text-xs); line-height: 1.45; border-radius: 6px; opacity: 0; transform: translateY(6px); transition: opacity .25s var(--ease-out), transform .25s var(--ease-out); pointer-events: none; }
.tx-toast.show { opacity: 1; transform: none; }
@media (max-width: 64rem) { .tx-frame { aspect-ratio: 4 / 3; } }
@media (prefers-reduced-motion: reduce) { #tx .screen, #tx .row, #tx .node, #tx .endnode, #tx .arrow line, #tx .arrow path { transition: none; } }

/* ── Spectral page: numbered steps (a real sequence) and named functions ── */
.io-steps { margin: var(--space-lg) 0 0; padding: 0; list-style: none; counter-reset: step; display: grid; gap: .8rem; max-width: 46ch; }
.io-steps li { position: relative; padding-left: 2.2rem; color: var(--color-ink-2); line-height: 1.5; }
.io-steps li::before { counter-increment: step; content: counter(step); position: absolute; left: 0; top: .05em; width: 1.5rem; height: 1.5rem; border-radius: 50%; border: 1.5px solid var(--color-accent); color: var(--color-accent-text); font: 600 .85rem/1.5rem var(--font-figure); text-align: center; }
.io-steps b { color: var(--color-ink); font-weight: 600; }
.io-funcs { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-2xl); }
.io-funcs--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-xl); }
.io-func-group .kicker { margin-bottom: var(--space-md); }
.io-func { padding: var(--space-md) 0; border-top: var(--rule-hair) solid var(--color-rule); }
.io-func h3 { font-family: var(--font-display); font-weight: 600; font-size: var(--text-md); line-height: 1.2; margin: 0; }
.io-func h3 small { display: block; font-family: var(--font-mono); font-weight: 400; font-size: var(--text-xs); color: var(--color-muted); margin-top: .25rem; letter-spacing: .02em; }
.io-func p { margin: .5rem 0 0; color: var(--color-ink-2); font-size: var(--text-sm); line-height: 1.5; max-width: 46ch; }
@media (max-width: 64rem) { .io-funcs, .io-funcs--3 { grid-template-columns: 1fr; } }

/* media placeholder: a film or image still to come */
.anim-slot--media::before { content: "Media " attr(data-slot) "  ·  film or image to come"; }
.anim-slot--media { min-height: 14rem; background: repeating-linear-gradient(-45deg, transparent 0 14px, rgba(43,33,23,.06) 14px 15px); border-color: var(--color-muted); }
.anim-slot--media::before { color: var(--color-muted); }

/* ── Build 04, a claim's journey (js/claim-journey.js) ─────────────────
   The toca.legal case lifecycle at a high level, turned vertical to sit in
   the legal entry's body column. Scoped under .j04 (site.css still carries
   the legacy .journey-stage rules). Authored at stage 4; the script walks it
   from 0. Grid: the case card column, the rail, the stage rows. */
.j04 { display: grid; gap: var(--space-md); margin: 0; padding: var(--space-lg) 0 var(--space-md); border-top: var(--rule-hair) solid var(--color-rule); border-bottom: var(--rule-hair) solid var(--color-rule); --card: 10.5rem; --gap: var(--space-lg); }
.j04-head, .j04-body { display: grid; grid-template-columns: var(--card) 2px minmax(0, 1fr); column-gap: var(--gap); }
.j04-head span { font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: .14em; text-transform: uppercase; color: var(--color-muted); }
.j04-head span:nth-child(2) { justify-self: center; transform: translateX(-50%); margin-left: 1px; }
.j04-body { position: relative; }
.j04-rail { position: relative; grid-column: 2; align-self: stretch; background: var(--color-rule); --lit: 100%; }
.j04-rail::after { content: ""; position: absolute; left: 0; right: 0; top: 0; height: var(--lit); background: var(--color-accent); transition: height .6s var(--ease-out); }
.j04-rail::before { content: ""; position: absolute; left: 50%; top: var(--lit); width: 9px; height: 9px; margin: -4.5px 0 0 -4.5px; border-radius: 50%; background: var(--color-accent); transition: top .6s var(--ease-out); }
.j04-rows { grid-column: 3; list-style: none; margin: 0; padding: 0; }
.j04-rows li { display: grid; grid-template-columns: max-content minmax(0, 1fr); column-gap: .7rem; row-gap: .15rem; align-items: baseline; padding: .8rem 0; border-bottom: var(--rule-hair) solid var(--color-rule); opacity: .38; transition: opacity .4s var(--ease-out); }
.j04-rows li:first-child { padding-top: .2rem; }
.j04-rows li:last-child { border-bottom: 0; }
.j04-rows .n { font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: .14em; color: var(--color-muted); }
.j04-rows b { font-family: var(--font-display); font-weight: 600; font-size: 1.15rem; line-height: 1.02; letter-spacing: -.005em; color: var(--color-ink); }
.j04-rows .svc { grid-column: 2; font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: .06em; text-transform: uppercase; color: var(--color-muted); transition: color .4s var(--ease-out); }
.j04.s0 .j04-rows li:nth-child(1), .j04.s1 .j04-rows li:nth-child(-n+2), .j04.s2 .j04-rows li:nth-child(-n+3), .j04.s3 .j04-rows li:nth-child(-n+4), .j04.s4 .j04-rows li { opacity: 1; }
.j04.s0 .j04-rows li:nth-child(1) .svc, .j04.s1 .j04-rows li:nth-child(2) .svc, .j04.s2 .j04-rows li:nth-child(3) .svc, .j04.s3 .j04-rows li:nth-child(4) .svc, .j04.s4 .j04-rows li:nth-child(5) .svc { color: var(--color-accent-text); }

/* the case card: one element, moved down the column by the script */
.j04-card { position: absolute; left: 0; width: var(--card); bottom: 0; box-sizing: border-box; padding: .55rem .75rem .6rem; background: var(--color-paper-3); border: 1.5px solid var(--color-ink); clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 0 100%); transition: top .6s var(--ease-out); }
.j04.is-live .j04-card { bottom: auto; }
.j04-card .source { display: block; letter-spacing: .08em; text-transform: uppercase; }
.j04-card b { display: block; font-family: var(--font-mono); font-weight: 500; font-size: .95rem; letter-spacing: .1em; text-transform: uppercase; color: var(--color-ink); margin-top: .15rem; }
.j04 > .source { margin: 0; }
.j04 > .source .tlink { font: inherit; letter-spacing: inherit; }
.j04.is-live > .source { opacity: 0; transition: opacity .4s linear; }
.j04.is-live.done > .source { opacity: 1; }

@media (max-width: 40rem) {
  .j04 { --card: 7.6rem; --gap: var(--space-md); }
  .j04-head span:first-child, .j04-head span:nth-child(2) { display: none; }
  .j04-head span:last-child { grid-column: 3; }
  .j04-rows b { font-size: 1rem; }
  .j04-card { padding: .45rem .55rem .5rem; }
  .j04-card .source { letter-spacing: .04em; }   /* 12.8px like every small label (WCAG floor, 10 Nov 2026) */
  .j04-card .source span { white-space: nowrap; }   /* wraps as CASE / 2026-04871, never at the hyphen */
  .j04-card b { font-size: .8rem; }
}
@media (prefers-reduced-motion: reduce) { .j04 *, .j04 .j04-rail::before, .j04 .j04-rail::after { transition-duration: 1ms !important; } }

/* ── Build 05: the payday peak (home, payroll entry; js/payday-peak.js) ──
   A month of EPM's executions a day: low for most of it, several times higher in the payday window.
   Authored at full height; the script scales the bars up from the baseline and counts the total. */
.pp { margin: 0; padding: var(--space-lg); background: var(--color-paper-3); border: var(--rule-hair) solid var(--color-rule); border-radius: 10px; }
.pp-head { display: flex; flex-wrap: wrap; justify-content: space-between; gap: .5rem 1.5rem; align-items: baseline; font-size: var(--text-sm); color: var(--color-muted); }
.pp-n { font-family: var(--font-figure); font-weight: 600; font-size: 1.9em; color: var(--color-ink); font-variant-numeric: tabular-nums; margin-right: .25rem; }
.pp-win { font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: .06em; }
.pp-win::before { content: ""; display: inline-block; width: .7em; height: .7em; background: color-mix(in srgb, var(--color-accent) 18%, transparent); border: 1px solid var(--color-accent); margin-right: .5em; vertical-align: -.05em; }
.pp-bars { display: flex; align-items: flex-end; gap: 3px; height: 11rem; margin-top: var(--space-md); padding: 0 0 1px; border-bottom: var(--rule-hair) solid var(--color-rule); }
.pp-bars i { flex: 1 1 0; background: var(--color-muted); opacity: .55; border-radius: 2px 2px 0 0; transform-origin: bottom; }
.pp-bars i.peak { background: var(--color-accent); opacity: .9; }
.pp-axis { display: flex; justify-content: space-between; margin-top: .4rem; font-family: var(--font-mono); font-size: var(--text-xs); color: var(--color-muted); }
.pp .source { margin-top: var(--space-md); }
.pp.is-live .pp-bars i { transform: scaleY(0); transition: transform .6s var(--ease-out); }
.pp.is-live.in .pp-bars i { transform: none; }
@media (prefers-reduced-motion: reduce) { .pp.is-live .pp-bars i { transform: none; transition: none; } }

/* ── Build 06, products assembling (js/stack-assemble.js) ─────────────
   The platform stack: slabs slide in, layers rise, a pink trace draws up
   the left gutter from Integration through Automation to Apps. The cards
   are authored at rest; .is-live hides then reveals. */
.io-stack { position: relative; }
.io-stack .trace { position: absolute; top: 0; left: 0; overflow: visible; pointer-events: none; }
.io-stack .trace path { fill: none; stroke: var(--color-accent); stroke-width: 1.5; stroke-linejoin: round; stroke-dashoffset: 0; }
.io-stack .trace circle { fill: var(--color-accent); stroke: var(--color-paper); stroke-width: 2; }
.io-stack.is-live .io-product { opacity: 0; transform: translateX(40px); transition: opacity .55s var(--ease-out), transform .55s var(--ease-out); }
.io-stack.is-live .io-product:nth-child(2) { transition-delay: .12s; } .io-stack.is-live .io-product:nth-child(3) { transition-delay: .24s; }
.io-stack.is-live .cap-label, .io-stack.is-live .cap { opacity: 0; transform: translateY(16px); transition: opacity .5s var(--ease-out) .45s, transform .5s var(--ease-out) .45s; }
.io-stack.is-live .cap:nth-child(2) { transition-delay: .55s; }
.io-stack.is-live.in .io-product, .io-stack.is-live.in .cap-label, .io-stack.is-live.in .cap { opacity: 1; transform: none; }
.io-stack.is-live .trace path { stroke-dashoffset: var(--len, 2000); }
.io-stack.is-live .trace circle { opacity: 0; transform: scale(.4); transform-box: fill-box; transform-origin: center; }
.io-stack.is-live.traced .trace path { transition: stroke-dashoffset 1.1s var(--ease-out); stroke-dashoffset: 0; }
.io-stack.is-live.traced .trace circle { opacity: 1; transform: none; transition: opacity .3s var(--ease-out), transform .4s var(--ease-out); }
.io-stack.is-live.traced .trace circle:nth-of-type(1) { transition-delay: .05s; } .io-stack.is-live.traced .trace circle:nth-of-type(2) { transition-delay: .6s; } .io-stack.is-live.traced .trace circle:nth-of-type(3) { transition-delay: 1.05s; }
.io-stack.is-live.in .io-product:hover { transform: translateX(6px); }
@media (max-width: 40rem) { .io-stack .trace { display: none; } }

/* ── Customers (company page) and the short homepage bar ─────────────── */
.proof-bar--logos .proof-more { order: 3; flex: 0 0 auto; margin-left: auto; font-size: var(--text-sm); }
.proof-bar--plain { padding: 0; border: 0; }
.proof-bar--logos > .band-narrow, .proof-bar--plain { display: flex; flex-wrap: wrap; align-items: center; column-gap: clamp(1.4rem, 2.6vw, 2.6rem); row-gap: var(--space-md); }
.cust-group { display: grid; grid-template-columns: 11rem minmax(0, 1fr); gap: var(--space-md) var(--space-xl); align-items: start; padding: var(--space-lg) 0; border-top: var(--rule-hair) solid var(--color-rule); }
.cust-group:last-of-type { border-bottom: var(--rule-hair) solid var(--color-rule); }
.cust-label { margin: .2rem 0 0; font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: .14em; text-transform: uppercase; color: var(--color-muted); }
#customers > .band-narrow > .source { margin-top: var(--space-md); }
#customers > .band-narrow > .source .tlink { font: inherit; letter-spacing: inherit; }
.tile.tile--here:hover { transform: none; }
@media (max-width: 40rem) { .cust-group { grid-template-columns: 1fr; } .proof-bar--logos .proof-more { margin-left: 0; flex: 1 0 100%; } }

/* ── Toca BASIC reference (basic.html) ──────────────────────────────── */
.ref-page h2 { font-family: var(--font-display); font-weight: 600; font-size: 1.6rem; letter-spacing: -.01em; margin: var(--space-xl) 0 var(--space-md); }
.ref-page h2:first-child { margin-top: 0; }
.ref-page .support code, .ref-page td code, .ref-page th code { font-family: var(--font-mono); font-size: .92em; background: var(--color-paper-2); padding: .05em .35em; border-radius: 3px; }
.ref-page table.ref { width: 100%; border-collapse: collapse; margin: 0 0 var(--space-md); }
.ref-page table.ref tr { border-top: var(--rule-hair) solid var(--color-rule); }
.ref-page table.ref tr:last-child { border-bottom: var(--rule-hair) solid var(--color-rule); }
.ref-page table.ref th { text-align: left; font-weight: 500; white-space: nowrap; padding: .6rem 1.2rem .6rem 0; vertical-align: top; width: 16rem; }
.ref-page table.ref td { padding: .6rem 0; color: var(--color-ink-2); line-height: 1.5; font-size: var(--text-sm); }
.ref-page pre.listing { font-family: var(--font-mono); font-size: var(--text-sm); line-height: 1.5; background: var(--bbs-black); color: #c9c9c9; padding: 1rem 1.25rem; border-radius: 6px; margin: 0 0 var(--space-md); overflow-x: auto; }
@media (max-width: 40rem) { .ref-page table.ref th { display: block; width: auto; padding-bottom: 0; } .ref-page table.ref td { display: block; padding-top: .2rem; } }

/* ── From the news (homepage strip, filled by js/news-cards.js from news.toca.io) ── */
#news .io-head .support { display: flex; flex-wrap: wrap; gap: .5rem 1.5rem; align-items: baseline; }
.news-strip { display: grid; gap: var(--space-md); }
.news-strip[hidden] { display: none; }
.news-lead, .news-card { display: grid; text-decoration: none; color: var(--color-ink); background: var(--color-paper-3); border: var(--rule-hair) solid var(--color-rule); border-radius: 10px; overflow: hidden; transition: transform var(--dur-short) var(--ease-out), border-color var(--dur-short); }
.news-lead:hover, .news-card:hover { transform: translateY(-4px); border-color: var(--color-muted); }
.news-lead { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); align-items: stretch; }
.news-lead .txt { display: flex; flex-direction: column; gap: var(--space-sm); padding: var(--space-xl) var(--space-xl) var(--space-lg); }
.news-lead .who { display: flex; flex-wrap: wrap; gap: .25rem 1rem; align-items: baseline; font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: .1em; text-transform: uppercase; color: var(--color-muted); }
.news-lead .who b { font-weight: 600; color: var(--color-ink); }
.news-lead .who .sector { color: var(--color-accent-text); }
.news-lead h3 { font-family: var(--font-display); font-weight: 600; font-size: clamp(1.7rem, 2.6vw + .4rem, 2.6rem); line-height: 1.06; margin: 0; max-width: 20ch; }
.news-lead p { margin: 0; color: var(--color-ink-2); max-width: 52ch; line-height: 1.5; }
.news-lead .lead-fig { display: flex; flex-direction: column; gap: .2rem; margin-top: var(--space-xs); }
.news-lead .lead-fig b { font-family: var(--font-figure); font-weight: 600; font-size: clamp(1.8rem, 2.6vw, 2.6rem); line-height: 1; letter-spacing: -.01em; }
.news-lead .by { display: flex; flex-direction: column; margin-top: var(--space-xs); font-size: var(--text-sm); color: var(--color-muted); line-height: 1.4; }
.news-lead .by b { font-weight: 500; color: var(--color-ink); }
.news-lead .source { margin-top: auto; padding-top: var(--space-md); }
.news-lead .tlink { align-self: flex-start; }
.news-lead .pic { display: block; min-height: 16rem; background: var(--color-paper-2); }
.news-lead .pic img { display: block; width: 100%; height: 100%; object-fit: cover; }
.news-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-md); }
.news-card { grid-template-rows: auto 1fr; }
.news-card .pic { display: block; aspect-ratio: 16 / 9; background: var(--color-paper-2); }
.news-card .pic img { display: block; width: 100%; height: 100%; object-fit: cover; }
.news-card .txt { display: flex; flex-direction: column; gap: .5rem; padding: var(--space-lg); }
.news-card b { font-family: var(--font-display); font-weight: 600; font-size: var(--text-md); line-height: 1.15; color: var(--color-ink); }
.news-card p { margin: 0; font-size: var(--text-sm); line-height: 1.5; color: var(--color-ink-2); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.news-card .source { margin-top: auto; padding-top: .5rem; }
@media (max-width: 64rem) { .news-grid { grid-template-columns: 1fr; } .news-lead { grid-template-columns: 1fr; } .news-lead .pic { order: -1; min-height: 0; aspect-ratio: 16 / 9; } .news-lead .txt { padding: var(--space-lg); } }
@media (prefers-reduced-motion: reduce) { .news-lead, .news-card, .news-lead:hover, .news-card:hover { transition: none; transform: none; } }

/* ── Build AU2: the pace of the platform (automation page, js/rate-counter.js) ── */
.rate { margin: 0; padding: var(--space-lg); background: var(--color-paper-3); border: var(--rule-hair) solid var(--color-rule); border-radius: 10px; }
.rate-figs { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-lg); }
.rate-figs b { display: block; font-family: var(--font-figure); font-weight: 600; font-size: clamp(2.2rem, 3.4vw, 3.2rem); line-height: 1; letter-spacing: -.01em; color: var(--color-ink); font-variant-numeric: tabular-nums; }
.rate-figs small { font-size: .42em; font-weight: 500; color: var(--color-muted); margin-left: .15em; }
.rate-figs span { display: block; margin-top: .4rem; font-size: var(--text-sm); color: var(--color-muted); max-width: 20ch; }
.rate-live { margin: var(--space-lg) 0 0; padding-top: var(--space-md); border-top: var(--rule-hair) solid var(--color-rule); font-size: var(--text-md); line-height: 1.4; color: var(--color-ink-2); }
.rate-live b { font-family: var(--font-figure); font-weight: 600; font-size: 1.35em; color: var(--color-ink); font-variant-numeric: tabular-nums; }
.rate figcaption { margin-top: var(--space-sm); }
@media (max-width: 30rem) { .rate-figs { grid-template-columns: 1fr; } }

/* ── Build P2: low-code to pro-code, the code drawer (platform page, js/code-drawer.js) ── */
.p2-stage { margin: 0; }
.p2-frame { position: relative; aspect-ratio: 16 / 10; border: var(--rule-hair) solid var(--color-rule); border-radius: 10px; overflow: hidden; background: #fff; box-shadow: 0 24px 60px -30px rgba(43,33,23,.35); }
.p2-frame svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.p2-stage figcaption { margin-top: var(--space-sm); min-height: 2.6em; }
#p2 .mono { font-family: var(--font-mono); }
#p2 .row { opacity: 0; transition: opacity .45s var(--ease-out); }
#p2 .row.on { opacity: 1; }
#p2 .node { opacity: .5; transition: opacity .4s var(--ease-out); }
#p2 .node.run, #p2 .node.done { opacity: 1; }
#p2 .node .st-run, #p2 .node .st-done { display: none; }
#p2 .node.run .st-run { display: block; }
#p2 .node.done .st-done { display: block; }
#p2 .arrow line, #p2 .arrow path { opacity: 0; transition: opacity .45s var(--ease-out), stroke .4s var(--ease-out); }
#p2 .arrow.on line, #p2 .arrow.on path { opacity: 1; }
#p2 .arrow.lit line, #p2 .arrow.lit path { stroke: #17a89b; }
#p2 .endnode { opacity: .35; transition: opacity .4s var(--ease-out); }
#p2 .endnode.on { opacity: 1; }
#p2 { pointer-events: none; }
#p2.is-live .hit { pointer-events: all; cursor: pointer; }
#p2 #p2-code.hidden { opacity: 0; }
/* the editable code: a transparent textarea over a highlighted mirror, placed over the drawer's code area
   (scene 1600x1000: code at x 392, top 470, 31px lines, 18px type; the frame scales it with --p2-scale) */
.p2-frame { --p2-scale: 0.4; }
.p2-editor { position: absolute; left: 24.5%; top: 46.3%; width: 70%; height: 27.9%; font-family: var(--font-mono); font-size: calc(18px * var(--p2-scale)); line-height: calc(31px * var(--p2-scale)); }
.p2-editor .p2-hl, .p2-editor textarea.p2-ta { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; padding: 0; border: 0; border-radius: 0; box-shadow: none; background: transparent; font: inherit; line-height: inherit; white-space: pre; overflow: hidden; tab-size: 4; }
.p2-hl { color: #e6e9ee; pointer-events: none; }
.p2-hl .k { color: #c4a7ff; } .p2-hl .t { color: #7fd7cc; } .p2-hl .s { color: #7ee2b8; } .p2-hl .c { color: #7c8794; font-style: italic; } .p2-hl .p { color: #9aa3af; }
.p2-editor textarea.p2-ta { color: transparent; caret-color: #fff; resize: none; outline: none; -webkit-text-fill-color: transparent; }
.p2-ta::selection { background: rgba(232,23,93,.35); }
.p2-publish { position: absolute; right: -2%; top: calc(-58px * var(--p2-scale)); height: calc(30px * var(--p2-scale)); padding: 0 calc(14px * var(--p2-scale)); border: 0; border-radius: calc(6px * var(--p2-scale)); background: var(--color-accent-solid); color: #fff; font: 600 calc(13px * var(--p2-scale)) / 1 var(--font-body); letter-spacing: .02em; cursor: pointer; }
.p2-publish:hover { background: var(--color-accent-deep); }
.p2-toast { position: absolute; left: 1rem; bottom: 1rem; max-width: calc(100% - 2rem); padding: .55rem .85rem; background: var(--color-ink); color: var(--color-paper-3); font-family: var(--font-mono); font-size: var(--text-xs); line-height: 1.45; border-radius: 6px; opacity: 0; transform: translateY(6px); transition: opacity .25s var(--ease-out), transform .25s var(--ease-out); pointer-events: none; }
.p2-toast.show { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { #p2 .row, #p2 .node, #p2 .endnode, #p2 .arrow line, #p2 .arrow path { transition: none; } }

/* ── Build P3: sovereign deployment, the boundary (platform page, js/sovereign.js) ── */
.sv-stage { margin: 0; }
.sv-frame { position: relative; aspect-ratio: 1200 / 760; border: var(--rule-hair) solid var(--color-rule); border-radius: 10px; overflow: hidden; background: var(--color-paper); }
.sv-frame svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.sv-stage figcaption { margin-top: var(--space-sm); }
#sv .mono { font-family: var(--font-mono); }
/* authored = finished. With the script up, everything starts hidden and comes in on the s1..s6 classes. */
#sv.is-live .sv-line { stroke-dasharray: 1000; stroke-dashoffset: 1000; transition: stroke-dashoffset 1.3s var(--ease-out); }
#sv.is-live.s1 .sv-line { stroke-dashoffset: 0; }
#sv.is-live .sv-in, #sv.is-live .sv-out, #sv.is-live .sv-end { opacity: 0; transition: opacity .5s var(--ease-out); }
#sv.is-live.s2 .sv-in { opacity: 1; }
#sv.is-live.s3 .sv-out-1, #sv.is-live.s4 .sv-out-2, #sv.is-live.s5 .sv-out-3, #sv.is-live.s6 .sv-end { opacity: 1; }
#sv.is-live .sv-arrow { stroke-dasharray: 1000; stroke-dashoffset: 1000; transition: stroke-dashoffset .7s var(--ease-out); }
#sv.is-live .sv-stop { opacity: 0; transform: scale(.4); transform-box: fill-box; transform-origin: center; transition: opacity .25s var(--ease-out) .55s, transform .35s var(--ease-out) .55s; }
#sv.is-live.s3 .sv-out-1 .sv-arrow, #sv.is-live.s4 .sv-out-2 .sv-arrow, #sv.is-live.s5 .sv-out-3 .sv-arrow { stroke-dashoffset: 0; }
#sv.is-live.s3 .sv-out-1 .sv-stop, #sv.is-live.s4 .sv-out-2 .sv-stop, #sv.is-live.s5 .sv-out-3 .sv-stop { opacity: 1; transform: none; }


/* ── "In detail" under the platform chapters: the product pages, folded in (24 Sept) ── */
.io-more { margin-top: var(--space-lg); border-top: var(--rule-hair) solid var(--color-rule); }
.io-more summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: .6rem; padding: var(--space-sm) 0; font-weight: 500; color: var(--color-ink); }
.io-more summary::-webkit-details-marker { display: none; }
.io-more summary::before { content: ""; flex: none; width: .9rem; height: .9rem; border: 1.5px solid var(--color-ink); border-radius: 50%; background: linear-gradient(var(--color-ink), var(--color-ink)) center / .45rem 1.5px no-repeat, linear-gradient(var(--color-ink), var(--color-ink)) center / 1.5px .45rem no-repeat; transition: transform var(--dur-short) var(--ease-out); }
.io-more[open] summary::before { transform: rotate(45deg); }
.io-more summary:hover { color: var(--color-accent-text); }
.io-more h3 { font-family: var(--font-display); font-weight: 600; font-size: 1.2rem; line-height: 1.2; margin: var(--space-lg) 0 0; max-width: 30ch; }
.io-more .support { margin-top: var(--space-xs); }
.io-more .video { margin-top: var(--space-md); max-width: 30rem; }
.io-more .pointlist { margin-top: var(--space-sm); }
.io-more .built { margin-top: var(--space-lg); }
.io-more .rate { margin-top: var(--space-md); }


/* ── Hero art on the page heads (tools/hero_art.py): line diagrams behind the text ── */
.hero-art text.mono, .hero-art .mono { font-family: var(--font-mono); font-weight: 500; }
.io .page-head--art { min-height: 30rem; display: flex; align-items: center; }
.io .page-head--art .band-narrow { position: relative; width: 100%; }
.io .page-head--art .support { max-width: 46ch; }
/* Where the drawing shows (site.css hides it at 64rem and under), the text keeps the left half and the drawing takes the
   right: the heading wraps to a fourth line before it shrinks, and the intro, which at 46ch alone ran 45px into the
   drawing between 1025 and 1300px wide (iPad landscape, small laptops), stops at 48%. Under 64rem both take the full
   column; the heading's half-width cap had squeezed it to 177px on an iPhone (11 Nov 2026). */
@media (min-width: 64.01rem) { .io .page-head--art h1 { max-width: min(18ch, 50%); } .io .page-head--art .support { max-width: min(46ch, 48%); } }
/* the drawing sits in the right half of the column, vertically centred on the text, and scales with the column, not the viewport */
.io .page-head--art .hero-art { position: absolute; inset: auto; right: 0; top: 50%; transform: translateY(-50%); width: 48%; height: auto; max-height: 100%; }
.io .page-head--art .page-head-copy { position: relative; }   /* a head with figures under its text (company): the drawing centres on the text, clear of the figures (10 Nov 2026) */
.hero-art .ha-flow { stroke-dashoffset: 0; animation: heroFlow 1.6s linear infinite; }
@keyframes heroFlow { to { stroke-dashoffset: -22; } }
@media (prefers-reduced-motion: reduce) { .hero-art .ha-flow { animation: none; } }

/* ── Spectral · prism figure (the toca.health and toca.legal figure, invoice scenario) ── */
.prism-fig { margin: var(--space-xl) 0 0; }
.prism-fig svg { display: block; width: 100%; height: auto; }
.prism-scroll { overflow-x: auto; overscroll-behavior-x: contain; }
.prism-hint { display: none; }
@media (max-width: 64rem) {
  .prism-scroll svg { min-width: 54rem; }
  .prism-hint { display: block; margin: var(--space-sm) 0 0; font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: .06em; text-transform: uppercase; color: var(--color-muted); }
}
.prism-fig figcaption { margin-top: var(--space-md); font-size: var(--text-xs); color: var(--color-muted); max-width: 72ch; }
.prism-fig figcaption .tlink { font-size: inherit; }

/* ── Spectral · Consensus Validation, four steps across ── */
.cv-steps { margin: var(--space-xl) 0 0; padding: 0; list-style: none; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-xl); counter-reset: step; }
.cv-steps li { counter-increment: step; border-top: 2px solid var(--color-rule); padding-top: var(--space-md); }
.cv-steps li::before { content: counter(step, decimal-leading-zero); display: block; font-family: var(--font-mono); font-size: var(--text-xs); font-weight: 500; letter-spacing: .14em; color: var(--color-accent-text); margin-bottom: var(--space-sm); }
.cv-steps h3 { font-family: var(--font-display); font-weight: 600; font-size: var(--text-md); margin: 0 0 var(--space-xs); }
.cv-steps p { margin: 0; font-size: var(--text-sm); color: var(--color-ink-2); line-height: 1.5; }
@media (max-width: 64rem) { .cv-steps { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 40rem) { .cv-steps { grid-template-columns: 1fr; } }

/* ── Spectral · the console, a strip of screens ── */
.console { margin-top: var(--space-xl); display: flex; gap: var(--space-md); overflow-x: auto; scroll-snap-type: x mandatory; padding-bottom: .6rem; scrollbar-width: thin; }
.console figure { flex: 0 0 min(78vw, 420px); scroll-snap-align: start; margin: 0; }
.console .shot { border-radius: 10px; overflow: hidden; background: #fff; box-shadow: 0 0 0 1px var(--color-rule), 0 18px 40px -24px rgba(31,26,20,.4); aspect-ratio: 16 / 10; }
.console img { width: 100%; height: 100%; display: block; object-fit: cover; object-position: top left; }
.console figcaption { margin-top: .6rem; font-size: .82rem; line-height: 1.45; color: var(--color-muted); }
.console figcaption b { display: block; font-family: var(--font-mono); font-weight: 500; font-size: var(--text-xs); letter-spacing: .08em; text-transform: uppercase; color: var(--color-accent-text); margin-bottom: .2rem; }
.console-cue { display: none; font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: .08em; text-transform: uppercase; color: var(--color-muted); margin: .4rem 0 0; }
@media (max-width: 1100px) { .console-cue { display: block; } }

/* ── Company · two even columns (recognition beside responsibility) ── */
.duo-io--even { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.duo-io .pull { margin-top: var(--space-xl); }
@media (max-width: 64rem) { .duo-io--even { grid-template-columns: 1fr; } }

/* ── Footer · the legal and social row, quieter than the site links ── */
.foot-links--small { gap: var(--space-xs) var(--space-lg); margin-bottom: var(--space-md); }
.foot-links--small a { font-size: var(--text-xs); color: var(--color-muted); }
/* The wordmark row (Mat, 11 Nov 2026): toca.health moved up into the links above the line, where it had floated alone in
   the middle of this row; the social icons sit at the right beside the copyright line, and on phones get a line of
   their own under the wordmark. Also the law-firm footer's row (gen.py SOCIAL); news.toca.io's css/news.css copies these. */
.foot-meta { align-items: center; }
.foot-meta .foot-social { display: flex; gap: .25rem; margin: 0 0 0 auto; padding: 0; list-style: none; }
.foot-meta .foot-social a { display: grid; place-items: center; width: 2.5rem; height: 2.5rem; border: 0; border-radius: 50%; color: var(--color-ink-2); transition: color .15s ease, background-color .15s ease; }
.foot-meta .foot-social a:hover { color: var(--color-ink); background: var(--color-paper-2); }
.foot-social svg { display: block; width: 1.25rem; height: 1.25rem; }
@media (max-width: 40rem) { .foot-meta .foot-social { order: 3; flex-basis: 100%; margin: 0 0 0 -.625rem; } }
@media (prefers-reduced-motion: reduce) { .foot-meta .foot-social a { transition: none; } }

/* ── Legal documents · verbatim terms, set for reading (content/legal/) ── */
.page-head .kicker a { color: inherit; text-decoration: none; border-bottom: 1px solid var(--color-rule); }
.legal-doc { max-width: 72ch; font-size: var(--text-sm); line-height: 1.65; color: var(--color-ink-2); overflow-wrap: anywhere; }
.legal-doc img { max-width: 100%; height: auto; }   /* the carbon plan's chart ran past a phone's edge (11 Nov 2026) */
.legal-doc p, .legal-doc ul, .legal-doc ol { margin: 0 0 var(--space-sm); }
.legal-doc ul, .legal-doc ol { padding-left: 1.4rem; }
.legal-doc li { margin: 0 0 .3rem; }
.legal-doc h2 { font-family: var(--font-display); font-weight: 600; font-size: var(--text-md); line-height: 1.25; color: var(--color-ink); margin: var(--space-xl) 0 var(--space-sm); scroll-margin-top: 6rem; }
.legal-doc p[id] { scroll-margin-top: 6rem; }   /* the cookie banner links to the privacy policy's #analytics (11 Nov 2026) */
.legal-doc h3, .legal-doc h4 { font-family: var(--font-body); font-weight: 600; font-size: var(--text-sm); color: var(--color-ink); margin: var(--space-lg) 0 var(--space-xs); }
.legal-doc strong { color: var(--color-ink); font-weight: 600; }
.legal-doc a { color: var(--color-accent-text); text-underline-offset: .2em; }
.legal-doc img { display: block; margin: var(--space-md) 0; height: auto; }
.legal-table { overflow-x: auto; margin: 0 0 var(--space-md); }
.legal-table table { border-collapse: collapse; min-width: 32rem; width: 100%; }
.legal-table td, .legal-table th { border: var(--rule-hair) solid var(--color-rule); padding: .5rem .7rem; vertical-align: top; text-align: left; }
.legal-table td p, .legal-table th p { margin: 0 0 .3rem; }

/* ── News cards · one story on its own, in a page column (partners: Exenai) ── */
[data-news-cards][data-slug] .news-grid { grid-template-columns: 1fr; }
.legal-table td, .legal-table th { overflow-wrap: normal; word-break: normal; hyphens: manual; }
.legal-table td:first-child, .legal-table th:first-child { min-width: 9rem; }

/* ── Spectral · the application bar: pick the documents, see what comes out (js/spectral-areas.js) ── */
.areas { margin-top: var(--space-xl); }
.area-bar { display: flex; flex-wrap: wrap; align-items: center; gap: .55rem .5rem; padding-bottom: var(--space-md); border-bottom: var(--rule-hair) solid var(--color-rule); }
.area-group { font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: .1em; text-transform: uppercase; color: var(--color-muted); margin: 0 .2rem 0 0; white-space: nowrap; }
.area-group:not(:first-child) { margin-left: var(--space-md); }
.area-tab { font: 500 var(--text-sm) var(--font-body); padding: .5rem .95rem; border-radius: 999px; border: var(--rule-hair) solid var(--color-rule); background: var(--color-paper); color: var(--color-ink-2); text-decoration: none; white-space: nowrap; transition: background-color .15s ease, color .15s ease, border-color .15s ease; }
.area-tab:hover { border-color: var(--color-ink-2); color: var(--color-ink); }
.areas.is-live .area-tab[aria-selected="true"] { background: var(--color-ink); border-color: var(--color-ink); color: var(--color-paper-3); }
.area { padding-top: var(--space-lg); }
.areas:not(.is-live) .area + .area { margin-top: var(--space-2xl); border-top: var(--rule-hair) solid var(--color-rule); }
.area:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 6px; border-radius: 6px; }
.area .prism-fig { margin-top: 0; }
.area-facts { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--space-xl) var(--space-3xl); margin-top: var(--space-xl); padding-top: var(--space-lg); border-top: var(--rule-hair) solid var(--color-rule); }
.area-intro h3 { font-family: var(--font-display); font-weight: 600; font-size: var(--text-lg, 1.5rem); line-height: 1.15; color: var(--color-ink); margin: 0; }
.area-intro .kicker { margin-bottom: var(--space-xs); }
.area-status { margin: .5rem 0 0; font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: .06em; color: var(--color-accent-text); }
.area-proof { display: grid; gap: .25rem; margin: var(--space-lg) 0 var(--space-md); }
.area-proof b { font-family: var(--font-display); font-weight: 600; font-size: clamp(1.8rem, 2.4vw + .6rem, 2.6rem); line-height: 1; color: var(--color-ink); }
.area-proof span { font-size: var(--text-sm); color: var(--color-muted); max-width: 34ch; }
.area-rows { margin: 0; }
.area-rows > div { display: grid; grid-template-columns: 8rem minmax(0, 1fr); gap: var(--space-md); padding: var(--space-sm) 0; border-bottom: var(--rule-hair) solid var(--color-rule); }
.area-rows > div:first-child { padding-top: 0; }
.area-rows dt { font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: .08em; text-transform: uppercase; color: var(--color-muted); padding-top: .2rem; }
.area-rows dd { margin: 0; color: var(--color-ink-2); line-height: 1.5; max-width: 52ch; }
@media (max-width: 64rem) { .area-facts { grid-template-columns: 1fr; } }
@media (max-width: 40rem) {
  .area-bar { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: thin; padding-bottom: var(--space-sm); }
  .area-rows > div { grid-template-columns: 1fr; gap: .2rem; }
}
@media (prefers-reduced-motion: reduce) { .area-tab { transition: none; } }
.area[hidden] { display: none; }

/* Company page photos, from the old About page (9 Nov 2026) */
.co-photo { margin: 0 0 var(--space-lg); border-radius: 10px; overflow: hidden; background: var(--color-paper-2); }
.co-photo img { display: block; width: 100%; height: auto; }
/* Company page, where we are: the address on its lines, how to reach us, and an OpenStreetMap map (no tracking cookies) */
.co-address { font-style: normal; font-size: var(--text-md); line-height: 1.5; color: var(--color-ink); margin: var(--space-lg) 0 0; }
.co-reach { margin: var(--space-lg) 0 0; display: grid; gap: .55rem; }
.co-reach > div { display: grid; grid-template-columns: 8rem minmax(0, 1fr); gap: var(--space-md); align-items: baseline; }
.co-reach dt { font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: .08em; text-transform: uppercase; color: var(--color-muted); }
.co-reach dd { margin: 0; }
.co-map { margin: 0; aspect-ratio: 4 / 3; border-radius: 10px; overflow: hidden; border: var(--rule-hair) solid var(--color-rule); background: var(--color-paper-2); }
.co-map iframe { display: block; width: 100%; height: 100%; border: 0; filter: saturate(.6); }
.co-map-links { display: flex; flex-wrap: wrap; gap: var(--space-xs) var(--space-lg); margin: var(--space-md) 0 0; }

/* Partners page: every way in (tools/routes_art.py) */
.routes { margin: var(--space-2xl) 0 0; }
.routes-fig { display: block; width: 100%; height: auto; }
.routes-fig .mono { font-family: var(--font-mono); font-weight: 500; }
@media (max-width: 40rem) { .routes { overflow-x: auto; } .routes-fig { min-width: 44rem; } }

/* ── The recording banner and Cookie settings (js/analytics.js; SEO-GEO.md 1.2a) ──
   One question, bottom left, clear of Ami's launcher on the right. Built by JS only,
   so without JS there is no banner and no tracking. Tokens, so both themes follow. */
.rec-ask { position: fixed; left: 1.25rem; bottom: 1.25rem; z-index: 61; width: min(26rem, calc(100vw - 2.5rem)); padding: 1rem 1.1rem; background: var(--color-paper-3); color: var(--color-ink); border: var(--rule-hair) solid var(--color-rule); border-radius: 14px; box-shadow: 0 24px 60px -20px rgba(43,33,23,.35); font-size: var(--text-sm); line-height: 1.45; }
.rec-ask p { margin: 0; }
.rec-ask b { font-weight: 600; }
.rec-ask p a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }
.rec-ask p a:hover { color: var(--color-accent-text); }
.rec-ask-acts { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .9rem; margin-top: .8rem; }
.rec-ask-acts .tlink { background: none; border: 0; padding: 0; font: inherit; color: var(--color-muted); cursor: pointer; text-decoration: underline; text-underline-offset: 3px; }
.rec-ask-now { margin-top: .6rem !important; color: var(--color-muted); font-size: var(--text-xs); }
@media (max-width: 40rem) { .rec-ask { left: .75rem; right: .75rem; width: auto; bottom: 4.5rem; } .cx.open ~ .rec-ask { display: none; } }   /* the banner is appended after Ami's panel, so it steps aside while she is open on a phone */
.foot-cookie { background: none; border: 0; padding: 0; font: inherit; font-size: var(--text-xs); color: var(--color-muted); cursor: pointer; }
.foot-cookie:hover { color: var(--color-ink); text-decoration: underline; text-underline-offset: 3px; }

/* ── The narrowest phones (11 Nov 2026) ──
   At 320px (small Androids, the first iPhone SE) the Company page's phone number ran 14px off the screen; at 280px (the
   original Galaxy Fold's cover screen) so did a handful of links, a chip, the strip's >_ and the BASIC reference's
   statements, and html's overflow clip cut them off. site.css keeps .tlink on one line, which is right everywhere
   else; here links wrap, the strip's tools drop to a second line, and the reference's statements wrap. */
@media (max-width: 22.5rem) {
  .io .tlink, .io .hero-links .chip { white-space: normal; }
  .io .hero-links .chip { text-align: center; flex-shrink: 1; }
}
@media (max-width: 20rem) {
  .family > .band-narrow { flex-wrap: wrap; row-gap: 0; }
  .ref-page table.ref th { white-space: normal; width: auto; }
}
