/* ============================================================================
   CONTINUUM — homepage system
   Tokens come from variables.css (the locked v8 "Living Thread" palette).
   This file is the rebuilt page's layout, components and motion.

   Motion law, enforced here and in CI:
     - transform and opacity ONLY. Never width/height/top/left/margin/filter.
     - 250ms ceiling on interaction motion. Exactly ONE ~800ms spectacle per page.
     - prefers-reduced-motion renders the FINAL, FULLY VISIBLE state. Reduced motion
       must never be the reason content is invisible.
     - Content is visible by default. Animation is additive, armed by a pre-paint
       script that sets html.u-motion. If JS never runs, everything is simply visible.
     - No backdrop-filter on a fixed full-page element (measured iOS GPU whiteout).
     - No count-up number animation, ever. Numbers render at final value in one frame.
   ========================================================================= */

/* ── reset ─────────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  background: var(--bg-deepest);
  color: var(--text-primary);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.6;
  letter-spacing: var(--track-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  font-variant-numeric: tabular-nums;
  overflow-x: hidden;
}

img, svg, video { display: block; max-width: 100%; height: auto; }
button, input, textarea, select { font: inherit; color: inherit; }
a { color: inherit; text-decoration: none; }
h1, h2, h3, h4 { text-wrap: balance; font-weight: 400; }
p { text-wrap: pretty; }

:focus-visible {
  outline: 2px solid var(--aqua);
  outline-offset: 3px;
  border-radius: 3px;
}

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

.skip-link {
  position: absolute; left: 50%; top: 0; transform: translate(-50%, -110%);
  z-index: 200; background: var(--iris); color: #0A0B16; font-weight: 700;
  padding: 12px 20px; border-radius: 0 0 var(--radius) var(--radius);
  transition: transform 160ms var(--ease-out-quart);
}
.skip-link:focus { transform: translate(-50%, 0); }

/* The prose pages mark up literals — a storage key, a URL fragment, a script path —
   with `.mono` and `<code>`, and neither had a rule on the four pages that load THIS
   stylesheet: `.mono` is defined in typography.css and home.css, which these pages do
   not load, so the class was inert and `cnt.vault.v1` rendered in the body face inside
   a sentence telling you to go find that exact string in the Application tab. A literal
   you are asked to match by eye has to look like a literal. */
.legal .mono, .legal code { font-family: var(--font-mono); font-size: 0.94em; }

/* ── layout ────────────────────────────────────────────────────────────── */
.wrap { width: 100%; max-width: var(--container-max); margin-inline: auto; padding-inline: clamp(20px, 5vw, 72px); }
.wrap--narrow { max-width: var(--container-narrow); }
.wrap--prose { max-width: var(--container-prose); }

section { position: relative; }
.band { padding-block: clamp(80px, 12vh, 160px); }
.band--tight { padding-block: clamp(56px, 8vh, 104px); }

.eyebrow {
  font-family: var(--font-mono);
  font-size: var(--text-eyebrow);
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: var(--space-5);
}

.display {
  font-family: var(--font-display);
  font-weight: 500;
  line-height: 1.02;
  letter-spacing: var(--track-display);
}
.h2 { font-size: var(--text-h2); font-family: var(--font-display); font-weight: 500; line-height: 1.06; letter-spacing: var(--track-h2); }
.h3 { font-size: var(--text-h3); font-family: var(--font-display); font-weight: 500; line-height: 1.12; letter-spacing: var(--track-h3); }

.lede { font-size: clamp(17px, 2vw, 21px); color: var(--text-secondary); max-width: 58ch; }
.small { font-size: var(--text-sm); color: var(--text-secondary); }

.thread-text {
  background: var(--thread);
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
}

/* ── E: the living thread (the signature) ──────────────────────────────── */
/* One continuous line of light, iris to mint, that runs the length of the page.
   It is the product metaphor made visible: one file, one life, unbroken.
   Built as a masked gradient column, so it costs one composited layer and
   animates only its own transform. */
.thread-rail {
  position: fixed;
  left: 50%; top: 0;
  width: 1px; height: 100vh;
  transform: translateX(-50%);
  background: linear-gradient(180deg,
    transparent 0%,
    rgba(157,124,255,0.00) 6%,
    rgba(157,124,255,0.55) 22%,
    rgba(79,168,255,0.55) 45%,
    rgba(52,230,224,0.55) 68%,
    rgba(111,239,192,0.40) 86%,
    transparent 100%);
  opacity: 0.16;
  filter: blur(0.5px);
  pointer-events: none;
  z-index: -1;
}
@media (max-width: 900px) { .thread-rail { display: none; } }

