/* Motion: hidden initial states, scoped to html.motion, which the shell's
   gate adds only when the visitor does not prefer reduced motion and the
   loader has not given up. Without the class nothing here applies. */

html.motion [data-reveal] { opacity: 0; transform: translateY(24px); }
html.motion [data-reveal="stagger"] { opacity: 1; transform: none; }
html.motion [data-reveal="stagger"] > * { opacity: 0; transform: translateY(24px); }
html.motion [data-count] { font-variant-numeric: tabular-nums; }

/* Pinned sections hide their steps only while motion.js is actually driving
   them. The mark is data-pin-armed, which motion.js sets inside a
   gsap.matchMedia("(min-width: 768px)") branch and removes when that branch
   is reverted. Keying these rules off the mark rather than off a media query
   of their own means the stylesheet and the script can never disagree: a
   phone rotated into landscape, or a desktop window narrowed below 768px,
   loses the mark and the hidden state in the same frame it loses the
   timeline. */
html.motion [data-pin-armed] [data-step] { opacity: 0; transform: translateY(30px); }

/* The cinematic hero. Without html.motion, or without the armed mark, it is a
   tall photo hero with the three proofs listed under the headline. */
.hero-cinema { min-height: 100svh; align-items: center; }
.hero-media { position: absolute; inset: -8% 0; overflow: hidden; }
.hero-media .hero-bg, .hero-media .hero-video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.hero-media .hero-video { opacity: 0; transition: opacity .8s; }
html.motion .hero-media .hero-video { opacity: 1; }
.hero-dim { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(31,26,23,.35), rgba(31,26,23,.9)); opacity: .55; }
.hero-cinema .hero-body { padding-top: clamp(96px, 16vh, 180px); }
.hero-steps { position: relative; z-index: 1; width: min(1160px, 100% - 2 * var(--gutter)); margin: 0 auto; padding-bottom: 48px; display: grid; gap: 32px; }
.hero-step { max-width: 44ch; }
.hero-step h2 { color: #fff; }
.hero-step p { color: #E6DDD1; font-size: 1.1rem; }
.hero-step .eyebrow { color: var(--gold); }
html.motion [data-pin-armed] .hero-steps { position: absolute; inset: 0; display: grid; place-items: center; padding: 0 var(--gutter); pointer-events: none; }
html.motion [data-pin-armed] .hero-step { grid-area: 1 / 1; text-align: center; }
@media (max-width: 767px) { .hero-media { inset: 0; } }

/* Drawings and figures */
.art { margin: 0; color: var(--ink-soft); }
.art svg { width: 100%; height: auto; }
.art figcaption { font: 500 .85rem/1.5 var(--sans); color: var(--ink-soft); margin-top: 10px; }
.art-tall { max-width: 320px; margin-inline: auto; }
.band-dark .art { color: #CFC5B8; }
.cards.one { grid-template-columns: 1fr; }
.split.wide-left { grid-template-columns: minmax(0, 2fr) minmax(260px, 1fr); align-items: center; }
@media (max-width: 760px) { .split.wide-left { grid-template-columns: 1fr; } }
.stat { display: flex; align-items: baseline; gap: 14px; margin: .2em 0; }
.stat .num { font: 600 clamp(2rem, 4vw, 3rem)/1 var(--serif); color: var(--ember); letter-spacing: -.01em; }
.stat .lbl { color: var(--ink-soft); }

/* Pinned sequences */
.pin-grid { display: grid; gap: 40px; grid-template-columns: minmax(0, 1fr) minmax(280px, 460px); align-items: center; }
.pin-steps { display: grid; gap: 40px; }
.pin-step { max-width: 46ch; }
.pin-figure { margin: 0; }
html.motion .band.pin[data-pin-armed] { min-height: 100svh; display: flex; align-items: center; }
html.motion [data-pin-armed] .pin-steps { align-content: center; min-height: 40vh; }
html.motion [data-pin-armed] .pin-step { grid-area: 1 / 1; }
@media (max-width: 860px) {
  .pin-grid { grid-template-columns: 1fr; }
  .pin-figure { max-width: 360px; margin-inline: auto; }
}

html.motion .card-shift { transform: scale(1.12); }

/* Reveal variants. motion.js animates every kind home to opacity 1, no offset,
   full size; these are only where each one starts. */
html.motion [data-reveal="left"] { opacity: 0; transform: translateX(-44px); }
html.motion [data-reveal="right"] { opacity: 0; transform: translateX(52px) scale(.95); }
html.motion [data-reveal="tiles"], html.motion [data-reveal="rows"] { opacity: 1; transform: none; }
html.motion [data-reveal="tiles"] > * { opacity: 0; transform: translateY(20px) scale(.93); }
html.motion [data-reveal="rows"] tbody tr { opacity: 0; transform: translateY(10px); }

/* Hero entrance: pure CSS, so the headline never waits on a script. The
   keyframes name only where things start; they finish wherever the element's
   own styles put it, which is why the phone's ghosted hero art still works. */
@keyframes hero-rise { from { opacity: 0; transform: translateY(24px); } }
@keyframes art-in { from { opacity: 0; transform: translateX(70px) scale(.93); } }
@keyframes art-float { from { transform: translateY(-7px); } to { transform: translateY(7px); } }
@keyframes lines-in { from { opacity: 0; } }
html.motion .hero-body > * { animation: hero-rise .9s cubic-bezier(.2, .7, .2, 1) backwards; }
html.motion .hero-body > *:nth-child(1) { animation-delay: .05s; }
html.motion .hero-body > *:nth-child(2) { animation-delay: .16s; }
html.motion .hero-body > *:nth-child(3) { animation-delay: .30s; }
html.motion .hero-body > *:nth-child(4) { animation-delay: .44s; }
html.motion .hero-art { animation: art-in 1.1s .2s cubic-bezier(.2, .7, .2, 1) backwards, art-float 6s 1.5s ease-in-out infinite alternate; }
html.motion .hero-lines { animation: lines-in 1.8s .1s backwards; }

/* Scroll progress: a thin ember line on the header's lower edge */
.scroll-progress { display: none; }
html.motion .scroll-progress { display: block; position: absolute; left: 0; right: 0; bottom: -3px; height: 3px; background: var(--ember); transform: scaleX(0); transform-origin: 0 50%; pointer-events: none; }

/* Reveals play as CSS transitions, not script tweens: opacity and transform
   transitions run on the compositor, so a slow main thread cannot make the
   scroll stutter while a table arrives row by row. motion.js only numbers the
   children (--i) and adds .in when the element comes into view; .done follows
   once everything has landed, handing hover transitions back to site.css. */
html.motion [data-reveal]:not(.done),
html.motion [data-reveal="stagger"]:not(.done) > *,
html.motion [data-reveal="tiles"]:not(.done) > *,
html.motion [data-reveal="rows"]:not(.done) tbody tr {
  transition: opacity .9s cubic-bezier(.22, 1, .36, 1), transform .9s cubic-bezier(.22, 1, .36, 1);
}
html.motion [data-reveal="stagger"]:not(.done) > * { transition-delay: calc(var(--i, 0) * 120ms); }
html.motion [data-reveal="tiles"]:not(.done) > * { transition-duration: .7s; transition-timing-function: ease-out, cubic-bezier(.34, 1.56, .64, 1); transition-delay: calc(var(--i, 0) * 90ms); }
html.motion [data-reveal="rows"]:not(.done) tbody tr { transition-duration: .5s; transition-delay: calc(var(--i, 0) * 60ms); }
html.motion [data-reveal="left"]:not(.done), html.motion [data-reveal="right"]:not(.done) { transition-duration: 1.1s; transition-timing-function: cubic-bezier(.16, 1, .3, 1); }
html.motion [data-reveal].in,
html.motion [data-reveal="stagger"].in > *,
html.motion [data-reveal="tiles"].in > *,
html.motion [data-reveal="rows"].in tbody tr { opacity: 1; transform: none; }
