/* ═══════════════════════════════════════════════════════════════════════════
   CONTINUUM HOME — the Ramp-framework system, built 2026-08-01.

   David's mandate: Ramp's theme, structure, coloring, menu and craft to a tee,
   shifted to Continuum's product and mission. Ramp's system, measured live:
   warm white ground, near-black ink, ONE accent, hairlines for all elevation,
   two-tone headlines (ink lead + gray completion in one sentence), dense
   product UI rendered inside marketing cards, a dot-grid blueprint canvas,
   live counters, and a dark footer the white page lifts away from.

   This file owns its tokens. It is loaded by index.html ONLY, so nothing here
   can reach the legal pages or the demo.

   Honesty constitution still binds inside the craft:
   - clinical mocks carry ONLY: Allergies, Medications, Immunizations,
     Conditions, Recent visits. Categories, never values.
   - every product render is an illustration and the page says so.
   - no invented adoption numbers. Every ticking counter on this page is a
     verifiable product fact, and the signature counters are ZEROS.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  /* GROUND — Ramp's measured neutrals, verbatim. */
  --paper:   #FFFFFF;   /* page */
  --putty:   #F7F6F3;   /* section fill, card fill, the warm gray that makes white read designed */
  --putty-2: #F1EFEA;   /* nested fill, hover step */
  --ink:     #0C0A08;   /* ALL primary text + CTA label text. Near-black, warm, never #000 */
  --ink-60:  rgba(12,10,8,0.60);  /* Ramp's entire secondary system: primary at 60% */
  --ink-40:  rgba(12,10,8,0.56);  /* captions, ticks. Was 0.40, Ramp's own value,
                                     which measures ~2.9:1 on white: a caption you
                                     cannot read is not a caption. 0.56 keeps the
                                     whisper and clears AA on both grounds. */
  --hair:    #D2CECB;   /* THE hairline. One border color, 1px, everywhere */
  --hair-soft: #E5E2DE;
  --footer-ink: #0E0E0C;

  /* ACCENT — one. Continuum's iris where Ramp holds chartreuse.
     Ink on iris measures 6.47:1; white on iris fails. Label is always ink. */
  --accent:       #9D7CFF;
  --accent-hover: #C4B0FF;
  --accent-down:  #6B4FCF;
  --accent-soft:  rgba(157,124,255,0.10);
  /* The living thread survives as Continuum's one brand flourish. */
  --thread: linear-gradient(105deg,#9D7CFF 0%,#4FA8FF 36%,#34E6E0 68%,#6FEFC0 100%);
  /* Red exists ONLY inside the status-quo collage. Nowhere else on the page. */
  --oldworld-red: #D64545;

  /* TYPE — Ramp's discipline on Continuum's editorial triad. */
  --f-display: 'Cormorant Garamond', Georgia, serif;
  --f-body: 'Plus Jakarta Sans', -apple-system, 'SF Pro Text', system-ui, sans-serif;
  --f-mono: 'JetBrains Mono', 'SF Mono', ui-monospace, monospace;

  /* RHYTHM */
  --sec: 128px;
  --container: 1240px;
  --gutter: 24px;
  --nav-h: 72px;

  /* RADIUS — Ramp: 16px cards, pill CTAs, tiny chips. */
  --r-card: 16px;
  --r-cell: 12px;
  --r-chip: 6px;
  --r-pill: 999px;

  /* MOTION */
  --dur-micro: 120ms;
  --dur-ui: 200ms;
  --dur-enter: 250ms;
  --dur-reveal: 400ms;   /* Ramp ships nothing slower outside its pinned act */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-reveal: cubic-bezier(0.19, 1, 0.22, 1);
  --ease-sym: cubic-bezier(0.45, 0.05, 0.55, 0.95);
  --rise: 20px;
}
@media (max-width: 767px) { :root { --sec: 72px; } }