/* ── nav ───────────────────────────────────────────────────────────────── */
.nav {
  position: fixed; inset-block-start: 0; inset-inline: 0; z-index: 100;
  /* An opaque plate, deliberately. A live backdrop-filter on a fixed element
     whited out an entire estate site on iOS, and no desktop or headless test
     reproduces it. Do not "restore the blur for mobile".

     AND IT HAS TO ACTUALLY BE OPAQUE. This said "opaque, deliberately" above a
     value of 0.92 for as long as it has existed: the comment recorded the
     intent and the number did not carry it out. At 8% transparency the page
     scrolls THROUGH the bar — "/.well-known/security.txt" was legible behind
     the nav links on /security at 1440. A comment is not a control; the value
     is the control. */
  background: #06070F;
  border-bottom: 1px solid var(--border);
  transform: translateY(0);
  transition: transform 220ms var(--ease-out-quart);
  will-change: transform;
}
.nav.is-hidden { transform: translateY(-100%); }
.nav__inner { display: flex; align-items: center; gap: var(--space-6); height: 68px; }
/* The brand is a LOCKUP, not a spacer. Both the lockup and the mark inside it are
   pinned to `flex: 0 0 auto` because the default `flex-shrink: 1` let the flex line
   take its overflow out of the logo: measured on /security, /privacy and /terms the
   384x384 knot rendered 10.30 x 34 at 320px (aspect 0.30, 70% horizontally crushed),
   15.23 x 34 at 375, 16.59 x 34 at 390, 17.52 x 34 at 414 and 29.31 x 34 at 560,
   reaching a correct 34 x 34 only at 768 and up. A squashed identity mark passes every
   "the image is present" assertion and is obvious in a screenshot.
   Locking only the IMG was rejected: that leaves squareness resting on the image's
   automatic minimum size, which is the exact thing `overflow: clip` on the links strip
   already defeated once. `min-width: 34px` was rejected too — 34 is not the universal
   declared size of this mark (28px and 24px and 42px versions exist in other layers), so
   a hardcoded floor would produce 34 wide x 24 tall the day one of those wins the
   cascade: the guard would become the distortion. Declaring neither `object-fit:
   contain` nor a constant, only "do not shrink", keeps the box square at whatever size
   the cascade declares. The 23px of squeeze this moves off the logo lands on the links
   strip, which is a real overflow-x scroller and keeps every link reachable. */
.nav__brand { display: flex; align-items: center; gap: 10px; margin-right: auto; flex: 0 0 auto; }
.nav__brand img { width: 34px; height: 34px; flex: 0 0 auto; }
.nav__wordmark { font-family: var(--font-body); font-weight: 700; font-size: 17px; letter-spacing: -0.02em; }
.nav__links { display: flex; align-items: center; gap: var(--space-6); }
.nav__link { font-size: 15px; color: var(--text-secondary); position: relative; padding-block: 6px; transition: color 180ms var(--ease-out-quart); }
.nav__link:hover { color: var(--text-primary); }
/* underline grows from the centre on hover, transform-only */
.nav__link::after {
  content: ''; position: absolute; left: 0; bottom: 0; width: 100%; height: 1px;
  background: var(--aqua); transform: scaleX(0); transform-origin: 50% 50%;
  transition: transform 200ms var(--ease-out-quart);
}
.nav__link:hover::after, .nav__link:focus-visible::after { transform: scaleX(1); }
.nav__actions { display: flex; align-items: center; gap: var(--space-4); }

.nav__burger {
  display: none; width: 44px; height: 44px; align-items: center; justify-content: center;
  background: none; border: 1px solid var(--border-strong); border-radius: var(--radius-sm); cursor: pointer;
}
.nav__burger span { display: block; width: 18px; height: 1.5px; background: var(--text-primary); position: relative; }
.nav__burger span::before, .nav__burger span::after {
  content: ''; position: absolute; left: 0; width: 18px; height: 1.5px; background: var(--text-primary);
  transition: transform 200ms var(--ease-out-quart);
}
.nav__burger span::before { transform: translateY(-6px); }
.nav__burger span::after  { transform: translateY(6px); }

.nav__sheet {
  position: fixed; inset: 0; z-index: 99;
  background: var(--bg-deepest);
  transform: translateX(100%);
  transition: transform 250ms var(--ease-out-quart);
  display: flex; flex-direction: column; justify-content: center; gap: var(--space-5);
  padding: var(--space-9) clamp(20px, 5vw, 48px);
}
.nav__sheet[data-open='true'] { transform: translateX(0); }
.nav__sheet a { font-family: var(--font-display); font-size: 34px; letter-spacing: var(--track-h3); }

@media (max-width: 900px) {
  .nav__links { display: none; }
  .nav__actions .btn--ghost { display: none; }
  .nav__burger { display: flex; }
  /* The label wrapped to two lines at 390 and pushed into the burger. Keep it on one
     line and let the sheet carry the longer wording. */
  .nav__actions .btn--primary { padding: 0 16px; font-size: 14px; white-space: nowrap; min-height: 44px; }
}
@media (max-width: 400px) {
  .nav__actions .btn--primary { padding: 0 13px; font-size: 13px; }
  .nav__brand .nav__wordmark { font-size: 15px; }
}

