/* ==========================================================================
   Bonus Missions - landing page
   Type: Bricolage Grotesque (display) + Archivo (text), self-hosted.
   Radius rule: buttons + inputs are pill, everything else is 14px.
   Accent: one signal orange, used identically in every section.
   ========================================================================== */

/* ---------- Fonts ---------- */
@font-face {
  font-family: "Bricolage Grotesque";
  src: url("../fonts/bricolage-latin.woff2") format("woff2");
  font-weight: 200 800;
  font-stretch: 75% 100%;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Archivo";
  src: url("../fonts/archivo-latin.woff2") format("woff2");
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ---------- Tokens ---------- */
:root {
  /* White page, neutral greys, one orange accent. Locked to light: the
     brand commits to this, so there is no dark variant to drift against. */
  --bg:        #FFFFFF;
  --bg-2:      #F5F5F4;
  --bg-3:      #E8E8E6;
  --ink:       #16161A;
  --ink-2:     #56565C;
  --line:      rgba(22, 22, 26, 0.14);
  --line-2:    rgba(22, 22, 26, 0.07);
  --accent:    #C93F0D;
  --accent-dim: rgba(201, 63, 13, 0.09);
  --on-accent: #FFFFFF;
  --danger:    #A3300B;
  /* Deeper step of the accent, for large filled surfaces only. */
  --panel-deep: #A6330A;

  --radius:    14px;
  --pill:      999px;

  --font-display: "Bricolage Grotesque", "Archivo", system-ui, sans-serif;
  --font-text: "Archivo", system-ui, -apple-system, "Segoe UI", sans-serif;

  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --gutter: clamp(1.25rem, 5vw, 4.5rem);
  --section: clamp(3.25rem, 7vw, 6rem);
  --maxw: 1280px;
  --stagger: 55ms;

  color-scheme: light;
  /* Lets the FAQ animate from 0 to auto height. Ignored where unsupported. */
  interpolate-size: allow-keywords;
}

/* ---------- 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);
  color: var(--ink);
  font-family: var(--font-text);
  font-size: clamp(1rem, 0.96rem + 0.2vw, 1.0625rem);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img, svg { display: block; max-width: 100%; }
button, input, textarea { font: inherit; color: inherit; }
a { color: inherit; text-decoration: none; }

::selection { background: var(--accent); color: var(--on-accent); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}

/* Grain is deliberately absent. On a white page it reads as dirt, not
   texture. The paper stays clean. */

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 200;
  background: var(--accent);
  color: var(--on-accent);
  padding: 0.75rem 1.25rem;
  border-radius: var(--pill);
  font-weight: 600;
}
.skip:focus { left: 1rem; top: 1rem; }

/* ---------- Layout primitives ---------- */
.wrap {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.section { padding-block: var(--section); }
/* Where one padded section follows another, the second drops its top padding
   so the two do not stack into a double gap. */
.section--flush { padding-top: 0; }

/* Anchor targets clear the sticky nav. Without this an in-page jump parks
   the section under the 68px header and the heading is simply gone. */
:where(#top, #missions, #how, #faq, #waitlist, #main) { scroll-margin-top: calc(68px + 1.5rem); }

/* Vertical rhythm for stacked prose. More space above a heading than below
   it, and a tighter step between sibling paragraphs than after a heading. */
h2 + .lede,
h3 + .lede,
.eyebrow + .lede { margin-top: clamp(1rem, 2vw, 1.4rem); }
.lede + .lede { margin-top: clamp(0.85rem, 1.7vw, 1.2rem); }

/* ---------- Type ---------- */
h1, h2, h3, .display {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.032em;
  line-height: 1.02;
  text-wrap: balance;
}
h2 { font-size: clamp(2.15rem, 1.4rem + 3.4vw, 4.15rem); }
h3 { font-size: clamp(1.35rem, 1.15rem + 0.9vw, 1.85rem); letter-spacing: -0.022em; line-height: 1.15; }

.lede {
  font-size: clamp(1.09rem, 1rem + 0.5vw, 1.35rem);
  line-height: 1.55;
  color: var(--ink-2);
  max-width: 54ch;
}
.muted { color: var(--ink-2); }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  white-space: nowrap;
  padding: 0.95rem 1.7rem;
  border: 1px solid transparent;
  border-radius: var(--pill);
  background: var(--accent);
  color: var(--on-accent);
  font-family: var(--font-text);
  font-weight: 600;
  font-size: 1rem;
  letter-spacing: -0.005em;
  cursor: pointer;
  transition: transform 0.35s var(--ease), box-shadow 0.35s var(--ease),
    background 0.25s ease;
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.16) inset,
    0 10px 26px -14px rgba(201, 63, 13, 0.65);
}
.btn:hover { transform: translateY(-2px); box-shadow: 0 1px 0 rgba(255,255,255,.18) inset, 0 16px 34px -14px rgba(201,63,13,.7); }
.btn:active { transform: scale(0.98) translateY(0); }
.btn[disabled] { opacity: 0.6; cursor: not-allowed; transform: none; }