/* ── RESET-ADJACENT ──────────────────────────────────────────────────────── */
* { box-sizing: border-box; margin: 0; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
body {
  background: var(--paper); color: var(--ink);
  font-family: var(--f-body); font-size: 16px; line-height: 1.6;
  letter-spacing: -0.011em;
  -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility;
  overflow-x: clip;
}
img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
::selection { background: rgba(157,124,255,0.25); }

.wrap { max-width: var(--container); margin-inline: auto; padding-inline: clamp(20px, 4vw, 48px); }
.skip-link {
  position: absolute; left: 16px; top: -60px; z-index: 400;
  background: var(--ink); color: var(--paper); padding: 10px 18px; border-radius: var(--r-chip);
  transition: top var(--dur-ui) var(--ease-out);
}
.skip-link:focus-visible { top: 12px; }

:where(a,button,input,[tabindex]):focus-visible {
  outline: 2px solid var(--accent-down); outline-offset: 2px; border-radius: var(--r-chip);
}
@media (forced-colors: active) {
  :where(a,button,input,[tabindex]):focus-visible { outline: 2px solid Highlight; }
}

/* ── TYPE SYSTEM — two-tone headlines are the entire hierarchy ───────────── */
.d1 { font-family: var(--f-display); font-weight: 560; font-size: clamp(2.9rem, 6.4vw, 5.5rem); line-height: 1.0; letter-spacing: -0.015em; }
.d2 { font-family: var(--f-display); font-weight: 560; font-size: clamp(2.1rem, 3.8vw, 3.4rem); line-height: 1.04; letter-spacing: -0.012em; }
.d3 { font-family: var(--f-display); font-weight: 560; font-size: clamp(1.5rem, 2.4vw, 2rem); line-height: 1.12; }
.t-hush { color: var(--ink-60); }   /* the gray completion clause. Same face, same size. */
.lede { font-size: clamp(1.02rem, 1.35vw, 1.19rem); line-height: 1.6; color: var(--ink-60); max-width: 56ch; }
.mono { font-family: var(--f-mono); font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; font-weight: 500; }
.eyebrow { display: inline-flex; align-items: center; gap: 10px; color: var(--ink-60); }
.eyebrow::before { content: ""; width: 22px; height: 1px; background: var(--accent); }

/* the honesty clause is a designed element: body size, ink, amber rule. */
.disclose {
  border-left: 2px solid rgba(201,142,78,0.55);
  padding-left: 12px; font-size: 13px; line-height: 1.55;
  color: var(--ink); max-width: 34ch;
}

/* ── BUTTONS — Ramp's pair: one accent fill, one quiet gray ─────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  border-radius: var(--r-pill); font-weight: 600; font-size: 15px;
  padding: 13px 26px; white-space: nowrap;
  transition: background-color var(--dur-micro) var(--ease-sym),
              color var(--dur-micro) var(--ease-sym),
              border-color var(--dur-micro) var(--ease-sym);
}
.btn--accent { background: var(--accent); color: var(--ink); }
.btn--accent:hover { background: var(--accent-hover); }
.btn--accent:active { background: var(--accent-down); color: var(--paper); }
.btn--quiet { background: var(--paper); color: var(--ink); border: 1px solid var(--hair); }
.btn--quiet:hover { background: var(--putty-2); }
.btn--ink { background: var(--ink); color: var(--paper); }
.btn--ink:hover { background: #262320; }
.textlink { font-weight: 600; font-size: 15px; color: var(--ink);
             display: inline-flex; align-items: center; min-height: 24px; }
.textlink .arr { display: inline-block; transition: transform var(--dur-ui) var(--ease-out); }
.textlink:hover .arr { transform: translateX(4px); }

/* the combined input+button conversion unit, Ramp's signature CTA object */
.convert {
  display: flex; align-items: center; gap: 8px;
  background: var(--paper); border: 1px solid var(--hair);
  border-radius: var(--r-pill); padding: 6px 6px 6px 20px;
  max-width: 460px; width: 100%;
  transition: border-color var(--dur-micro) var(--ease-sym), box-shadow var(--dur-micro) var(--ease-sym);
}
.convert:focus-within { border-color: var(--ink-40); box-shadow: 0 0 0 3px rgba(157,124,255,0.18); }
.convert input {
  flex: 1; min-width: 0; border: 0; background: none; font: inherit; font-size: 15px;
  color: var(--ink); outline: none;
}
.convert input::placeholder { color: var(--ink-40); }
.convert .btn { flex-shrink: 0; }
@media (max-width: 560px) {
  .hero__eyebrow { flex-direction: column; align-items: flex-start; gap: 8px; }
  .convert { flex-direction: column; align-items: stretch; padding: 8px; border-radius: 22px; gap: 8px; }
  .convert input { padding: 10px 14px; }
}

/* ── NAV ─────────────────────────────────────────────────────────────────── */
.nav {
  position: fixed; inset-inline: 0; top: 0; z-index: 300;
  background: rgba(255,255,255,0.94); backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--hair-soft);
  transition: transform var(--dur-ui) var(--ease-out);
}
.nav.is-tucked { transform: translateY(-100%); }
.nav__inner { display: flex; align-items: center; gap: 28px; height: var(--nav-h); }
.nav__brand { display: flex; align-items: center; gap: 10px; font-weight: 700; letter-spacing: -0.01em; font-size: 17px; }
.nav__brand img { width: 28px; height: 28px; }
.nav__links { display: flex; gap: 26px; margin-inline: auto; }
.nav__links a { font-size: 14.5px; font-weight: 500; color: var(--ink-60); transition: color var(--dur-enter) var(--ease-sym); }
.nav__links a:hover { color: var(--ink); }
.nav__actions { display: flex; align-items: center; gap: 10px; }
.nav__actions .btn { padding: 10px 20px; font-size: 14px; }
.nav__burger { display: none; width: 42px; height: 42px; border: 1px solid var(--hair); border-radius: 10px; position: relative; }
.nav__burger span, .nav__burger::before, .nav__burger::after {
  content: ""; position: absolute; left: 12px; right: 12px; height: 1.6px; background: var(--ink);
  transition: transform var(--dur-ui) var(--ease-out), opacity var(--dur-ui) linear;
}
.nav__burger::before { top: 15px; } .nav__burger span { top: 20px; } .nav__burger::after { top: 25px; }
.nav__burger[aria-expanded="true"]::before { transform: translateY(5px) rotate(45deg); }
.nav__burger[aria-expanded="true"] span { opacity: 0; }
.nav__burger[aria-expanded="true"]::after { transform: translateY(-5px) rotate(-45deg); }
@media (max-width: 900px) {
  /* The burger and its sheet only exist on the homepage. Every other page using
     this nav therefore had ZERO navigation on a phone: no links, no burger, just
     a CTA. A person reading the manifesto could not reach anything from it.
     Rather than duplicate a sheet onto five pages, the links become a single
     horizontally scrollable row: still reachable, still one tap, and it degrades
     to the same thing on the homepage where the burger also exists. */
  .nav__links {
    display: flex; gap: 16px; margin-inline: 0; min-width: 0; font-size: 13.5px;
    overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
    padding-block: 4px;
  }
  .nav__links::-webkit-scrollbar { display: none; }
  .nav__links a { white-space: nowrap; display: inline-flex; align-items: center; min-height: 32px; }
  .nav__actions .btn--quiet { display: none; }
  /* Where a sheet DOES exist, the burger replaces the scroll strip. */
  .nav__inner:has(.nav__burger) .nav__links { display: none; }
  .nav__burger { display: block; }
}
/* The nav collapse above is conditioned on a burger EXISTING, and only index.html
   has one. On the prose pages (manifesto, protocol, life-os) the links therefore
   stay as a scroll strip all the way down, and it degrades badly. Measured on
   production, strip visible width against its 369px content:
       320: 31px (8%)   390: 67px (18%)   480: 157px (43%)
       560: 232px (63%) 640: 301px (82%)  768: 369px (100%)
   At 320 and 390 what a person sees is one clipped word mid-letter, which reads
   as a broken page rather than as something scrollable.

   FIRST ATTEMPT WAS WRONG AND THE GATE CAUGHT IT: hiding the strip below 640
   left /manifesto, /protocol, /life-os and /compose with ZERO navigation at 390
   (verify-a11y "has navigation": 0 links, burger=false, on four pages). A clipped
   affordance is bad; no affordance is worse. The footer carrying links does not
   make the header accessible.

   So the strip stays and is made to READ as scrollable: a fade on the trailing
   edge, so the cut looks deliberate instead of broken, and the scroll is padded
   so the last item can reach the left edge. */
@media (max-width: 639px) {
  .nav__inner:not(:has(.nav__burger)) .nav__links {
    -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 28px), transparent);
    mask-image: linear-gradient(90deg, #000 calc(100% - 28px), transparent);
    padding-right: 28px;
    scroll-padding-inline: 12px;
  }
}

/* At 320 the brand plus the accent button plus the burger measured 326.9px
   inside a 280px content box, which was the other 6.9px of the page's
   horizontal scroll. Tighten the chrome rather than drop a control: every
   affordance stays reachable, it just stops being sized for a 390 phone. */
@media (max-width: 359px) {
  .nav__actions { gap: 8px; }
  .nav__actions .btn { padding: 9px 13px; font-size: 13px; }
  .nav__brand { font-size: 15px; gap: 7px; }
  .nav__brand img { width: 24px; height: 24px; }
  .nav__burger { width: 38px; height: 38px; }
}
.nav__sheet {
  position: fixed; inset: 0; z-index: 290; background: var(--paper);
  display: flex; flex-direction: column; gap: 6px; padding: calc(var(--nav-h) + 24px) 24px 24px;
  transform: translateY(-8px); opacity: 0; pointer-events: none;
  transition: opacity var(--dur-ui) var(--ease-out), transform var(--dur-ui) var(--ease-out);
}
.nav__sheet[data-open="true"] { transform: none; opacity: 1; pointer-events: auto; }
.nav__sheet a { font-size: 22px; font-family: var(--f-display); font-weight: 560; padding: 12px 4px; border-bottom: 1px solid var(--hair-soft); }
/* scroll progress: 1px thread at the nav's lower edge, scroll-driven, zero JS */
.nav__progress { position: absolute; left: 0; bottom: -1px; height: 2px; width: 100%; background: var(--accent); transform-origin: 0 50%; transform: scaleX(0); }
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .nav__progress { animation: navprog linear both; animation-timeline: scroll(root block); }
  }
}
@keyframes navprog { from { transform: scaleX(0) } to { transform: scaleX(1) } }

/* ── REVEAL PRIMITIVE ────────────────────────────────────────────────────────
   Hidden state exists ONLY under .u-motion, which only JS adds, so a JS-off
   or reduced-motion page is simply visible. 400ms, 20px, once. */
@media (prefers-reduced-motion: no-preference) {
  html.u-motion [data-r] {
    opacity: 0; transform: translate3d(0, var(--rise), 0);
    transition: opacity var(--dur-reveal) var(--ease-reveal), transform var(--dur-reveal) var(--ease-reveal);
    transition-delay: var(--d, 0ms);
  }
  html.u-motion [data-r].in { opacity: 1; transform: none; }
}