/* ── buttons ───────────────────────────────────────────────────────────── */
.btn {
  --btn-lift: 0px;
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  min-height: 48px; padding: 0 24px;
  border-radius: var(--radius-pill);
  font-weight: 600; font-size: 15px; letter-spacing: -0.01em;
  border: 1px solid transparent; cursor: pointer;
  transform: translateY(var(--btn-lift));
  transition: transform 180ms var(--ease-out-quart), opacity 180ms linear, background-color 180ms linear;
}
.btn--primary { background: var(--iris); color: #08060F; }
.btn--primary:hover { --btn-lift: -2px; background: var(--iris-bright); }
.btn--ghost { border-color: var(--border-strong); color: var(--text-primary); background: transparent; }
.btn--ghost:hover { --btn-lift: -2px; border-color: var(--border-gold-strong); }
.btn:active { --btn-lift: 0px; opacity: 0.9; }
.btn--lg { min-height: 56px; padding: 0 32px; font-size: 16px; }

.textlink {
  display: inline-flex; align-items: center; gap: 8px;
  color: var(--aqua); font-weight: 500; font-size: 15px;
  min-height: 44px;
}
.textlink .arrow { display: inline-block; transition: transform 200ms var(--ease-out-quart); }
.textlink:hover .arrow { transform: translateX(4px); }

/* ── hero ──────────────────────────────────────────────────────────────── */
.hero { padding-block: clamp(120px, 20vh, 200px) clamp(72px, 10vh, 128px); position: relative; overflow: hidden; }

/* Aurora: three oversized radial fields drifting on transform only.
   At the calm tier the drift stops; the field itself never disappears, because a
   weak phone should get a calmer page, never an uglier one. */
.aurora { position: absolute; inset: -25% -10%; z-index: -1; pointer-events: none; }
.aurora span {
  position: absolute; display: block; border-radius: 50%;
  filter: blur(90px); opacity: 0.30;
  will-change: transform;
}
.aurora span:nth-child(1) { width: 46vw; height: 46vw; left: 2%;  top: 4%;  background: var(--iris); }
.aurora span:nth-child(2) { width: 40vw; height: 40vw; right: 4%; top: 18%; background: var(--azure); opacity: 0.22; }
.aurora span:nth-child(3) { width: 34vw; height: 34vw; left: 34%; top: 42%; background: var(--aqua);  opacity: 0.16; }

.hero__grid { display: grid; grid-template-columns: 1fr; gap: clamp(48px, 7vw, 88px); align-items: center; }
@media (min-width: 1000px) { .hero__grid { grid-template-columns: 1.08fr 0.92fr; } }

.hero h1 {
  font-family: var(--font-display);
  font-size: var(--text-hero);
  font-weight: 500;
  line-height: 0.98;
  letter-spacing: var(--track-display);
  margin-bottom: var(--space-5);
}
.hero__tagline {
  font-size: clamp(19px, 2.4vw, 26px);
  font-weight: 600;
  letter-spacing: -0.02em;
  margin-bottom: var(--space-5);
}
.hero__lede { margin-bottom: var(--space-7); }
.hero__cta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4); margin-bottom: var(--space-4); }
.hero__micro { font-size: var(--text-sm); color: var(--text-secondary); margin-bottom: var(--space-7); }

/* ── the file object (the product, drawn) ──────────────────────────────── */
.filecard {
  position: relative;
  aspect-ratio: 4 / 5;
  width: min(100%, 440px);
  margin-inline: auto;
  border-radius: var(--radius-xl);
  background:
    linear-gradient(160deg, rgba(255,255,255,0.07), rgba(255,255,255,0.015)),
    var(--bg-card);
  border: 1px solid var(--border-strong);
  box-shadow: var(--shadow-deep);
  overflow: hidden;
  display: grid;
  place-items: center;
  /* the sheen is a single transform-driven pass, not an animated gradient */
  isolation: isolate;
}
.filecard::after {
  content: ''; position: absolute; inset: -40% -120%;
  background: linear-gradient(78deg, transparent 42%, rgba(255,255,255,0.10) 50%, transparent 58%);
  transform: translateX(-30%);
  transition: transform 900ms var(--ease-out-expo);
  pointer-events: none; z-index: 3;
}
.filecard:hover::after { transform: translateX(30%); }

.filecard__inner { display: grid; place-items: center; gap: var(--space-5); text-align: center; padding: var(--space-7); position: relative; z-index: 2; }
.filecard__mark { width: clamp(96px, 20vw, 150px); height: auto; }
.filecard__name { font-family: var(--font-mono); font-size: clamp(20px, 3.4vw, 30px); letter-spacing: -0.02em; }
.filecard__meta { font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-muted); }

/* Fragments converging into the file. This is the page's ONE spectacle.
   Scroll-driven where supported, one-shot on load otherwise, final state always. */
