/* Components for the /next/ site. Built only from tokens.css; no literal
   colours here. Rules: transform and opacity are the only properties that
   animate; a quiet edge is a solid hairline; nothing is hidden until JS runs. */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }
/* Anchor targets and focused controls in the page stop clear of the sticky
   nav. Not scroll-padding on html: browsers apply that to focus landing inside
   the sticky nav too, which scrolled the page up ~450 px every time the menu
   opened or closed or a nav link took focus (ISSUES NAV-01). */
main, main [id], main a[href], main button, main summary, main [tabindex] {
  scroll-margin-top: calc(var(--nav-h) + var(--space-2));
}
/* Big screens: everything is in rem, so growing the root grows the page (and
   its measure) instead of leaving a small column in the middle of a wide one. */
@media (min-width: 120rem) { html { font-size: 112.5%; } }
@media (min-width: 150rem) { html { font-size: 125%; } }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: var(--fw-body) var(--fs-body)/var(--lh-body) var(--font);
}

img, svg { display: block; max-width: 100%; height: auto; }
a { color: var(--accent); }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Above the sticky nav (z-index 10), or it is focused out of sight under it. */
.skip-link {
  position: absolute; z-index: 20; left: var(--space-2); top: -4rem;
  padding: var(--space-1) var(--space-2);
  background: var(--panel); color: var(--text);
  border: var(--stroke) solid var(--border); border-radius: var(--r-button);
}
.skip-link:focus { top: var(--space-2); }

.wrap { max-width: var(--page-max); margin: 0 auto; padding-inline: var(--gutter); }

/* A themed surface. The style guide wraps each scheme in one of these. */
.scope { background: var(--bg); color: var(--text); }

.sr-only {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---- Type roles ---------------------------------------------------------- */

.t-display {
  margin: 0; font-size: var(--fs-display); font-weight: var(--fw-display);
  letter-spacing: var(--track-display); line-height: var(--lh-display);
}
.t-headline {
  margin: 0; font-size: var(--fs-headline); font-weight: var(--fw-display);
  letter-spacing: var(--track-headline); line-height: var(--lh-headline); text-wrap: balance;
}
.t-title {
  margin: 0; font-size: var(--fs-title); font-weight: var(--fw-title);
  letter-spacing: var(--track-title); line-height: var(--lh-title);
}
.t-section { margin: 0; font-size: var(--fs-section); font-weight: var(--fw-section); line-height: 1.3; }
.t-meta { font-size: var(--fs-meta); color: var(--text-2); }
.t-label {
  font-size: var(--fs-label); font-weight: var(--fw-label);
  letter-spacing: var(--track-label); text-transform: uppercase;
}

/* ---- Button ---------------------------------------------------------------
   Primary is the action: bright amber fill, its own ink, and the app's slab
   lip (accentFillEdge) as a 3D edge under it; a flat fill, no gradient.
   Secondary is a hairline on the surface with a hairline-coloured edge.
   Sizes: --sm 44px, default 48px, --lg 52px (full width under 600px). A press
   sinks the button onto its edge (down by --lip less 1px, the edge to 1px) on
   the app's press spring; hover changes colour or opacity at once and never
   moves the button under the pointer. The edge is a shadow, so it takes no
   layout space. */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-1);
  min-height: 3rem; padding: 0.75rem var(--space-3);
  border: var(--stroke) solid transparent; border-radius: var(--r-button);
  font: var(--fw-button) var(--fs-body)/1.2 var(--font);
  text-decoration: none; cursor: pointer;
  --edge: var(--border);
  box-shadow: 0 var(--lip) 0 var(--edge);
  transition: transform var(--dur-press) var(--ease-press), box-shadow var(--dur-press) var(--ease-press), opacity var(--dur-snappy) var(--ease-out);
}
.btn:active { transform: translateY(calc(var(--lip) - 1px)); box-shadow: 0 1px 0 var(--edge); }

.btn--primary { --edge: var(--accent-edge); background: var(--accent-fill); color: var(--accent-fill-ink); }
.btn--primary:hover { opacity: 0.92; }

.btn--secondary { background: var(--bg); color: var(--text); border-color: var(--border); }
.btn--secondary:hover { background: var(--well); }