/* ── SECTION FURNITURE ───────────────────────────────────────────────────── */
.band { padding-block: var(--sec); position: relative; }
.band--putty { background: var(--putty); }
.band__head { max-width: 720px; margin-bottom: clamp(36px, 5vw, 64px); }
.band__head .lede { margin-top: 18px; }
.seam { height: 1px; background: var(--hair); border: 0; }

/* ── HERO ────────────────────────────────────────────────────────────────── */
.hero { padding-top: calc(var(--nav-h) + clamp(40px, 6.5vh, 80px)); position: relative; }
.hero__grid { display: grid; grid-template-columns: minmax(0, 1.12fr) minmax(0, 0.88fr); gap: clamp(32px, 4vw, 64px); align-items: center; }
.hero__right { display: flex; justify-content: center; }
@media (max-width: 999px) { .hero__grid { grid-template-columns: 1fr; } .hero__right { margin-top: 40px; padding-inline: 6px; } }
.hero__eyebrow {
  display: inline-flex; align-items: center; gap: 10px; flex-wrap: wrap;
  color: var(--ink-60); margin-bottom: 26px;
}
.hero__eyebrow .chip {
  font-family: var(--f-mono); font-size: 12px; letter-spacing: 0.04em;
  border: 1px solid var(--hair); border-radius: var(--r-pill); padding: 3px 10px;
  color: var(--ink); background: var(--paper); font-variant-numeric: tabular-nums;
}
.hero__tam { display: block; font-family: var(--f-display); font-size: clamp(1.1rem, 1.5vw, 1.3rem); font-weight: 560; color: var(--ink-40); margin-bottom: 14px; letter-spacing: -0.005em; }
.hero h1 span.t-hush { display: block; }
.hero .d1 { max-width: 15ch; }

/* ── THE THREE-LINE HERO ──────────────────────────────────────────────────────
   The headline is three AUTHORED lines now, not one line left to wrap, so each
   sets as its own block and the ragged edge is designed rather than accidental.

   `max-width: 15ch` above has to be lifted for them. That cap exists to break
   ONE long line into a pleasing measure; applied to lines that already break
   where they were written, it re-wraps a 28-character line inside a
   15-character block, and the headline reads "Every life will / have a file.
   The / only question is / when." The authored break and the cap were solving
   the same problem twice, in opposite directions.

   And it comes down in size. 5.5rem was tuned for one or two lines; at three it
   filled the viewport and pushed the lede, the form and the closer below the
   fold at 1440. Magnificent is a function of the line, not of the pixel count.

   ★ THIS LIVES IN break.css, NOT home.css. index.html loads break.css alone.
   I wrote all of this into home.css first and it changed nothing, because six
   other pages read that file and the homepage is not one of them. The browser
   said so: getComputedStyle reported display:inline and font-size:88px while
   the rule sat in the bundle, unmatched. Check which stylesheet the SURFACE
   loads before editing the one with the familiar name. */
/* SIZED FROM THE MEASUREMENT, NOT FROM TASTE. The longest of the three lines
   needs 1022px of width per 100px of font-size, so the ceiling at any viewport
   is column-width x 0.098. Measured columns and their maxima:
       1440 -> 608px col, 59.5px max      1024 -> 505px col, 49.0px max
        768 -> 707px col, 68.4px max       390 -> 350px col, 33.8px max
        320 -> 280px col, 27.1px max
   768 is roomier than 1024 because the grid has already collapsed to one column
   by then, which is why a single vw ramp cannot serve both and the breakpoint
   below is not decorative. Each value sits just under its own ceiling. */
.hero__h1 span.d1 {
  display: block;
  max-width: none;
  font-size: clamp(1.55rem, 8.3vw, 2.6rem);
}
@media (min-width: 901px) {
  .hero__h1 span.d1 { font-size: clamp(2.2rem, 4.02vw, 3.6rem); }
}
.hero__closer {
  margin-top: 22px; font-size: 15px; line-height: 1.5; max-width: 46ch;
  color: var(--ink); font-weight: 500;
}
@media (max-width: 560px) { .hero__closer { font-size: 14px; margin-top: 18px; } }
.hero__lede { margin-top: 22px; }
.hero__cta { margin-top: 30px; display: flex; flex-direction: column; gap: 12px; }
.hero__micro { font-size: 13px; color: var(--ink-60); }
.hero__film { display: inline-flex; align-items: center; gap: 10px; margin-top: 18px; font-weight: 600; font-size: 14.5px; }
.hero__film .play {
  width: 34px; height: 34px; border-radius: 50%; border: 1px solid var(--hair);
  display: grid; place-items: center; background: var(--paper);
  transition: border-color var(--dur-micro) var(--ease-sym), background-color var(--dur-micro) var(--ease-sym);
}
.hero__film:hover .play { background: var(--putty); border-color: var(--ink-40); }
.hero__film .dur { font-family: var(--f-mono); font-size: 12px; color: var(--ink-60); font-variant-numeric: tabular-nums; }
.hero__filmbar { height: 2px; background: var(--hair-soft); border-radius: 1px; overflow: hidden; width: 132px; }
.hero__filmbar i { display: block; height: 100%; width: 0; background: var(--accent); }

/* THE CANVAS — Ramp's blueprint desk: dot grid + floating product cards
   with registration corners, micro-caps process captions, dashed connectors. */
.canvas {
  position: relative; margin-top: clamp(40px, 6vw, 64px);
  min-height: 380px;
  background-image: radial-gradient(var(--hair) 1.1px, transparent 1.1px);
  background-size: 26px 26px;
  border-top: 1px solid var(--hair-soft);
  overflow: clip;
}
.canvas__fade { position: absolute; inset-inline: 0; height: 80px; pointer-events: none; z-index: 2; }
.canvas__fade--top { top: 0; background: linear-gradient(var(--paper), transparent); }
.canvas__fade--bot { bottom: 0; background: linear-gradient(transparent, var(--paper)); }
.canvas__caption { position: absolute; left: 50%; bottom: 14px; transform: translateX(-50%); z-index: 3; color: var(--ink-40); font-size: 11px; font-family: var(--f-mono); letter-spacing: 0.05em; white-space: nowrap; }

/* floating cards share one physical language */
.fcard {
  position: absolute; background: var(--paper);
  border: 1px solid var(--hair); border-radius: var(--r-cell);
  box-shadow: 0 1px 2px rgba(12,10,8,0.04), 0 12px 32px rgba(12,10,8,0.07);
  padding: 16px;
}
.fcard__tag { font-family: var(--f-mono); font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-40); margin-bottom: 10px; display: flex; align-items: center; gap: 6px; }
.fcard__tag .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }
/* registration corners: the design-tool selection marks */
.reg { position: absolute; width: 7px; height: 7px; border: 1.4px solid var(--accent); background: var(--paper); border-radius: 1px; }
.reg--tl { top: -4px; left: -4px; } .reg--tr { top: -4px; right: -4px; }
.reg--bl { bottom: -4px; left: -4px; } .reg--br { bottom: -4px; right: -4px; }