.filecard__frag {
  position: absolute; z-index: 1;
  width: 62px; height: 44px; border-radius: 8px;
  background: var(--bg-elevated);
  border: 1px solid var(--border-strong);
  opacity: 0.85;
}
.filecard__frag i { display: block; height: 3px; border-radius: 2px; background: var(--text-faded); margin: 8px 9px 0; }
.filecard__frag i:first-child { margin-top: 11px; width: 60%; background: var(--text-muted); }
.filecard__frag--1 { left: 6%;  top: 12%; }
.filecard__frag--2 { right: 8%; top: 20%; }
.filecard__frag--3 { left: 10%; bottom: 22%; }
.filecard__frag--4 { right: 6%; bottom: 14%; }

/* ── film player ───────────────────────────────────────────────────────── */
.film { display: flex; align-items: center; gap: var(--space-4); flex-wrap: wrap; }
.film__btn {
  display: inline-flex; align-items: center; gap: 12px;
  min-height: 52px; padding: 0 22px 0 14px;
  border-radius: var(--radius-pill);
  background: transparent; border: 1px solid var(--border-strong);
  cursor: pointer; color: var(--text-primary);
  transition: border-color 200ms linear, transform 180ms var(--ease-out-quart);
}
.film__btn:hover { border-color: var(--border-gold-strong); transform: translateY(-2px); }
.film__icon {
  width: 34px; height: 34px; border-radius: 50%;
  display: grid; place-items: center; flex: 0 0 34px;
  background: var(--thread);
  color: #07060E;
}
.film__icon svg { width: 14px; height: 14px; }
.film__label { font-size: 15px; font-weight: 600; }
.film__dur { font-family: var(--font-mono); font-size: 13px; color: var(--text-muted); }
.film__progress { flex: 1 1 160px; height: 2px; background: var(--border-strong); border-radius: 2px; overflow: hidden; min-width: 120px; }
.film__progress i { display: block; height: 100%; width: 100%; background: var(--thread); transform: scaleX(0); transform-origin: 0 50%; }

/* ── generic card ──────────────────────────────────────────────────────── */
.card {
  position: relative;
  padding: var(--space-6);
  border-radius: var(--radius-lg);
  background: var(--bg-card);
  border: 1px solid var(--border);
  transition: transform 200ms var(--ease-out-quart), border-color 200ms linear;
  overflow: hidden;
}
.card:hover { transform: translateY(-4px); border-color: var(--border-strong); }
/* spotlight border: a radial gradient masked to the ring, positioned by --mx/--my */
.card::before {
  content: ''; position: absolute; inset: 0; border-radius: inherit; padding: 1px;
  background: radial-gradient(180px circle at var(--mx, 50%) var(--my, 0%),
              rgba(157,124,255,0.55), transparent 70%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
  opacity: 0; transition: opacity 200ms linear; pointer-events: none;
}
.card:hover::before { opacity: 1; }
.card__label { font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--aqua); margin-bottom: var(--space-3); }
.card__body { color: var(--text-secondary); }

