/* The site layer — everything reads from `tokens.css` (ADR-0052 "clinical")
 * and adds nothing to the palette.
 *
 * REGISTER, v3: centred hero, two-tone headline, and the PRODUCT ITSELF as
 * the first thing below the fold, inside a window frame. Drawn against
 * peec.ai and attio.com, which converge on the same formula: badge, sentence-
 * case headline whose second half drops to grey, two centred CTAs, then a
 * large, believable app screenshot. The difference here is that the frame is
 * not a screenshot — it is the real interface, rebuilt in HTML from the same
 * tokens, and its tabs work.
 *
 * Two rules from the ADR that still hold everywhere:
 *   D2 — `--accent` paints focus, active nav and selection ONLY. It is not a
 *        series colour and it is not decoration. The primary button is
 *        `--ink-1`, which is achromatic and matches both references.
 *   D3 — chroma tier follows mark size: `--cN` for dots, swatches and ≤2px
 *        lines, `--cNm` for bands and bars, `--cNf` for heat cells.
 */

/* ------------------------------------------------------------------ reset */

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--page);
  color: var(--ink-1);
  font-family: var(--ff-ui);
  font-size: var(--t-ui-base-size);
  line-height: var(--t-ui-base-leading);
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

h1, h2, h3, h4, p, figure, ul, ol, dl, dd { margin: 0; }
ul, ol { padding: 0; list-style: none; }
img, svg { display: block; max-width: 100%; }
button { font: inherit; color: inherit; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 3px; }

:root {
  --t-hero: clamp(36px, 5.6vw, 68px);
  --t-h2: clamp(26px, 3.2vw, 42px);
  --t-h3: clamp(17px, 1.5vw, 20px);
  --t-lede: clamp(15px, 1.25vw, 17.5px);
  --t-body: clamp(13.5px, 1vw, 15px);

  --shell: 1280px;
  --shell-pad: clamp(18px, 3.4vw, 40px);
  --band-pad: clamp(56px, 7vw, 108px);

  /* Where the two vertical section rules stand. At the shell's own edge once
     the viewport is wider than the shell; a small gutter in from the viewport
     below that, so the page reads as ruled rather than bordered. */
  --rule-x: max(10px, calc((100% - var(--shell)) / 2));

  /* Depth. `--e1`/`--e2` are the product's two steps; a page-scale window
     frame needs a third, and it is defined here rather than added to the
     token file because no product surface floats this far off the page. */
  --e3: 0 1px 1px rgba(16,20,24,.04), 0 8px 24px rgba(16,20,24,.06), 0 32px 64px rgba(16,20,24,.07);
}

/* -------------------------------------------------------------- type atoms */

.display { font-family: var(--ff-display); font-weight: 600; letter-spacing: -0.035em; }

/* The two-tone headline: the claim in ink, its continuation one step lighter
   at the same size. Both references use it and it is the reason their pages
   read as calm rather than shouted — the second half carries the
   qualification instead of a second, smaller paragraph.

   The lighter half is `--ink-2` (6.0:1), not `--ink-3` (2.9:1). `--ink-3`
   misses even the 3:1 large-text threshold, and this half is real copy the
   reader has to finish the sentence with. The step from 17.8:1 to 6.0:1 is
   still unmistakably two-tone. */
.h1 {
  font-size: var(--t-hero);
  font-weight: 600;
  letter-spacing: -0.042em;
  line-height: 1.06;
  text-wrap: balance;
}
.h1 .rest, .h2 .rest { color: var(--ink-2); }
.band--ink .h1 .rest, .band--ink .h2 .rest { color: var(--fg2); }

.h2 { font-size: var(--t-h2); letter-spacing: -0.04em; line-height: 1.12; text-wrap: balance; }
.h3 { font-size: var(--t-h3); letter-spacing: -0.025em; line-height: 1.3; }
.h4 { font-size: var(--t-display-m-size); line-height: var(--t-display-m-leading); }

.lede { font-size: var(--t-lede); line-height: 1.55; color: var(--ink-2); max-width: 60ch; }
.body { color: var(--ink-2); line-height: 1.6; font-size: var(--t-body); max-width: 66ch; }
.body strong, .lede strong { color: var(--ink-1); font-weight: 500; }

/* CONTRAST NOTE — and the reason this is `--ink-2` and not `--ink-3`.
 *
 * `--ink-3` (#8E959D) on `--page` measures 2.9:1, which is below AA for text
 * at any size, and this is the site's smallest voice at 9.5px. The fix is NOT
 * to change the token: `--ink-3` is a design-system value with valid uses
 * (large numerals, disabled state, dividers), and moving it would need an
 * ADR-0052 amendment and would ripple into the SPA.
 *
 * The fix is to stop spending it on 9.5px uppercase. `--ink-2` (#5A6169) is
 * 5.9:1 on `--page`, is already in the system, and reads as the same
 * register one step firmer. Same choice for `.num`. */
.cap {
  font-family: var(--ff-mono);
  font-size: var(--t-mono-label-size);
  line-height: var(--t-mono-label-leading);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--ink-2);
}

.num { font-family: var(--ff-mono); font-size: var(--t-mono-num-size); color: var(--ink-2); }

/* The eyebrow pill. Achromatic — both references tint theirs with the brand
   accent, which here would put hue on chrome and break D2. */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 28px;
  padding-inline: 12px;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--surface);
  box-shadow: var(--e1);
  font-size: var(--t-ui-sm-size);
  color: var(--ink-2);
  text-decoration: none;
}
.pill b { color: var(--ink-1); font-weight: 500; }
.pill .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--pos); flex: 0 0 auto; }

/* Inline chip, used inside a running sentence to name a metric. */
.ichip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 8px;
  margin-inline: 1px;
  border: 1px solid var(--rule);
  border-radius: var(--r);
  background: var(--surface);
  color: var(--ink-1);
  font-size: 0.92em;
  white-space: nowrap;
}
.ichip i { width: 7px; height: 7px; border-radius: 2px; background: var(--h); flex: 0 0 auto; }

/* ------------------------------------------------------------------ shell */

.shell { width: 100%; max-width: var(--shell); margin: 0 auto; padding-inline: var(--shell-pad); }
.shell--tight { max-width: 940px; }

.band { padding-block: var(--band-pad); }
.band + .band { border-top: 1px solid var(--rule); }
.hero + .band { border-top: 1px solid var(--rule); }
.band--surface { background: var(--surface); }
.band--tight { padding-block: clamp(40px, 5vw, 68px); }

/* THE RULED PAGE. Two hairlines standing at the shell's edges for the full
   height of every section, so the whole document reads as one drawing on
   ruled paper rather than as a stack of unrelated blocks — the structural
   signature both references share, and the one that costs nothing but a
   pseudo-element. They line up across sections because every section puts
   them at the same x, which is what makes them read as continuous.

   The horizontal rules were already there (`.band + .band`); these are the
   other two sides of the same frame. */
.hero, .band { position: relative; }
.hero::before, .hero::after,
.band::before, .band::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--rule);
  pointer-events: none;
}
.hero::before, .band::before { left: var(--rule-x); }
.hero::after, .band::after { right: var(--rule-x); }
.band--ink::before, .band--ink::after { background: var(--line); }
/* Below the phone breakpoint the gutter is narrower than the shell padding,
   so the rules would sit inside the text measure. */
@media (max-width: 560px) {
  .hero::before, .hero::after, .band::before, .band::after { display: none; }
}

.band--ink {
  background-color: var(--ink-1);
  /* A wash from the top edge and a faint dot grid — the same ground the
     reference gives its closing panel. Both are backgrounds on the element
     itself because the two pseudo-elements are spent on the section rules. */
  background-image:
    radial-gradient(64% 90% at 50% 0%, rgba(255, 255, 255, 0.055), transparent 70%),
    radial-gradient(rgba(255, 255, 255, 0.05) 1px, transparent 1px);
  background-size: auto, 18px 18px;
  --fg: #EDEFF2; --fg2: #9BA3AC; --fg3: #6B737C; --line: #272C32;
  color: var(--fg);
  border-top: 0;
}
.band--ink .lede, .band--ink .body, .band--ink .feat p { color: var(--fg2); }
/* `--fg3` on the ink ground is 3.8:1 — fine for a divider, short of AA for
   9.5px type. Same reasoning as `--ink-3` above: spend `--fg2` (7.3:1) on the
   text and leave `--fg3` for rules and dimmed marks. */
/* The plate behind the closing panel. It is the real brands table, left in
   its own light palette and dimmed to a watermark, turned away from the
   reader and faded out towards the copy. Not re-coloured for the dark ground:
   the product has no dark theme, and drawing one here would be advertising an
   interface that does not exist.

   `overflow: hidden` on the band is what lets it run off the right edge
   without widening the document — the same trap the hero's ground wash fell
   into once. */
.band--ink { overflow: hidden; }
.band--ink .shell { position: relative; z-index: 1; }
/* Deliberately taller and wider than the band. Both of its own edges are cut
   off by the band's `overflow: hidden`, so what shows is the INTERIOR of a
   surface that continues past the frame — a plate whose four corners are all
   visible reads as a sticker floating on the panel. */
.cta-plate {
  position: absolute;
  top: 50%;
  right: -70px;
  width: 860px;
  transform-origin: right center;
  transform: translateY(-50%) perspective(1600px) rotateY(-19deg) rotateX(6deg) rotate(-3deg) scale(1.45);
  opacity: 0.22;
  pointer-events: none;
  /* Gone before it reaches the copy: the headline runs to roughly the middle
     of the band and nothing should be competing with it there. */
  -webkit-mask-image: linear-gradient(to left, #000 24%, transparent 84%);
  mask-image: linear-gradient(to left, #000 24%, transparent 84%);
}
/* No room for it beside the copy, and a plate under the text is a smudge. */
@media (max-width: 1100px) { .cta-plate { display: none; } }

.band--ink .cap, .band--ink .num, .band--ink .stat-sub { color: var(--fg2); }
.band--ink .pill { background: transparent; border-color: var(--line); color: var(--fg2); box-shadow: none; }
.band--ink .pill b { color: var(--fg); }

/* Section head. Centred by default — both references centre everything above
   a full-width product block, and a left-aligned head over a centred frame
   reads as two layouts. */
.head { max-width: 760px; margin: 0 auto clamp(32px, 4vw, 56px); text-align: center; }
/* The section eyebrow is the same object as the hero badge, one size down:
   a chip, not a floating line of tracked-out mono. Both references open every
   section with one, and it is what gives a long page its punctuation. The
   text is unchanged, so the section rail still reads its label from here. */
.head .cap {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 25px;
  padding-inline: 11px;
  margin-bottom: var(--sp-4);
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--surface);
  box-shadow: var(--e1);
  letter-spacing: 0.1em;
}
.head .cap::before {
  content: '';
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--rule-strong);
  flex: 0 0 auto;
}
.band--surface .head .cap { background: var(--page); }
.band--ink .head .cap { background: transparent; border-color: var(--line); box-shadow: none; }
.band--ink .head .cap::before { background: var(--fg3); }
.head .lede { margin: var(--sp-4) auto 0; }
.head--left { margin-inline: 0; text-align: left; }
.head--left .lede { margin-inline: 0; }