.btn--ghost {
  background: transparent;
  color: var(--ink);
  border-color: var(--line);
  box-shadow: none;
}
.btn--ghost:hover { background: var(--bg-2); border-color: var(--ink-2); box-shadow: none; }

.btn--lg { padding: 1.1rem 2.1rem; font-size: 1.06rem; }
.btn .ico { width: 1.15em; height: 1.15em; fill: currentColor; flex: none; }

/* ---------- Nav ---------- */
.nav {
  position: sticky;
  top: 0;
  z-index: 80;
  height: 68px;
  display: flex;
  align-items: center;
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: blur(14px) saturate(150%);
  -webkit-backdrop-filter: blur(14px) saturate(150%);
  border-bottom: 1px solid transparent;
  transition: border-color 0.3s ease, background 0.3s ease;
}
.nav.is-stuck { border-bottom-color: var(--line-2); }
@media (prefers-reduced-transparency: reduce) {
  .nav { background: var(--bg); backdrop-filter: none; -webkit-backdrop-filter: none; }
}
.nav__in {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gutter);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
}
.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.06rem;
  letter-spacing: -0.03em;
}
.brand { padding-block: 0.62rem; }
.brand__mark { width: 26px; height: 26px; flex: none; }
.nav__links { display: none; gap: 1.5rem; font-size: 0.94rem; color: var(--ink-2); }
.nav__links a { transition: color 0.2s ease; padding: 0.68rem 0.4rem; }
.nav__links a:hover { color: var(--ink); }
.nav .btn { padding: 0.62rem 1.15rem; font-size: 0.92rem; box-shadow: none; }
@media (min-width: 900px) { .nav__links { display: flex; } }

/* ==========================================================================
   HERO
   Split on the white page: copy plus a three-up fact row on the left, a
   three-photo collage on the right with one floating card.
   Fixed 600px tall once the two columns are side by side.
   ========================================================================== */
.hero {
  display: grid;
  align-items: center;
  /* Tight top and bottom. The 600px box does the spacing work, not padding. */
  padding-block: clamp(0.5rem, 1.5vw, 1rem);
}
/* 600px applies only where the split layout fits it. Below this the hero
   stacks and must be free to grow, or the content would be clipped. */
@media (min-width: 1000px) {
  .hero { height: 600px; }
}

.hero__grid { width: 100%; display: grid; gap: clamp(2.25rem, 5vw, 3.5rem); }
@media (min-width: 1000px) {
  .hero__grid {
    grid-template-columns: 1.06fr 0.94fr;
    align-items: center;
    column-gap: clamp(2rem, 4vw, 4rem);
  }
}

/* ---- Left column ---- */
.hero h1 {
  font-size: clamp(2.3rem, 1.15rem + 3.6vw, 3.65rem);
  font-weight: 800;
  max-width: 18ch;
}
/* Emphasis stays in the same family, accent colour only. */
.hero h1 .hi { color: var(--accent); }

.hero__lede {
  margin-top: clamp(1rem, 2vw, 1.4rem);
  font-size: clamp(1.02rem, 0.96rem + 0.35vw, 1.16rem);
  line-height: 1.6;
  color: var(--ink-2);
  max-width: 46ch;
}
.hero__cta {
  margin-top: clamp(1.5rem, 3vw, 2rem);
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem;
}

/* ---- Fact row ----
   Three statements, hairline separated. Deliberately words rather than
   metrics: a pre-launch product has no learner counts or ratings to quote,
   so there is not a single number here to invent. */