/* the .continue artifact: the hero object, a physical file plate */
.plate {
  position: relative; width: min(400px, 86vw);
  background: linear-gradient(175deg, #FDFCFA, #F4F2EE);
  border: 1px solid var(--hair); border-radius: 20px;
  box-shadow: 0 1px 2px rgba(12,10,8,0.05), 0 24px 64px rgba(12,10,8,0.10);
  padding: 30px 28px 24px;
}
.plate::before { /* top edge light: the single detail that makes a card physical */
  content: ""; position: absolute; inset: 0 0 auto; height: 1px; border-radius: 20px 20px 0 0;
  background: rgba(255,255,255,0.9);
}
.plate__mark { width: 44px; height: 44px; margin-bottom: 18px; }
.plate__name { font-family: var(--f-mono); font-size: 30px; font-weight: 500; letter-spacing: -0.03em; margin-bottom: 4px; }
.plate__sub { font-family: var(--f-mono); font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-40); margin-bottom: 20px; }
.plate dl { display: grid; grid-template-columns: 84px 1fr; row-gap: 9px; font-size: 13.5px; border-top: 1px solid var(--hair-soft); padding-top: 16px; }
.plate dt { font-family: var(--f-mono); font-size: 10.5px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-40); align-self: center; }
.plate dd { font-weight: 600; }
.plate__seal { margin-top: 18px; display: flex; align-items: center; gap: 8px; font-family: var(--f-mono); font-size: 11px; color: var(--ink-60); border-top: 1px solid var(--hair-soft); padding-top: 14px; }
.plate__seal .lock { width: 14px; height: 14px; }