/* The opened-out head: claim left at band width, qualification right behind a
   rule. `align-items: end` sits the paragraph on the headline's last line
   rather than floating it beside the eyebrow. */
.head--split {
  max-width: none;
  margin-inline: 0;
  text-align: left;
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: clamp(24px, 4vw, 64px);
  align-items: end;
}
.head--split .lede {
  margin: 0;
  max-width: 52ch;
  padding-left: clamp(20px, 2.6vw, 38px);
  border-left: 1px solid var(--rule);
}
@media (max-width: 860px) {
  .head--split { grid-template-columns: minmax(0, 1fr); align-items: start; }
  .head--split .lede { padding-left: 0; border-left: 0; }
}

/* --------------------------------------------------------------- skip link */

.skip {
  position: absolute; left: -9999px; top: 0; z-index: var(--z-modal);
  background: var(--surface); color: var(--ink-1);
  border: 1px solid var(--rule-strong); border-radius: var(--r);
  padding: var(--sp-2) var(--sp-3);
}
.skip:focus { left: var(--sp-3); top: var(--sp-3); }

/* -------------------------------------------------------------------- nav */

.topbar {
  position: sticky; top: 0; z-index: var(--z-nav);
  background: color-mix(in srgb, var(--page) 84%, transparent);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--rule);
}
.topbar-in { display: flex; align-items: center; gap: var(--sp-5); height: 62px; }

.wm {
  display: inline-flex; align-items: center; gap: 9px;
  font-family: var(--ff-display); font-weight: 700; font-size: 15.5px; letter-spacing: -0.035em;
  color: var(--ink-1); text-decoration: none; white-space: nowrap;
}
.wm-text { display: inline-block; }
/* The separator is a typographic mark, not text: `--ink-3` is its job. */
.wm i { font-style: normal; color: var(--ink-3); padding-inline: 1px; }
/* The tile already carries its own rounded ink ground, so it needs no radius
   and no background from here — only a size. */
.wm-mark { width: 26px; height: 26px; flex: 0 0 auto; }
.band--ink .wm { color: var(--fg); }
.band--ink .wm i { color: var(--fg3); }

.nav { display: flex; align-items: center; gap: var(--sp-1); margin-left: var(--sp-5); }
.nav a {
  display: inline-flex; align-items: center; height: 32px; padding-inline: var(--sp-3);
  border-radius: var(--r); color: var(--ink-2); text-decoration: none; font-size: var(--t-ui-sm-size);
  transition: background var(--mo-fast), color var(--mo-fast);
}
.nav a:hover { color: var(--ink-1); background: var(--raised); }
.nav a[aria-current='page'] { color: var(--accent); background: var(--accent-dim); }

.topbar-end { margin-left: auto; display: flex; align-items: center; gap: var(--sp-2); }

.lang { display: flex; border: 1px solid var(--rule); border-radius: var(--r); overflow: hidden; background: var(--surface); }
/* Button on a client-side route, anchor on a baked blog page — one document in
   three languages versus three documents at three URLs. Same control either
   way, so the rules take both, and the selectors below stay off the element
   name for the same reason. `--accent` on the active one is selection state,
   which is what D2 spends it on. */
.lang button, .lang a {
  border: 0; background: transparent; cursor: pointer; padding: 0 var(--sp-2); height: 28px;
  font-family: var(--ff-mono); font-size: var(--t-mono-label-size); letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--ink-2);
  text-decoration: none; display: inline-flex; align-items: center;
  transition: color var(--mo-fast), background var(--mo-fast);
}
.lang > * + * { border-left: 1px solid var(--rule); }
.lang button:hover, .lang a:hover { color: var(--ink-1); background: var(--raised); }
/* `aria-pressed` is invalid on an anchor; a link to the page you are on says
   `aria-current`. Both spell the same state, so both paint it. */
.lang [aria-pressed='true'], .lang [aria-current='true'] { color: var(--accent); background: var(--accent-dim); }

.navtoggle {
  display: none; align-items: center; height: 28px; padding-inline: var(--sp-2);
  background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r); cursor: pointer;
  font-family: var(--ff-mono); font-size: var(--t-mono-label-size); letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--ink-2);
}
.nav a.nav-cta { display: none; }

@media (max-width: 940px) {
  .navtoggle { display: inline-flex; }
  .nav {
    position: absolute; inset-inline: var(--shell-pad); top: 62px;
    flex-direction: column; align-items: stretch; gap: 0; margin: 0; padding: var(--sp-2);
    background: var(--surface); border: 1px solid var(--rule-strong); border-radius: var(--r); box-shadow: var(--e2);
  }
  .nav[hidden] { display: none; }
  .nav a { height: 38px; }
  .nav a.nav-cta { display: inline-flex; margin-top: var(--sp-2); border-top: 1px solid var(--rule); padding-top: var(--sp-3); border-radius: 0; }
  .nav a.nav-cta + a.nav-cta { margin-top: 0; border-top: 0; padding-top: 0; }
  .topbar-end .btn--ghost { display: none; }
}
@media (max-width: 560px) { .topbar-end .btn--primary { display: none; } }

/* ----------------------------------------------------------------- button */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  height: 36px; padding-inline: var(--sp-4);
  border: 1px solid transparent; border-radius: var(--r);
  font-size: var(--t-ui-sm-size); font-weight: 500; text-decoration: none; cursor: pointer; white-space: nowrap;
  transition: background var(--mo-fast), border-color var(--mo-fast), color var(--mo-fast), box-shadow var(--mo-fast),
    transform var(--mo-base);
}
/* One pixel. Enough for the button to answer the pointer, not enough to move
   anything around it. */
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: none; }
/* Achromatic primary. Colour stays on the data (D2), and it is what both
   references do. */