.btn--sm { min-height: var(--hit); padding: 0.5rem var(--space-2); }
.btn--lg { min-height: 3.25rem; padding: 0.875rem var(--space-4); font-size: 1.125rem; }
@media (max-width: 37.49rem) { .btn--lg { width: 100%; } }

/* "Coming soon": the fallback for a CTA slot when the TestFlight link is off.
   Not a link, so no hover or press. */
.badge-soon {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--hit); padding: 0.75rem var(--space-3);
  background: var(--well); color: var(--text-2);
  border: var(--stroke) solid var(--border); border-radius: var(--r-button);
  font: var(--fw-button) var(--fs-body)/1.2 var(--font);
}

/* ---- Section header ------------------------------------------------------- */

.section-header { max-width: var(--measure); }
.section-header__eyebrow { margin: 0 0 var(--space-1); color: var(--accent); }
.section-header__title { margin: 0; }
.section-header__line { margin: var(--space-2) 0 0; color: var(--text-2); font-size: var(--fs-lede); line-height: 1.5; }

/* ---- Tag: "Pro" -------------------------------------------------------------- */

.tag {
  display: inline-block; margin-left: var(--space-1); padding: 0.125rem 0.625rem; vertical-align: 0.15em;
  border: var(--stroke) solid var(--accent); border-radius: var(--r-pill);
  color: var(--accent); font-size: var(--fs-label); font-weight: var(--fw-label);
  letter-spacing: var(--track-label); text-transform: uppercase;
}

/* ---- Card ----------------------------------------------------------------- */

.card {
  padding: var(--space-3);
  background: var(--panel); color: var(--text);
  border: var(--stroke) solid var(--border); border-radius: var(--r-panel);
}
@media (min-width: 64rem) { .card { padding: var(--space-4); } }
.card__title { margin: 0; }
.card__body { margin: var(--space-1) 0 0; color: var(--text-2); }
.card__stat {
  margin: var(--space-2) 0 0; padding: var(--space-2);
  background: var(--well); border-radius: var(--r-card);
}
.card__figure {
  display: block; font-size: var(--fs-figure); font-weight: 700; letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums; line-height: 1.05;
}
.card__figure-label { display: block; margin-top: var(--space-half); color: var(--text-2); font-size: var(--fs-meta); }

/* ---- Playing card ----------------------------------------------------------
   White face in either scheme, a hairline edge, the card radius. Rank in the
   suit's colour with the suit shape beneath it: <img class="pcard__suit"
   src="/assets/suits/spade-v2.svg" alt="" width="26" height="26">. Add
   .pcard--red for hearts and diamonds. Name the card for assistive tech on the
   element, e.g. aria-label="Ace of spades". Two-colour deck only on the site. */

.pcard {
  display: inline-flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--space-half); width: 3.875rem; height: 5.5rem;
  background: var(--card-face); color: var(--suit-ink);
  border: var(--stroke) solid var(--border); border-radius: var(--r-card);
  font-size: 1.875rem; font-weight: 700; line-height: 1;
}
.pcard--red { color: var(--suit-red); }
.pcard__suit { width: 1.625rem; height: 1.625rem; }

.cards { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-3); }
.cards__group { display: flex; gap: var(--space-1); }

/* ---- FAQ item: a plain <details>, so it works without JS ------------------- */

.faqs__list { border-top: var(--stroke) solid var(--border); }
.faq { border-bottom: var(--stroke) solid var(--border); }
.faq__q {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
  min-height: var(--hit); padding: var(--space-2) 0;
  font-size: var(--fs-section); font-weight: var(--fw-section); line-height: 1.3;
  cursor: pointer; list-style: none;
}
.faq__q::-webkit-details-marker { display: none; }
.faq__q::after {
  content: ""; flex: none; width: 0.5rem; height: 0.5rem;
  border-right: 2px solid var(--accent); border-bottom: 2px solid var(--accent);
  transform: rotate(45deg);
  transition: transform var(--dur-snappy) var(--ease-out);
}
.faq[open] > .faq__q::after { transform: rotate(-135deg); }
.faq__a { margin: 0; padding: 0 0 var(--space-2); color: var(--text-2); max-width: var(--measure); }
/* Only with motion allowed, and no fill after the end: a finished animation
   that holds its last frame stays in document.getAnimations(), which Reduce
   Motion must leave empty (redesign Phase 2, the demo probe). */