/* in-card product miniatures */
.mini { font-size: 12.5px; }
.mini__row { display: flex; align-items: center; gap: 10px; padding: 8px 2px; border-top: 1px solid var(--hair-soft); }
.mini__row:first-child { border-top: 0; }
.mini__ava { width: 22px; height: 22px; border-radius: 50%; background: var(--putty-2); border: 1px solid var(--hair-soft); display: grid; place-items: center; font-family: var(--f-mono); font-size: 9px; font-weight: 600; color: var(--ink-60); flex-shrink: 0; }
.mini__grow { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.mini__t { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mini__s { font-size: 11px; color: var(--ink-40); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mini__row .chip, .trow .chip { flex-shrink: 0; }
.chip {
  display: inline-flex; align-items: center; gap: 5px;
  font-family: var(--f-mono); font-size: 10px; letter-spacing: 0.05em;
  border: 1px solid var(--hair); border-radius: var(--r-chip); padding: 2.5px 7px;
  color: var(--ink-60); background: var(--paper); white-space: nowrap;
}
.chip--on { border-color: rgba(157,124,255,0.45); color: var(--ink); background: var(--accent-soft); }
.chip--seal { border-color: var(--hair); color: var(--ink-60); background: var(--putty); }
.tgl { width: 26px; height: 16px; border-radius: 999px; background: var(--hair); position: relative; flex-shrink: 0; }
.tgl::after { content: ""; position: absolute; top: 2px; left: 2px; width: 12px; height: 12px; border-radius: 50%; background: var(--paper); box-shadow: 0 1px 2px rgba(12,10,8,0.2); }
.tgl--on { background: var(--accent); }
.tgl--on::after { left: auto; right: 2px; }

/* dashed connector strings between canvas cards */
.strings { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
.strings path { fill: none; stroke: var(--ink-40); stroke-width: 1.2; stroke-dasharray: 4 5; }

/* canvas float choreography: slow drift, transform only, desktop only */
@media (prefers-reduced-motion: no-preference) and (min-width: 1000px) {
  html.u-motion .fcard { animation: floaty 9s var(--ease-sym) infinite alternate; animation-delay: var(--fd, 0s); }
  @keyframes floaty { from { transform: translateY(0) } to { transform: translateY(-10px) } }
  html.u-motion .plate { animation: floaty 11s var(--ease-sym) infinite alternate; }
}

/* ── TICKER — the pinned proof bar. Continuum's numbers are ZEROS. ───────── */
.ticker {
  border-top: 1px solid var(--hair-soft); border-bottom: 1px solid var(--hair-soft);
  background: var(--paper); overflow: hidden;
}
.ticker__inner { display: flex; gap: 40px; align-items: center; padding: 13px 0; flex-wrap: wrap; justify-content: center; }
.tick { display: inline-flex; align-items: center; gap: 9px; }
.tick__label { font-family: var(--f-mono); font-size: 10.5px; letter-spacing: 0.13em; text-transform: uppercase; color: var(--ink-40); }
.tick__val {
  font-family: var(--f-mono); font-size: 12.5px; font-weight: 600; color: var(--ink);
  border: 1px solid var(--hair); border-radius: var(--r-chip); padding: 2px 8px;
  font-variant-numeric: tabular-nums; min-width: 3ch; text-align: center;
}
.tick__val.is-zero { color: var(--ink); border-color: var(--hair); }

/* ── CHAOS COLLAGE — the clipboard era, argued in artifacts ──────────────── */
.chaos { position: relative; min-height: 620px; margin-top: clamp(36px, 5vw, 56px); }
.chaos .fcard { box-shadow: 0 1px 2px rgba(12,10,8,0.05), 0 16px 40px rgba(12,10,8,0.09); }
.chaos .fcard--tilt1 { transform: rotate(-2.2deg); }
.chaos .fcard--tilt2 { transform: rotate(1.6deg); }
.chaos .fcard--tilt3 { transform: rotate(-1deg); }
.badge {
  position: absolute; top: -8px; right: -8px; min-width: 20px; height: 20px; padding: 0 6px;
  border-radius: 999px; background: #B3391F; color: #fff;
  font-size: 11px; font-weight: 700; display: grid; place-items: center;
  font-family: var(--f-mono);
}
.err { color: #B3391F; font-size: 11px; font-weight: 600; }
.field-bad { border: 1px solid var(--oldworld-red) !important; }
.doc-lines i { display: block; height: 6px; border-radius: 3px; background: var(--putty-2); margin: 6px 0; }
.doc-lines i:nth-child(2n) { width: 86%; } .doc-lines i:nth-child(3n) { width: 72%; }
/* the resolution beat: the chaos repeated at 12% opacity with ONE lit card */
.resolve { position: relative; }
.resolve .chaos { min-height: 480px; opacity: 1; }
.resolve .ghost { opacity: 0.13; filter: saturate(0.2); }
.resolve__one { position: relative; z-index: 2; }

/* ── BENTO — headline inside the card, ↗ chip, content bleeding the edge ─── */
.bento { display: grid; gap: 20px; grid-template-columns: repeat(2, 1fr); }
.bento--3 { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 900px) { .bento, .bento--3 { grid-template-columns: 1fr; } }
.cell--sm { min-height: 300px !important; }
.cell--sm .cell__media { margin-top: 18px; }
.cell {
  position: relative; background: var(--putty); border-radius: var(--r-card);
  border: 1px solid var(--hair-soft);
  padding: 28px 28px 0; overflow: clip;
  min-height: 420px;
  /* A grid item defaults to min-width:auto, so a wide descendant (the .trow
     "26px 1fr auto auto" tracks inside the product window) sizes the whole
     track to its content and pushes the card past the viewport. Measured on
     production at 320: the cell rendered 326.7px inside a 280px content box,
     which was 26.7px of the page's 27px horizontal scroll. overflow:clip hides
     the child but does not stop it sizing the track; only min-width:0 does. */
  min-width: 0;
  display: flex; flex-direction: column;
}
.cell__head { font-size: clamp(1.2rem, 1.7vw, 1.45rem); font-weight: 700; letter-spacing: -0.015em; line-height: 1.25; max-width: 24ch; margin-bottom: 6px; }
.cell__head .t-hush { font-weight: 700; }
.cell__sub { font-size: 13.5px; color: var(--ink-60); max-width: 40ch; margin-bottom: 20px; }
.cell__go {
  position: absolute; top: 20px; right: 20px; width: 34px; height: 34px;
  border-radius: 50%; background: var(--paper); border: 1px solid var(--hair);
  display: grid; place-items: center; font-size: 15px;
  transition: background-color var(--dur-micro) var(--ease-sym), transform var(--dur-ui) var(--ease-out);
}
.cell:hover .cell__go { background: var(--accent); transform: rotate(45deg); }
.cell__media { margin-top: auto; position: relative; }
/* the in-cell product window: mac chrome + real structure, cropped by the cell */
.window {
  background: var(--paper); border: 1px solid var(--hair);
  border-radius: 12px 12px 0 0; border-bottom: 0;
  box-shadow: 0 -1px 2px rgba(12,10,8,0.03), 0 -12px 40px rgba(12,10,8,0.05);
  overflow: hidden;
}
.window__bar { display: flex; align-items: center; gap: 6px; padding: 9px 12px; border-bottom: 1px solid var(--hair-soft); background: var(--putty); }
.window__bar .wdot { width: 9px; height: 9px; border-radius: 50%; background: var(--putty-2); border: 1px solid var(--hair-soft); }
.window__bar .wtitle { font-family: var(--f-mono); font-size: 10px; letter-spacing: 0.08em; color: var(--ink-60); margin-left: 8px; }
.window__body { padding: 14px; }
.wtabs { display: flex; gap: 4px; margin-bottom: 12px; }
.wtab { font-size: 11.5px; font-weight: 600; color: var(--ink-40); padding: 5px 10px; border-radius: var(--r-chip); }
.wtab--on { color: var(--ink); background: var(--putty); }
.wsearch { display: flex; align-items: center; gap: 8px; border: 1px solid var(--hair-soft); border-radius: 8px; padding: 7px 10px; font-size: 12px; color: var(--ink-40); margin-bottom: 10px; }

/* table rows dense enough to read real */
.trow { display: grid; grid-template-columns: 26px 1fr auto auto; gap: 10px; align-items: center; padding: 8px 2px; border-top: 1px solid var(--hair-soft); font-size: 12.5px; }
.trow:first-of-type { border-top: 0; }

/* ── ACCESS CARDS ────────────────────────────────────────────────────────── */
.acards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
@media (max-width: 900px) { .acards { grid-template-columns: 1fr; } }
.acard {
  background: var(--paper); border: 1px solid var(--hair); border-radius: var(--r-card);
  padding: 24px; position: relative; display: flex; flex-direction: column;
  transition: border-color var(--dur-ui) var(--ease-out), background-color var(--dur-ui) var(--ease-out);
}
.acard:hover { border-color: var(--ink-40); }
.acard__who { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.acard__who .mini__ava { width: 30px; height: 30px; font-size: 10px; }
.acard__role { font-weight: 700; font-size: 15px; }
.acard__view { font-family: var(--f-mono); font-size: 10.5px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-40); }
.acard ul { list-style: none; padding: 0; margin: 0 0 14px; }
.acard__meta { margin-top: auto; }
.acard li { display: flex; justify-content: space-between; align-items: center; padding: 7px 0; border-top: 1px solid var(--hair-soft); font-family: var(--f-mono); font-size: 12px; }
.acard li:first-child { border-top: 0; }
.acard li .ok { color: var(--ink-60); font-size: 11px; }
.acard li .no { color: var(--ink-40); font-size: 11px; text-decoration: line-through; }
.acard__meta { display: flex; gap: 8px; flex-wrap: wrap; }

/* ── DAY RAIL ────────────────────────────────────────────────────────────── */
.day { border-top: 1px solid var(--hair-soft); max-width: 900px; }
.day__row { display: grid; grid-template-columns: 96px 1fr auto; gap: 18px; align-items: center; padding: 22px 0; border-bottom: 1px solid var(--hair-soft); }
.day__t { font-family: var(--f-mono); font-size: 12px; color: var(--ink-60); font-variant-numeric: tabular-nums; }
.day__txt { font-size: clamp(1.05rem, 1.5vw, 1.25rem); font-weight: 560; font-family: var(--f-display); }
.day__chip { justify-self: end; }
@media (max-width: 640px) { .day__row { grid-template-columns: 72px 1fr; } .day__chip { display: none; } }

/* ── SYSTEMS CLOUD ───────────────────────────────────────────────────────── */
.cloud { display: grid; grid-template-columns: repeat(5, 1fr); gap: 12px; }
@media (max-width: 1100px) { .cloud { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 700px) { .cloud { grid-template-columns: repeat(2, 1fr); } }
.designedcard {
  grid-column: 1 / -1; background: var(--putty); border: 1px solid var(--hair-soft);
  border-radius: var(--r-cell); padding: 18px 20px;
}
.designedcard h4 { font-family: var(--f-mono); font-size: 10.5px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-60); font-weight: 500; margin-bottom: 10px; }
.designedcard p { font-family: var(--f-mono); font-size: 12.5px; line-height: 2; color: var(--ink-60); }
.designedcard p b { color: var(--ink); font-weight: 500; }
.sys {
  background: var(--paper); border: 1px solid var(--hair-soft); border-radius: var(--r-cell);
  padding: 14px 12px; display: flex; flex-direction: column; gap: 6px;
  transition: border-color var(--dur-ui) var(--ease-out);
}
.sys:hover { border-color: var(--hair); }
.sys__name { font-weight: 700; font-size: 13.5px; }
.sys__st { font-family: var(--f-mono); font-size: 9.5px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-40); }
.sys--live .sys__st { color: var(--accent-down); }
.sys--live { border-color: rgba(157,124,255,0.45); }

/* custody: panel + the real passphrase mock side by side (judge #7: the band's
   right half was 530px of nothing) */
.custody2 { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,0.8fr); gap: 32px; align-items: start; }
@media (max-width: 900px) { .custody2 { grid-template-columns: 1fr; } }
.passmock .window__body { padding: 20px; }
.passfield { display: flex; align-items: center; gap: 8px; border: 1px solid var(--hair); border-radius: 10px; padding: 12px 14px; margin: 10px 0 14px; }
.passfield i { width: 8px; height: 8px; border-radius: 50%; background: var(--ink-60); }
.band--snug { padding-block: calc(var(--sec) * 0.62); }

/* ── QUIET PANELS (custody, protocol) ────────────────────────────────────── */
.panel { background: var(--putty); border: 1px solid var(--hair-soft); border-radius: var(--r-card); padding: 28px 32px; max-width: 680px; }
.panel p + p { margin-top: 12px; }

/* ── PRICING ─────────────────────────────────────────────────────────────── */
.plans { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; align-items: start; }
@media (max-width: 900px) { .plans { grid-template-columns: 1fr; } }
.plan { background: var(--paper); border: 1px solid var(--hair); border-radius: var(--r-card); padding: 28px; }
.plan--lead { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.plan__name { font-weight: 700; font-size: 15px; margin-bottom: 6px; }
.plan__price { font-family: var(--f-display); font-size: 2.1rem; font-weight: 560; letter-spacing: -0.01em; }
.plan__price small { font-size: 0.95rem; color: var(--ink-60); font-family: var(--f-body); }
.plan__body { font-size: 13.5px; color: var(--ink-60); margin: 12px 0 20px; }
.plan .btn { width: 100%; }

/* ── ORIGIN / STAT CARD ──────────────────────────────────────────────────── */
.origin { display: grid; grid-template-columns: 1fr 300px; gap: 40px; align-items: center; }
@media (max-width: 900px) { .origin { grid-template-columns: 1fr; } }
.stat {
  background: var(--ink); color: var(--paper); border-radius: var(--r-card);
  padding: 32px 28px; position: relative; overflow: clip;
}
.stat__n { font-family: var(--f-body); font-size: 4.6rem; line-height: 1; font-weight: 700; letter-spacing: -0.03em; font-variant-numeric: lining-nums; }
.stat__cap { color: rgba(255,255,255,0.6); font-size: 13.5px; margin-top: 6px; max-width: 22ch; }
.stat::after { content: ""; position: absolute; inset-inline: 0; bottom: 0; height: 2px; background: var(--accent); }

/* ── CLOSE + FOOTER: the white sheet lifts off a dark base ───────────────── */
.close { text-align: center; padding-block: clamp(96px, 14vh, 176px); }
.close__bookend { font-family: var(--f-display); font-weight: 560; font-size: clamp(1.4rem, 2.4vw, 2rem); color: var(--ink-40); margin-bottom: 14px; }
.close .d2 { margin-bottom: 12px; }
.close .convert { margin-inline: auto; margin-top: 28px; }
.close__micro { margin-top: 14px; font-size: 13px; color: var(--ink-60); }
.sheetend { background: var(--paper); border-radius: 0 0 28px 28px; position: relative; z-index: 2; box-shadow: 0 18px 40px rgba(12,10,8,0.18); }
.footer { background: var(--footer-ink); color: rgba(255,255,255,0.62); margin-top: -28px; padding-top: calc(28px + 64px); padding-bottom: 40px; }
.footer a { transition: color var(--dur-micro) var(--ease-sym); }
.footer a:hover { color: #fff; }
.footer__grid { display: grid; grid-template-columns: 1.3fr repeat(3, 1fr); gap: 32px; margin-bottom: 48px; }
@media (max-width: 800px) { .footer__grid { grid-template-columns: 1fr 1fr; } }
.footer__col h3 { color: #fff; font-size: 12px; font-family: var(--f-mono); letter-spacing: 0.12em; text-transform: uppercase; font-weight: 500; margin-bottom: 14px; }
.footer__col a { display: block; font-size: 14px; padding: 5px 0; }
.footer__brand { display: flex; align-items: center; gap: 10px; color: #fff; font-weight: 700; margin-bottom: 12px; }
.footer__brand img { width: 26px; height: 26px; }
.footer__note { font-size: 13px; max-width: 34ch; line-height: 1.6; }
.footer__base { border-top: 1px solid rgba(255,255,255,0.12); padding-top: 22px; display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap; font-size: 12.5px; }
.footer__thread { height: 2px; background: var(--accent); opacity: 0.55; margin-bottom: 48px; }

/* ── COUNTER TICK ────────────────────────────────────────────────────────── */
.n-tick { font-variant-numeric: tabular-nums; }

/* ── FORM (real signup) ──────────────────────────────────────────────────── */
.f-err { color: #B3391F; font-size: 13px; margin-top: 8px; min-height: 1.2em; }
.f-done { max-width: 460px; margin-inline: auto; }
.f-done h3 { font-family: var(--f-display); font-size: 1.6rem; font-weight: 560; margin-bottom: 8px; }
.f-done p { color: var(--ink-60); font-size: 14.5px; }
.f-done .btn { margin-top: 18px; }

/* ── PRINT / SMALL SANITY ────────────────────────────────────────────────── */
@media (max-width: 430px) {
  .canvas { min-height: 480px; }
  .chaos { min-height: 560px; }
}

/* ── MOBILE CHOREOGRAPHY ─────────────────────────────────────────────────────
   Measured on ramp.com at 390: the hero collage collapses to ONE centered card
   over the dot grid, and nothing overflows. Density is re-choreographed, not
   amputated. Absolute stages become flow stages below 900px. */
@media (max-width: 900px) {
  .canvas { min-height: 0; padding: 40px 20px 56px; }
  .canvas .strings { display: none; }
  .canvas .fcard { position: static; width: 100% !important; max-width: 400px; margin: 14px auto 0; }
  .plate { position: relative !important; left: auto !important; top: auto !important; margin: 0 auto !important; width: min(400px, 100%); }
  .canvas__caption { position: static; transform: none; display: block; text-align: center; margin-top: 18px; white-space: normal; }

  .chaos { min-height: 0; }
  .chaos .strings { display: none; }
  .chaos .fcard { position: static; width: 100% !important; max-width: 420px; margin: 14px auto 0; }
  .chaos .fcard--tilt1 { transform: rotate(-1.2deg); }
  .chaos .fcard--tilt2 { transform: rotate(0.9deg); }
  .chaos .fcard--tilt3 { transform: rotate(-0.6deg); }
  .badge { top: 10px; right: 10px; }

  .cell { min-height: 0; }
  .origin { gap: 24px; }
  .day__row { padding: 18px 0; }
  .ticker__inner { gap: 18px 28px; }
}


/* ══ GROUND: OBSIDIAN ═════════════════════════════════════════════════════════
   Founder ruling, 2026-08-02: "all dark". The estate had been split seven pages
   light and five dark, so a person clicking Security from the homepage landed
   somewhere that looked like a different company. This closes that.

   The values below are NOT invented: they are the palette the already-dark
   surfaces (/demo, /intake, /security, /privacy, /terms) have been shipping from
   variables.css, so the whole estate now resolves to one ground rather than to
   two that merely both happen to be dark.

   ★ THE ONE TRAP, AND IT IS WHY THIS IS A REMAP AND NOT A FIND-AND-REPLACE:
   `--ink` does double duty in this file. It is the primary TEXT colour, and it
   is also the LABEL colour on the accent fill (.btn--accent). Flipping it alone
   turns every CTA into light violet text on a light violet pill. Text moves to
   light here; the fills that sit under a label are pinned to near-black further
   down, exactly as the /demo migration had to do.
   ═════════════════════════════════════════════════════════════════════════ */
:root {
  --paper:   #06070F;
  --putty:   #10131F;
  --putty-2: #161A2A;
  --ink:     #F3F1FF;
  --ink-60:  rgba(243,241,255,0.72);
  --ink-40:  rgba(243,241,255,0.58);
  --hair:      rgba(255,255,255,0.14);
  --hair-soft: rgba(255,255,255,0.08);
  --footer-ink: #04050B;          /* the footer still reads as a base, one step under the page */
  --accent-soft: rgba(157,124,255,0.14);
}

/* THE ACCENT FILLS. The hue is correct and the ink-safe token is not: these
   paint a solid violet behind a label, and #0C0A08 on #9D7CFF measures 6.47:1,
   which is the estate's own CTA contract. Pinned to the literal so the text
   token above can go light without dragging the labels with it. */
.btn--accent, .btn--primary { color: #0C0A08 !important; }
.btn--accent:active { color: #0C0A08 !important; }

/* Two surfaces painted their own light and never asked a token, so they stayed
   white while the text on them went light. verify-contrast caught both, at
   1.08:1, on every page that loads this file.

   The nav is an OPAQUE plate on purpose across this estate: a live
   backdrop-filter on a fixed element has measured as a full-page GPU whiteout on
   iOS, and no desktop or headless test reproduces it. So it takes a solid value,
   not a translucent one, and the blur comes off with it. */
.nav { background: #06070F; backdrop-filter: none; }

/* The card's top-edge highlight is the one detail that makes it read as a
   physical object. At 0.9 white on a dark ground it is a glare line, not an
   edge; at 0.16 it is the same gesture doing the same job. */
.plate::before { background: rgba(255,255,255,0.16); }

/* ── ACCENT: THE SPLIT ────────────────────────────────────────────────────────
   On paper one violet could be both a fill and a label. On obsidian it cannot.
   #9D7CFF as a FILL under near-black measures 6.47:1 and is the estate contract;
   #6B4FCF as TEXT on #06070F measures 3.49:1 and fails, which is what
   verify-contrast reported on /life-os.
   So: a lighter violet for text, the original hue for fills, and every element
   that paints an accent behind a label gets its label pinned near-black.
   Enumerated by grepping `background: var(--accent` rather than by reading,
   because doing it by eye on the /demo migration produced a list that was the
   right length and the wrong four rules. */
:root { --accent-text: #C4B0FF; }        /* 9.1:1 on #06070F */

.sys--live .sys__st { color: var(--accent-text); }

/* Labels sitting ON an accent fill. */
.btn--accent, .btn--primary,
.btn--accent:hover, .btn--accent:active,
.purp[aria-pressed="true"],
.tab--center .tab__ico,
.navitem__badge {
  color: #0C0A08 !important;
}

/* Semantic colours were chosen against paper and invert like everything else.
   Measured on obsidian: the error red #B3391F reads 3.37:1 and the success teal
   #177F6F reads 4.12:1, both under the floor, both on the homepage. */
:root { --danger-text: #FF8F7A; --ok-text: #6FEFC0; }
.f-err, [class*="err"] { color: var(--danger-text); }
.stat__cap { color: var(--ink-60); }

/* THE LAST FOUR, each found by asking the DOM for the element rather than
   grepping for a colour. */

/* 1. .stat was an INVERTED card: background:var(--ink), color:var(--paper). On
      paper that is a dark card on white. With the tokens flipped it became a
      WHITE card on obsidian, and its caption stayed light on light at 1:1.
      On an all-dark estate the inverse of the page is not a light slab, it is a
      raised surface. */
.stat { background: var(--putty-2); color: var(--ink); }
.stat__cap { color: var(--ink-60); }

/* 2. A label on the accent fill, missed because it lives on a prose page. */
.number-step__num { color: #0C0A08 !important; }

/* 3. accent-down as text, on two more classes than the first pass caught.
      3.49:1 on obsidian; --accent-text is 9.1:1. */
.losc__st, .sys__st { color: var(--accent-text); }

/* 4. The zero-state chip's success teal was picked against paper: #177F6F reads
      4.12:1 here. Mint is the estate's existing dark-ground positive. */
.chip.is-zero { color: #6FEFC0; }

/* THE PLATE. A literal light gradient, so no token reached it and
   verify-contrast could not see it either: that gate skips gradient-backed
   elements by design, because a gradient has no backgroundColor to walk up to.
   It rendered as a cream card carrying light text, effectively blank, and it is
   the product artifact in the hero. Only the screenshot showed it.
   Same gesture, obsidian: a raised surface lifted off the page, not a slab of
   paper on it. */
.plate {
  background: linear-gradient(175deg, #14162E, #0C0E1C);
  box-shadow: 0 1px 2px rgba(0,0,0,0.5), 0 24px 64px rgba(0,0,0,0.55);
}

/* ══ CINEMA ══════════════════════════════════════════════════════════════════
   Scroll-driven, native, and off the main thread. `animation-timeline: view()`
   ties an animation to an element's own passage through the viewport, so there
   is no scroll listener, no rAF loop, no layout read on every frame, and no
   jank on a mid-range phone. The nav progress bar on this page already uses the
   same mechanism, so the technique is established here rather than new.

   Everything below is transform and opacity ONLY, and every effect is wrapped
   in BOTH @supports and prefers-reduced-motion, so a browser without
   scroll-timelines and a person who asked for less motion both get the finished
   composition immediately. Motion is additive here; nothing depends on it to
   become visible. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {

    /* THE SCATTER HAS DEPTH. The collage argues that a life is strewn across
       systems that were never built for it, and it argued that as a flat
       picture. Three depth planes drift at different rates as the section
       passes, so the pile reads as physically distributed rather than printed.
       Ranges are small on purpose: this is parallax, not a carousel. */
    .chaos .fcard { animation: drift linear both; animation-timeline: view(); animation-range: cover 0% cover 100%; }
    .chaos .fcard[data-depth="1"] { --dz: 26px; }
    .chaos .fcard[data-depth="2"] { --dz: 14px; }
    .chaos .fcard[data-depth="3"] { --dz: 6px; }
    @keyframes drift {
      from { transform: translate3d(0, calc(var(--dz) * 1), 0); }
      to   { transform: translate3d(0, calc(var(--dz) * -1), 0); }
    }

    /* THE TANGLE DRAWS ITSELF. The dashed connectors between the scattered
       artifacts are the whole point of the picture: everything is joined to
       everything and none of it is joined to the person. They now draw as the
       section enters, so the web is watched being made instead of arriving
       already made. stroke-dashoffset animates on the compositor for SVG and
       affects no layout. */
    .chaos .strings path {
      stroke-dasharray: 1400; animation: drawline linear both;
      animation-timeline: view(); animation-range: cover 0% cover 55%;
    }
    @keyframes drawline { from { stroke-dashoffset: 1400 } to { stroke-dashoffset: 0 } }

    /* SECTIONS ARRIVE. A band lifts the last few pixels into place as it
       enters. 14px, once, on the way in only, so scrolling back up does not
       replay anything. */
    .band__head { animation: bandrise linear both; animation-timeline: view(); animation-range: entry 10% entry 70%; }
    @keyframes bandrise {
      from { opacity: 0.35; transform: translate3d(0, 14px, 0); }
      to   { opacity: 1; transform: none; }
    }
  }
}

/* ── THE LIVING THREAD ────────────────────────────────────────────────────────
   One unbroken line of light down the page, iris to mint, drawn as the page is
   scrolled. The brand's signature and the product's whole argument in one
   gesture: one file, one life, unbroken.

   Fixed and 1px wide, so it costs a single composited layer and never
   reflows. It scales on transform only, from a top origin, tied to the document
   scroll timeline - the same mechanism the nav progress bar already uses here.
   z-index sits below content; it is behind everything and touches nothing. */
.thread {
  position: fixed; left: 50%; top: 0; width: 1px; height: 100vh;
  transform: translateX(-50%);
  pointer-events: none; z-index: 0;
  opacity: 0.22;
}
.thread i {
  display: block; width: 100%; height: 100%;
  background-image: linear-gradient(180deg,
    rgba(157,124,255,0) 0%, rgba(157,124,255,.85) 12%,
    rgba(79,168,255,.85) 40%, rgba(52,230,224,.85) 68%,
    rgba(111,239,192,.55) 90%, rgba(111,239,192,0) 100%);
  transform-origin: 50% 0%;
  transform: scaleY(1);
}
/* Below 900 the column is narrow enough that a centre line crosses text, so it
   moves to the gutter rather than being switched off: the metaphor is the point
   and a phone should still get it. */
@media (max-width: 900px) { .thread { left: 14px; opacity: 0.16; } }

@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    /* It DRAWS. scaleY from nothing to full across the document's scroll, so
       the line is being written as the page is read. */
    .thread i { animation: threadgrow linear both; animation-timeline: scroll(root block); }
    @keyframes threadgrow { from { transform: scaleY(0) } to { transform: scaleY(1) } }
  }
}

/* ── HERO DEPTH ON EXIT ───────────────────────────────────────────────────────
   The hero used to leave the screen as a flat slide: everything in it moved at
   exactly the same rate, which is what a printed page does, not what a space
   does. Two layers now move at different rates as the hero exits, so scrolling
   away reads as travelling THROUGH the composition rather than past it.

   The near layer is the .continue plate, which is the object closest to the
   viewer and so moves most. The far layer is the headline, which is the
   backdrop and barely moves. The gap between them is the whole illusion, and
   it is deliberately small: 60px against 18px. Parallax that announces itself
   is a carousel.

   The transforms live on their own nested wrappers because .hero__right already
   carries the reveal primitive's transform and .plate carries the idle float.
   Three transforms on one element is one transform; nesting is what makes them
   compose.

   animation-range is `exit`, so nothing moves while the hero is being read. It
   begins only once the hero starts leaving. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .hero .par { animation: heroexit linear both; animation-timeline: view(); animation-range: exit 0% exit 100%; }
    .hero .par--near { --px: -60px; }
    .hero .par--far  { --px: -18px; }
    @keyframes heroexit {
      from { transform: translate3d(0, 0, 0); }
      to   { transform: translate3d(0, var(--px), 0); }
    }
  }
}

/* ── TACTILITY ────────────────────────────────────────────────────────────────
   Every control on this page changed COLOUR and nothing else. A premium control
   answers the hand: it depresses when pressed and lifts when reachable. These
   are the smallest motions on the site and they are the ones a person feels
   most often, because they happen on every single interaction rather than once
   per scroll.

   transform only, so nothing reflows. 90ms on press, which is under the
   threshold where a control starts to feel laggy rather than responsive.

   The LIFT is behind (hover: hover). A touch device has no hover, and applying
   a hover state there means the control stays lifted after a tap, which reads
   as stuck. The PRESS applies everywhere, because every device presses. */
.btn { transition: background-color var(--dur-micro) var(--ease-sym),
                   color var(--dur-micro) var(--ease-sym),
                   border-color var(--dur-micro) var(--ease-sym),
                   transform 90ms var(--ease-sym),
                   box-shadow 140ms var(--ease-sym); }
/* The press must outrank the lift. `.btn:active` and `.btn--accent:hover` have
   identical specificity, and the hover rule is written later, so a button being
   pressed WHILE hovered showed the lift and never the press: every mouse press
   on this site, which is all of them. Measured before this: translateY(-1px) on
   hover and translateY(-1px) on press, identical. The active state now names
   the variants so it wins on specificity rather than on source order, which a
   future edit could reverse without noticing. */
.btn:active,
.btn--accent:active, .btn--quiet:active, .btn--ink:active,
.btn--accent:hover:active, .btn--quiet:hover:active, .btn--ink:hover:active {
  transform: scale(0.972);
  box-shadow: none;
}

@media (hover: hover) {
  .btn--accent:hover { transform: translateY(-1px); box-shadow: 0 6px 20px rgba(157,124,255,.28); }
  .btn--quiet:hover,
  .btn--ink:hover { transform: translateY(-1px); }
  /* The arrow leads. A link that says "see all twenty-four" and points right
     should move right when it is about to be followed. */
  .textlink .arr, .textlink .arrow { display: inline-block; transition: transform 140ms var(--ease-sym); }
  .textlink:hover .arr, .textlink:hover .arrow { transform: translateX(3px); }
}

/* A focus ring that is as visible as the hover state, because a keyboard user
   gets no hover at all and was being given the quieter of the two signals. */
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

@media (prefers-reduced-motion: reduce) {
  .btn, .textlink .arr, .textlink .arrow { transition: background-color var(--dur-micro) linear, color var(--dur-micro) linear; }
  .btn:active, .btn--accent:hover, .btn--quiet:hover, .btn--ink:hover,
  .textlink:hover .arr, .textlink:hover .arrow { transform: none; }
}

/* ── THE BROWSER'S OWN HALF OF THE GROUND ────────────────────────────────────
   The estate flipped every token it owns and shipped "all dark". Six controls
   on /compose stayed PURE WHITE anyway — #pp, #dur, #gpin, #rtopic, #rtext,
   #rsource — measured rgb(255,255,255) on live production, because a rule that
   sets border, radius, padding and font but no `background` does not fall back
   to the page. It falls back to the USER AGENT, and the user agent paints a
   light form control until the document says otherwise.

   `color-scheme: dark` is that sentence. It is not a nicety: it is what makes
   the browser's own surfaces obsidian — the fields, the <select> popup a page
   cannot style at all, the scrollbars, the spinners, the caret, the autofill
   wash that would otherwise drop a pale yellow slab over a passphrase field.
   Every page also carries <meta name="color-scheme" content="dark"> so this is
   true in the frames BEFORE this stylesheet arrives, which is where the white
   flash lived.

   The explicit field rules below exist because the UA's dark defaults are grey,
   not Continuum's. They are element selectors on purpose: lowest specificity in
   the cascade, so any page that has already dressed its own fields keeps them,
   and any page that forgets can no longer ship white. */
:root { color-scheme: dark; }

input, select, textarea {
  background: var(--putty);
  color: var(--ink);
  border: 1px solid var(--hair);
  border-radius: var(--r-cell, 12px);
  font: inherit;
}
input::placeholder, textarea::placeholder { color: var(--ink-40); opacity: 1; }
input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px; border-color: var(--accent);
}
/* Chrome paints autofilled fields with its own light wash and ignores
   `background`. The inset shadow is the only property it honours, and without
   it a saved passphrase turns the field white again on the next visit — the
   same defect, arriving later and only for people who came back. */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--ink);
  -webkit-box-shadow: 0 0 0 1000px var(--putty) inset;
  caret-color: var(--ink);
}

/* ── TAP TARGETS, MEASURED AT 390 ────────────────────────────────────────────
   Measured on live production with a real viewport, not asserted: the menu
   button was 42x42 and the hero's "Play the story" was 36px tall. The house
   floor is 44, and `verify-app` was found filtering at 24 under a label reading
   "tap targets", which is why eleven undersized controls shipped green before.
   Two pixels is not a rounding error on the only navigation a phone has. */
.nav__burger { width: 44px; height: 44px; }
/* The film control is a row, not a box: growing the disc would change the hero's
   composition, so the row itself carries the height and the disc stays 34. */
.hero__film { min-height: 44px; }

/* ── .btn--ink, DEFUSED ──────────────────────────────────────────────────────
   "Ink" meant near-black on paper. On obsidian the same token is #F3F1FF, so
   this rule paints a WHITE pill — the identical inversion that turned `.stat`
   into a white slab and had to be undone. Its one use, the Seal button inside
   the homepage's intake mock, now correctly uses the accent it has in the real
   product. The rule is corrected rather than deleted so the next lane that
   reaches for it gets an elevated surface instead of a hole in the page. */
.btn--ink { background: var(--putty-2); color: var(--ink); border: 1px solid var(--hair); }
.btn--ink:hover { background: var(--surface-3, #161A2E); border-color: var(--ink-40); }