.btn--primary { background: var(--ink-1); color: var(--page); box-shadow: var(--e1); }
.btn--primary:hover { background: #23282E; }
.btn--ghost { background: var(--surface); border-color: var(--rule-strong); color: var(--ink-1); box-shadow: var(--e1); }
.btn--ghost:hover { background: var(--raised); }
.btn--lg { height: 44px; padding-inline: var(--sp-5); font-size: 14.5px; }
.band--ink .btn--primary { background: var(--fg); color: var(--ink-1); }
.band--ink .btn--primary:hover { background: #FFF; }
.band--ink .btn--ghost { background: transparent; border-color: var(--line); color: var(--fg); box-shadow: none; }
.band--ink .btn--ghost:hover { background: rgba(255,255,255,.06); }

.btn-row { display: flex; flex-wrap: wrap; gap: var(--sp-3); }
.btn-row--center { justify-content: center; }

.link { color: var(--ink-1); text-decoration: none; border-bottom: 1px solid var(--rule-strong); transition: border-color var(--mo-fast); }
.link:hover { border-bottom-color: var(--ink-1); }
.band--ink .link { color: var(--fg); border-bottom-color: var(--line); }
.band--ink .link:hover { border-bottom-color: var(--fg2); }

/* ------------------------------------------------------------------- hero */

.hero { padding-block: clamp(48px, 6.5vw, 92px) 0; text-align: center; position: relative; }
.hero-in { max-width: 900px; margin: 0 auto; }
.hero .pill { margin-bottom: clamp(20px, 2.6vw, 30px); }
.hero .lede { margin: clamp(18px, 2.2vw, 26px) auto 0; max-width: 62ch; }
.hero .btn-row { margin-top: clamp(24px, 3vw, 34px); }
/* Sentence case, not the mono cap. A reassurance line set in tracked-out
   uppercase reads as a warning label. */
.hero-note { margin-top: var(--sp-4); font-size: var(--t-ui-sm-size); color: var(--ink-2); }

/* The ground behind the product frame. A single very low-alpha wash of the
   own-brand hue, which is the one place a brand colour is allowed to touch
   the page: it sits under DATA, not under chrome. */
/* The stage carries its own head-room rather than taking it as margin,
   because the graph-paper band below is painted INTO that head-room — anchor
   it to a margin and it would sit on top of the frame instead of above it. */
.hero-stage { position: relative; margin-top: clamp(8px, 1.2vw, 16px); padding-top: clamp(44px, 5vw, 92px); }
/* `inset` stays 0 on the horizontal axis. A negative inline inset widened the
   document by 168px at 1440 — `overflow-x: hidden` on the body hides the
   scrollbar but the page is still that wide, which is the same bug either
   way. The spread does the work instead. */
.hero-stage::before {
  content: '';
  position: absolute;
  inset: 8% 0 -6%;
  background: radial-gradient(85% 70% at 50% 42%, color-mix(in srgb, var(--c1) 14%, transparent), transparent 72%);
  pointer-events: none;
}
/* Graph paper under the top edge of the frame, fading out before it reaches
   the chrome. It is what stops the band between the CTAs and the window from
   reading as an empty gap. */
.hero-stage::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: clamp(44px, 5vw, 92px);
  background-image: radial-gradient(var(--rule-strong) 1px, transparent 1px);
  background-size: 17px 17px;
  opacity: 0.6;
  -webkit-mask-image: linear-gradient(to bottom, #000 8%, transparent 96%);
  mask-image: linear-gradient(to bottom, #000 8%, transparent 96%);
  pointer-events: none;
}
/* The frame and its caption sit above the two grounds. */
.hero-stage > * { position: relative; z-index: 1; }

/* ------------------------------------------------------- the product frame */

.frame {
  position: relative;
  border: 1px solid var(--rule-strong);
  border-radius: 10px;
  background: var(--surface);
  box-shadow: var(--e3);
  overflow: hidden;
}
.frame-bar {
  display: flex; align-items: center; gap: var(--sp-3);
  height: 38px; padding-inline: var(--sp-3);
  border-bottom: 1px solid var(--rule);
  background: var(--raised);
}
.frame-dots { display: flex; gap: 6px; }
.frame-dots i { width: 9px; height: 9px; border-radius: 50%; background: var(--rule-strong); }
/* A block, not a flex row: `text-overflow` needs one. As a centred flex
   container it clipped BOTH ends on a phone, which turned the host into
   `op.bementioned.ai` — a URL bar that lies about the domain. */
.frame-url {
  flex: 1 1 auto; max-width: 420px; margin-inline: auto;
  height: 22px; line-height: 21px; padding-inline: 10px; text-align: center;
  border-radius: 999px; background: var(--surface); border: 1px solid var(--rule);
  font-family: var(--ff-mono); font-size: var(--t-mono-label-size); color: var(--ink-2);
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
/* Tall enough that switching workspace does not resize the frame under the
   reader's cursor — Flow is the tallest panel and Actions the shortest, and a
   200px jump between them reads as the page breaking. */
.frame-body { display: grid; grid-template-columns: 194px minmax(0, 1fr); min-height: 620px; }
@media (max-width: 820px) { .frame-body { min-height: 0; } }

/* left rail */
.pnav { border-right: 1px solid var(--rule); padding: var(--sp-3); background: var(--surface); }
.pnav-proj {
  display: flex; align-items: center; gap: 7px;
  padding: 6px 7px; border-radius: var(--r); border: 1px solid var(--rule);
  font-size: var(--t-ui-sm-size); font-weight: 500; margin-bottom: var(--sp-4);
}
.pnav-proj .mono-slot { margin-right: 0; }
.pnav-group { margin-top: var(--sp-4); }
.pnav-group:first-of-type { margin-top: 0; }
.pnav-group > .cap { display: block; padding-inline: 7px; margin-bottom: 6px; }
.pnav-item {
  display: flex; align-items: center; gap: 8px; width: 100%;
  height: 27px; padding-inline: 7px; border-radius: var(--r);
  font-size: var(--t-ui-sm-size); color: var(--ink-2);
  border: 0; background: transparent; text-align: left;
}
/* Only the three destinations with a working panel are buttons. The other
   four are drawn and inert, and they do not get a pointer — an affordance
   that does nothing is worse than no affordance. */
.pnav-item--live { cursor: pointer; }
.pnav-item--live:hover { background: var(--raised); color: var(--ink-1); }
.pnav-item.on { background: var(--accent-dim); color: var(--accent); font-weight: 500; }
.pnav-item.on:hover { background: var(--accent-dim); color: var(--accent); }
/* A dot, not an outlined square: at 13px a bordered square in a left rail
   reads as an unchecked checkbox, which is a control this rail does not have. */
.pnav-item .gl { width: 5px; height: 5px; border-radius: 50%; background: currentColor; opacity: .45; flex: 0 0 auto; margin-inline: 4px; }

/* main column */
.pmain { min-width: 0; display: flex; flex-direction: column; }

/* the `.ctx` flag row (ADR-0052 D4, amended): one line, a label, one flag per
   filter stating its SELECTION, freshness pinned right. */
.pctx {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: 7px var(--sp-4); border-bottom: 1px solid var(--rule);
  background: var(--surface); flex-wrap: wrap;
}
/* The context flags are a DEPICTION of state, not controls. In the product
   each one opens a searchable popup (ADR-0052 D4); inside this frame they do
   nothing, so they must not wear a control's outline. Filled chip, no border:
   reads as "this is the current selection", which is exactly what it is.
   This is the same rule that turned four of the seven rail entries back into
   plain text — an affordance that does nothing is worse than none. */
.pflag {
  display: inline-flex; align-items: center; gap: 6px;
  height: 24px; padding-inline: 9px;
  border: 0; border-radius: var(--r);
  font-size: var(--t-ui-sm-size); color: var(--ink-1); background: var(--raised);
}
.pflag .k { color: var(--ink-2); font-family: var(--ff-mono); font-size: var(--t-mono-label-size); letter-spacing: .08em; text-transform: uppercase; }
.pctx .stamp-r { margin-left: auto; }

/* view switcher */
/* `overflow-y: hidden` matters: with `auto` on both axes the tab's active
   underline (previously a border plus `margin-bottom: -1px`) made the strip
   1px taller than its own box and Chromium drew a vertical scrollbar inside
   the frame. The underline is an inset shadow now, so nothing overflows. */
.ptabs { display: flex; gap: 2px; padding: 0 var(--sp-4); border-bottom: 1px solid var(--rule); background: var(--surface); overflow-x: auto; overflow-y: hidden; }
.ptab {
  appearance: none; border: 0; background: transparent; cursor: pointer;
  padding: 10px 11px;
  font-size: var(--t-ui-sm-size); color: var(--ink-2); white-space: nowrap;
  transition: color var(--mo-fast), box-shadow var(--mo-fast);
}
.ptab:hover { color: var(--ink-1); }
.ptab[aria-selected='true'] { color: var(--accent); box-shadow: inset 0 -2px 0 var(--accent); font-weight: 500; }

.ppanel { padding: var(--sp-4); flex: 1 1 auto; background: var(--page); }
.ppanel > * + * { margin-top: var(--sp-4); }

/* stat strip inside the app */
.pstats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); border: 1px solid var(--rule); border-radius: var(--r); background: var(--surface); }
.pstat { padding: var(--sp-3) var(--sp-4); min-width: 0; }
.pstat + .pstat { border-left: 1px solid var(--rule); }
.pstat .cap { display: block; margin-bottom: 5px; }
.pstat b { font-family: var(--ff-display); font-size: 23px; font-weight: 600; letter-spacing: -0.03em; display: block; }
.pstat .delta { font-family: var(--ff-mono); font-size: var(--t-mono-num-size); }
.pstat .delta.up { color: var(--pos); }
.pstat .delta.down { color: var(--neg); }
@media (max-width: 860px) { .pstats { grid-template-columns: repeat(2, minmax(0, 1fr)); } .pstat:nth-child(2n+1) { border-left: 0; } .pstat:nth-child(n+3) { border-top: 1px solid var(--rule); } }

.pcard { border: 1px solid var(--rule); border-radius: var(--r); background: var(--surface); overflow: hidden; }
.pcard-head { display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-2) var(--sp-4); border-bottom: 1px solid var(--rule); }
.pcard-head .cap:last-child { margin-left: auto; }
.pcard-body { padding: var(--sp-4); }
.pcard-body--flush { padding: 0; }

/* the in-app brands table */
.ptable { width: 100%; border-collapse: collapse; }
.ptable th, .ptable td { text-align: left; padding: 9px var(--sp-4); font-size: var(--t-ui-sm-size); }
.ptable thead th {
  font-family: var(--ff-mono); font-size: var(--t-mono-label-size); font-weight: 400;
  letter-spacing: .12em; text-transform: uppercase; color: var(--ink-2);
  border-bottom: 1px solid var(--rule); padding-block: 7px;
}
.ptable tbody tr + tr { border-top: 1px solid var(--rule); }
.ptable tbody tr.own { background: var(--row-hover); }
.ptable .b-name { display: flex; align-items: center; white-space: nowrap; color: var(--ink-1); }
.ptable .b-name b { font-weight: 500; }
.ptable .n { font-family: var(--ff-mono); font-size: var(--t-mono-num-size); color: var(--ink-1); }
.ptable .fieldbar { display: flex; height: 8px; border-radius: 2px; overflow: hidden; background: var(--raised); min-width: 96px; }
.ptable .fieldbar i { display: block; height: 100%; }

/* ------------------------------------------------- entrance animation */

/* THE BOUNDARY, restated where it is implemented: an entrance may animate, a
   change of data state may not. Everything below runs once, when an element
   is first drawn. Nothing here animates from one dataset to another — that
   would draw a movement that never happened, which is what ADR-0052's "charts
   never animate" exists to prevent. */

/* `backwards`, never `both`. A forwards-filling animation keeps its last
   keyframe applied for good and beats every later declaration — including
   `:hover` — so the ribbon highlight would stop working the moment the
   entrance finished. `backwards` holds the FIRST frame during the delay and
   then hands the element back to normal CSS. */
.sankey .sk-rib { animation: rib-in 420ms cubic-bezier(.2, 0, 0, 1) backwards; animation-delay: calc(var(--i, 0) * 22ms); }
@keyframes rib-in { from { opacity: 0; } }

/* Bars grow from their own left edge. `scaleX` rather than `width` because
   the width is inline and per-segment; the transform needs to know nothing. */
.reveal.in .mini-bar,
.reveal.in .impact-bar,
.reveal.in .fr-bar,
.reveal.in .fieldbar {
  animation: bar-in 520ms cubic-bezier(.2, 0, 0, 1) backwards;
  transform-origin: left center;
}
@keyframes bar-in { from { transform: scaleX(0); } }

@media (prefers-reduced-motion: reduce) {
  .sankey .sk-rib { animation: none; opacity: 0.42; }
  .reveal.in .mini-bar,
  .reveal.in .impact-bar,
  .reveal.in .fr-bar,
  .reveal.in .fieldbar { animation: none; transform: none; }
}

/* ------------------------------------------------------ section rail */

/* A column of dots in the left margin, one per section, marking where the
   reader is and jumping there on click. Shown only where there is margin to
   put it in — below 1200px it would sit on top of the content. */
.srail {
  position: fixed;
  left: max(10px, calc((100vw - var(--shell)) / 2 - 34px));
  top: 50%;
  transform: translateY(-50%);
  z-index: var(--z-sticky);
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.srail-dot {
  position: relative;
  display: block;
  width: 22px;
  height: 22px;
  border: 0;
  background: transparent;
  cursor: pointer;
  padding: 0;
}
/* The dot itself is the pseudo-element, so the hit target stays 22px while
   the mark stays small. */
.srail-dot::before {
  content: '';
  position: absolute;
  left: 8px;
  top: 9px;
  width: 6px;
  height: 4px;
  border-radius: 2px;
  background: var(--rule-strong);
  transition: width var(--mo-base), background var(--mo-base);
}
.srail-dot:hover::before { background: var(--ink-2); }
.srail-dot[aria-current='true']::before { width: 14px; left: 4px; background: var(--ink-1); }

.srail-label {
  position: absolute;
  left: 26px;
  top: 50%;
  transform: translateY(-50%) translateX(-4px);
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  padding: 3px 8px;
  border-radius: var(--r);
  background: var(--ink-1);
  color: var(--page);
  font-family: var(--ff-mono);
  font-size: var(--t-mono-label-size);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  transition: opacity var(--mo-base), transform var(--mo-base);
}
/* One label at a time, and only for the dot under the pointer. Showing the
   whole set on rail hover put five ink pills across the content — at 1280px
   of shell in a 1440px viewport there is no margin wide enough to hold them
   beside it, so it has to behave like a tooltip, not like a legend. */
.srail-dot:hover .srail-label,
.srail-dot:focus-visible .srail-label {
  opacity: 1;
  transform: translateY(-50%) translateX(0);
  box-shadow: var(--e2);
}

@media (max-width: 1199px) { .srail { display: none; } }
@media (prefers-reduced-motion: reduce) {
  .srail-dot::before, .srail-label { transition: none; }
}

/* ------------------------------------------------------------- hovers */

/* The Sankey proved the pattern; the rest of the page answers to the cursor
   the same way — light the thing under the pointer, drop everything else. */

.card, .bento-card, .tier {
  transition: border-color var(--mo-base), box-shadow var(--mo-base), transform var(--mo-base);
}
.card:hover, .bento-card:hover { border-color: var(--rule-strong); box-shadow: var(--e1); }
/* The bento is the one grid where a card is an object rather than a row of a
   table, so it is the one that lifts. Two pixels, and only there. */
.bento-card:hover { transform: translateY(-2px); box-shadow: var(--e2); }
.tier:hover { border-color: var(--rule-strong); }
.tier--feature:hover { border-color: var(--ink-1); }

/* Heat grid: a crosshair. A row is reachable with `tr:hover`; a column needs
   `:has()` and the `data-col` the cells carry. The FILL is never touched —
   it encodes the value — only the surrounding cells dim. */
.mx tbody td, .mx tbody .mx-prompt { transition: opacity var(--mo-fast); }
.mx tbody:hover td, .mx tbody:hover .mx-prompt { opacity: 0.4; }
.mx tbody tr:hover td, .mx tbody tr:hover .mx-prompt { opacity: 1; }
.mx:has(td[data-col='0']:hover) td[data-col='0'],
.mx:has(td[data-col='1']:hover) td[data-col='1'],
.mx:has(td[data-col='2']:hover) td[data-col='2'],
.mx:has(td[data-col='3']:hover) td[data-col='3'],
.mx:has(td[data-col='4']:hover) td[data-col='4'] { opacity: 1; }
@media (hover: none) { .mx tbody:hover td, .mx tbody:hover .mx-prompt { opacity: 1; } }

/* Bump ladder: one brand's whole path — line, dots and label. */
.bump .bp-line, .bump .bp-dot, .bump .bp-label { transition: opacity var(--mo-base); }
.bump:hover .bp-line, .bump:hover .bp-dot, .bump:hover .bp-label { opacity: 0.22; }
.bump:has(.bp-line[data-brand='0']:hover) [data-brand='0'],
.bump:has(.bp-dot[data-brand='0']:hover) [data-brand='0'],
.bump:has(.bp-label[data-brand='0']:hover) [data-brand='0'],
.bump:has(.bp-line[data-brand='1']:hover) [data-brand='1'],
.bump:has(.bp-dot[data-brand='1']:hover) [data-brand='1'],
.bump:has(.bp-label[data-brand='1']:hover) [data-brand='1'],
.bump:has(.bp-line[data-brand='2']:hover) [data-brand='2'],
.bump:has(.bp-dot[data-brand='2']:hover) [data-brand='2'],
.bump:has(.bp-label[data-brand='2']:hover) [data-brand='2'],
.bump:has(.bp-line[data-brand='3']:hover) [data-brand='3'],
.bump:has(.bp-dot[data-brand='3']:hover) [data-brand='3'],
.bump:has(.bp-label[data-brand='3']:hover) [data-brand='3'],
.bump:has(.bp-line[data-brand='4']:hover) [data-brand='4'],
.bump:has(.bp-dot[data-brand='4']:hover) [data-brand='4'],
.bump:has(.bp-label[data-brand='4']:hover) [data-brand='4'] { opacity: 1; }
@media (hover: none) { .bump:hover .bp-line, .bump:hover .bp-dot, .bump:hover .bp-label { opacity: 1; } }

/* Prompt rows and the field-row table. */
.plist-row { transition: background var(--mo-fast); margin-inline: calc(-1 * var(--sp-3)); padding-inline: var(--sp-3); }
.plist-row:hover { background: var(--row-hover); }
.plist-row:hover .plist-cta { border-color: var(--ink-1); color: var(--ink-1); }
.plist-cta { transition: border-color var(--mo-fast), color var(--mo-fast); }

.fr tbody tr { transition: opacity var(--mo-fast); }
.fr tbody:hover tr { opacity: 0.5; }
.fr tbody tr:hover { opacity: 1; }
@media (hover: none) { .fr tbody:hover tr { opacity: 1; } }

.ptable tbody tr { transition: background var(--mo-fast); }
.ptable tbody tr:hover { background: var(--row-hover); }

/* Sankey hover. Pure CSS: pointing at a ribbon, a node or a label drops
   everything that is not on that path to 12%. No JS, no state to keep in
   sync, and it degrades to a plain readable figure if the pointer never
   arrives — a touch device gets the `<title>` tooltips instead.
   `has()` is what makes it possible; where it is unsupported the figure
   simply stays at rest, which is the correct fallback. */
.sankey .sk-rib { opacity: 0.42; transition: opacity var(--mo-base); }
.sankey .sk-node, .sankey .sk-label { transition: opacity var(--mo-base); }

.sankey:hover .sk-rib { opacity: 0.12; }
.sankey:hover .sk-node, .sankey:hover .sk-label { opacity: 0.35; }

.sankey .sk-rib:hover { opacity: 0.72; }
.sankey .sk-node:hover, .sankey .sk-label:hover { opacity: 1; }

/* One source: its ribbons, its node, its label, and every brand they reach. */
.sankey:has(.sk-label[data-src='0']:hover) .sk-rib[data-src='0'],
.sankey:has(.sk-node[data-src='0']:hover) .sk-rib[data-src='0'],
.sankey:has(.sk-label[data-src='1']:hover) .sk-rib[data-src='1'],
.sankey:has(.sk-node[data-src='1']:hover) .sk-rib[data-src='1'],
.sankey:has(.sk-label[data-src='2']:hover) .sk-rib[data-src='2'],
.sankey:has(.sk-node[data-src='2']:hover) .sk-rib[data-src='2'],
.sankey:has(.sk-label[data-src='3']:hover) .sk-rib[data-src='3'],
.sankey:has(.sk-node[data-src='3']:hover) .sk-rib[data-src='3'],
.sankey:has(.sk-label[data-src='4']:hover) .sk-rib[data-src='4'],
.sankey:has(.sk-node[data-src='4']:hover) .sk-rib[data-src='4'],
.sankey:has(.sk-label[data-src='5']:hover) .sk-rib[data-src='5'],
.sankey:has(.sk-node[data-src='5']:hover) .sk-rib[data-src='5'],
.sankey:has(.sk-label[data-src='6']:hover) .sk-rib[data-src='6'],
.sankey:has(.sk-node[data-src='6']:hover) .sk-rib[data-src='6'],
.sankey:has(.sk-label[data-src='7']:hover) .sk-rib[data-src='7'],
.sankey:has(.sk-node[data-src='7']:hover) .sk-rib[data-src='7'] { opacity: 0.72; }

/* One brand: every source that feeds it. */
.sankey:has(.sk-label[data-brand='0']:hover) .sk-rib[data-brand='0'],
.sankey:has(.sk-node[data-brand='0']:hover) .sk-rib[data-brand='0'],
.sankey:has(.sk-label[data-brand='1']:hover) .sk-rib[data-brand='1'],
.sankey:has(.sk-node[data-brand='1']:hover) .sk-rib[data-brand='1'],
.sankey:has(.sk-label[data-brand='2']:hover) .sk-rib[data-brand='2'],
.sankey:has(.sk-node[data-brand='2']:hover) .sk-rib[data-brand='2'],
.sankey:has(.sk-label[data-brand='3']:hover) .sk-rib[data-brand='3'],
.sankey:has(.sk-node[data-brand='3']:hover) .sk-rib[data-brand='3'],
.sankey:has(.sk-label[data-brand='4']:hover) .sk-rib[data-brand='4'],
.sankey:has(.sk-node[data-brand='4']:hover) .sk-rib[data-brand='4'] { opacity: 0.72; }

@media (hover: none) {
  .sankey:hover .sk-rib { opacity: 0.42; }
  .sankey:hover .sk-node, .sankey:hover .sk-label { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .sankey .sk-rib, .sankey .sk-node, .sankey .sk-label { transition: none; }
}

/* The source table gets the same treatment, one row at a time. */
.src-table tbody tr { transition: background var(--mo-fast); }
.src-table tbody:hover tr { opacity: 0.45; }
.src-table tbody tr:hover { opacity: 1; background: var(--row-hover); }
@media (hover: none) { .src-table tbody:hover tr { opacity: 1; } }

/* Sources ▸ Domains — "who gets named on each source". The dense table the
   product is actually for: a cited page, its citation count, and the brands
   it put into the answer. */
.src-wrap { overflow-x: auto; }
.src-table { min-width: 620px; }
.src-domain { font-family: var(--ff-mono); font-size: var(--t-mono-num-size); color: var(--ink-1); white-space: nowrap; }
.src-fav { display: inline-block; width: 11px; height: 11px; border-radius: 2px; background: var(--rule-strong); margin-right: 8px; vertical-align: -1px; }
.src-named { display: flex; flex-wrap: wrap; gap: 5px 7px; }
.src-brand {
  display: inline-flex; align-items: center; gap: 5px;
  border: 1px solid var(--rule); border-radius: var(--r);
  padding: 2px 7px 2px 3px; font-size: 11.5px; color: var(--ink-2); background: var(--surface);
}
.src-brand .mono-slot { width: 15px; height: 15px; font-size: 9px; margin-right: 0; }
.src-brand b { font-family: var(--ff-mono); font-size: var(--t-mono-label-size); color: var(--ink-1); font-weight: 400; }
.src-brand.own { border-color: var(--rule-strong); color: var(--ink-1); }
.src-brand.absent { background: var(--absent); border-color: transparent; color: var(--ink-2); padding-left: 7px; }
.src-brand.absent i { width: 6px; height: 6px; border-radius: 50%; background: var(--ink-3); opacity: .45; }

/* Actions ▸ Owned / Earned */
.act-where { font-family: var(--ff-mono); font-size: var(--t-mono-num-size); color: var(--ink-1); white-space: nowrap; }
.act-prompt { color: var(--ink-2); font-size: var(--t-ui-sm-size); }
.act-state {
  display: inline-flex; align-items: center; height: 22px; padding-inline: 9px;
  border-radius: 999px; font-family: var(--ff-mono); font-size: var(--t-mono-label-size);
  letter-spacing: .09em; text-transform: uppercase;
  box-shadow: inset 0 0 0 1px var(--rule-strong); color: var(--ink-2); white-space: nowrap;
}
.act-state--stDone { color: var(--pos); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--pos) 45%, transparent); }
.act-state--stTodo { color: var(--warn); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--warn) 45%, transparent); }

