/* The landing story (index.html). Everything else is css/page.css.

   Layers, back to front: the breathing water (web/js/background.js, in
   still-water mode here), the particle field (.story-field, web/js/field.js),
   then the page. Each chapter's text arrives its own way (web/js/reveal.js);
   the hidden start states apply only once JS is running (html.js), so the
   text is never lost without it.

   The intro is an overlay on the real landing, timed here in CSS so it can
   never get stuck. --intro-length must match INTRO_MS in web/js/motion.js
   (web/tests/motion.test.js checks). */

:root {
    --intro-length: 4800ms;
    /* When the wordmark builds, and when the rest of the landing arrives.
       Returning visitors in this session skip the intro. */
    --wordmark-delay: 0.1s;
    --landing-delay: 0.35s;
    --clear: 238, 243, 248;
}
html:not([data-intro="seen"]) {
    --wordmark-delay: calc(var(--intro-length) * 0.5);
    --landing-delay: calc(var(--intro-length) * 0.8);
}

.story-field {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: 0;
    pointer-events: none;
}
.story, .story-page .site-footer { position: relative; z-index: 1; }

/* ---- intro: the question, spelt in particles once the field is ready ---- */

.intro {
    position: fixed;
    inset: 0;
    z-index: 20;
    display: grid;
    place-items: center;
    padding: 0 var(--gutter);
    pointer-events: none;
    animation: intro-out var(--intro-length) linear both;
}
html[data-intro="seen"] .intro { display: none; }
.intro-question {
    font-size: clamp(34px, 5.4vw, 72px);
    font-weight: 600;
    letter-spacing: -0.035em;
    line-height: 1.05;
    color: var(--ink);
    text-align: center;
    text-shadow: 0 0 18px rgba(255, 255, 255, 0.95), 0 0 42px rgba(255, 255, 255, 0.85);
    animation: intro-question var(--intro-length) ease both;
    transition: color 0.8s ease, text-shadow 0.8s ease;
}
/* The particles carry the words; the text stays for screen readers. */
html.has-field .intro-question { color: transparent; text-shadow: none; }
.intro-progress {
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 2px;
    background: var(--accent);
    transform-origin: left;
    animation: intro-progress var(--intro-length) linear both;
}
@keyframes intro-out { 0%, 92% { opacity: 1; visibility: visible; } 100% { opacity: 0; visibility: hidden; } }
@keyframes intro-question {
    0% { opacity: 0; transform: translateY(14px); }
    10%, 40% { opacity: 1; transform: none; }
    50%, 100% { opacity: 0; transform: translateY(-10px); }
}
@keyframes intro-progress { from { transform: scaleX(0); } to { transform: scaleX(1); } }

/* ---- landing: the one halo card ---- */

.landing {
    min-height: 100svh;
    max-width: var(--page-max);
    margin: 0 auto;
    padding: 72px var(--gutter) 48px;
    display: grid;
    align-content: center;
    justify-items: start;
    gap: 28px;
}
.landing-card { max-width: 640px; padding: 48px 52px; animation: rise 0.9s cubic-bezier(0.2, 0.7, 0.2, 1) var(--wordmark-delay) both; }
.landing-wordmark {
    font-size: clamp(64px, 8.2vw, 116px);
    font-weight: 700;
    letter-spacing: -0.045em;
    line-height: 1;
    color: var(--accent-bright);
    margin-bottom: 30px;
}
.landing-wordmark .cut {
    padding: 0 0.07em;
    border-radius: 0.07em;
    clip-path: inset(0 100% 0 0);
    animation: wipe 0.8s cubic-bezier(0.65, 0, 0.35, 1) calc(var(--wordmark-delay) + 0.4s) forwards;
}
.landing-catch { font-size: clamp(22px, 2.4vw, 30px); font-weight: 600; color: var(--ink); letter-spacing: -0.02em; line-height: 1.25; }
.landing-line { margin-top: 14px; font-size: 17px; max-width: 46ch; }
.landing-in { animation: rise 0.8s cubic-bezier(0.2, 0.7, 0.2, 1) var(--landing-delay) both; }
.scroll-hint { font-size: 13px; color: var(--ink-faint); padding-left: 4px; }