.facts {
  margin-top: clamp(1.75rem, 3.5vw, 2.5rem);
  display: grid;
  grid-template-columns: repeat(3, auto);
  justify-content: start;
}
.fact {
  padding-inline: clamp(1rem, 2.5vw, 2rem);
  border-left: 1px solid var(--line);
}
.fact:first-child { padding-left: 0; border-left: 0; }
.facts dt {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.2rem, 1.05rem + 0.6vw, 1.6rem);
  letter-spacing: -0.028em;
  line-height: 1.1;
}
.facts dd { margin-top: 0.2rem; font-size: 0.85rem; color: var(--ink-2); }

/* ---- Collage ---- */
.collage {
  position: relative;
  display: grid;
  grid-template-columns: 1.3fr 0.82fr;
  grid-template-rows: repeat(2, minmax(0, 1fr));
  gap: clamp(0.55rem, 1.2vw, 0.8rem);
  /* Capped so it always sits inside the 600px hero with room for the
     floating card to overhang the bottom edge. */
  height: clamp(300px, 46vh, 440px);
}
.collage__main { grid-column: 1; grid-row: 1 / 3; }
.collage__a { grid-column: 2; grid-row: 1; }
.collage__b { grid-column: 2; grid-row: 2; }
.collage .shot { border: 0; min-height: 0; }
.collage .shot img { object-position: 50% 28%; }

/* Floating card overlapping the tall photo, where the reference puts its
   rating pill. Holds an illustrative mission rather than invented numbers. */
.floatcard {
  position: absolute;
  z-index: 3;
  left: clamp(0.75rem, 5%, 2.25rem);
  bottom: clamp(-1.5rem, -4%, -0.6rem);
  max-width: 15.5rem;
  padding: 0.85rem 1.1rem 0.95rem;
  background: var(--bg);
  border: 1px solid var(--line-2);
  border-radius: var(--radius);
  box-shadow: 0 22px 44px -20px rgba(0, 0, 0, 0.3);
}
.floatcard__k {
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--accent);
}
.floatcard__t {
  margin-top: 0.3rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.04rem;
  letter-spacing: -0.022em;
  line-height: 1.18;
}
.floatcard__m { margin-top: 0.25rem; font-size: 0.8rem; color: var(--ink-2); }

/* Mobile: collage becomes one wide shot over two squares, card sits under. */
@media (max-width: 999px) {
  .collage {
    height: auto;
    /* Equal columns here, or the two squares come out different sizes. */
    grid-template-columns: 1fr 1fr;
    grid-template-rows: auto auto auto;
  }
  .collage__main { grid-column: 1 / -1; grid-row: 1; aspect-ratio: 16 / 11; }
  .collage__a { grid-column: 1; grid-row: 2; aspect-ratio: 1; }
  .collage__b { grid-column: 2; grid-row: 2; aspect-ratio: 1; }
  .floatcard {
    position: static;
    grid-column: 1 / -1;
    grid-row: 3;
    max-width: none;
    box-shadow: none;
    margin-top: 0.2rem;
  }
}

/* ---------- Photo slot ---------- */
/* Shows a designed, labelled placeholder until a real file is dropped in.
   The image element removes itself on error, revealing the frame beneath. */
.shot {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background:
    linear-gradient(135deg, var(--accent-dim), transparent 55%),
    repeating-linear-gradient(
      -45deg,
      var(--bg-2) 0 12px,
      var(--bg-3) 12px 24px
    );
  display: grid;
  place-items: center;
  min-height: 120px;
}
.shot img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 2;
}
.shot::after {
  content: attr(data-shot);
  display: block;
  padding: 1.25rem;
  max-width: 26ch;
  text-align: center;
  font-size: 0.8rem;
  line-height: 1.45;
  color: var(--ink-2);
  letter-spacing: 0.01em;
}
/* 11:5 rather than a thinner letterbox, so the community photo keeps its
   people instead of being cropped to a strip. */
.shot--wide { aspect-ratio: 11 / 5; }