.grid { display: grid; gap: var(--space-5); }
@media (min-width: 760px)  { .grid--3 { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 620px)  { .grid--2 { grid-template-columns: repeat(2, 1fr); } }

/* ── problem stack ─────────────────────────────────────────────────────── */
.formstack { display: grid; gap: 10px; opacity: 0.55; }
.formrow {
  display: flex; align-items: center; gap: 14px;
  padding: 13px 16px; border-radius: var(--radius-sm);
  background: var(--bg-elevated); border: 1px solid var(--border);
  font-family: var(--font-mono); font-size: 13px; color: var(--text-muted);
}
.formrow span:last-child { margin-left: auto; width: 84px; height: 8px; border-radius: 4px; background: var(--text-faded); }

/* ── day timeline ──────────────────────────────────────────────────────── */
.day { display: grid; gap: var(--space-5); }
@media (min-width: 900px) { .day { grid-template-columns: repeat(3, 1fr); } }
.day__item { padding-top: var(--space-5); border-top: 1px solid var(--border-strong); }
.day__time { font-family: var(--font-mono); font-size: 13px; color: var(--aqua); letter-spacing: 0.06em; margin-bottom: var(--space-3); }
.day__text { color: var(--text-secondary); }

/* ── life OS grid ──────────────────────────────────────────────────────── */
.oslist { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
@media (min-width: 390px)  { .oslist { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 760px)  { .oslist { grid-template-columns: repeat(4, 1fr); } }
@media (min-width: 1200px) { .oslist { grid-template-columns: repeat(6, 1fr); } }
.oschip {
  display: flex; flex-direction: column; gap: 6px;
  padding: 14px; border-radius: var(--radius);
  background: var(--bg-elevated); border: 1px solid var(--border);
  transition: transform 200ms var(--ease-out-quart), border-color 200ms linear;
}
.oschip:hover { transform: translateY(-3px); border-color: var(--border-strong); }
.oschip__dot { width: 7px; height: 7px; border-radius: 50%; background: var(--dot, var(--iris)); }
.oschip__name { font-size: 14px; font-weight: 600; }
.oschip__tag { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-muted); }

/* ── pricing ───────────────────────────────────────────────────────────── */
.plans { display: grid; gap: var(--space-5); }
@media (min-width: 900px) { .plans { grid-template-columns: repeat(3, 1fr); } }
.plan { display: flex; flex-direction: column; gap: var(--space-4); padding: var(--space-7) var(--space-6); border-radius: var(--radius-lg); background: var(--bg-card); border: 1px solid var(--border); }
.plan__name { font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-muted); }
.plan__price { font-family: var(--font-display); font-size: clamp(34px, 5vw, 48px); line-height: 1; letter-spacing: -0.03em; }
.plan__price small { font-family: var(--font-body); font-size: 15px; letter-spacing: 0; color: var(--text-muted); }
.plan__line { color: var(--text-secondary); flex: 1; }
.plan .btn { width: 100%; }

/* ── signup ────────────────────────────────────────────────────────────── */
.signup { display: grid; gap: var(--space-4); max-width: 460px; }
.field { display: grid; gap: 7px; }
.field label { font-size: 14px; font-weight: 600; }
.field input {
  min-height: 52px; padding: 0 16px;
  background: var(--bg-elevated);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  color: var(--text-primary);
  transition: border-color 180ms linear;
}
.field input:focus { border-color: var(--iris); outline: none; }
.field input[aria-invalid='true'] { border-color: #FF8A8A; }
.field__err { font-size: 13px; color: #FF9E9E; min-height: 0; }
.formnote { font-size: var(--text-sm); color: var(--text-muted); }

/* ── credibility strip ─────────────────────────────────────────────────── */
.origin { max-width: 60ch; margin-inline: auto; text-align: center; color: var(--text-secondary); font-size: 16px; }

/* ── footer ────────────────────────────────────────────────────────────── */
.foot { border-top: 1px solid var(--border); padding-block: var(--space-9) var(--space-7); }
.foot__grid { display: grid; gap: var(--space-7); grid-template-columns: 1fr; }
@media (min-width: 760px) { .foot__grid { grid-template-columns: 1.6fr 1fr 1fr 1fr; } }
.foot__brand img { width: 46px; height: 46px; margin-bottom: var(--space-4); }
.foot h4 { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-muted); margin-bottom: var(--space-4); font-weight: 400; }
.foot ul { list-style: none; padding: 0; display: grid; gap: 10px; }
.foot a { color: var(--text-secondary); font-size: 15px; display: inline-block; min-height: 32px; }
.foot a:hover { color: var(--text-primary); }
.foot__base { margin-top: var(--space-8); padding-top: var(--space-5); border-top: 1px solid var(--border); display: flex; flex-wrap: wrap; gap: var(--space-4); justify-content: space-between; color: var(--text-muted); font-size: var(--text-sm); }

/* ============================================================================
   REVEALS
   Content is visible by default. The pre-paint script in <head> adds
   html.u-motion, and only then do these hide-then-reveal rules apply. If the
   script is blocked, slow, or errors, every element below simply stays visible.
   That is the opposite of the shipped page, where 112 elements sat at opacity:0
   waiting for JS that might never arrive.
   ========================================================================= */
.u-motion [data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 620ms var(--ease-out-expo), transform 620ms var(--ease-out-expo);
  transition-delay: var(--d, 0ms);
}
.u-motion [data-reveal='left']  { transform: translateX(-22px); }
.u-motion [data-reveal='right'] { transform: translateX(22px); }
.u-motion [data-reveal='scale'] { transform: scale(0.965); }
.u-motion [data-reveal].is-in { opacity: 1; transform: none; }

/* The ONE spectacle: fragments converge into the file. ~800ms, once, on the hero. */
.u-motion .filecard__frag {
  opacity: 0;
  transform: translate(var(--fx, 0), var(--fy, 0)) rotate(var(--fr, 0deg)) scale(0.9);
  transition: opacity 500ms var(--ease-out-expo), transform 800ms var(--ease-out-expo);
  transition-delay: var(--d, 0ms);
}
.u-motion .filecard.is-in .filecard__frag { opacity: 0.85; transform: none; }
.filecard__frag--1 { --fx: -70px; --fy: -50px; --fr: -8deg; --d: 60ms; }
.filecard__frag--2 { --fx:  70px; --fy: -40px; --fr:  7deg; --d: 140ms; }
.filecard__frag--3 { --fx: -60px; --fy:  55px; --fr:  6deg; --d: 220ms; }
.filecard__frag--4 { --fx:  62px; --fy:  48px; --fr: -7deg; --d: 300ms; }

.u-motion .filecard__inner { opacity: 0; transform: scale(0.97); transition: opacity 600ms var(--ease-out-expo) 260ms, transform 700ms var(--ease-out-expo) 260ms; }
.u-motion .filecard.is-in .filecard__inner { opacity: 1; transform: none; }

/* Kinetic headline: each line rides up out of a clipped box. */
.u-motion .kine { display: block; overflow: clip; }
.u-motion .kine > span { display: block; transform: translateY(105%); transition: transform 760ms var(--ease-out-expo); transition-delay: var(--d, 0ms); }
.u-motion .kine.is-in > span { transform: none; }

/* Aurora drift, transform only, very slow. */
.u-motion .aurora span { animation: drift 26s var(--ease-in-out) infinite alternate; }
.u-motion .aurora span:nth-child(2) { animation-duration: 34s; animation-delay: -8s; }
.u-motion .aurora span:nth-child(3) { animation-duration: 30s; animation-delay: -15s; }
@keyframes drift {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(3vw, -2vh, 0) scale(1.08); }
}

/* ============================================================================
   CAPABILITY TIERS
   Only CONTINUOUS DECORATIVE LOOPS get cheaper on weak hardware. Every one-shot
   reveal is preserved at every tier, because a slow phone gets a calmer page,
   never an uglier one, and tearing down painted content mid-session was measured
   as a 0.92 CLS catastrophe on this estate.
   ========================================================================= */
html[data-fx='calm'] .aurora span { animation: none; }
html[data-fx='calm'] .filecard::after { display: none; }
html[data-fx='calm'] .card::before { display: none; }

/* ============================================================================
   REDUCED MOTION
   Every element lands on its FINAL, FULLY VISIBLE state with zero animation.
   Reduced motion is never the reason something is invisible.
   ========================================================================= */
@media (prefers-reduced-motion: reduce) {
  .u-motion [data-reveal],
  .u-motion .filecard__frag,
  .u-motion .filecard__inner,
  .u-motion .kine > span {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .u-motion .filecard__frag { opacity: 0.85 !important; }
  .u-motion .aurora span { animation: none !important; }
  .filecard::after, .card::before { display: none; }
  .btn, .card, .oschip, .film__btn, .nav { transition: none !important; }
}

/* ============================================================================
   POLISH PASS — 2026-07-31
   Perceptual upgrades only. The page was already functionally green, so every
   addition here has to earn its frame budget. All compositor-only.
   ========================================================================= */

/* E05 · GRAIN. A large smooth gradient on a near-black field bands visibly on
   8-bit displays, and the aurora is the biggest gradient on the site. A fixed,
   very light noise layer dithers it away. Baked as a data URI so it costs no
   request, and pointer-events:none so it can never intercept a click. */
body::after {
  content: '';
  position: fixed; inset: 0; z-index: 1;
  pointer-events: none;
  opacity: 0.035;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 140px 140px;
}
html[data-fx='calm'] body::after,
html[data-fx='still'] body::after { opacity: 0.02; }

/* E06 · DOT MATRIX. A faint engineering grid that brightens around the cursor.
   The mask position moves via a custom property, so nothing repaints: one
   composited layer follows the pointer. Desktop only, and it fades out entirely
   below the hero so it never competes with reading. */
.hero::before {
  content: '';
  position: absolute; inset: 0; z-index: 0;
  pointer-events: none;
  background-image: radial-gradient(circle at 1px 1px, rgba(255,255,255,0.16) 1px, transparent 0);
  background-size: 26px 26px;
  -webkit-mask-image: radial-gradient(320px circle at var(--mx, 50%) var(--my, 30%), #000 0%, transparent 72%);
  mask-image: radial-gradient(320px circle at var(--mx, 50%) var(--my, 30%), #000 0%, transparent 72%);
  opacity: 0.7;
}
@media (hover: none), (max-width: 900px) {
  /* On touch there is no cursor to follow, so a tracking mask is a lie. Show a
     calm static field instead of nothing: the texture is part of the identity. */
  .hero::before {
    -webkit-mask-image: radial-gradient(80% 60% at 50% 30%, #000 0%, transparent 75%);
    mask-image: radial-gradient(80% 60% at 50% 30%, #000 0%, transparent 75%);
    opacity: 0.45;
  }
}

/* E30 · HIGHLIGHT SWEEP. One phrase on the page gets a single pass of light,
   once, on entrance. It runs on the already-gradient-clipped tagline, so it is
   an opacity animation over existing paint rather than a new layer. */
.u-motion .hero__tagline { position: relative; }
.u-motion .hero__tagline::after {
  content: '';
  position: absolute; inset: -6% -12%;
  background: linear-gradient(96deg, transparent 38%, rgba(255,255,255,0.34) 50%, transparent 62%);
  transform: translateX(-38%);
  opacity: 0;
  pointer-events: none;
}
.u-motion .hero__tagline.is-in::after {
  animation: sweep 1100ms var(--ease-out-expo) 520ms 1 both;
}
@keyframes sweep {
  0%   { opacity: 0;    transform: translateX(-38%); }
  22%  { opacity: 0.85; }
  100% { opacity: 0;    transform: translateX(38%); }
}

/* FOCUS. 2px iris with an outer glow, so the ring is unmissable on obsidian
   without the harsh doubled outline that a plain colour change produces. */
:focus-visible {
  outline: 2px solid var(--iris);
  outline-offset: 3px;
  box-shadow: 0 0 0 6px rgba(157, 124, 255, 0.22);
  border-radius: 4px;
}

/* BUTTON MICRO-STATES. A primary CTA needs three distinguishable states, not
   two: resting, reachable, and committed. The press must be visible or a slow
   connection feels like a dead button. */
.btn--primary {
  position: relative;
  box-shadow: 0 0 0 0 rgba(157, 124, 255, 0.0);
  transition: transform 180ms var(--ease-out-quart), background-color 180ms linear,
              box-shadow 220ms var(--ease-out-quart);
}
.btn--primary:hover { box-shadow: 0 10px 34px -10px rgba(157, 124, 255, 0.55); }
.btn--primary:active { transform: translateY(0) scale(0.985); box-shadow: none; }
.btn--ghost:active { transform: scale(0.99); }
.btn[disabled], .btn[aria-disabled='true'] { opacity: 0.55; pointer-events: none; }

/* SECTION RHYTHM. Alternating surfaces stop eleven sections reading as one
   undifferentiated column. Lightness only, one step on the ramp, no borders. */
.band:nth-of-type(even) { background: linear-gradient(180deg, transparent, var(--e1) 18%, var(--e1) 82%, transparent); }

/* CARD ELEVATION on obsidian is surface lightness and a hairline, never a
   shadow: a drop shadow on a near-black field reads as a smudge. */
.card, .plan { background: var(--e2); }
.card:hover, .plan:hover { background: var(--e3); }
.plan { transition: background-color 200ms linear, border-color 200ms linear, transform 200ms var(--ease-out-quart); }
.plan:hover { transform: translateY(-3px); border-color: var(--border-strong); }

/* The hero fills the viewport in svh, never vh. On mobile, vh is measured
   against the tallest URL-bar state and then reflows when the bar collapses,
   which is a layout shift you did not write. */
@media (min-width: 900px) {
  .hero { min-height: 92svh; display: flex; align-items: center; }
}

/* SCROLL HAIRLINE. 2px of progress at the top of the page, scaled by a
   scroll-driven timeline where supported so it costs the main thread nothing.
   Purely decorative, so it simply does not exist under reduced motion. */
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .thread-rail::after {
      content: '';
      position: fixed; top: 0; left: 0; height: 2px; width: 100vw;
      background: var(--thread);
      transform-origin: 0 50%;
      transform: scaleX(0);
      animation: progress linear both;
      animation-timeline: scroll(root block);
      z-index: 101;
    }
    @keyframes progress { to { transform: scaleX(1); } }
  }
}

@media (prefers-reduced-motion: reduce) {
  .u-motion .hero__tagline.is-in::after { animation: none !important; opacity: 0 !important; }
  .btn--primary, .btn--ghost, .card, .plan { transition: none !important; }
}

/* ══════════════════════════════════════════════════════════════════════════
   RAMP ELEVATION LAYER — war room binding spec v1.0, 2026-07-31
   Scoped to continuum.css, which only the homepage and the legal pages load,
   so nothing here can reach the legacy stack on /manifesto, /protocol or
   /life-os. Appended last so it wins on cascade order without !important;
   a rule that has to shout to win is usually losing to something you have
   not found yet.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── 1. RHYTHM. One number, repeated. ───────────────────────────────────────
   Was clamp(80px, 12vh, 160px), which resolves to ~108px at a 900px viewport
   on EVERY band, so ten sections were metrically indistinguishable and the
   page read as one undifferentiated column. The single most transferable
   structural trait of the reference sites is that their section spacing is
   one constant, and the only deviation is extra silence before the close. */
.band { padding-block: var(--sec); }
.band--tight { padding-block: calc(var(--sec) * 0.62); }
#start.band { padding-block: var(--sec-close); }

/* ── 2. CONTAINER. 1200/640. ────────────────────────────────────────────────
   The measured content column was 891px inside a 1440px page, leaving 549px
   of dead gutter, which is why the page looked under-built at desktop while
   being cramped in prose. Reference pages run ~1312 of 1440. */
.wrap { max-width: var(--container); padding-inline: clamp(20px, 5vw, 64px); }
.wrap--narrow { max-width: 840px; }
.wrap--prose { max-width: var(--prose); }

/* ── 3. THREE ACTS, THREE GROUNDS, THREE SEAMS. ─────────────────────────────
   The page had no chapters: every band sat on the same void, so a reader had
   no sense of having moved. Act I states the problem on void. Act II lifts to
   surface-1 and is where the product is explained. Act III returns to void for
   the institutional material. The close lifts once more and then drops away.
   The lift is 1.48 L*, deliberately small: a big jump reads cheap on dark. */
#file, #access, #day { background: var(--surface-1); }
#origin { background: var(--surface-1); }

/* The seam. One 1px thread hairline at each act boundary, at low alpha, so the
   change of ground is announced rather than merely happening. Rendered on a
   pseudo-element with zero height so it can never contribute to layout or to
   CLS (a decorative layer sized by content is how this estate shipped a CLS
   bomb once already). */
#file::before, #systems::before, #origin::before, #start::before {
  content: ""; position: absolute; inset-inline: 0; top: 0; height: 1px;
  background: var(--thread); opacity: 0.30; pointer-events: none;
}

/* ── 4. SECTION FURNITURE. ──────────────────────────────────────────────────
   A mono eyebrow with a short thread rule is what converts "text on a dark
   field" into "a chapter", at essentially zero cost and zero payload. This is
   the cheapest craft upgrade available to the eight sections that measured as
   visually dead. */
.band > .wrap > .eyebrow::before,
.band > .wrap > * > .eyebrow::before {
  content: ""; display: inline-block; width: 24px; height: 1px;
  margin-right: 10px; vertical-align: middle;
  background: var(--thread); opacity: 0.75;
}

/* ── 5. CARDS DO NOT LIFT. ──────────────────────────────────────────────────
   Measured on the reference site: card hover is transform none -> none and
   transition: all 0s. A lift on something that is not a link is an affordance
   lie, and half the cards on this page are not links. Elevation stays in the
   hairline; the ring is a box-shadow so the row never reflows on hover. */
.card:hover, .tile:hover, .oscard:hover { transform: none; }
.card, .tile { transition: box-shadow var(--dur-ui) var(--ease-out),
                           border-color var(--dur-ui) var(--ease-out); }
.card:hover, .tile:hover { box-shadow: var(--ring); }

/* ── 6. FOCUS. Visible, on every ground, never removed. ─────────────────── */
:where(a, button, input, [tabindex]):focus-visible {
  outline: 2px solid var(--aqua); outline-offset: 3px; border-radius: var(--r-ctl);
}
/* ...except on the skip link's own target. `<main tabindex="-1">` exists so the skip
   link can move focus past the header; it is a 2,700px-tall container, not a control.
   The `[tabindex]` branch above starts matching it the moment that attribute is added,
   and the result is a 2px aqua line drawn the full width and height of the page — every
   geometry assertion still passes and only a screenshot shows it. The user's cue here is
   the scroll position and the screen reader's landmark announcement, not a ring. The
   `:where()` above carries zero specificity, so this single-class-free rule wins cleanly
   and changes nothing that a person can actually focus with the keyboard. */
main[tabindex="-1"]:focus, main[tabindex="-1"]:focus-visible { outline: none; }

@media (prefers-reduced-motion: reduce) {
  .card, .tile { transition: none; }
}

/* ── 7. THE HERO, FORK B. ───────────────────────────────────────────────────
   The page led with "The largest TAM ever pursued." at 128px. That is an
   investor sentence, and it was the first thing a person deciding whether to
   put their medical record into a file had to read. The product promise sat
   beneath it as a subhead.

   David asked that the TAM line be KEPT, and the war room recorded it as an
   explicit overrule, so it is NOT deleted and NOT moved: it remains the h1,
   byte-identical, in the same node. What changes is optical rank. The promise
   becomes the largest thing on the page and the TAM line becomes the quiet
   line above it, which is the relationship those two sentences actually have.

   The 128px cap also goes. 128px at 1440 is roughly twice the reference site's
   measured h1 on a page with a third of its content: a poster, not a headline,
   and part of why the old 891px column looked under-built. */
.hero h1 {
  font-size: clamp(1.6rem, 2.2vw, 1.875rem);
  line-height: 1.15;
  letter-spacing: -0.015em;
  font-weight: 500;
  color: var(--text-hushed);
  max-width: 20ch;
  margin-bottom: 10px;
}
.hero .hero__tagline {
  font-size: clamp(2.75rem, 6vw, 4.5rem);
  line-height: 1.0;
  letter-spacing: -0.02em;
  font-weight: 500;
  font-family: var(--font-display);
  max-width: 14ch;
  margin-block: 0 22px;
}
/* Solid, not gradient. Gradient headline text paints through a transparent
   fill, so it cannot be contrast-checked, it degrades badly when the gradient
   fails to clip, and it is decoration doing a job hierarchy should do. The
   thread belongs on the seams and the spine, not on the sentence. */
.hero .hero__tagline.thread-text {
  background: none;
  -webkit-text-fill-color: currentColor;
  color: var(--text-primary);
}