@media (prefers-reduced-motion: no-preference) {
  .faq[open] > .faq__a { animation: faq-in var(--dur-snappy) var(--ease-out) backwards; }
}
@keyframes faq-in { from { opacity: 0; } to { opacity: 1; } }

/* ---- Entrance ----------------------------------------------------------------
   For pictures only: [data-enter] on an element, [data-enter-group] on a parent
   to stagger its [data-enter] children. Text, prices and buttons never enter.
   CSS hides nothing by itself: site.js sets data-enter="pending" only when it
   can reveal the element (motion allowed, IntersectionObserver present, the
   element still below the screen), then plays opacity and a 12px rise once,
   when it scrolls in. With no JS or Reduce Motion it is simply there. */

[data-enter="pending"] { opacity: 0; transform: translateY(var(--entrance-rise)); }

/* ---- Nav ------------------------------------------------------------------
   Sticky, solid --bg, one hairline underneath (no blur: WebKit repaints a
   backdrop-filtered sticky bar over moving content). The bar is a container, so it
   collapses by its own width (the style guide shows the narrow form in a
   narrow box). Without JS a wide bar shows its links inline and a narrow one just the brand
   and the button (the footer has the links); site.js sets
   [data-enhanced], turns that row into a menu behind the toggle and runs it
   (aria-expanded, focus trap, Escape) and sets [data-open] while it is open. The CTA stays in the bar at every
   width. Open and close fade and rise 12px: transform and opacity only. */

:root { --nav-h: 4rem; }

.nav {
  position: sticky; top: 0; z-index: 10;
  container-type: inline-size;
  background: var(--bg);
  border-bottom: var(--stroke) solid var(--border);
}
.nav--static { position: relative; }

.nav__bar {
  display: flex; align-items: center; flex-wrap: wrap;
  column-gap: var(--space-1); min-height: var(--nav-h);
}
.nav__brand {
  display: inline-flex; align-items: center; gap: var(--space-1);
  min-height: var(--hit); margin-right: auto;
  color: var(--text); text-decoration: none;
  font-size: 1.125rem; font-weight: 600; letter-spacing: -0.02em;
}
.nav__mark { width: 1.5rem; height: 1.5rem; }

.nav__links { display: flex; flex-wrap: wrap; gap: var(--space-half); }
.nav__links a {
  display: inline-flex; align-items: center; min-height: var(--hit);
  padding: 0 var(--space-2); border-radius: var(--r-button);
  color: var(--text-2); text-decoration: none; font-weight: 400;
}
.nav__links a:hover { color: var(--text); }
/* The page you are on (site.js sets aria-current: the header is shared, so
   the markup can't say which page it is on). */
.nav__links a[aria-current="page"] {
  color: var(--text);
  text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 0.4em;
}

.nav__toggle {
  display: none; position: relative; flex: none;
  width: var(--hit); height: var(--hit); padding: 0; cursor: pointer;
  background: transparent; color: var(--text);
  border: var(--stroke) solid var(--border); border-radius: var(--r-button);
}
.nav__toggle::before, .nav__toggle::after {
  content: ""; position: absolute; left: 0.75rem; right: 0.75rem; top: 50%;
  height: 2px; margin-top: -1px; border-radius: 1px; background: currentColor;
  transition: transform var(--dur-settle) var(--ease-out);
}
.nav__toggle::before { transform: translateY(-4px); }
.nav__toggle::after { transform: translateY(4px); }
.nav__toggle[aria-expanded="true"]::before { transform: rotate(45deg); }
.nav__toggle[aria-expanded="true"]::after { transform: rotate(-45deg); }

.nav__scrim { display: none; }

/* Wide: links inline between brand and CTA. */
@container (min-width: 40rem) {
  .nav__bar { flex-wrap: nowrap; column-gap: var(--space-2); }
  .nav__panel { order: 1; }
  .nav__bar > .btn, .nav__bar > .badge-soon { order: 2; }
}

