/* ============================================================
   FOUNDER COCKPIT — HERO FLIGHT
   Scroll-scrubbed cinematic entry + 3D coin-flip logo.
   Owns only .ff-* / body.ff-cinema. Nothing else on the page.
   ============================================================ */

/* premium.css sets `body{overflow-x:hidden}`, which makes the body a scroll
   container and silently kills `position:sticky` inside it. `clip` gives the
   same horizontal containment WITHOUT creating a scroll container.
   (Browsers too old for `clip` keep the `hidden` fallback from premium.css.) */
html, body { overflow-x: clip; }

.ff {
  position: relative;
  z-index: 1;
  /* Scroll distance for the whole flight. One "screen" per ~3s of film. */
  height: 520vh;
  background: var(--bg-dark, #0C1233);
  /* The film is the light source — keep the page dark behind it so the
     sticky stage never shows a seam at the top or bottom of the section. */
  color: #fff;
}

.ff-stage {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
  background: #06091d;
  isolation: isolate;
}

/* ---- film ---------------------------------------------------- */
.ff-film,
.ff-poster {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 48%;
}

.ff-poster {
  z-index: 1;
  transition: opacity .5s ease;
}

.ff-film {
  opacity: 0;
  transition: opacity .5s ease;
}

/* Tier one sits under tier two. The swap is a cross-fade over a frame the
   quality file has already seeked to, so it reads as the picture simply
   getting sharper — never as a cut. */
.ff-film--a { z-index: 2; }
.ff-film--b { z-index: 3; }

.ff.is-playing .ff-film--a { opacity: 1; }
.ff.is-playing .ff-poster { opacity: 0; }
.ff.is-hq .ff-film--b { opacity: 1; transition: opacity .8s ease; }

/* Cinematic grade: vignette + a warm gold bloom top-right, cool navy floor.
   Pure CSS, no per-frame cost. */
.ff-grade {
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  background:
    radial-gradient(58% 42% at 76% 12%, rgba(233, 203, 161, .16), transparent 68%),
    radial-gradient(80% 60% at 50% 108%, rgba(12, 18, 51, .72), transparent 72%),
    radial-gradient(120% 100% at 50% 50%, transparent 46%, rgba(4, 7, 20, .58) 100%);
  mix-blend-mode: multiply;
  opacity: .9;
}

.ff-grade-2 {
  position: absolute;
  inset: 0;
  z-index: 5;
  pointer-events: none;
  background: radial-gradient(70% 50% at 50% 44%, rgba(248, 217, 171, .10), transparent 70%);
  mix-blend-mode: screen;
}

/* ---- coin ---------------------------------------------------- */
.ff-coin-wrap {
  position: absolute;
  inset: 0;
  z-index: 7;
  display: grid;
  place-items: center;
  perspective: 1400px;
  perspective-origin: 50% 46%;
  pointer-events: none;
  /* The fade lives HERE, outside the 3D context. `opacity` (and
     `will-change: opacity`) on the preserve-3d element itself forces the
     browser to flatten the subtree, which disables backface-visibility and
     shows the mirrored front face through the back of the coin. */
  opacity: var(--ff-coin-op);
  /* driven by JS */
  --ff-coin-rot: 0deg;
  --ff-coin-scale: 1;
  --ff-coin-z: 0px;
  --ff-coin-op: 1;
}

.ff-coin {
  position: relative;
  /* A round badge — so it flips like an actual coin, not a card. */
  width: min(34vw, 400px);
  aspect-ratio: 1;
  /* Struck thickness, in px, written by JS from the coin's own rendered
     diameter — a fallback only, so the edge is never zero before the first
     frame. See paintCoin() for why it is not a plain CSS ratio. */
  --ff-coin-t: 22px;
  transform-style: preserve-3d;
  transform:
    translate3d(0, -4vh, var(--ff-coin-z))
    rotateY(var(--ff-coin-rot))
    scale(var(--ff-coin-scale));
  will-change: transform;
}

/* NOTE: nothing inside .ff-coin may use `filter` or `mix-blend-mode` at the
   top level — both force the browser to flatten a preserve-3d subtree, which
   silently kills backface-visibility and shows the mirrored front face
   through the back of the coin. The gold glow therefore lives on the face
   image's own drop-shadow. */

.ff-coin__face {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  display: grid;
  place-items: center;
}

.ff-coin__face img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  filter:
    drop-shadow(0 18px 44px rgba(0, 0, 0, .55))
    drop-shadow(0 0 26px rgba(233, 203, 161, .30))
    drop-shadow(0 0 70px rgba(233, 203, 161, .18));
}