/* ------------------------------------- the answer, annotated four ways */

/* ONE ANSWER, FOUR LAYERS. The metric rail does not swap panels; it sets
   `data-layer` on this wrapper and the annotation over the same paragraph
   changes. Everything specific to a metric is a rule below keyed off that
   attribute — no JS decides what a layer looks like.

   The chat framing (the question as a bubble, the engine's avatar beside its
   answer) is the reference's, and it earns its place: it says in one glance
   that the thing being measured is a conversation, which no card header ever
   managed to. */
/* The whole surface fills the column the rail sets, so the four layers never
   resize the section as they turn over. */
.chat { display: flex; flex-direction: column; gap: var(--sp-3); height: 100%; }
.chat-ask { display: flex; justify-content: flex-end; }
.chat-bubble {
  max-width: 74%;
  padding: 9px var(--sp-4);
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--surface);
  box-shadow: var(--e1);
  font-size: var(--t-ui-sm-size);
  color: var(--ink-1);
}
.band--surface .chat-bubble { background: var(--page); }
.chat-turn { display: grid; grid-template-columns: 30px minmax(0, 1fr); gap: var(--sp-3); align-items: stretch; flex: 1 1 auto; }
.chat-av {
  display: inline-grid; place-items: center; width: 30px; height: 30px;
  align-self: start;
  border: 1px solid var(--rule); border-radius: 50%; background: var(--surface);
}
/* `visible`, against `.pcard`'s own `hidden`: the mention card opens above
   the paragraph and would be sliced off at the card's edge otherwise. */