/* Narrow: no JS keeps a row of links under the bar; enhanced gets the menu. */
@container (max-width: 39.99rem) {
  .nav__panel { order: 5; flex-basis: 100%; padding-bottom: var(--space-1); }
  .nav__links { margin-inline: calc(var(--space-2) * -1); }
  /* Before JS has built the menu a narrow bar shows brand and button only (the
     links are in the footer). A row of links here made the bar taller until JS
     collapsed it into the menu, shifting the whole page once on load. */
  .nav:not([data-enhanced]) .nav__panel { display: none; }
  /* The toggle's slot is kept (unseen) until site.js enhances the bar, so the
     button beside it doesn't jump left when it appears (CLS 0.0015 on load). */
  .nav .nav__toggle { display: block; }
  .nav:not([data-enhanced]) .nav__toggle { visibility: hidden; }
  .nav[data-enhanced] .nav__panel {
    position: absolute; top: 100%; left: 0; right: 0; z-index: 2;
    padding: var(--space-1) calc(var(--gutter) - var(--space-2)) var(--space-2);
    background: var(--panel);
    border-bottom: var(--stroke) solid var(--border);
  }
  .nav[data-enhanced]:not([data-open]) .nav__panel { display: none; }
  .nav[data-enhanced] .nav__links { flex-direction: column; margin-inline: 0; }
  .nav[data-enhanced] .nav__links a { color: var(--text); font-size: var(--fs-section); }
  .nav[data-enhanced][data-open] .nav__panel { animation: nav-in var(--dur-entrance) var(--ease-out) both; }
  .nav[data-enhanced][data-open] .nav__scrim {
    /* 100lvh, the large viewport: it still covers the screen when the iOS
       toolbar collapses (SPEC §6.1). The vh line is for browsers without lvh. */
    display: block; position: absolute; top: 100%; left: 0; right: 0; height: 100vh; height: 100lvh;
    background: var(--bg); opacity: 0.6;
    animation: scrim-in var(--dur-entrance) var(--ease-out) both;
  }
}
/* While the menu is open its bar and scrim fill the screen, so no touch can
   pan the page behind them; taps still work (see lock() in site.js). */
.nav[data-open] .nav__bar, .nav[data-open] .nav__scrim { touch-action: none; }
@media (max-width: 22.49rem) { .nav__bar > .btn--sm { padding-inline: 0.75rem; } }
@keyframes nav-in {
  from { opacity: 0; transform: translateY(calc(var(--entrance-rise) * -1)); }
  to { opacity: 1; transform: none; }
}
@keyframes scrim-in { from { opacity: 0; } to { opacity: 0.6; } }

/* ---- Footer ---------------------------------------------------------------
   Brand and one line on the left, three short link groups (three columns at
   every width; they fit at 320), then the contact address, the fine print and the theme toggle. A
   hairline above. */

.footer { border-top: var(--stroke) solid var(--border); padding-block: var(--space-3); }
.footer__grid { display: grid; gap: var(--space-2); grid-template-columns: repeat(3, auto); justify-content: space-between; }
.footer__about { grid-column: 1 / -1; display: flex; flex-wrap: wrap; align-items: center; column-gap: var(--space-2); }
.footer__brand {
  display: inline-flex; align-items: center; gap: var(--space-1); min-height: var(--hit);
  color: var(--text); text-decoration: none;
  font-size: var(--fs-section); font-weight: 600; letter-spacing: -0.02em;
}
.footer__line { margin: 0; color: var(--text-2); }
.footer__group { margin: 0; padding: 0; list-style: none; }
.footer__head { margin: 0 0 var(--space-1); color: var(--text-3); }
/* Hit area is 44px square at least: the padding widens a short word's target and
   the equal negative margin keeps the text where it was. */
.footer__group a {
  display: inline-flex; align-items: center; min-height: var(--hit); min-width: var(--hit);
  padding-inline: var(--space-1); margin-inline: calc(var(--space-1) * -1);
  color: var(--text-2); text-decoration: none; white-space: nowrap;
}
.footer__group a:hover { color: var(--text); text-decoration: underline; }
.footer__base {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-3);
  margin-top: var(--space-2); padding-top: var(--space-2);
  border-top: var(--stroke) solid var(--border);
  color: var(--text-2); font-size: var(--fs-meta);
}
.footer__base p { margin: 0; }
/* The address and the theme toggle share the first row; the fine print takes
   the next, so a phone's footer stays three short rows (redesign SPEC §6.11). */