/* ---------- Marquee (one per page) ---------- */
.marquee {
  border-block: 1px solid var(--line-2);
  padding-block: clamp(1.5rem, 3vw, 2.4rem);
  overflow: hidden;
  background: var(--bg-2);
}
.marquee__label {
  padding-inline: var(--gutter);
  max-width: var(--maxw);
  margin: 0 auto clamp(1.2rem, 2.5vw, 1.9rem);
  font-size: clamp(1.25rem, 1.05rem + 0.85vw, 1.7rem);
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -0.026em;
}
.marquee__track {
  display: flex;
  width: max-content;
  gap: 0;
  animation: slide 42s linear infinite;
}
.marquee:hover .marquee__track { animation-play-state: paused; }
.marquee__set { display: flex; align-items: center; gap: 0; flex: none; }
.marquee__item {
  display: inline-flex;
  align-items: center;
  gap: 1.4rem;
  padding-inline: 1.4rem;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.5rem, 1.1rem + 1.8vw, 2.7rem);
  letter-spacing: -0.03em;
  white-space: nowrap;
  color: var(--ink);
}
.marquee__item::after {
  content: "";
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--accent);
  flex: none;
}
@keyframes slide { to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) {
  .marquee__track { animation: none; }
  .marquee { overflow-x: auto; }
}

/* ---------- Editorial statement ---------- */
.statement__grid { display: grid; gap: clamp(2.5rem, 6vw, 5rem); }
@media (min-width: 900px) { .statement__grid { grid-template-columns: 1fr 1fr; align-items: end; } }

.loop {
  list-style: none;
  padding: 0;
  margin-top: clamp(2rem, 4vw, 3rem);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(2rem, 1.2rem + 3.6vw, 3.6rem);
  letter-spacing: -0.035em;
  line-height: 1.14;
}
.loop li { color: var(--ink-2); opacity: 0.42; transition: opacity 0.7s var(--ease), color 0.7s var(--ease); }
.loop li:last-child { color: var(--accent); opacity: 1; }
.reveal.in .loop li { opacity: 1; }
/* Faded enough to read as "the routine blurs together", but still above the
   3:1 large-text contrast floor. Do not lower this. */
.reveal.in .loop li:not(:last-child) { color: var(--ink); opacity: 0.52; }

/* ---------- Bento grid ---------- */
.bento {
  display: grid;
  gap: 0.9rem;
  grid-template-columns: 1fr;
  margin-top: clamp(1.5rem, 3vw, 2.25rem);
}
@media (min-width: 700px) { .bento { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .bento { grid-template-columns: repeat(4, 1fr); } }

.tile {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: clamp(1.4rem, 2.4vw, 1.9rem);
  background: var(--bg-2);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: 168px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.1rem, 1rem + 0.45vw, 1.35rem);
  letter-spacing: -0.024em;
  line-height: 1.18;
  transition: transform 0.45s var(--ease), border-color 0.45s var(--ease);
}
.tile:hover { transform: translateY(-4px); border-color: var(--ink-2); }
.tile--accent { background: var(--accent); color: var(--on-accent); border-color: transparent; }
.tile--tint { background: var(--accent-dim); border-color: transparent; }
.tile--shot { padding: 0; overflow: hidden; min-height: 168px; }
.tile--shot .shot { border: 0; border-radius: 0; height: 100%; width: 100%; }
@media (min-width: 1000px) {
  .tile--w2 { grid-column: span 2; }
  .tile--h2 { grid-row: span 2; }
}