/* The faces are pushed out to the two rims of the blank, not stacked in
   the middle — otherwise the "thickness" would sit in front of the art. */
.ff-coin__face--front { transform: translateZ(calc(var(--ff-coin-t) / 2)); }
.ff-coin__face--back  { transform: rotateY(180deg) translateZ(calc(var(--ff-coin-t) / 2)); }

/* ---- the milled edge ------------------------------------------
   A cylinder is not expressible in CSS, so the edge is a stack of discs spread
   across the thickness (positions written by JS). Face-on they hide
   behind the opaque art; edge-on their rims overlap into one solid,
   shaded band of gold. The whole stack rides the single transform on
   .ff-coin, so it costs nothing per frame. */
.ff-coin__slice {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  /* Cylindrical shading: dark where the edge turns away from the key
     light, a hot specular band across the middle. */
  background: linear-gradient(90deg,
    #6E5B3E 0%,
    #A98B60 12%,
    #E9CBA1 30%,
    #FFF6E6 48%,
    #D8BA8C 66%,
    #8B7452 86%,
    #5C4C33 100%);
}

/* The two outermost discs are the machined lips: darker, so the edge
   reads as turning away from the light rather than as a printed band. */
.ff-coin__slice--lip {
  background: linear-gradient(90deg, #4E4029, #7A6544 30%, #B99A6E 48%, #7A6544 70%, #40341F);
}

/* ---- language, offered up front -------------------------------
   The nav is off-screen for the whole flight, so the choice has to live
   on the stage itself. Top-right, over the darkest corner of the grade,
   on its own layer above the coin. */
.ff-lang {
  position: absolute;
  top: clamp(18px, 3.2vh, 40px);
  right: clamp(18px, 3vw, 48px);
  z-index: 10;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 9px;
  transition: opacity .45s ease, transform .45s var(--ease, cubic-bezier(.22, 1, .36, 1));
}

.ff-lang__cap {
  display: flex;
  align-items: center;
  gap: 7px;
  font-family: var(--font-sans, 'Inter', system-ui, sans-serif);
  font-size: .62rem;
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .72);
  text-shadow: 0 2px 14px rgba(0, 0, 0, .8);
}

.ff-lang__cap svg {
  width: 13px;
  height: 13px;
  fill: none;
  stroke: var(--gold, #E9CBA1);
  stroke-width: 1.5;
}

/* Smoked glass, gold hairline — the same material as the platform chrome. */
.ff-lang__pick {
  position: relative;
  display: flex;
  padding: 4px;
  border-radius: 999px;
  background: rgba(9, 14, 38, .52);
  border: 1px solid rgba(233, 203, 161, .34);
  -webkit-backdrop-filter: blur(18px) saturate(1.3);
  backdrop-filter: blur(18px) saturate(1.3);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .16),
    0 10px 30px -12px rgba(0, 0, 0, .9),
    0 0 0 0 rgba(233, 203, 161, .5);
  pointer-events: auto;
}

/* The gold pill slides between the two options instead of appearing under
   the new one — it is the thing the eye follows. */
.ff-lang__thumb {
  position: absolute;
  top: 4px;
  bottom: 4px;
  left: 4px;
  width: calc(50% - 4px);
  border-radius: 999px;
  background: linear-gradient(135deg, #F8D9AB, #E9CBA1 42%, #C9A87C);
  box-shadow: 0 2px 10px -2px rgba(0, 0, 0, .6), inset 0 1px 0 rgba(255, 255, 255, .7);
  transition: transform .42s var(--ease, cubic-bezier(.22, 1, .36, 1));
  pointer-events: none;
}

.ff-lang__thumb { transform: translateX(calc(100% * var(--ff-lang-i, 0))); }

.ff-lang .lang-btn {
  position: relative;
  z-index: 1;
  flex: 1 0 auto;
  min-width: 92px;
  padding: 9px 18px;
  border: 0;
  border-radius: 999px;
  background: none;
  font-family: var(--font-sans, 'Inter', system-ui, sans-serif);
  font-size: .78rem;
  font-weight: 600;
  letter-spacing: .04em;
  color: rgba(255, 255, 255, .82);
  cursor: pointer;
  transition: color .3s ease;
}

.ff-lang .lang-btn:hover { color: #fff; }
.ff-lang .lang-btn.active { color: var(--navy, #0C1233); }
.ff-lang .lang-btn:focus-visible { outline: 2px solid var(--gold-bright, #F8D9AB); outline-offset: 3px; }

/* Until it is touched, a slow gold breath draws the eye to it. Stops for
   good on first interaction — and never runs for reduced-motion users. */
.ff-lang:not(.is-used) .ff-lang__pick { animation: ff-lang-breathe 3.4s ease-in-out infinite; }

@keyframes ff-lang-breathe {
  0%, 100% { box-shadow: inset 0 1px 0 rgba(255,255,255,.16), 0 10px 30px -12px rgba(0,0,0,.9), 0 0 0 0 rgba(233,203,161,.45); }
  50%      { box-shadow: inset 0 1px 0 rgba(255,255,255,.16), 0 10px 30px -12px rgba(0,0,0,.9), 0 0 0 9px rgba(233,203,161,0); }
}

/* Hand back to the nav's own switcher once the flight releases the viewport.
   Keyed to a class that starts absent, so there is no flash on first paint. */
body.ff-past .ff-lang {
  opacity: 0;
  transform: translateY(-12px);
  pointer-events: none;
}

/* ---- beat copy ----------------------------------------------- */
.ff-copy {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 8;
  padding: 0 clamp(20px, 6vw, 84px) clamp(96px, 16vh, 190px);
  pointer-events: none;
}

.ff-beat {
  position: absolute;
  left: clamp(20px, 6vw, 84px);
  right: clamp(20px, 6vw, 84px);
  bottom: clamp(96px, 16vh, 190px);
  max-width: 720px;
  opacity: 0;
  transform: translateY(18px);
  will-change: opacity, transform;
}

.ff-beat__k {
  display: block;
  font-family: var(--font-sans, 'Inter', system-ui, sans-serif);
  font-size: clamp(.66rem, 1.1vw, .76rem);
  font-weight: 700;
  letter-spacing: .28em;
  text-transform: uppercase;
  color: var(--gold, #E9CBA1);
  margin-bottom: 14px;
  text-shadow: 0 2px 18px rgba(0, 0, 0, .6);
}

.ff-beat__t {
  font-family: var(--font-serif, 'Playfair Display', Georgia, serif);
  font-size: clamp(2.1rem, 5.4vw, 4.2rem);
  line-height: 1.05;
  font-weight: 600;
  color: #fff;
  margin: 0;
  text-shadow: 0 6px 40px rgba(0, 0, 0, .7);
}

.ff-beat__t em {
  font-style: italic;
  font-weight: 400;
  /* Metallic gold, matching the platform headline treatment. */
  background: linear-gradient(96deg, #F8D9AB 0%, #E9CBA1 28%, #FFF3DF 46%, #C9A87C 68%, #F3D3A4 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

.ff-beat__d {
  margin-top: 16px;
  max-width: 46ch;
  font-size: clamp(.98rem, 1.4vw, 1.14rem);
  line-height: 1.6;
  color: rgba(255, 255, 255, .82);
  text-shadow: 0 2px 22px rgba(0, 0, 0, .7);
}

/* Bottom scrim so copy stays legible over any frame. */
.ff-scrim {
  position: absolute;
  inset: 40% 0 0 0;
  z-index: 6;
  pointer-events: none;
  background: linear-gradient(180deg, transparent, rgba(6, 9, 29, .30) 45%, rgba(6, 9, 29, .82));
}

/* ---- progress + cue ------------------------------------------ */
.ff-rail {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  z-index: 9;
  background: rgba(255, 255, 255, .12);
}

.ff-rail i {
  display: block;
  height: 100%;
  width: 100%;
  transform: scaleX(0);
  transform-origin: 0 50%;
  background: linear-gradient(90deg, var(--gold-dark, #AF997A), var(--gold-bright, #F8D9AB));
  box-shadow: 0 0 14px rgba(233, 203, 161, .6);
}

.ff-cue {
  position: absolute;
  left: 50%;
  bottom: clamp(26px, 5vh, 48px);
  z-index: 9;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  font-size: .68rem;
  letter-spacing: .24em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .68);
  pointer-events: none;
  transition: opacity .4s ease;
}

.ff-cue i {
  width: 22px;
  height: 34px;
  border-radius: 12px;
  border: 1.5px solid rgba(255, 255, 255, .35);
  position: relative;
}

.ff-cue i::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 7px;
  width: 3px;
  height: 7px;
  border-radius: 2px;
  background: var(--gold, #E9CBA1);
  transform: translateX(-50%);
  animation: ff-wheel 1.7s ease-in-out infinite;
}

@keyframes ff-wheel {
  0%   { opacity: 0; top: 6px; }
  40%  { opacity: 1; }
  100% { opacity: 0; top: 18px; }
}

/* ---- loading ---------------------------------------------------
   The camera is held at zero until tier one can paint, so the wait has to
   be worth staying for: a real byte count under the coin, and the rail
   filling with the download before it becomes the flight's own rail. */
.ff-load {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 9;
  transform: translate(-50%, 0);
  /* clear of the coin, which is centred a little above the middle */
  margin-top: clamp(120px, 21vh, 240px);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  pointer-events: none;
  opacity: 0;
}

/* A warm cache resolves in well under a second — only show this if the
   visitor is actually going to be kept waiting. */
.ff.is-loading .ff-load { animation: ff-load-in .5s ease .45s forwards; }

@keyframes ff-load-in { to { opacity: 1; } }

.ff-load__pct {
  font-family: var(--font-serif, 'Playfair Display', Georgia, serif);
  font-size: clamp(1.5rem, 2.6vw, 2.1rem);
  font-weight: 600;
  line-height: 1;
  background: linear-gradient(96deg, #F8D9AB, #FFF3DF 46%, #C9A87C);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  font-variant-numeric: tabular-nums;
}

.ff-load__txt {
  font-family: var(--font-sans, 'Inter', system-ui, sans-serif);
  font-size: .64rem;
  font-weight: 600;
  letter-spacing: .26em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .62);
  text-shadow: 0 2px 16px rgba(0, 0, 0, .8);
}

/* The rail is carrying the download at this point — dim it so it reads as
   "filling up", not as flight progress already made. */
.ff.is-loading .ff-rail i { opacity: .5; }
.ff.is-loading .ff-cue { opacity: 0 !important; }

/* ---- nav handoff --------------------------------------------- */
/* While the flight owns the viewport the nav gets out of the way —
   the coin is the branding for those seconds. */
body.ff-cinema .site-nav {
  transform: translateY(-104%);
  opacity: 0;
  pointer-events: none;
  transition: transform .45s var(--ease, cubic-bezier(.22, 1, .36, 1)), opacity .3s ease;
}

.site-nav {
  transition: transform .45s var(--ease, cubic-bezier(.22, 1, .36, 1)),
              opacity .3s ease,
              box-shadow var(--t-mid, .32s),
              background var(--t-mid, .32s);
}

/* ---- responsive ---------------------------------------------- */
@media (max-width: 860px) {
  .ff { height: 420vh; }
  .ff-coin { width: min(56vw, 320px); }
  .ff-film, .ff-poster { object-position: center 46%; }
  .ff-beat { bottom: calc(clamp(80px, 14vh, 140px) + env(safe-area-inset-bottom)); }
  .ff-cue { bottom: calc(18px + env(safe-area-inset-bottom)); }
}

/* ---- touch: the flight is bought with distance, not with a speed cap --
   Keyed to the pointer, NOT to the viewport width, because it has to match
   the rate override in the engine — which is also keyed to the pointer. A
   narrow desktop window is still a wheel: give it 900vh with the slow cap
   and the flight becomes nine screens of grinding.

   On touch the cap is raised so the picture follows the finger, so the
   "cannot be rushed" guarantee comes from travel instead: ~9 screens is
   several deliberate swipes, and one hard flick covers about a third of
   the flight. At 420vh a single flick scrolled the whole section past a
   film still sitting at 0.00s — which is what "scroll doesn't work on
   mobile" actually was. */
@media (hover: none) and (pointer: coarse) {
  .ff { height: 900vh; }
}

/* ---- reduced motion ------------------------------------------ */
/* No scrub, no film download: the poster stays, the coin fades in place. */
@media (prefers-reduced-motion: reduce) {
  .ff { height: 100vh; }
  .ff-cue i::after { animation: none; }
  .ff-coin { transform: none; opacity: 1; }
}