.footer__base p:not(:first-child) { order: 1; flex-basis: 100%; text-wrap: pretty; }
.footer__base a { display: inline-flex; align-items: center; min-height: var(--hit); color: var(--text-2); }
.footer__base a:hover { color: var(--text); }
.footer__base .btn { margin-left: auto; }
@media (min-width: 48rem) {
  .footer__grid { grid-template-columns: 2fr repeat(3, 1fr); }
  .footer__about { grid-column: auto; display: block; max-width: 22rem; }
}

/* ---- CTA band --------------------------------------------------------------
   CTA C, at the end of the app gallery (redesign SPEC §4.4): a panel with a
   headline, one line and the same [data-cta] button as the nav and hero.
   Stacked with a full-width button on a phone, one row from 48rem. */

.cta-band {
  display: flex; flex-direction: column; align-items: stretch; gap: var(--space-3);
  padding: var(--space-4) var(--space-3);
  background: var(--panel); color: var(--text);
  border: var(--stroke) solid var(--border); border-radius: var(--r-panel);
}
.cta-band__title { margin: 0; text-wrap: balance; }
.cta-band__line { margin: var(--space-1) 0 0; color: var(--text-2); max-width: var(--measure); text-wrap: pretty; }
.cta-band__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }
@media (min-width: 48rem) {
  .cta-band { flex-direction: row; align-items: center; justify-content: space-between; gap: var(--space-5); padding: var(--space-4) var(--space-5); }
  .cta-band__actions { flex: none; flex-wrap: nowrap; }
}

/* ---- Hero (redesign SPEC §6.2) ----------------------------------------------
   Copy, then the playable demo: stacked on a phone, side by side from 768px,
   on the 12-column grid from 1024px (copy in columns 1-6, the phone's right
   edge on column 12, in line with the nav button). The headline and the button
   are plain HTML: no entrance, nothing waits on JS, so the headline is what
   paints first (it must stay the LCP element). A landscape phone stacks too,
   the phone at its natural size below the copy. */

.hero { padding-block: var(--space-3) var(--space-5); }
.hero__grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-3); }
.hero__title { max-width: 11em; text-wrap: balance; }
.hero__accent { color: var(--accent); }
.hero__line { margin: var(--space-2) 0 0; max-width: 28rem; color: var(--text-2); font-size: var(--fs-lede); line-height: 1.5; }
.hero__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); margin-top: var(--space-3); }
.hero__cta { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-1); }
@media (max-width: 37.49rem) { .hero__cta { width: 100%; } }
.hero__note { margin: 0; color: var(--text-2); font-size: var(--fs-meta); }
.hero__demo { display: flex; flex-direction: column; align-items: center; min-width: 0; }

@media (min-width: 48rem) {
  .hero { padding-block: clamp(1.5rem, 4svh, 3rem); }
  .hero__grid { grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: var(--space-5); }
}
@media (min-width: 64rem) {
  .hero__grid { grid-template-columns: repeat(12, minmax(0, 1fr)); gap: var(--space-3); }
  .hero__copy { grid-column: 1 / 7; }
  .hero__demo { grid-column: 7 / 13; justify-self: end; }
}
@media (orientation: landscape) and (max-height: 500px) {
  .hero__grid { grid-template-columns: minmax(0, 1fr); }
  .hero__copy, .hero__demo { grid-column: auto; justify-self: stretch; }
}

/* The QR sits beside the button on a desktop with a pointer and nowhere else:
   a phone has the button, and the code is for opening the link on one. A card
   like the rest, around a static SVG made offline by scripts/make-qr.py from
   the same URL the button uses. */
.qr {
  display: none; align-items: center; gap: var(--space-2); margin: 0;
  padding: var(--space-1) var(--space-2) var(--space-1) var(--space-1);
  background: var(--panel); border: var(--stroke) solid var(--border); border-radius: var(--r-panel);
}
.qr__img { width: 6.5rem; height: 6.5rem; border-radius: var(--r-card); }
.qr__cap { max-width: 8rem; margin: 0; color: var(--text-2); font-size: var(--fs-meta); }
@media (min-width: 60rem) and (hover: hover) and (pointer: fine) { .qr { display: flex; } }