/* ---------- Steps (staggered offsets) ---------- */
.steps {
  display: grid;
  gap: clamp(2rem, 4vw, 2.5rem);
  margin-top: clamp(1.75rem, 3.5vw, 2.75rem);
  counter-reset: step;
}
@media (min-width: 760px) { .steps { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1060px) { .steps { grid-template-columns: repeat(4, 1fr); } }

.step { position: relative; padding-top: 2.6rem; border-top: 1px solid var(--line); }
/* Staircase offset is margin, not transform, so the reveal animation can own
   translate without flattening the composition. */
@media (min-width: 1060px) {
  .step:nth-child(2) { margin-top: 2.2rem; }
  .step:nth-child(3) { margin-top: 4.4rem; }
  .step:nth-child(4) { margin-top: 6.6rem; }
}
.step__ico {
  position: absolute;
  top: 1.5rem;
  right: 0;
  width: 1.55rem;
  height: 1.55rem;
  fill: var(--accent);
  opacity: 0.9;
}
.step h3 { margin-bottom: 0.7rem; }
.step p { color: var(--ink-2); max-width: 32ch; }
.step::before {
  counter-increment: step;
  content: counter(step, decimal-leading-zero);
  position: absolute;
  top: 1.35rem;
  left: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.86rem;
  letter-spacing: 0.04em;
  color: var(--accent);
}

/* ---------- Full-bleed band ---------- */
.band { position: relative; padding-block: var(--section); background: var(--bg-2); border-block: 1px solid var(--line-2); }
/* Separation between the band's prose and its wide image. */
.band__media { margin-top: clamp(2.25rem, 4.5vw, 3.5rem); }
.band__grid { display: grid; gap: clamp(2rem, 5vw, 4rem); align-items: center; }
@media (min-width: 900px) { .band__grid { grid-template-columns: 0.9fr 1.1fr; } }
.band h2 { max-width: 14ch; }
.band p + p { margin-top: 1.1rem; }

/* ---------- Benefits (2-col, hairline divided) ---------- */
.benefits { display: grid; gap: 0; margin-top: clamp(1.5rem, 3vw, 2.25rem); }
@media (min-width: 780px) { .benefits { grid-template-columns: 1fr 1fr; column-gap: clamp(2.5rem, 5vw, 5rem); } }
.benefit {
  display: flex;
  align-items: flex-start;
  gap: 1.15rem;
  padding-block: clamp(1.4rem, 2.6vw, 1.9rem);
  border-bottom: 1px solid var(--line-2);
}
.benefit__ico {
  width: 1.6rem;
  height: 1.6rem;
  flex: none;
  fill: var(--accent);
  margin-top: 0.15rem;
}
.benefit h3 { font-size: clamp(1.15rem, 1.05rem + 0.4vw, 1.4rem); margin-bottom: 0.3rem; }
.benefit p { color: var(--ink-2); font-size: 0.97rem; }

/* ---------- Manifesto (centered scroll reveal) ---------- */
.manifesto { text-align: center; }
/* Centred intro line above the manifesto stack. */
.manifesto__intro { margin: clamp(1.1rem, 2.2vw, 1.5rem) auto 0; text-align: center; }
.manifesto__lines {
  list-style: none;
  padding: 0;
  margin-top: clamp(1.5rem, 3vw, 2.25rem);
  display: grid;
  gap: clamp(0.75rem, 1.5vw, 1.15rem);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.35rem, 0.95rem + 1.9vw, 2.5rem);
  letter-spacing: -0.03em;
  line-height: 1.16;
  max-width: 22ch;
  margin-inline: auto;
}
.js .manifesto__lines li { opacity: 0; transform: translateY(18px); transition: opacity 0.75s var(--ease), transform 0.75s var(--ease); }
.manifesto__lines.in li { opacity: 1; transform: none; }
.manifesto__lines.in li:nth-child(1) { transition-delay: 0.04s; }
.manifesto__lines.in li:nth-child(2) { transition-delay: 0.14s; }
.manifesto__lines.in li:nth-child(3) { transition-delay: 0.24s; }
.manifesto__lines.in li:nth-child(4) { transition-delay: 0.34s; }
.manifesto__lines.in li:nth-child(5) { transition-delay: 0.44s; }
.manifesto__lines.in li:nth-child(6) { transition-delay: 0.54s; }
.manifesto__lines .hi { color: var(--accent); }
.manifesto__tail { margin-top: clamp(1.5rem, 3vw, 2.25rem); color: var(--ink-2); font-size: 1.1rem; }

/* ---------- Waitlist form ---------- */
.waitlist { background: var(--bg-2); border-block: 1px solid var(--line-2); }
.waitlist__grid { display: grid; gap: clamp(2.5rem, 5vw, 4.5rem); align-items: start; }
@media (min-width: 940px) { .waitlist__grid { grid-template-columns: 1fr 1fr; } }

.card {
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: clamp(1.5rem, 3.5vw, 2.4rem);
}
.field { display: grid; gap: 0.5rem; margin-bottom: 1.15rem; }
.field label { font-size: 0.92rem; font-weight: 600; letter-spacing: -0.006em; }
.field input {
  width: 100%;
  padding: 0.9rem 1.15rem;
  border-radius: var(--pill);
  border: 1px solid var(--line);
  background: var(--bg-2);
  color: var(--ink);
  transition: border-color 0.2s ease, background 0.2s ease;
}
.field input::placeholder { color: var(--ink-2); opacity: 0.85; }
.field input:hover { border-color: var(--ink-2); }
.field input:focus { outline: none; border-color: var(--accent); background: var(--bg); }
.field .hint { font-size: 0.83rem; color: var(--ink-2); }
.field .err { font-size: 0.83rem; color: var(--danger); font-weight: 500; min-height: 0; }
.field.is-bad input { border-color: var(--danger); }
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.form__foot { margin-top: 1.5rem; display: grid; gap: 0.9rem; }
.form__foot .btn { width: 100%; }
.form__note { font-size: 0.85rem; color: var(--ink-2); text-align: center; }