.chat-card { overflow: visible; }
@media (max-width: 560px) {
  .chat-turn { grid-template-columns: minmax(0, 1fr); }
  .chat-av { display: none; }
}

.answer { font-size: var(--t-body); line-height: 1.9; color: var(--ink-1); max-width: 78ch; }
.answer .mention {
  position: relative;
  display: inline-flex; align-items: baseline; gap: 5px;
  border-radius: 3px; padding: 1px 5px; margin-inline: -1px;
  background: color-mix(in srgb, var(--h) 30%, var(--surface));
  box-shadow: inset 0 -2px 0 var(--h);
  white-space: nowrap;
  transition: background var(--mo-base), box-shadow var(--mo-base);
}
.answer .mention-rank,
.answer .mention-score {
  display: none;
  font-family: var(--ff-mono); font-size: var(--t-mono-label-size); color: var(--ink-2);
}

/* Layer 1 — Visibility. The plain marked answer, and the one that carries the
   strip saying the own brand is absent from it. Also the default, which is
   what the bento card renders. */

/* Layer 2 — Share of Voice: the five-brand footing, under the answer the
   mentions were counted in. */
.answer-shares { display: none; margin-top: var(--sp-4); padding-top: var(--sp-4); border-top: 1px solid var(--rule); }
.answer-shares > .cap { display: block; margin-bottom: var(--sp-3); }
.chat[data-layer='sov'] .answer-shares { display: block; }
/* Inside the explainer the footing keeps its box on every layer, because the
   rail turns the panel over by itself: a card that grew 43px every seven
   seconds would walk the rest of the page up and down under the reader.
   `visibility`, not `opacity` — an invisible block should not be read out
   either. Elsewhere (the bento card) the layer never changes, so the space is
   simply not reserved.

   The reservation is desktop-only, and so is the autoplay that makes it
   necessary (`startAuto` checks the same breakpoint). On a phone the layer
   changes only when the reader taps, a jump on their own tap is expected, and
   reserving the space there would just be a hole in the card. */
@media (min-width: 901px) {
  .mex .chat:not([data-layer='sov']) .answer-shares { display: block; visibility: hidden; }
}

/* Layer 3 — Position: the first-appearance ordinal, in front of the name. */
.chat[data-layer='position'] .mention-rank { display: inline; }
.chat[data-layer='position'] .mention { box-shadow: inset 0 -2px 0 var(--h), var(--e1); }

/* Layer 4 — Sentiment: the 0–100 the product writes per answer × brand, on
   the brand's own mention. NOT a green-and-red wash over clauses of the
   paragraph — that is the reference's version of this layer and it describes
   a measurement we do not take. */
.chat[data-layer='sentiment'] .mention-score { display: inline; color: var(--ink-1); }
.chat[data-layer='sentiment'] .mention-score::before {
  content: '';
  display: inline-block; width: 3px; height: 9px; margin-right: 4px;
  border-radius: 1px; background: var(--ink-3); vertical-align: -1px;
}
/* Three bands, and the number is printed next to the tick either way — the
   colour is a reading aid, never the fact. */
.mention-score[data-band='pos']::before { background: var(--pos); }
.mention-score[data-band='mid']::before { background: var(--warn); }
.mention-score[data-band='neg']::before { background: var(--neg); }

/* The card that opens over a mention: the brand's row of numbers, which is
   what the reference puts behind its own hover. Hover only, and therefore
   `aria-hidden` and never the only place a number lives — every figure in it
   is also on the page in the Share-of-Voice and Sentiment layers. */
.mpop {
  position: absolute;
  bottom: calc(100% + 9px);
  left: 50%;
  z-index: var(--z-overlay);
  display: grid;
  grid-auto-flow: column;
  gap: var(--sp-4);
  padding: 9px var(--sp-4);
  border-radius: var(--r);
  background: var(--ink-1);
  box-shadow: var(--e2);
  white-space: nowrap;
  opacity: 0;
  transform: translate(-50%, 3px);
  pointer-events: none;
  transition: opacity var(--mo-base), transform var(--mo-base);
}
.mpop-head { display: flex; align-items: center; gap: 7px; font-size: var(--t-ui-sm-size); color: #EDEFF2; }
.mpop-head i { width: 8px; height: 8px; border-radius: 2px; flex: 0 0 auto; }
.mpop-row { display: flex; flex-direction: column; gap: 2px; }
.mpop-row .cap { color: #9BA3AC; }
.mpop-row b { font-family: var(--ff-mono); font-size: var(--t-mono-num-size); font-weight: 400; color: #FFF; }
@media (hover: hover) {
  .answer .mention:hover { background: color-mix(in srgb, var(--h) 52%, var(--surface)); }
  .answer .mention:hover .mpop { opacity: 1; transform: translate(-50%, 0); }
}
@media (max-width: 640px) { .mpop { display: none; } }
@media (prefers-reduced-motion: reduce) { .mpop { transition: none; } }
.answer-meta { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-3); margin-bottom: var(--sp-3); }
.answer-miss {
  display: flex; align-items: flex-start; gap: 9px;
  margin-top: var(--sp-4); padding: var(--sp-3) var(--sp-4);
  background: var(--raised); border-left: 3px solid var(--warn); border-radius: 0 var(--r) var(--r) 0;
  font-size: var(--t-ui-sm-size); color: var(--ink-1);
}
.answer-miss b { font-weight: 500; }
.answer-src { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-3); }
.srcchip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 9px; border: 1px solid var(--rule); border-radius: var(--r);
  font-family: var(--ff-mono); font-size: var(--t-mono-num-size); color: var(--ink-2); background: var(--surface);
}
.srcchip .fav { width: 11px; height: 11px; border-radius: 2px; background: var(--rule-strong); flex: 0 0 auto; }

@media (max-width: 820px) {
  .frame-body { grid-template-columns: minmax(0, 1fr); }
  .pnav { display: none; }
  .frame-url { max-width: none; text-align: left; }
}

/* --------------------------------------------------------- before / after */

.vs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(16px, 2.4vw, 30px); align-items: stretch; }
@media (max-width: 800px) { .vs { grid-template-columns: minmax(0, 1fr); } }
.vs-col { display: flex; flex-direction: column; border: 1px solid var(--rule); border-radius: var(--r); background: var(--surface); overflow: hidden; }
.vs-col--muted { background: var(--raised); border-style: dashed; }
.vs-head { padding: var(--sp-4); border-bottom: 1px solid var(--rule); }
.vs-head .cap { display: block; margin-bottom: 6px; }
.vs-head h3 { color: var(--ink-1); }
.vs-col--muted .vs-head h3 { color: var(--ink-2); }
.vs-body { padding: var(--sp-4); flex: 1 1 auto; display: flex; flex-direction: column; gap: var(--sp-3); }
.vs-empty {
  border: 1px dashed var(--rule-strong); border-radius: var(--r);
  padding: var(--sp-5); text-align: center; color: var(--ink-2);
  font-family: var(--ff-mono); font-size: var(--t-mono-num-size); letter-spacing: .04em;
}
.vs-line { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--t-ui-sm-size); color: var(--ink-2); }
.vs-line .mk { font-family: var(--ff-mono); font-size: 11px; color: var(--ink-2); flex: 0 0 auto; }
.vs-line.on .mk { color: var(--pos); }
.vs-line.off { color: var(--ink-2); }

/* ------------------------------------------------------------------- grid */

.grid { display: grid; gap: clamp(16px, 2vw, 26px); }
.grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 980px) { .grid--3, .grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px) { .grid--2, .grid--3, .grid--4 { grid-template-columns: minmax(0, 1fr); } }

.card { border: 1px solid var(--rule); border-radius: var(--r); background: var(--surface); padding: clamp(18px, 2vw, 26px); }
.band--surface .card { background: var(--page); }
.band--ink .card { background: rgba(255,255,255,.03); border-color: var(--line); }
.card .h3, .card .h4 { margin-bottom: var(--sp-2); }
.card p { color: var(--ink-2); line-height: 1.6; font-size: var(--t-body); }
.card .cap { display: block; margin-bottom: var(--sp-3); }