/* ---- Proof strip (redesign SPEC §6.3) -----------------------------------------
   Four true numbers flush under the hero: no cards, a hairline grid. 2 x 2
   below 1024px (a rule between the columns and one between the rows), four
   columns from there. The figure stays on one line at every width, which is
   why "bb" lives in the label. The numbers are in the HTML; site.js counts two
   of them up only if they start below the screen. */

.proof { padding-block: 0 var(--section-y); }
.proof__list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); margin: 0; padding: 0; list-style: none; }
.proof__item { display: flex; flex-direction: column; min-width: 0; padding: var(--space-2) 0.75rem; }
.proof__fig {
  font-size: var(--fs-figure); font-weight: 700; line-height: 1.05; letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.proof__label { color: var(--text-2); font-size: var(--fs-meta); line-height: 1.45; }
@media (max-width: 22.49rem) { .proof__fig { font-size: 1.5rem; } }
@media (max-width: 63.99rem) {
  .proof__item:nth-child(odd) { padding-left: 0; border-right: var(--stroke) solid var(--border); }
  .proof__item:nth-child(-n+2) { border-bottom: var(--stroke) solid var(--border); }
}
@media (min-width: 64rem) {
  .proof__list { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .proof__item { padding: var(--space-3); }
  .proof__item:first-child { padding-left: 0; }
  .proof__item + .proof__item { border-left: var(--stroke) solid var(--border); }
}

/* ---- Range chart (SPEC §5) ------------------------------------------------------
   Drawn by next/js/chart.js: 13 x 13, each cell a bar split fold / call /
   raise left to right, widths set through the CSSOM. The hero's hand has an
   amber ring inside the cell ("amber outlined = you"), with a --bg line inside
   that, so the ring clears 3:1 on every fill (amber on the raise green alone is
   1.4:1). A picked hand gets a --text outline outside the cell, never a bigger
   square: a scaled cell would cover its neighbours and steal the pointer. */

.cgrid { display: grid; grid-template-columns: repeat(13, minmax(0, 1fr)); gap: 2px; border-radius: var(--r-card); }
.cell { position: relative; aspect-ratio: 1; display: flex; overflow: hidden; border-radius: 2px; background: var(--well); }
.cell__seg { display: block; height: 100%; flex: 0 0 auto; }
.cell__seg--f { background: var(--act-fold); } .cell__seg--c { background: var(--act-call); } .cell__seg--r { background: var(--act-raise); }
.cell__t {
  position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none;
  font-size: clamp(0.4rem, 2.5cqw, 0.75rem); font-weight: 600; letter-spacing: -0.02em; color: var(--text);
}
.cell--empty .cell__t { color: var(--text-3); }
/* Label ink on a fill is --act-ink, as on the buttons: near-black clears 4.5:1
   on every fill in both schemes, where white on the light fold red was 3.7:1. */
.cell--ink-f .cell__t, .cell--ink-c .cell__t, .cell--ink-r .cell__t { color: var(--act-ink); }
.cell.is-hero::before {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  border: 2px solid var(--accent); border-radius: 2px; box-shadow: inset 0 0 0 1px var(--bg);
}
.cell.is-sel { z-index: 2; outline: 2px solid var(--text); outline-offset: 1px; }

.clegend { display: flex; flex-wrap: wrap; gap: var(--space-half) var(--space-2); margin: 0; padding: 0; list-style: none; color: var(--text-2); font-size: var(--fs-meta); }
.clegend li { display: inline-flex; align-items: center; gap: 0.4em; }
.clegend__sw { width: 0.75em; height: 0.75em; border-radius: 2px; }
.clegend__sw--f { background: var(--act-fold); } .clegend__sw--c { background: var(--act-call); } .clegend__sw--r { background: var(--act-raise); }
.clegend__sw--none { background: var(--well); box-shadow: inset 0 0 0 var(--stroke) var(--border); }

/* ---- Caption ----------------------------------------------------------------------
   Under a picture that could be taken for a capture, saying what it is
   (SPEC §4.2): 14px, --text-3, at most two lines. */
.figcap { margin: 0; color: var(--text-3); font-size: var(--fs-meta); line-height: 1.45; text-wrap: balance; }

[hidden] { display: none !important; }