.spinner {
  width: 1.05em; height: 1.05em; flex: none;
  border: 2px solid color-mix(in srgb, var(--on-accent) 35%, transparent);
  border-top-color: var(--on-accent);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.btn:not(.is-loading) .spinner { display: none; }
.btn.is-loading .btn__text { opacity: 0.85; }

.formmsg { display: none; border-radius: var(--radius); padding: 1.1rem 1.25rem; font-size: 0.95rem; margin-bottom: 1.25rem; }
.formmsg.is-on { display: block; }
.formmsg--ok { background: var(--accent-dim); border: 1px solid var(--accent); }
.formmsg--bad { background: color-mix(in srgb, var(--danger) 12%, transparent); border: 1px solid var(--danger); }

.success { text-align: center; padding-block: 1.5rem; }
.success__ico { width: 3rem; height: 3rem; fill: var(--accent); margin: 0 auto 1.1rem; }
.success h3 { margin-bottom: 0.6rem; }
.success p { color: var(--ink-2); max-width: 34ch; margin-inline: auto; }

/* ---------- FAQ ---------- */
.faq { max-width: 820px; margin-top: clamp(1.25rem, 2.5vw, 2rem); }
.faq details { border-bottom: 1px solid var(--line-2); }
.faq summary {
  list-style: none;
  cursor: pointer;
  padding-block: clamp(1.15rem, 2.4vw, 1.6rem);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.08rem, 1rem + 0.5vw, 1.35rem);
  letter-spacing: -0.022em;
  transition: color 0.2s ease;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { color: var(--accent); }
.faq summary .ico { width: 1.15rem; height: 1.15rem; fill: var(--accent); flex: none; transition: transform 0.35s var(--ease); }
.faq details[open] summary .ico { transform: rotate(180deg); }
.faq__body { overflow: hidden; color: var(--ink-2); padding-bottom: 1.4rem; max-width: 62ch; }

/* ---------- Final CTA ----------
   A wide brand-filled panel inset on the white page. Copy left, two tilted
   photo cards bleeding off the bottom right. */
.final { padding-block: var(--section); }

.final__panel {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  border-radius: clamp(18px, 2vw, 26px);
  /* A deeper step of the brand orange. Large saturated fields need more
     depth than the button colour, and white clears 6.7:1 on this. */
  background: var(--panel-deep);
  color: #FFFFFF;
  padding: clamp(1.6rem, 4vw, 3.25rem);
  display: grid;
  gap: clamp(1.75rem, 4vw, 2.5rem);
}
@media (min-width: 900px) {
  .final__panel {
    grid-template-columns: 1.02fr 0.98fr;
    align-items: center;
    min-height: clamp(300px, 30vw, 375px);
  }
}

/* Faint graph grid, same device as the reference. Background pattern only,
   so it costs nothing to paint and never intercepts a pointer. */
.final__panel::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    repeating-linear-gradient(to right, rgba(255, 255, 255, 0.07) 0 1px, transparent 1px 74px),
    repeating-linear-gradient(to bottom, rgba(255, 255, 255, 0.07) 0 1px, transparent 1px 74px);
}

.final__panel h2 {
  font-size: clamp(1.95rem, 1.2rem + 2.4vw, 3rem);
  max-width: 20ch;
}
.final__lede {
  margin-top: clamp(0.9rem, 2vw, 1.3rem);
  font-size: clamp(0.98rem, 0.94rem + 0.25vw, 1.1rem);
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.86);
  max-width: 44ch;
}
.final__panel .btn { margin-top: clamp(1.5rem, 3vw, 2.1rem); }

/* White pill on the panel, label in the panel colour. */
.btn--onpanel {
  background: #FFFFFF;
  color: var(--panel-deep);
  box-shadow: 0 10px 26px -14px rgba(0, 0, 0, 0.5);
}
.btn--onpanel:hover {
  background: #FFFFFF;
  box-shadow: 0 16px 34px -14px rgba(0, 0, 0, 0.55);
}