/* Definition rows — the metric list. */
.defs { border-top: 1px solid var(--rule); }
.def { display: grid; grid-template-columns: minmax(160px, 240px) minmax(0, 1fr); gap: var(--sp-5); padding: var(--sp-5) 0; border-bottom: 1px solid var(--rule); }
.def dt { font-family: var(--ff-display); font-weight: 600; letter-spacing: -0.03em; font-size: clamp(17px, 1.6vw, 21px); display: flex; align-items: center; gap: 8px; }
.def dt .sw { width: 9px; height: 9px; border-radius: 2px; background: var(--h); flex: 0 0 auto; }
.def dd { color: var(--ink-2); line-height: 1.6; font-size: var(--t-body); max-width: 74ch; }
.def dd .formula { display: inline-block; margin-top: 7px; font-family: var(--ff-mono); font-size: var(--t-mono-num-size); color: var(--ink-2); }
@media (max-width: 640px) { .def { grid-template-columns: minmax(0, 1fr); gap: var(--sp-2); } }

/* --------------------------------------------------- metric explainer */

/* A rail of metrics on the left, the surface each one comes from on the
   right. The rail is buttons, not tabs-in-name-only: pressed state, keyboard
   focus, and a panel that swaps in place without re-rendering the page. */
/* `stretch`, not `start`. The four panels are 196–345px tall against a 481px
   rail, so aligning to the top left the short ones floating over a hole and
   resized the section every time the rail turned over. The panel column is
   the rail's height and its card fills it. */
.mex { display: grid; grid-template-columns: minmax(280px, 380px) minmax(0, 1fr); gap: clamp(16px, 2.4vw, 34px); align-items: stretch; }
@media (max-width: 900px) { .mex { grid-template-columns: minmax(0, 1fr); } }

/* The rail plays itself. Each metric holds the panel for `--dwell` and hands
   over to the next, and the left edge of the active card is a progress line
   that shows how long it has left — the reference's move, and the reason its
   explainer reads as a demo rather than as four buttons nobody presses.

   Three things stop it, all of them in `sections.js`: the pointer or focus
   entering the widget (pause, and the line freezes with it), the reader
   choosing a metric (stop for good — they are driving now), and the widget
   leaving the viewport. `prefers-reduced-motion` never starts it. */
.mex { --dwell: 7000ms; }

.mrail { display: flex; flex-direction: column; gap: var(--sp-2); }
.mrail-item {
  position: relative;
  overflow: hidden;
  appearance: none; text-align: left; cursor: pointer;
  border: 1px solid var(--rule); border-radius: var(--r);
  background: var(--surface); padding: var(--sp-4);
  transition: border-color var(--mo-fast), box-shadow var(--mo-fast), background var(--mo-fast);
}
.band--surface .mrail-item { background: var(--page); }
.mrail-item:hover { border-color: var(--rule-strong); }
/* The selected one is the only place `--accent` appears in this block: it is
   selection state, which is exactly what D2 reserves it for. */
.mrail-item[aria-selected='true'] { border-color: var(--accent); box-shadow: var(--e1); background: var(--surface); }

.mrail-prog { position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: transparent; }
.mrail-prog i { display: block; width: 100%; height: 100%; background: var(--accent); transform: scaleY(0); transform-origin: top center; }
.mrail-item[aria-selected='true'] .mrail-prog { background: var(--accent-dim); }
.mrail-item[aria-selected='true'] .mrail-prog i { animation: mprog var(--dwell) linear forwards; }
@keyframes mprog { from { transform: scaleY(0); } to { transform: scaleY(1); } }
/* Paused, not reset: the reader who stops to read keeps the place they were
   at. Hover on a touch device sticks, so it is the pointer query that gates
   this rather than `:hover` alone. */
@media (hover: hover) {
  .mex:hover .mrail-prog i { animation-play-state: paused; }
}
.mex:focus-within .mrail-prog i { animation-play-state: paused; }
/* Stopped: the line is simply the selection marker it always was. */
.mex--static { --dwell: 0s; }

@media (prefers-reduced-motion: reduce) {
  .mex { --dwell: 0s; }
}
.mrail-term { display: block; font-family: var(--ff-display); font-weight: 600; font-size: 17px; letter-spacing: -0.025em; }
.mrail-body { display: block; margin-top: 6px; color: var(--ink-2); font-size: var(--t-ui-sm-size); line-height: 1.55; }
.mrail-formula { display: none; margin-top: var(--sp-3); font-family: var(--ff-mono); font-size: var(--t-mono-num-size); color: var(--ink-2); }
.mrail-item[aria-selected='true'] .mrail-formula { display: block; }
.mex-panel { min-width: 0; display: flex; flex-direction: column; }
.mex-panel > * { flex: 1 1 auto; }