@keyframes rise { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: none; } }
@keyframes wipe { to { clip-path: inset(0 0 0 0); } }

/* ---- chapters: text in the water ---- */

.chapter {
    min-height: 115svh;
    max-width: var(--page-max);
    margin: 0 auto;
    padding: 14svh var(--gutter);
    display: grid;
    align-items: center;
}
.chapter-text { max-width: 560px; position: relative; }
.side-left .chapter-text { justify-self: start; }
.side-right .chapter-text { justify-self: end; }

/* A pool of clearer water behind the text, so it reads over the particles. */
.chapter-text::before, .col::before, .closing::before, .centred::before {
    content: "";
    position: absolute;
    inset: -16% -22%;
    z-index: -1;
    pointer-events: none;
    background: radial-gradient(closest-side, rgba(var(--clear), 0.9), rgba(var(--clear), 0.62) 55%, rgba(var(--clear), 0));
}

.chapter-title { font-size: clamp(34px, 4.2vw, 58px); letter-spacing: -0.035em; line-height: 1.14; margin-bottom: 26px; }
.chapter-title .cut, .finale-title .cut { padding: 0 0.1em; color: #FFFFFF; }
.editorial { font-size: clamp(20px, 1.9vw, 26px); line-height: 1.42; font-weight: 500; color: var(--ink); letter-spacing: -0.01em; max-width: 30ch; }
.editorial + .editorial { margin-top: 18px; }
.lead { font-size: 19px; line-height: 1.55; margin-bottom: 14px; max-width: 46ch; }
.aside { font-size: 15px; color: var(--ink-faint); max-width: 48ch; }
.note { font-size: 14px; color: var(--ink-faint); max-width: 48ch; }
.chapter-link { display: inline-block; margin-top: 16px; font-weight: 500; }

/* Mask: headline lines slide up out of their own clip; the rest rises after. */
.masked .line { display: inline-block; overflow: hidden; vertical-align: bottom; padding-bottom: 0.1em; }
.masked .line > span { display: inline-block; }
.js .masked .line > span { transform: translateY(108%); transition: transform 0.9s cubic-bezier(0.2, 0.7, 0.2, 1); }
.js .masked .line + .line > span { transition-delay: 0.12s; }
.js .is-in .masked .line > span { transform: none; }
.js [data-reveal="mask"] .rise, .js [data-reveal="mask"] .fact {
    opacity: 0;
    transform: translateY(14px);
    transition: opacity 0.7s ease, transform 0.7s cubic-bezier(0.2, 0.7, 0.2, 1);
}
.js .is-in .rise, .js .is-in .fact { opacity: 1; transform: none; }
.js .is-in .rise { transition-delay: 0.35s; }
.js .is-in .fact:nth-child(1) { transition-delay: 0.55s; }
.js .is-in .fact:nth-child(2) { transition-delay: 0.65s; }
.js .is-in .fact:nth-child(3) { transition-delay: 0.75s; }
.js .is-in .fact:nth-child(4) { transition-delay: 0.85s; }
.js .is-in .aside.rise { transition-delay: 1s; }

.facts { display: grid; grid-template-columns: 1fr 1fr; gap: 18px 28px; margin: 24px 0; }
.fact { display: flex; flex-direction: column-reverse; justify-content: flex-end; gap: 2px; }
.fact dd { font-size: clamp(30px, 3vw, 44px); font-weight: 600; color: var(--ink); letter-spacing: -0.03em; font-variant-numeric: tabular-nums; line-height: 1.1; }
.fact dt { font-size: 13px; color: var(--ink-faint); }

/* Split: RNA and protein, one column each, with the atlas between them. */
.side-centre { align-content: center; gap: 6svh; }
.centred { position: relative; text-align: center; max-width: 16ch; margin: 0 auto; }
.cols { display: grid; grid-template-columns: minmax(0, 340px) 1fr minmax(0, 340px); gap: 24px; }
.col { position: relative; }
.col-rna { grid-column: 1; }
.col-prot { grid-column: 3; }
.col .bead { margin-bottom: 12px; }
.col .editorial { font-size: clamp(19px, 1.6vw, 23px); }
.closing { position: relative; max-width: 44ch; margin: 0 auto; text-align: center; font-size: 19px; color: var(--ink); }
.js [data-reveal="split"] .closing { opacity: 0; transform: translateY(12px); transition: opacity 0.7s ease, transform 0.7s ease; }
.js .is-closed .closing { opacity: 1; transform: none; }

/* Steps: a pinned 1 to 4 sequence; the current step opens. */
.pin { height: 340svh; display: block; max-width: none; padding: 0; min-height: 0; }
.pin-stage {
    position: sticky;
    top: 0;
    min-height: 100svh;
    max-width: var(--page-max);
    margin: 0 auto;
    padding: 0 var(--gutter);
    display: grid;
    align-items: center;
}
.steps { list-style: none; position: relative; display: grid; gap: 10px; margin: 6px 0 22px; }
.steps::before, .steps::after {
    content: "";
    position: absolute;
    left: 16px;
    top: 17px;
    width: 2px;
    border-radius: 1px;
}
.steps::before { bottom: 17px; background: var(--line); }
.steps::after { height: calc(var(--progress, 1) * (100% - 34px)); background: var(--accent-bright); }
.step { display: grid; grid-template-columns: 34px 1fr; grid-template-rows: auto 1fr; column-gap: 16px; align-items: center; position: relative; z-index: 1; }
.step h3 { font-size: 22px; margin: 0; letter-spacing: -0.02em; }
.step p { grid-column: 2; font-size: 17px; max-width: 42ch; margin-top: 4px; min-height: 0; }
.step-num {
    width: 34px;
    height: 34px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    font-size: 15px;
    font-weight: 600;
    color: var(--ink);
    background: var(--well);
    box-shadow: inset 1px 1px 3px rgba(var(--shade), 0.18);
    z-index: 1;
}
.js [data-reveal="steps"] .step { grid-template-rows: auto 0fr; opacity: 0.38; transition: grid-template-rows 0.5s ease, opacity 0.4s ease; }
.js [data-reveal="steps"] .step p { opacity: 0; overflow: hidden; transition: opacity 0.4s ease; }
.js .step.is-done { opacity: 0.66; }
.js [data-reveal="steps"] .step.is-current { grid-template-rows: auto 1fr; opacity: 1; }
.js .step.is-current p { opacity: 1; }
.step.is-current .step-num, .step.is-done .step-num { background: var(--accent-bright); color: #FFFFFF; box-shadow: none; }

/* Strike: the usual answer is struck out, then VivOME's arrives. */
.struck-text { position: relative; }
.struck-text::after {
    content: "";
    position: absolute;
    left: 0;
    top: 54%;
    height: 3px;
    width: calc(var(--strike, 1) * 100%);
    background: var(--ink);
    border-radius: 2px;
}
.js [data-reveal="strike"] .struck { opacity: calc(1 - var(--strike, 0) * 0.5); }
.answer { margin-top: 18px; }
.js [data-reveal="strike"] .answer { opacity: 0; transform: translateY(12px); transition: opacity 0.7s ease, transform 0.7s ease; }
.js .is-answered .answer { opacity: 1; transform: none; }

/* Underline: each benchmark rule draws its own line, in ink (a blue
   underline would read as a link). */
.rules { list-style: none; display: grid; gap: 14px; margin: 6px 0 22px; font-size: clamp(18px, 1.6vw, 21px); color: var(--ink); line-height: 1.45; }
.draw {
    background-image: linear-gradient(currentColor, currentColor);
    background-repeat: no-repeat;
    background-position: 0 100%;
    background-size: calc(var(--draw, 1) * 100%) 3px;
    padding-bottom: 3px;
    -webkit-box-decoration-break: clone;
    box-decoration-break: clone;
}

/* Timeline: the thread draws down through the releases. */
.timeline { list-style: none; position: relative; display: grid; gap: 24px; margin: 6px 0 24px; padding-left: 34px; }
.timeline::before, .timeline::after { content: ""; position: absolute; left: 7px; top: 8px; width: 2px; border-radius: 1px; }
.timeline::before { bottom: 8px; background: var(--line); }
.timeline::after { height: calc(var(--line, 1) * (100% - 16px)); background: linear-gradient(var(--rna), var(--prot)); }
.release { position: relative; }
.release::before {
    content: "";
    position: absolute;
    left: -34px;
    top: 5px;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: #FFFFFF;
    box-shadow: inset 0 0 0 3px var(--accent-bright);
}
.release-testing::before { background: transparent; box-shadow: none; border: 2px dashed var(--accent-bright); }
.release h3 { font-size: 20px; margin-bottom: 4px; letter-spacing: -0.015em; }
.release p { font-size: 16px; max-width: 44ch; }
.js [data-reveal="timeline"] .release { opacity: 0; transform: translateX(-10px); transition: opacity 0.6s ease, transform 0.6s ease; }
.js .release.is-in { opacity: 1; transform: none; }

/* Finale: the payoff line letter by letter, then the evidence. */
.finale { height: 240svh; }
.finale-title { line-height: 1.16; }
.finale-stage { align-items: end; justify-items: center; padding-bottom: 8svh; }
.finale-card { max-width: 780px; padding: 38px 46px; text-align: center; }
.finale-title { font-size: clamp(32px, 3.6vw, 50px); letter-spacing: -0.03em; line-height: 1.1; margin-bottom: 14px; }
.finale-rest p { max-width: 54ch; margin: 0 auto; }
.js [data-reveal="letters"] .finale-rest { opacity: 0; transform: translateY(12px); transition: opacity 0.7s ease, transform 0.7s ease; }
.js [data-reveal="letters"].is-in .finale-rest { opacity: 1; transform: none; }
.finale-actions { display: flex; gap: 22px; justify-content: center; align-items: center; flex-wrap: wrap; }
.finale-actions a:not(.btn) { font-weight: 500; }
.proof-points { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin: 22px 0 22px; }
.proof-point { display: flex; flex-direction: column-reverse; justify-content: flex-end; gap: 2px; padding: 12px 8px; }
.proof-point dd { font-size: 26px; font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }
.proof-point dt { font-size: 12px; color: var(--ink-faint); }

/* ---- phones: one column over a quieter field ---- */

@media (max-width: 820px) {
    .story-field { opacity: 0.6; }
    .landing { min-height: 88svh; padding-top: 40px; }
    .landing-card { padding: 32px 26px; }
    .chapter { min-height: 0; padding: 12svh var(--gutter); }
    .chapter-text, .side-right .chapter-text { justify-self: stretch; max-width: none; }
    .editorial { max-width: none; }
    .cols { grid-template-columns: 1fr; gap: 30px; }
    .col-prot { grid-column: auto; }
    .pin { height: 300svh; }
    .finale-card { padding: 30px 22px; }
    .proof-points { grid-template-columns: 1fr 1fr; }
}

/* ---- reduced motion: no pinning, everything shown ---- */

@media (prefers-reduced-motion: reduce) {
    .pin, .finale { height: auto; }
    .pin-stage { position: relative; min-height: 0; padding: 12svh var(--gutter); }
    .js [data-reveal="steps"] .step { grid-template-rows: auto 1fr; opacity: 1; }
    .js [data-reveal="steps"] .step p { opacity: 1; }
}