/* ---- Tilted cards ---- */
.final__cards { position: relative; min-height: clamp(210px, 25vw, 285px); }
.ctacard {
  position: absolute;
  width: clamp(140px, 19vw, 205px);
  aspect-ratio: 3 / 4;
  border-radius: 16px;
  overflow: hidden;
  background: var(--bg-3);
  box-shadow: 0 30px 58px -22px rgba(0, 0, 0, 0.5);
  /* rotate, not transform, so the hover lift below can compose with it */
  transition: transform 0.6s var(--ease);
}
.ctacard img { width: 100%; height: 100%; object-fit: cover; }
/* Both sit low enough that their lowest rotated corner clears the panel
   floor, so the pair reads as bleeding off the edge rather than tucked in. */
.ctacard--back  { left: 2%;  bottom: -26%; rotate: -9deg; z-index: 1; }
.ctacard--front { left: 33%; bottom: -38%; rotate: 6deg;  z-index: 2; }

/* The pair rises a little when the panel is hovered, so the whole block
   reads as one invitation rather than a static banner. */
@media (hover: hover) {
  .final__panel:hover .ctacard { transform: translateY(-8px); }
  .final__panel:hover .ctacard--front { transform: translateY(-14px); }
}

@media (max-width: 899px) {
  .final__cards { min-height: clamp(230px, 58vw, 300px); }
  .ctacard--back  { left: 6%;  bottom: -10%; }
  .ctacard--front { left: 42%; bottom: -20%; }
}

/* ---------- Footer ---------- */
.foot { border-top: 1px solid var(--line-2); padding-block: clamp(1.75rem, 3.5vw, 2.5rem); }
.foot__in { display: flex; flex-wrap: wrap; gap: 1.25rem; align-items: center; justify-content: space-between; }
.foot__tag { color: var(--ink-2); font-size: 0.92rem; }
.foot__links { display: flex; gap: 1rem; font-size: 0.92rem; color: var(--ink-2); margin-inline: -0.5rem; }
.foot__links a { padding: 0.68rem 0.5rem; transition: color 0.2s ease; }
.foot__links a:hover { color: var(--ink); }

/* ==========================================================================
   MOTION
   Every animation below earns its place: it either establishes hierarchy,
   tells the section's story in sequence, or acknowledges a user action.
   Nothing loops forever except the single marquee.
   ========================================================================== */

/* ---------- Scroll reveal (block level) ---------- */
.js .reveal { opacity: 0; transform: translateY(22px); transition: opacity 0.7s var(--ease), transform 0.7s var(--ease); }
.reveal.in { opacity: 1; transform: none; }
.reveal--d1 { transition-delay: 0.07s; }
.reveal--d2 { transition-delay: 0.14s; }
.reveal--d3 { transition-delay: 0.21s; }

/* ---------- Staggered children ----------
   The container is observed; children animate in reading order using an
   --i index that main.js assigns. Sequence carries the meaning. */
/* Entrance uses the standalone translate/scale properties, never transform.
   That leaves transform free for hover lifts and the steps staircase, so
   the two never overwrite each other. */
.js .stagger > * { opacity: 0; translate: 0 20px; }
.stagger.in > * {
  opacity: 1;
  translate: none;
  transition: opacity 0.62s var(--ease), translate 0.62s var(--ease);
  transition-delay: calc(var(--i, 0) * var(--stagger));
}

/* Photos scale back to rest as they arrive, so the image reads as settling
   into its frame rather than blinking on. */
.js .stagger > * .shot img { opacity: 0; scale: 1.07; }
.stagger.in > * .shot img {
  opacity: 1;
  scale: 1;
  transition: opacity 0.8s var(--ease), scale 1.15s var(--ease);
  transition-delay: calc(var(--i, 0) * var(--stagger));
}

/* Accent rule draws across each step in turn: four steps, one after the
   other, which is the point of the section. */
.stagger .step::after {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  height: 1px;
  width: 100%;
  background: var(--accent);
  /* scaleX, not width: stays on the compositor and never triggers layout. */
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.75s var(--ease);
  transition-delay: calc(var(--i, 0) * var(--stagger) + 0.12s);
}
.stagger.in .step::after { transform: scaleX(1); }