/* Compact brand rows, used by the explainer and by two bento cards. */
.mini-rows { display: flex; flex-direction: column; gap: 9px; }
.mini-row { display: grid; grid-template-columns: auto minmax(64px, 96px) minmax(0, 1fr) auto; align-items: center; gap: var(--sp-2); }
.mini-row .mono-slot { margin-right: 0; }
.mini-name { font-size: var(--t-ui-sm-size); color: var(--ink-1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mini-row.own .mini-name { font-weight: 500; }
.mini-bar { height: 9px; border-radius: 2px; background: var(--raised); overflow: hidden; }
.mini-bar i { display: block; height: 100%; }
.mini-val { font-family: var(--ff-mono); font-size: var(--t-mono-num-size); color: var(--ink-1); }

/* ---------------------------------------------------------- the bento */

.bento { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: clamp(14px, 1.6vw, 22px); }
.bento-card {
  --bento-pad: clamp(18px, 2vw, 28px);
  display: flex; flex-direction: column;
  border: 1px solid var(--rule); border-radius: var(--r);
  background: var(--surface); padding: var(--bento-pad); overflow: hidden;
}
.band--surface .bento-card { background: var(--page); }
.bento-card--wide { grid-column: span 4; }
.bento-card--narrow { grid-column: span 2; }
.bento-card--half { grid-column: span 3; }
.bento-card h3 { margin-bottom: var(--sp-2); }
.bento-card p { color: var(--ink-2); line-height: 1.55; font-size: var(--t-body); max-width: 58ch; }
@media (max-width: 1080px) {
  .bento { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .bento-card--wide, .bento-card--narrow, .bento-card--half { grid-column: span 1; }
}
@media (max-width: 700px) { .bento { grid-template-columns: minmax(0, 1fr); } }

/* The product fragment inside a bento card, as a RECESSED PANEL: it runs to
   the card's left, right and bottom edges on a raised ground behind a
   hairline, and it absorbs whatever height the tallest card in the row
   leaves over.
 *
 * That last part is the reason for it. With mixed card widths the row's
 * tallest card sets the height, and the shorter ones used to end with a
 * ragged band of white under the exhibit that read as a rendering fault.
 * Pushing the exhibit to the bottom instead just moved the hole above it.
 * A panel that grows has no hole either way, and the reference's bento gets
 * the same depth from cropping its illustrations at the card edge.
 *
 * The bottom fade is painted in the panel's OWN ground, so it is invisible
 * over empty space and only shows itself where content actually runs past
 * the edge — a phone, or a table wider than the card. */
.frag {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  margin: var(--sp-5) calc(-1 * var(--bento-pad)) calc(-1 * var(--bento-pad));
  padding: var(--sp-5) var(--bento-pad) var(--sp-6);
  border-top: 1px solid var(--rule);
  background: var(--raised);
  overflow: hidden;
}
/* Exactly as tall as the panel's own bottom padding, and no taller. Content
   that ends where it is supposed to sits clear of it; only content that has
   run past the padding — a table on a phone — is in the fade at all. A
   taller gradient dimmed the last row of lists that had no more rows, which
   reads as a rendering fault rather than as "there is more". */
.frag::after {
  content: '';
  position: absolute; left: 0; right: 0; bottom: 0; height: var(--sp-6);
  background: linear-gradient(to bottom, transparent, var(--raised));
  pointer-events: none;
}
.frag > .fr-wrap { margin-inline: calc(-1 * var(--bento-pad)); padding-inline: var(--bento-pad); }
.frag .fr { min-width: 560px; }
.frag .fr-spark, .frag .fr-leader { display: none; }
/* The bento exhibit is a thumbnail of a surface, not the surface. The mention
   card would be clipped by the panel it opens inside, and the layers that
   print its numbers are not on this card anyway. */
.frag .mpop { display: none; }

.eng-row { display: flex; align-items: center; gap: var(--sp-3); padding: 9px 0; border-top: 1px solid var(--rule); }
.eng-row:first-child { border-top: 0; }
.eng-mark { display: inline-grid; place-items: center; width: 26px; height: 26px; border: 1px solid var(--rule); border-radius: var(--r); flex: 0 0 auto; }
.eng-name { font-size: var(--t-ui-sm-size); color: var(--ink-1); }
.eng-row .cap { margin-left: auto; }
.eng-row .pflag { padding-inline: 7px; height: 22px; }

.impact { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-4); }
.impact-side .cap { display: block; margin-bottom: 4px; }
.impact-side b { display: block; font-family: var(--ff-display); font-size: 26px; font-weight: 600; letter-spacing: -0.04em; }
.impact-bar { display: block; height: 8px; margin-top: 7px; border-radius: 2px; background: var(--raised); overflow: hidden; }
.impact-bar i { display: block; height: 100%; background: var(--rule-strong); }
.impact-done { display: inline-flex; align-items: center; gap: 7px; margin-top: var(--sp-4); font-family: var(--ff-mono); font-size: var(--t-mono-label-size); letter-spacing: .08em; text-transform: uppercase; color: var(--ink-2); }
.impact-done i { width: 6px; height: 6px; border-radius: 50%; background: var(--pos); }

/* ------------------------------------------------------- prompt list */

/* THE PROMPT BAND. Three rows of tracked questions drifting past in
   alternating directions, masked at both edges — the reference's device, and
   the right one here: a prompt set is a long list nobody reads top to bottom,
   and showing it in motion says "there are many of these" in a way a
   four-item column cannot.

   The rows carry the same six prompts rotated by two, so each row is a
   different reading and no row is a copy of its neighbour. Each track holds
   the set twice and travels exactly one copy, which is what makes the loop
   seamless; the half-gap correction is because the two copies are separated
   by one more gap than sits inside a copy.

   Everything after the first copy of the first row is `aria-hidden`: a screen
   reader gets the six prompts once, not eighteen times. */
.mq {
  --mq-gap: 12px;
  display: flex;
  flex-direction: column;
  gap: var(--mq-gap);
  margin-inline: calc(-1 * var(--shell-pad));
  -webkit-mask-image: linear-gradient(to right, transparent, #000 11%, #000 89%, transparent);
  mask-image: linear-gradient(to right, transparent, #000 11%, #000 89%, transparent);
}
.mq-row { overflow: hidden; }
.mq-track {
  display: flex;
  gap: var(--mq-gap);
  width: max-content;
  animation: mq 68s linear infinite;
}
.mq-track--rev { animation-direction: reverse; }
@keyframes mq { to { transform: translateX(calc(-50% - var(--mq-gap) / 2)); } }
@media (hover: hover) {
  .mq:hover .mq-track { animation-play-state: paused; }
}

.mq-item {
  display: inline-flex; align-items: center; gap: 9px;
  height: 40px; padding: 0 var(--sp-3) 0 11px;
  border: 1px solid var(--rule); border-radius: 999px;
  background: var(--surface); white-space: nowrap;
  transition: border-color var(--mo-base), box-shadow var(--mo-base);
}
.band--surface .mq-item { background: var(--page); }
.mq-item:hover { border-color: var(--rule-strong); box-shadow: var(--e1); }
.mq-mark { display: inline-grid; place-items: center; width: 17px; height: 17px; flex: 0 0 auto; }
.mq-q { font-size: var(--t-ui-sm-size); color: var(--ink-1); }
.mq-cta {
  display: inline-flex; align-items: center; height: 24px; padding-inline: 10px;
  border-radius: 999px; background: var(--raised); color: var(--ink-2);
  font-family: var(--ff-mono); font-size: var(--t-mono-label-size);
  letter-spacing: 0.09em; text-transform: uppercase;
  transition: background var(--mo-fast), color var(--mo-fast);
}
.mq-item:hover .mq-cta { background: var(--ink-1); color: var(--page); }

@media (prefers-reduced-motion: reduce) {
  .mq-track { animation: none; }
}

/* ---------------------------------------------------- the engine strip */

/* The slot both references fill with a customer logo wall. We have no
   customers to name, and inventing some would be fraud (README, "no invented
   statistics"), so it carries the one roster that is a fact about the
   product: the four engines every tracked prompt runs against. */
.band--strip { padding-block: clamp(26px, 3vw, 40px); }
.strip-cap { text-align: center; margin-bottom: var(--sp-4); }
.strip .chans { justify-content: center; gap: var(--sp-3); }
.strip .chan { height: 38px; padding-inline: var(--sp-4); font-size: var(--t-ui-base-size); }
.strip .chan svg { width: 17px; height: 17px; }

.plist { border-top: 1px solid var(--rule); }
.plist-row {
  display: flex; align-items: center; gap: var(--sp-4);
  padding: var(--sp-4) 0; border-bottom: 1px solid var(--rule);
}
.plist-q { font-size: var(--t-lede); color: var(--ink-1); line-height: 1.4; }
.plist-cta {
  margin-left: auto; flex: 0 0 auto;
  display: inline-flex; align-items: center; height: 30px; padding-inline: var(--sp-3);
  border: 1px solid var(--rule-strong); border-radius: var(--r);
  background: var(--surface); color: var(--ink-2);
  font-size: var(--t-ui-sm-size); white-space: nowrap;
}
.band--surface .plist-cta { background: var(--page); }
@media (max-width: 620px) { .plist-row { flex-direction: column; align-items: flex-start; gap: var(--sp-3); } .plist-cta { margin-left: 0; } }

/* ------------------------------------------ figure with a floating panel */

/* The reference's integrations section: the product's own drawing carries the
   whole band and the copy sits on top of it in a card. It is the layout that
   says "this is what the export is OF" without a sentence saying so.
 *
 * The figure runs to the shell's edges — the same two hairlines every section
 * stands between — and the band reserves room on the right so the panel
 * overlaps the drawing's margin rather than its data. A figure with a third
 * of it under an opaque card is a figure nobody can read, which is the part
 * of the reference's version not worth copying. */
.over { --over-panel: 340px; position: relative; }
/* The figure's ground runs to the shell's edges, so the drawing stands
   between the same two hairlines every section does. */
.over-fig {
  margin-inline: calc(-1 * var(--shell-pad));
  padding: var(--sp-5) var(--shell-pad);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  background: var(--surface);
}
.band--surface .over-fig { background: var(--page); }
.over-fig .legend { margin-top: var(--sp-4); }
.over-panel {
  padding: var(--sp-5);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  background: var(--surface);
}
.over-item + .over-item { margin-top: var(--sp-4); padding-top: var(--sp-4); border-top: 1px solid var(--rule); }
.over-item h3 { margin-bottom: 5px; }
.over-item p { color: var(--ink-2); line-height: 1.5; font-size: var(--t-body); }

/* The panel floats over the figure's GROUND, never over its data: the card
   reserves exactly the panel's width plus its own bleed plus a gap, so the
   drawing stops where the panel starts. That arithmetic is in variables
   rather than in a magic number because it has to hold at every width the
   layout survives. A figure with a third of it under an opaque card is a
   figure nobody can read — which is the one part of the reference's version
   not worth copying. */
@media (min-width: 1101px) {
  .over-fig { padding-right: calc(var(--over-panel) + var(--shell-pad) + var(--sp-5)); }
  .over-panel {
    position: absolute;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
    width: var(--over-panel);
    box-shadow: var(--e2);
  }
  .band--surface .over-panel { background: var(--page); }
}
/* Below that the panel stops floating and simply follows the figure. */
@media (max-width: 1100px) {
  .over-panel { margin-top: var(--sp-5); }
  .over-item + .over-item { margin-top: var(--sp-3); padding-top: var(--sp-3); }
}

/* ------------------------------------------------------------ MCP band */

.split { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(24px, 4vw, 60px); align-items: center; }
@media (max-width: 860px) { .split { grid-template-columns: minmax(0, 1fr); } }

.tools { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px var(--sp-4); }
.tools li { display: flex; align-items: center; gap: 8px; font-family: var(--ff-mono); font-size: var(--t-mono-num-size); color: var(--ink-2); }
.tool-dot { width: 5px; height: 5px; border-radius: 50%; background: var(--c1); flex: 0 0 auto; }
@media (max-width: 480px) { .tools { grid-template-columns: minmax(0, 1fr); } }

/* ---------------------------------------------------------------- FAQ */

/* Native `<details>`: keyboard support, screen-reader semantics and a working
   open state before a single line of JS runs. */
.faq { border-top: 1px solid var(--rule); }
.faq-item { border-bottom: 1px solid var(--rule); }
.faq-item summary {
  display: flex; align-items: center; gap: var(--sp-4);
  padding: var(--sp-5) 0; cursor: pointer; list-style: none;
  font-family: var(--ff-display); font-weight: 600; font-size: clamp(15px, 1.5vw, 18px);
  letter-spacing: -0.025em; color: var(--ink-1);
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary:hover { color: var(--ink-2); }
.faq-mk { margin-left: auto; position: relative; width: 13px; height: 13px; flex: 0 0 auto; }
.faq-mk::before, .faq-mk::after {
  content: ''; position: absolute; background: var(--ink-3);
  transition: transform var(--mo-base), opacity var(--mo-base);
}
.faq-mk::before { left: 0; right: 0; top: 6px; height: 1px; }
.faq-mk::after { top: 0; bottom: 0; left: 6px; width: 1px; }
.faq-item[open] .faq-mk::after { transform: scaleY(0); opacity: 0; }
.faq-a { padding-bottom: var(--sp-5); }
.faq-a p { color: var(--ink-2); line-height: 1.65; font-size: var(--t-body); max-width: 78ch; }

/* ------------------------------------------------- the product tour */

/* A surface described beside the exact piece of UI it is about, alternating
   side down the page. The copy column keeps its own measure; the exhibit
   column is free to be as wide as the band allows. */
.srf { display: grid; grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr); gap: clamp(28px, 4vw, 64px); align-items: center; }
/* The exhibit keeps the WIDE track on both sides. Flipping with `order`
   alone moved the copy into column two and handed the UI the narrow one,
   which squeezed the heat grid below its own min-width and made it scroll. */
.srf--flip { grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); }
.srf--flip .srf-copy { order: 2; }
.srf-copy .cap { display: block; margin-bottom: var(--sp-3); }
.srf-copy .h2 { max-width: 14ch; }
.srf-copy .body { margin-top: var(--sp-4); }
.srf-exhibit { min-width: 0; }
.srf-exhibit > * + * { margin-top: var(--sp-4); }
@media (max-width: 900px) {
  .srf { grid-template-columns: minmax(0, 1fr); gap: var(--sp-5); }
  .srf--flip .srf-copy { order: 0; }
}

/* --------------------------------------------------------- not found */

.nf-links {
  display: flex; flex-wrap: wrap; justify-content: center; gap: var(--sp-3) var(--sp-5);
  margin-top: clamp(20px, 2.6vw, 30px);
  padding-top: var(--sp-4); border-top: 1px solid var(--rule);
}
.nf-link { font-size: var(--t-ui-sm-size); }

/* ---------------------------------------------------------- personas */

.who-role {
  display: inline-flex; align-items: center; height: 24px; padding-inline: 10px;
  border: 1px solid var(--rule-strong); border-radius: 999px;
  font-family: var(--ff-mono); font-size: var(--t-mono-label-size);
  letter-spacing: .1em; text-transform: uppercase; color: var(--ink-2);
  margin-bottom: var(--sp-3);
}

/* Steps */
.step .step-n {
  display: inline-grid; place-items: center; width: 26px; height: 26px; margin-bottom: var(--sp-3);
  border-radius: 50%; background: var(--ink-1); color: var(--page);
  font-family: var(--ff-mono); font-size: 11px;
}
.band--ink .step .step-n { background: var(--fg); color: var(--ink-1); }

/* ---------------------------------------------------------------- figures */

.fig { margin: 0; }
.fig svg { width: 100%; height: auto; }
.fig-cap {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-3);
  margin-top: var(--sp-3); font-family: var(--ff-mono); font-size: var(--t-mono-label-size);
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-2);
}
.fig-cap .sp { flex: 1 1 auto; }
.stamp {
  display: inline-flex; align-items: center; border: 1px solid var(--rule); border-radius: var(--r);
  padding: 2px 7px; font-family: var(--ff-mono); font-size: var(--t-mono-label-size);
  letter-spacing: 0.09em; text-transform: uppercase; color: var(--ink-2); background: var(--surface);
}
.band--ink .stamp { border-color: var(--line); color: var(--fg3); background: transparent; }

.legend { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4); }
.legend li { display: inline-flex; align-items: center; gap: 7px; font-size: var(--t-ui-sm-size); color: var(--ink-2); }
.legend .sw { width: 9px; height: 9px; border-radius: 2px; flex: 0 0 auto; }
.legend .own { box-shadow: 0 0 0 1px var(--own-outline); }
.legend b { color: var(--ink-1); font-weight: 500; }

