/* Futuresafe v8: motion after modal.com (research/MODAL-MOTION.md). Home first (27 Oct); every page since 31 Oct (Raph: Home's standard everywhere). Over v7.css.
   Words never move. Illustrations reveal once; chips arrive on the house curve; hover is color and opacity, never lift. */
@property --r { syntax: '<percentage>'; inherits: false; initial-value: 150%; }
:root { --e-arrive: cubic-bezier(.165,.84,.44,1); --e-intro: cubic-bezier(.22,1,.36,1); --e-color: cubic-bezier(.4,0,.2,1); --e-press: cubic-bezier(.2,.7,.3,1); --e-sweep: cubic-bezier(.42,.06,.4,.98); --e-inout: cubic-bezier(.65,0,.35,1); --e-rise: cubic-bezier(.05,.7,.1,1); }

/* no pinned scroll on Home (Modal pins nothing): both scenes sit in the page and step on their own every 5s */
.pin { height: auto !important; }
.pin-in { position: static; height: auto; display: block; }
.pin-in > .sec { padding-top: var(--sec); padding-bottom: var(--sec); }

/* ---- reveals: the cell fields light from the center out (2400ms diagram timeline, lines from 12%) ---- */
.mo:not(.mo-still) .rv .art svg, .mo:not(.mo-still) .rv .fart svg, .mo:not(.mo-still) .rv.panel > svg, .mo:not(.mo-still) .rv.cb-art svg {
  -webkit-mask-image: radial-gradient(circle at 50% 50%, #000 calc(var(--r) - 18%), transparent var(--r)); mask-image: radial-gradient(circle at 50% 50%, #000 calc(var(--r) - 18%), transparent var(--r));
  transition: --r 2400ms var(--e-intro) calc(var(--d, 0ms) + 290ms); }
.mo:not(.mo-still) .rv:not(.in) .art svg, .mo:not(.mo-still) .rv:not(.in) .fart svg, .mo:not(.mo-still) .rv.panel:not(.in) > svg, .mo:not(.mo-still) .rv.cb-art:not(.in) svg { --r: 0%; transition: none; }

/* product chips arrive like a dialog: rise 12px from .98, 500ms on the house curve, after the field has started */
.mo:not(.mo-still) .rv.panel .chip { transition: opacity 500ms var(--e-arrive), translate 500ms var(--e-arrive), scale 320ms var(--e-press); transition-delay: calc(var(--d, 0ms) + 500ms), calc(var(--d, 0ms) + 500ms), 0ms; }
.mo:not(.mo-still) .rv.panel:not(.in) .chip { opacity: 0; translate: 0 12px; transition: none; }
.mo:not(.mo-still) .rv.panel .ill { transition: opacity 400ms var(--e-arrive) 900ms; }
.mo:not(.mo-still) .rv.panel:not(.in) .ill { opacity: 0; transition: none; }

/* the capability strip on each failed answer: pills light in order across one 900ms timeline (rows at i/n x 0.77) */
.mo:not(.mo-still) .rv .cs { transition: opacity 144ms ease-out, box-shadow 200ms ease; }
.mo:not(.mo-still) .rv .cs:nth-child(1) { transition-delay: calc(var(--d) + 600ms); }
.mo:not(.mo-still) .rv .cs:nth-child(2) { transition-delay: calc(var(--d) + 739ms); }
.mo:not(.mo-still) .rv .cs:nth-child(3) { transition-delay: calc(var(--d) + 877ms); }
.mo:not(.mo-still) .rv .cs:nth-child(4) { transition-delay: calc(var(--d) + 1016ms); }
.mo:not(.mo-still) .rv .cs:nth-child(5) { transition-delay: calc(var(--d) + 1154ms); }
.mo:not(.mo-still) .rv:not(.in) .cs { opacity: 0; transition: none; }
.mo:not(.mo-still) .rv.key { transition: opacity 400ms var(--e-arrive) 600ms; }
.mo:not(.mo-still) .rv.key:not(.in) { opacity: 0; transition: none; }

/* ---- the prompt film: typed at 42ms a character, a 320ms press, then the verdict ---- */
.chip .q .ch { visibility: visible; }
.chip.typing .q .ch:not(.on) { visibility: hidden; }
.chip.typing .q .redact { background: transparent; }
.chip.typing .q .redact .ch.on { background: var(--paper); }
.chip.typing .q .ch.cur { box-shadow: 2px 0 0 var(--signal); animation: caret 1s steps(1) infinite; }
@keyframes caret { 50% { box-shadow: 2px 0 0 transparent; } }
.chip .file, .chip .vrow { transition: opacity 400ms var(--e-arrive); }
.chip.typing .file, .chip.typing .vrow, .chip.pressed .vrow { opacity: 0; transition: none; }
.chip.pressed { scale: .95; }
.chip::after { content: ''; position: absolute; inset: 0; border-radius: inherit; background: #fff; opacity: 0; pointer-events: none; transition: opacity 320ms var(--e-press); }
.chip.pressed::after { opacity: .05; transition: none; }
.chip.sent .vrow .vp { animation: mark-in 500ms var(--e-arrive) both; }
.chip.sent .vrow .vwhy { animation: fade-in 400ms var(--e-arrive) 120ms both; }
@keyframes mark-in { from { opacity: 0; scale: .7; filter: blur(8px); } to { opacity: 1; scale: 1; filter: blur(0); } }
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }

/* ---- hover: color and opacity only (rule 7) ---- */
.mo .pill { transition: background-color 150ms var(--e-color), color 150ms var(--e-color), box-shadow 150ms var(--e-color), filter 150ms var(--e-color); }
.mo .pill:hover { transform: none; filter: brightness(1.1); }
@media (hover: hover) and (pointer: fine) {
  .mo .cols4 .col, .mo .trip .card, .mo .prod3 .tab, .mo .prog .tab { transition: opacity 200ms ease; }
  .mo .cols4:has(.col:hover) .col:not(:hover), .mo .trip:has(.card:hover) .card:not(:hover) { opacity: .55; }
  .mo .prod3 .tabs:has(.tab:hover) .tab:not(:hover):not(.on), .mo .prog .tabs:has(.tab:hover) .tab:not(:hover):not(.on) { opacity: .6; }
}
/* hovering an answer takes its figure one step: a short spring beat, the covered capabilities flash */
.mo:not(.mo-still) .beat .fart svg, .mo:not(.mo-still) .beat .art svg { animation: beat 850ms cubic-bezier(.34,1.56,.64,1); }
.mo:not(.mo-still) .beat .cs:not(.miss) { animation: lit 850ms ease; }
@keyframes beat { 0% { scale: 1; } 30% { scale: 1.035; } 100% { scale: 1; } }
@keyframes lit { 30% { box-shadow: inset 0 0 0 1.5px var(--deep); } }

/* ---- the nav earns its motion once: the wordmark folds into the mark after 46px, back under 30px or on hover ---- */
@property --wm { syntax: '<length>'; inherits: true; initial-value: 140px; }
@property --rp { syntax: '<length>'; inherits: true; initial-value: 14px; }
/* the pinned nav swaps in a spacer of its own height; scroll anchoring would 'correct' that into a jump, so it is off on Home */
html { overflow-anchor: none; }
.nav.pinned { position: fixed; top: 0; left: 0; right: 0; background: rgba(5,14,22,.97); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); box-shadow: 0 1px 0 var(--paper-a08); animation: nav-in 300ms var(--e-arrive); }
@keyframes nav-in { from { translate: 0 -8px; opacity: .6; } to { translate: 0 0; opacity: 1; } }
.nav .logo { position: relative; overflow: hidden; width: var(--lw, 105px); --wm: 140px; --rp: 14px; transition: width 620ms var(--e-inout) 80ms, --wm 620ms var(--e-inout), --rp 620ms var(--e-inout); }
.nav .logo .lock { max-width: none; -webkit-mask-image: linear-gradient(90deg, #000 calc(var(--wm) - var(--rp)), transparent var(--wm)); mask-image: linear-gradient(90deg, #000 calc(var(--wm) - var(--rp)), transparent var(--wm)); transition: translate 620ms var(--e-inout), filter 620ms var(--e-inout); }
/* folded: the mark (0 to 24.5px of the lockup) stays fully drawn, the wordmark (from 27px) is gone */
.nav.fold .logo { width: 26px; --wm: 27px; --rp: 2.5px; }
.nav.fold.peek .logo { width: var(--lw, 105px); --wm: 140px; --rp: 14px; transition-duration: 570ms; transition-delay: 0ms; }
.nav .logo::after { content: ''; position: absolute; inset: 0; pointer-events: none; opacity: 0;
  background: linear-gradient(100deg, transparent 35%, rgba(255,255,255,.75) 50%, transparent 65%) 150% 0 / 250% 100% no-repeat;
  -webkit-mask: url(assets/fs-lockup-dark.svg?v=ecf74a1051) left center / auto 22px no-repeat; mask: url(assets/fs-lockup-dark.svg?v=ecf74a1051) left center / auto 22px no-repeat; }
.nav .logo.glint::after { animation: glint 950ms var(--e-sweep); }
@keyframes glint { 0% { opacity: 1; background-position: 150% 0; } 100% { opacity: 1; background-position: -50% 0; } }

/* ---- the margin teaser: one live slider ---- */
.hslide { max-width: 560px; margin-top: 28px; }
.hslide label { display: flex; justify-content: space-between; align-items: baseline; font: 500 14px var(--f-b); color: var(--slate); }
.hslide output { font: 600 20px var(--f-d); color: var(--navy); }
.hslide input[type=range] { margin-top: 6px; }
.g3 .v, .g3 .s { font-variant-numeric: tabular-nums; }

/* ---- ambient: the hero verdict breathes on a 3.2s pulse, and stops off-screen or in a hidden tab ---- */
.mo:not(.mo-still) .hchip .vp.live { animation: pulse 3.2s cubic-bezier(.65,0,.35,1) infinite; }
.mo-paused .hchip .vp { animation-play-state: paused; }
@keyframes pulse { 0%, 100% { box-shadow: 0 0 0 0 rgba(255,107,107,0); } 50% { box-shadow: 0 0 0 6px rgba(255,107,107,.18); } }

@media (prefers-reduced-motion: reduce) { .nav .logo, .nav .logo .lock { transition: none; } }

/* every hero begins empty and assembles once (no finished frame before the intro); its chip arrives after the field */
.mo-pre .hart[data-hero=home]:not(.hm-on) .mk-stage svg, .mo-pre .hart[data-hero]:not(.hm-on) svg.grid { visibility: hidden; }
.mo-pre .hart[data-hero]:not(.hm-on) .hchip, .mo-pre .hart[data-hero]:not(.hm-on) .chip { opacity: 0; }
.hart[data-hero] .hchip { transition: opacity 500ms var(--e-arrive) 1100ms; }
/* other heroes' chips and the one-pager's SLA disc arrive as the field reaches them (the field leaves their hole from ~600ms) */
.hart[data-hero] .chip, .hart[data-hero] .ringn { transition: opacity 400ms var(--e-arrive) 600ms; }
.mo-pre .hart[data-hero]:not(.hm-on) .ringn { opacity: 0; }

/* Jason, 27 Oct: the chain is seven steps; SOC and Support, the last two, carry the story (paper on the ramp) */
.hexsteps.n7 li { width: 112px; }
.hexsteps.n7 svg { width: 94px; }
.hexsteps.n7::before { left: 47px; right: 47px; top: 41px; }
.hexsteps .hx path { fill: var(--paper); stroke: var(--navy); stroke-width: 3; }
@media (max-width: 760px) {
  .hexsteps.n7 li { width: auto; }
  .hexsteps.n7 svg { width: 40px; }
  .hexsteps.n7::before { left: 20px; right: 20px; top: 17px; }
  .hexsteps.n7 span { font-size: 11px; }
}

/* ======== every other page (31 Oct): the same rules, on each page's own figures ======== */
/* cell fields (post thumbnails, the iboss field, the tier planes, the lifecycle panel) light from the center out, like Home's */
.mo:not(.mo-still) .rv svg.grid, .mo:not(.mo-still) .rv.dstage svg {
  -webkit-mask-image: radial-gradient(circle at 50% 50%, #000 calc(var(--r) - 18%), transparent var(--r)); mask-image: radial-gradient(circle at 50% 50%, #000 calc(var(--r) - 18%), transparent var(--r));
  transition: --r 2400ms var(--e-intro) calc(var(--d, 0ms) + 290ms); }
.mo:not(.mo-still) .rv:not(.in) svg.grid, .mo:not(.mo-still) .rv.dstage:not(.in) svg { --r: 0%; transition: none; }
/* line icons draw on, starting at 12% of a 900ms timeline on quart-out (rule 4); motion.js gives their strokes pathLength=1 */
.mo:not(.mo-still) .rv .drw [pathLength] { stroke-dasharray: 1; stroke-dashoffset: 0; transition: stroke-dashoffset 790ms cubic-bezier(.25,1,.5,1) calc(var(--d, 0ms) + 108ms); }
.mo:not(.mo-still) .rv:not(.in) .drw [pathLength] { stroke-dashoffset: 1; transition: none; }
.mo:not(.mo-still) .beat .drw [pathLength] { animation: redraw 850ms cubic-bezier(.25,1,.5,1); }
@keyframes redraw { 0% { stroke-dashoffset: 1; } 100% { stroke-dashoffset: 0; } }
.mo:not(.mo-still) .beat .thumb svg { animation: beat 850ms cubic-bezier(.34,1.56,.64,1); }
/* partner logos arrive in order (marks, not words): 400ms fades on the 170ms stagger */
.mo:not(.mo-still) .wall li.rv img { transition: opacity 400ms var(--e-arrive) calc(var(--d, 0ms) + 120ms); }
.mo:not(.mo-still) .wall li.rv:not(.in) img { opacity: 0; transition: none; }
/* the lifecycle panel plays like Home's film: the chip rises, then each step lands in turn, the detection dot last */
.mo:not(.mo-still) .rv.panel.boom .bchip { transition: opacity 500ms var(--e-arrive) 700ms, translate 500ms var(--e-arrive) 700ms; }
.mo:not(.mo-still) .rv.panel.boom:not(.in) .bchip { opacity: 0; translate: 0 12px; transition: none; }
.mo:not(.mo-still) .rv.panel.boom .stp, .mo:not(.mo-still) .rv.panel.boom .steps > svg { transition: opacity 400ms var(--e-arrive), filter 400ms var(--e-arrive); }
.mo:not(.mo-still) .rv.panel.boom .steps > :nth-child(1) { transition-delay: 900ms; }
.mo:not(.mo-still) .rv.panel.boom .steps > :nth-child(2) { transition-delay: 1070ms; }
.mo:not(.mo-still) .rv.panel.boom .steps > :nth-child(3) { transition-delay: 1240ms; }
.mo:not(.mo-still) .rv.panel.boom .steps > :nth-child(4) { transition-delay: 1410ms; }
.mo:not(.mo-still) .rv.panel.boom .steps > :nth-child(5) { transition-delay: 1580ms; }
.mo:not(.mo-still) .rv.panel.boom:not(.in) .steps > * { opacity: 0; filter: blur(4px); transition: none; }
.mo:not(.mo-still) .rv.panel.boom.in .sdot.live { animation: pulse 3.2s cubic-bezier(.65,0,.35,1) 3s infinite; border-radius: 50%; }
.mo-paused .sdot { animation-play-state: paused; }
/* the tier planes: each tab change replays the planes' reveal (as Home's program panels do) */
.mo:not(.mo-still) .rv.dstage .dp { transition: left 620ms var(--e-inout), width 620ms var(--e-inout), top 620ms var(--e-inout), opacity 400ms var(--e-arrive); }
/* hover: color and opacity only; a card dims its siblings and its own figure takes one step (rules 7 and 8) */
@media (hover: hover) and (pointer: fine) {
  .mo .capgrid .cap, .mo .pts4 .pt, .mo .pgrid .pc, .mo .open3 .oc, .mo .people .person, .mo .ccards .cc, .mo .wall li, .mo .outs4 li, .mo .cov3 li { transition: opacity 200ms ease; }
  .mo .capgrid:has(.cap:hover) .cap:not(:hover), .mo .pts4:has(.pt:hover) .pt:not(:hover), .mo .pgrid:has(.pc:hover) .pc:not(:hover), .mo .open3:has(.oc:hover) .oc:not(:hover),
  .mo .people:has(.person:hover) .person:not(:hover), .mo .ccards:has(.cc:hover) .cc:not(:hover), .mo .wall:has(li:hover) li:not(:hover),
  .mo .outs4:has(li:hover) li:not(:hover), .mo .cov3:has(li:hover) li:not(:hover) { opacity: .55; }
  .mo .ttabs:has(.ttab:hover) .ttab:not(:hover):not(.on) { opacity: .6; }
  .mo .ttab { transition: opacity 200ms ease, background-color 150ms var(--e-color), color 150ms var(--e-color), box-shadow 150ms var(--e-color); }
}
/* About: the struck line draws its strike (the words stay put); portraits arrive like Modal's marks, on the 170ms stagger */
@property --sx { syntax: '<percentage>'; inherits: false; initial-value: 100%; }
.mo .swapq s { text-decoration: none; background: linear-gradient(currentColor, currentColor) 0 56% / var(--sx) 3px no-repeat; }
.mo:not(.mo-still) .rv.swapq s { transition: --sx 620ms var(--e-inout) 500ms; }
.mo:not(.mo-still) .rv.swapq:not(.in) s { --sx: 0%; transition: none; }
.mo:not(.mo-still) .rv.person .ph { transition: opacity 500ms var(--e-arrive) var(--d, 0ms), filter 500ms var(--e-arrive) var(--d, 0ms); }
.mo:not(.mo-still) .rv.person:not(.in) .ph { opacity: 0; filter: blur(8px); transition: none; }
/* hover is color, not physics: the portrait takes its color back and does not zoom */
.mo .person .ph img, .mo .person:hover .ph img, .mo .person:focus-visible .ph img { transform: none; }
/* Book a call: the scheduler plays like Home's film. Open slots light column by column (i/n x 0.77 of 900ms), then the chosen one is pressed */
.mo:not(.mo-still) .rv.sched .sc-t:not(.off) { transition: opacity 144ms ease-out, background-color 320ms var(--e-press), color 320ms var(--e-press), scale 320ms var(--e-press); transition-delay: var(--sd, 0ms); }
.mo:not(.mo-still) .rv.sched:not(.in) .sc-t:not(.off) { opacity: .25; transition: none; }
.mo:not(.mo-still) .sched .sc-t.wait { background: transparent; color: inherit; box-shadow: inset 0 0 0 1px var(--paper-a14); }
.mo:not(.mo-still) .sched .sc-t.press { scale: .95; }
/* one-pager: the outcome icons draw on (the SLA figure stays still: a count would move the word beside it) */
.sla-n span { font-variant-numeric: tabular-nums; }

/* ---- 31 Oct review fixes ---- */
/* the tier planes fit their frame (the 3D corners were clipped at x627); the lower plane's label sits under it, clear of the top plane */
.dstage { transform: rotateX(56deg) rotateZ(-32deg) translateY(-20px) scale(.8); }
.tierx[data-depth="2"] .dp1 .dpl { top: auto; bottom: -30px; }
/* a tier change: the planes leave first (200ms ease-in, rule 6), then come back on the 900ms list timeline */
.mo:not(.mo-still) .rv.dstage.out .dp { opacity: 0; transition: opacity 200ms ease-in; }
.mo:not(.mo-still) .rv.dstage.rp svg { transition-duration: 900ms; transition-delay: 0ms; }
/* the scheduler film starts from no pick at all; the press is its own 320ms beat */
.mo:not(.mo-still) .rv.sched:not(.in) .sc-t.on { background: transparent; color: inherit; box-shadow: inset 0 0 0 1px var(--paper-a14); }
/* Services: four service areas as a 2 x 2 with the Safeguard link across the foot (no orphan row); every use case open, nothing jumps on hover */
@media (min-width: 761px) { .open3 { grid-template-columns: repeat(2, minmax(0, 1fr)); } .open3 .ox { grid-column: 1 / -1; } }
.rows.exp .more { grid-template-rows: 1fr; } .rows.exp .more > p { padding-top: 16px; }
.rows.exp li { transition: none; }
/* posts: a reading measure, quotes set as quotes */
.docbody .doc > * { max-width: 33em; }
.doc blockquote { margin: 36px 0; padding: 2px 0 2px 26px; border-left: 3px solid var(--deep); }
.doc blockquote p { margin: 0; font: 500 21px/1.5 var(--f-d); letter-spacing: -.005em; color: var(--navy); }
.doc blockquote cite { margin-top: 12px; }
/* legal pages: a jump (contents link, 'Read the …') lands its heading below the pinned nav, not under it */
html { scroll-padding-top: 88px; }
@media (max-width: 760px) { html { scroll-padding-top: 76px; } }
/* a 16px legal text at a readable measure (it ran 105-112 characters a line) */
.legaldoc { max-width: 32em; }
/* the contents box: no fade over its last entries */
.htoc { -webkit-mask-image: none; mask-image: none; }
/* on a phone the contents fold into the hero, under the button (the side list does not fit) */
.mtoc { display: none; }
@media (max-width: 760px) {
  .mtoc { display: block; margin-top: 24px; background: var(--raised-a); border-radius: 14px; box-shadow: inset 0 0 0 1px var(--paper-a08); padding: 4px 18px; max-height: 46svh; overflow: auto; }
  .mtoc summary { cursor: pointer; padding: 14px 0; font: 700 12px var(--f-b); letter-spacing: .14em; text-transform: uppercase; color: var(--mist); }
  .mtoc ol { padding-bottom: 12px; display: flex; flex-direction: column; } .mtoc a { display: block; padding: 7px 0; color: var(--mist); font-size: 15px; }
}
/* thank-you: its mark assembles like every other figure */
.mo:not(.mo-still) .rv.tk-art svg.grid { transition-delay: 100ms; }
/* ---- re-review fixes ---- */
/* the planes fit their frame in both depths and on a phone: depth 1 lifts the faded plane less, the phone stage is smaller */
.tierx[data-depth="1"] .dp2 { transform: translateZ(140px); }
@media (max-width: 760px) { .dstage { transform: rotateX(56deg) rotateZ(-32deg) translateY(34px) scale(.6); } .depth { height: 360px; }
  .dp2, .tierx[data-depth="1"] .dp2 { transform: translateZ(110px); } }
/* the exit only fades (no 500ms slide under it) */
.mo:not(.mo-still) .rv.dstage.out .dp { transition: opacity 200ms ease-in, transform 0ms; }
/* contents boxes hold the whole list at desktop heights */
.htoc { max-height: calc(100svh - 200px); }
/* before the scheduler film, every slot sits back, the struck ones too */
.mo:not(.mo-still) .rv.sched:not(.in) .sc-t.off { opacity: .25; }
.mo:not(.mo-still) .rv.sched .sc-t.off { transition: opacity 144ms ease-out; }
.tierx[data-depth="1"] .dp { left: 13%; width: 74%; }
@media (max-width: 760px) { .tierx[data-depth="1"] .dp { left: 16%; width: 72%; } }

/* ======== entrances (Raph, 31 Oct: everything animates in; second note: real text animation, seen as it happens) ======== */
/* blocks (cards, panels, boxes, buttons) rise, settle from a slight scale and come out of a blur, on the long intro curve */
.mo:not(.mo-still) .en:not(.eok):not(.xt) { transition: opacity 900ms var(--e-intro), translate 900ms var(--e-intro), scale 900ms var(--e-intro), filter 900ms var(--e-intro); transition-delay: var(--ed, 0ms); }
.mo:not(.mo-still) .en:not(.ein):not(.xt) { opacity: 0; translate: 0 40px; scale: .97; filter: blur(4px); transition: none; }
.mo:not(.mo-still) .en.enb:not(.ein):not(.xt) { filter: none; }   /* many blocks at once: no blur, the frame budget goes to the text */
.mo:not(.mo-still) .en.ein:not(.eok):not(.xt) { will-change: translate, scale, opacity, filter; }
.mo:not(.mo-still) .pill.en:not(.ein) { translate: 0 18px; scale: .9; filter: blur(4px); }
/* text: the element stays put; its letters or words do the moving */
.mo:not(.mo-still) .xt .sw { display: inline-block; }
.mo:not(.mo-still) .xt .sc { display: inline-block; }
.mo:not(.mo-still) .xt.lk { white-space: nowrap; }   /* lines locked at the browser's own breaks while the text is split */
/* headlines: each word is a clipped line; its letters rise into it on an offset, with a small turn that settles */
.mo:not(.mo-still) .xtc .sw { overflow: clip; overflow-clip-margin: .22em; padding-bottom: .06em; margin-bottom: -.06em; vertical-align: top; }
.mo:not(.mo-still) .xtc .sc { transform-origin: 0 100%; transition: translate 800ms var(--e-rise), rotate 800ms var(--e-rise), opacity 360ms var(--e-arrive); transition-delay: calc(var(--ed, 0ms) + var(--ci, 0) * var(--cs, 22ms)); }
.mo:not(.mo-still) .xtc:not(.ein) .sc, .mo:not(.mo-still) .en:not(.ein) .xtc .sc { translate: 0 112%; rotate: 7deg; opacity: 0; transition: none; }
/* body copy (Raph, 1 Nov: not the letters again): line by line, each line slides up and settles in turn, no blur */
.mo:not(.mo-still) .xtw .sc { transition: opacity 700ms var(--e-arrive), translate 900ms var(--e-intro); transition-delay: calc(var(--ed, 0ms) + var(--li, 0) * var(--ls, 80ms)); }
.mo:not(.mo-still) .xtw:not(.ein) .sc, .mo:not(.mo-still) .en:not(.ein) .xtw .sc { opacity: 0; translate: 0 .7em; transition: none; }
/* the chain draws its rail, then each step lands in turn */
.mo:not(.mo-still) .hexsteps::before { transform-origin: left center; transition: transform 1100ms var(--e-intro) 150ms; }
.mo:not(.mo-still) .hexsteps:not(.hin)::before { transform: scaleX(0); transition: none; }
.mo:not(.mo-still) .hexsteps li { transition: opacity 500ms var(--e-arrive), translate 500ms var(--e-arrive), scale 500ms cubic-bezier(.34,1.56,.64,1); transition-delay: calc(250ms + var(--i) * 150ms); }
.mo:not(.mo-still) .hexsteps:not(.hin) li { opacity: 0; translate: 0 14px; scale: .7; transition: none; }
/* the first screen's words stay hidden from first paint until the entrance takes them (no show, vanish, replay on a slow network) */
.mo-in .first .hero :is(.label, .kick, .crumb, h1, p, .ctas, .docmeta, .mtoc, .thanks > *):not(.ein) { opacity: 0; }