/* The routine list ticks over one line at a time. */
.reveal.in .loop li { transition-delay: calc(var(--i, 0) * 70ms); }

/* ---------- Hero load-in ---------- */
.js .rise { opacity: 0; transform: translateY(22px); animation: rise 0.85s var(--ease) forwards; }
.rise--1 { animation-delay: 0.04s; }
.rise--2 { animation-delay: 0.14s; }
.rise--3 { animation-delay: 0.24s; }
.rise--4 { animation-delay: 0.30s; }
@keyframes rise { to { opacity: 1; transform: none; } }

/* Headline arrives word by word. main.js wraps each word and sets --i; if
   the script never runs, .rise above still reveals the whole line. */
.hero h1.split { opacity: 1; transform: none; animation: none; }
.hero h1.split .w {
  display: inline-block;
  opacity: 0;
  transform: translateY(0.4em);
  animation: word 0.7s var(--ease) forwards;
  animation-delay: calc(0.05s + var(--i, 0) * 40ms);
}
@keyframes word { to { opacity: 1; transform: none; } }

/* Hero photos settle in behind the words. Uses the standalone scale property,
   never transform: a forwards-filled animation would otherwise keep winning
   over the hover transform below and the zoom would never fire. */
.js .collage .shot img { opacity: 0; animation: settle 1.1s var(--ease) 0.3s forwards; }
@keyframes settle { from { opacity: 0; scale: 1.08; } to { opacity: 1; scale: 1; } }

/* ---------- Hover and interaction feedback ---------- */
.btn .ico { transition: transform 0.35s var(--ease); }
.btn:hover .ico { transform: translateX(3px); }

.nav__links a { position: relative; }
.nav__links a::after {
  content: "";
  position: absolute;
  left: 0.4rem;
  right: 0.4rem;
  bottom: 0.34rem;
  height: 1px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.35s var(--ease);
}
.nav__links a:hover::after { transform: scaleX(1); }

.tile--shot .shot img { transition: transform 0.7s var(--ease); }
.tile--shot:hover .shot img { transform: scale(1.04); }

/* Hero collage reads as a small gallery: the photo under the cursor eases up
   inside its frame while its neighbours step back, so attention follows the
   pointer. Deliberately no cursor change, these are images and not links.
   Gated on a real hover device so touch screens never get a stuck state. */
.collage .shot { transition: opacity 0.4s var(--ease); }
.collage .shot img { transition: transform 0.75s var(--ease); }
@media (hover: hover) {
  .collage:hover .shot { opacity: 0.55; }
  .collage .shot:hover { opacity: 1; }
  .collage .shot:hover img { transform: scale(1.06); }
}

/* Success is a state change, so it gets a small physical pop. */
.success__ico { animation: pop 0.5s var(--ease) both; }
@keyframes pop { from { opacity: 0; transform: scale(0.6); } to { opacity: 1; transform: none; } }

/* ---------- FAQ open/close ----------
   Progressive: browsers without ::details-content simply snap open. */
.faq details::details-content {
  block-size: 0;
  overflow: hidden;
  transition: block-size 0.38s var(--ease), content-visibility 0.38s allow-discrete;
}
.faq details[open]::details-content { block-size: auto; }

/* ---------- Scroll-driven parallax on the wide band ----------
   Native scroll timeline: no JS, no scroll listener, no main-thread cost.
   Browsers without support just show a static image. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .shot--wide img {
      scale: 1.14;
      animation: drift linear both;
      animation-timeline: view();
      animation-range: entry 0% exit 100%;
    }
    @keyframes drift {
      from { translate: 0 -4.5%; }
      to   { translate: 0 4.5%; }
    }
  }
}

/* ---------- Reduced motion ----------
   Everything above collapses to static. This is not negotiable. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    animation-delay: 0ms !important;
    transition-duration: 0.001ms !important;
    transition-delay: 0ms !important;
  }
  .reveal,
  .rise,
  .stagger > *,
  .stagger > * .shot img,
  .hero h1.split .w,
  .collage .shot img,
  .manifesto__lines li {
    opacity: 1 !important;
    transform: none !important;
    translate: none !important;
    scale: 1 !important;
  }
  .stagger .step::after { transform: scaleX(1) !important; }
  .shot--wide img { scale: 1 !important; translate: none !important; }
}