.fig svg text.ax { font-family: var(--ff-mono); font-size: var(--t-mono-label-size); letter-spacing: 0.06em; fill: var(--ink-2); }
.fig svg text.lb { font-family: var(--ff-mono); font-size: var(--t-mono-num-size); fill: var(--ink-2); }

/* Heat grid */
.mx-wrap, .fr-wrap { overflow-x: auto; }
.mx { width: 100%; border-collapse: collapse; min-width: 520px; }
.mx th, .mx td { text-align: left; padding: 0; }
.mx thead th { padding-bottom: var(--sp-2); vertical-align: bottom; }
.mx-prompt { font-weight: 400; color: var(--ink-2); font-size: var(--t-ui-sm-size); padding-right: var(--sp-4) !important; width: 38%; min-width: 180px; }
.mx tbody .mx-prompt { padding-block: 3px !important; }
.mx-brand { display: inline-flex; align-items: center; gap: 6px; font-family: var(--ff-mono); font-size: var(--t-mono-label-size); letter-spacing: .09em; text-transform: uppercase; color: var(--ink-2); }
.mx-brand::before { content: ''; width: 8px; height: 8px; border-radius: 2px; background: var(--h); }
.mx-cell { font-family: var(--ff-mono); font-size: var(--t-mono-num-size); color: var(--ink-1); text-align: center !important; border: 2px solid var(--surface); padding: 9px 4px !important; border-radius: 2px; min-width: 54px; }
.ppanel .mx-cell { border-color: var(--surface); }
.mx-absent { background: var(--absent); }
.mx-absent i { color: var(--ink-2); font-style: normal; }

/* Field rows */
.fr { width: 100%; border-collapse: collapse; min-width: 660px; }
.fr th, .fr td { text-align: left; padding: var(--sp-3) var(--sp-4) var(--sp-3) 0; }
.fr thead th { padding-block: 0 var(--sp-2); border-bottom: 1px solid var(--rule); font-family: var(--ff-mono); font-size: var(--t-mono-label-size); font-weight: 400; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-2); }
.fr tbody tr { border-bottom: 1px solid var(--rule); }
.fr tbody tr:last-child { border-bottom: 0; }
.fr-prompt { color: var(--ink-1); width: 34%; min-width: 190px; font-size: var(--t-body); }
.fr-field { width: 26%; min-width: 170px; }
.fr-bar { display: flex; height: 10px; border-radius: 2px; overflow: hidden; background: var(--raised); margin-bottom: 6px; }
.fr-bar i { display: block; height: 100%; }
.fr-field b { font-family: var(--ff-mono); font-size: var(--t-mono-num-size); font-weight: 400; color: var(--ink-1); }
.fr-field b.absent { color: var(--ink-2); background: var(--absent); border-radius: 2px; padding: 1px 5px; }
.fr-leader { white-space: nowrap; }
.fr-leader span { font-size: var(--t-ui-sm-size); color: var(--ink-2); vertical-align: middle; }
.fr-spark { width: 80px; }
.fr-engines { white-space: nowrap; }

.mono-slot {
  display: inline-grid; place-items: center; width: 17px; height: 17px; margin-right: 7px;
  border-radius: 3px; background: var(--h); color: var(--surface);
  font-family: var(--ff-display); font-size: 10px; font-weight: 600; vertical-align: middle; flex: 0 0 auto;
}
.pchip { display: inline-grid; place-items: center; width: 21px; height: 21px; border: 1px solid var(--rule); border-radius: var(--r); background: var(--surface); }
.pchip + .pchip { margin-left: 3px; }
.pchip.off { background: var(--raised); }
.pchip.off svg { opacity: .26; filter: grayscale(1); }

.chans { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.chan { display: inline-flex; align-items: center; gap: 7px; border: 1px solid var(--rule); border-radius: var(--r); padding: 6px 12px 6px 10px; font-size: var(--t-ui-sm-size); color: var(--ink-1); background: var(--surface); }
.chan svg { width: 15px; height: 15px; }
.band--ink .chan { border-color: var(--line); color: var(--fg); background: transparent; }

/* ---------------------------------------------------------------- pricing */

.tiers { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--sp-3); align-items: stretch; }
@media (max-width: 1040px) { .tiers { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px) { .tiers { grid-template-columns: minmax(0, 1fr); } }
.tier { display: flex; flex-direction: column; border: 1px solid var(--rule); border-radius: var(--r); background: var(--surface); padding: clamp(18px, 2vw, 26px); }
.band--surface .tier { background: var(--page); }
.tier--feature { border-color: var(--ink-1); box-shadow: var(--e2); }
.tier-name { font-family: var(--ff-display); font-weight: 600; font-size: 16px; letter-spacing: -0.025em; }
.tier-price { font-family: var(--ff-display); font-size: clamp(30px, 3vw, 38px); font-weight: 600; letter-spacing: -0.045em; line-height: 1; }
.tier-price small { font-family: var(--ff-ui); font-size: var(--t-ui-sm-size); font-weight: 400; color: var(--ink-2); letter-spacing: 0; margin-left: 6px; }
.tier-note { font-size: 11.5px; color: var(--ink-2); margin-top: 6px; min-height: 17px; }
.tier ul { margin-top: var(--sp-4); border-top: 1px solid var(--rule); }
.tier li { display: flex; gap: var(--sp-2); padding: 8px 0; border-bottom: 1px solid var(--rule); font-size: var(--t-ui-sm-size); color: var(--ink-2); }
.tier li:last-of-type { border-bottom: 0; }
.tier li .mk { flex: 0 0 auto; color: var(--ink-2); font-family: var(--ff-mono); font-size: 10px; padding-top: 3px; }
.tier li.on .mk { color: var(--pos); }
.tier li.off { color: var(--ink-2); }
.tier .btn { width: 100%; }
.tier .btn-slot { margin-top: auto; padding-top: var(--sp-5); }

.toggle { display: inline-flex; border: 1px solid var(--rule-strong); border-radius: var(--r); overflow: hidden; background: var(--surface); }
.toggle button { border: 0; background: transparent; cursor: pointer; height: 34px; padding-inline: var(--sp-5); font-size: var(--t-ui-sm-size); color: var(--ink-2); transition: color var(--mo-fast), background var(--mo-fast); }
.toggle button + button { border-left: 1px solid var(--rule); }
.toggle button[aria-pressed='true'] { color: var(--accent); background: var(--accent-dim); }

/* --------------------------------------------------------------------- qa */

.qa { border-top: 1px solid var(--rule); }
.qa > div { display: grid; grid-template-columns: minmax(220px, 340px) minmax(0, 1fr); gap: var(--sp-5); padding: var(--sp-5) 0; border-bottom: 1px solid var(--rule); }
.qa dt { font-family: var(--ff-display); font-weight: 600; font-size: clamp(15px, 1.5vw, 18px); letter-spacing: -0.025em; line-height: 1.25; }
.qa dd { color: var(--ink-2); line-height: 1.6; font-size: var(--t-body); max-width: 74ch; }
@media (max-width: 640px) { .qa > div { grid-template-columns: minmax(0, 1fr); gap: var(--sp-2); } }

/* ----------------------------------------------------------------- footer */

.foot { border-top: 1px solid var(--rule); background: var(--surface); padding-block: clamp(40px, 5vw, 62px); }
.foot-cols { display: grid; grid-template-columns: 1.6fr repeat(3, minmax(0, 1fr)); gap: var(--sp-6) var(--sp-5); }
@media (max-width: 800px) { .foot-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.foot h4 { margin-bottom: var(--sp-3); }
.foot ul li + li { margin-top: 8px; }
.foot a { color: var(--ink-2); text-decoration: none; font-size: var(--t-ui-sm-size); }
.foot a:hover { color: var(--ink-1); }
.foot-base { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3); margin-top: clamp(28px, 3.4vw, 44px); padding-top: var(--sp-4); border-top: 1px solid var(--rule); font-size: 11.5px; color: var(--ink-2); }
.foot-base .sp { flex: 1 1 auto; }

/* --------------------------------------------------------------- a11y bits */

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

/* ---------------------------------------------------------------- motion */

/* Scroll reveal. Opacity plus 14px of travel, staggered by the observer, and
   it is the ONLY movement on the site: figures never animate (ADR-0052's
   motion tokens exist for interaction state). Everything starts visible and
   the class is only added once JS confirms the observer exists, so a failed
   script leaves a readable page rather than a blank one. */
.reveal-on .reveal { opacity: 0; transform: translateY(14px); }
.reveal-on .reveal.in { opacity: 1; transform: none; transition: opacity 520ms cubic-bezier(.2,0,0,1), transform 520ms cubic-bezier(.2,0,0,1); }

/* THE HEADLINE ARRIVES A WORD AT A TIME. `motion.js` wraps each word of a
   hero or section headline in its own span and numbers it; the numbers become
   the delay. It is the one effect on the reference's page that is worth
   copying outright, because it makes the reader read the sentence instead of
   photographing it — and it costs no copy, no markup in the catalogs and no
   change to how the line wraps.
   Opacity only. A per-word transform would need `inline-block`, which changes
   how the line breaks and how `text-wrap: balance` measures it. */
.reveal-on .words .w { opacity: 0; }
.reveal-on .words.in .w {
  opacity: 1;
  animation: word-in 460ms cubic-bezier(.2, 0, 0, 1) backwards;
  animation-delay: calc(var(--w, 0) * 24ms);
}
@keyframes word-in { from { opacity: 0; } }

@media (prefers-reduced-motion: reduce) {
  :root { --mo-fast: 0ms; --mo-base: 0ms; }
  html { scroll-behavior: auto; }
  .reveal-on .reveal { opacity: 1; transform: none; }
  .reveal-on .reveal.in { transition: none; }
  .reveal-on .words .w { opacity: 1; }
  .reveal-on .words.in .w { animation: none; }
}

#view { animation: fade var(--mo-base) both; }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { #view { animation: none; } }
