/* ============================================================
   PYROPLAY — design system v3 "borderless"
   Gemini surface language: zero borders — separation by tone.
   Nested rounded islands · generous radii · ambient bloom as
   emphasis · sentence case · one accent, used sparingly.
   ============================================================ */
:root {
  /* palette */
  --palette-black-1200: #0a0806;
  --palette-grey-500:   #6f675f;
  --palette-grey-300:   #a39a90;
  --palette-white:      #fdf9f4;
  --palette-fire-500:   #ff5a1a;
  --palette-fire-400:   #ff6f33;
  --palette-fire-300:   #ff9d3d;
  --palette-fire-500-rgb: 255, 90, 26;
  --palette-white-rgb:  253, 249, 244;

  /* theme — tonal surface ladder (separation without lines) */
  --surface:            var(--palette-black-1200);
  --surface-container:  #14110b;
  --surface-high:       #1b160f;
  --surface-higher:     #231c13;
  --fill:               rgba(var(--palette-white-rgb), 0.05);
  --fill-hover:         rgba(var(--palette-white-rgb), 0.09);
  --on-surface:         var(--palette-white);
  --on-surface-variant: var(--palette-grey-300);
  --on-surface-muted:   var(--palette-grey-500);
  --accent:             var(--palette-fire-500);
  --accent-hover:       var(--palette-fire-400);
  --accent-bright:      var(--palette-fire-300);
  --ink:                #190a02;

  /* gradient language — the crisp-edge layer laid over the borderless base */
  --grad-fire:     linear-gradient(135deg, #ff9d3d 0%, #ff5a1a 52%, #ff3d00 100%);
  --grad-edge:     linear-gradient(135deg, rgba(var(--palette-fire-500-rgb), 0.14), rgba(var(--palette-white-rgb), 0.05) 42%, transparent 74%);
  --grad-edge-lit: linear-gradient(135deg, rgba(var(--palette-fire-500-rgb), 0.62), rgba(var(--palette-white-rgb), 0.07) 44%, transparent 76%);
  --grad-mesh:
    radial-gradient(880px 520px at 12% 6%, rgba(255, 90, 26, 0.075), transparent 62%),
    radial-gradient(720px 640px at 92% 82%, rgba(255, 61, 0, 0.05), transparent 60%);

  /* shape */
  --r-xs: 6px;
  --r-sm: 10px;
  --r-md: 16px;
  --r-card: 24px;
  --r-panel: 32px;
  --r-pill: 999px;

  /* glass overlay recipe */
  --glass: rgba(12, 10, 8, 0.42);
  --glass-strong: rgba(12, 10, 8, 0.56);
  --glass-blur: 12px;

  /* type */
  --font-display: "Inter Tight", "Inter", sans-serif;
  --font-body:    "Inter", sans-serif;

  /* motion */
  --ease-out:    cubic-bezier(0.165, 0.84, 0.44, 1);
  --ease-in-out: cubic-bezier(0.645, 0.045, 0.355, 1);
  --dur-link: 0.12s;
  --dur-btn:  0.15s;
  --dur-card: 0.3s;
  --dur-edge: 0.4s;

  /* layout */
  --container: 1280px;
  --gutter: clamp(16px, 5vw, 72px);
  --header-h: 72px;
}

/* ============ RESET ============ */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
/* The gutter is reserved permanently so that locking the scroll behind the age
   gate cannot take the scrollbar away and shift the whole page sideways. The
   page always has a scrollbar anyway, so in normal use this changes nothing. */
html { scroll-behavior: smooth; scrollbar-gutter: stable; }
html.has-smoother { scroll-behavior: auto; }
body {
  background: var(--surface);
  color: var(--on-surface);
  font-family: var(--font-body);
  font-optical-sizing: auto;
  font-size: 16px;
  line-height: 1.55;
  letter-spacing: 0.01em;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
img, svg { display: block; max-width: 100%; }
/* media protection — remove casual save/copy paths (long-press callout, drag-out) */
img, svg, canvas {
  -webkit-touch-callout: none;
  -webkit-user-drag: none;
  -webkit-user-select: none;
  user-select: none;
}
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
:focus { outline: none; }
:focus-visible { background-color: rgba(var(--palette-white-rgb), 0.08); }
::selection { background: rgba(var(--palette-fire-500-rgb), 0.85); color: var(--ink); }

body::before {
  content: "";
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(1100px 600px at 82% -5%, rgba(255, 90, 26, 0.05), transparent 60%),
    radial-gradient(900px 700px at -10% 40%, rgba(255, 61, 0, 0.025), transparent 55%);
}

.container { width: min(var(--container), 100% - var(--gutter) * 2); margin-inline: auto; }
.section { position: relative; padding: clamp(80px, 9vh, 120px) 0; }

/* ============ AMBIENT BLOOM (emphasis without outlines) ============ */
.bloom {
  position: absolute; pointer-events: none; filter: blur(80px);
}
.bloom--demo {
  inset: -14% -16%;
  background: radial-gradient(52% 52% at 58% 42%, rgba(255, 110, 26, 0.17), rgba(255, 61, 0, 0.05) 58%, transparent 78%);
}

/* ============ GLASS PILL (overlay UI over imagery) ============ */
.glass {
  background: var(--glass);
  backdrop-filter: blur(var(--glass-blur));
  -webkit-backdrop-filter: blur(var(--glass-blur));
  border-radius: var(--r-pill);
}

/* ============ GRADIENT HAIRLINE ============ */
/*
  The one place this system draws a line, and it still refuses to draw a box.

  Both states are masked pseudo-elements rather than a border-image, because a
  CSS gradient is not interpolable — transitioning between two of them snaps
  rather than travels. Two stacked rings cross-fading on opacity is the only
  version of this that actually ignites.

  .is-lit is JS saying the row has scrolled in; :hover is the pointer saying
  the same thing. Neither knows about the other.
*/
.edge { position: relative; }
.edge::before,
.edge::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  padding: 1px;
  pointer-events: none;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask-composite: exclude;
}
.edge::before { background: var(--grad-edge); }
.edge::after {
  background: var(--grad-edge-lit);
  opacity: 0;
  transition: opacity var(--dur-edge) var(--ease-out);
}
.edge:hover::after,
.edge.is-lit::after { opacity: 1; }

/* the sweep variant draws the lit ring in from the left instead of fading it */
.edge--sweep::after {
  opacity: 1;
  clip-path: inset(0 100% 0 0);
  transition: clip-path 0.65s var(--ease-out);
}
.edge--sweep.is-lit::after,
.edge--sweep:hover::after { clip-path: inset(0 0 0 0); }

/*
  The live variant is the same ring with the fire walking around it instead of
  waiting to be lit. It is the ignition loader's stroke-draw held as a loop
  rather than played once, which is what ties the 18+ door to the sequence that
  just finished burning.

  The angle is a registered custom property because an unregistered one is not
  animatable — and the `0deg` fallback inside var() is what keeps the border a
  handsome static gradient, rather than nothing at all, where @property is
  missing. Reduced motion freezes the travel through the global block below.
*/
@property --edge-angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}
.edge--live::after {
  opacity: 1;
  background: conic-gradient(from var(--edge-angle, 0deg),
    rgba(var(--palette-fire-500-rgb), 0)     0deg,
    rgba(255, 157, 61, 0.9)                 42deg,
    rgba(255, 61, 0, 0.95)                  88deg,
    rgba(var(--palette-fire-500-rgb), 0.16) 168deg,
    rgba(var(--palette-white-rgb), 0.07)    248deg,
    rgba(var(--palette-fire-500-rgb), 0)    360deg);
  animation: edge-travel 6s linear infinite;
  transition: opacity var(--dur-edge) var(--ease-out);
}
@keyframes edge-travel { to { --edge-angle: 360deg; } }

/* ============ STATEMENT TYPE ============ */
/*
  A second, much larger register than .section-title. The manifesto and the
  sign-off are the only two places on the site that speak at this size, which
  is most of what makes them read as statements rather than as headings.
*/
.statement {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(34px, 6vw, 92px);
  line-height: 0.98;
  letter-spacing: -0.04em;
  text-wrap: balance;
}
.statement em { font-style: normal; color: var(--accent); }
.statement--grad {
  background: var(--grad-fire);
  -webkit-background-clip: text;
          background-clip: text;
  -webkit-text-fill-color: transparent;
}
.statement--sm { font-size: clamp(28px, 4vw, 56px); letter-spacing: -0.032em; }

/* ============ PRELOADER ============ */
.preloader {
  position: fixed; inset: 0; z-index: 1000;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 24px;
  background: var(--surface);
  transition: opacity 0.45s var(--ease-out), visibility 0.45s;
}
.preloader.is-done { opacity: 0; visibility: hidden; }
.preloader__mark { position: relative; width: 92px; height: 92px; }
.preloader__star {
  width: 100%; height: 100%; object-fit: contain;
  filter: drop-shadow(0 0 18px rgba(255, 90, 26, 0.35));
  animation: loader-spin 1.2s linear infinite;
}
@keyframes loader-spin { to { transform: rotate(360deg); } }
.preloader__spark {
  position: absolute; left: 50%; top: 50%;
  width: var(--s, 4px); height: var(--s, 4px); border-radius: 50%;
  background: var(--c, #ffc53d);
  box-shadow: 0 0 8px 1px var(--c, #ffc53d);
  opacity: 0;
  animation: spark-fly 1.05s linear infinite;
  animation-delay: var(--t, 0s);
}

/* ============ IGNITION ============ */
/*
  Everything above is the no-JS fallback and stays exactly as it was — a
  spinning mark with looping embers, which is a perfectly good loader if the
  module never runs. `is-igniting` is JS saying "I have this", and only then
  does the spin stop and the sequence take over.
*/
.preloader__draw {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; overflow: visible;
  filter: drop-shadow(0 0 12px rgba(255, 122, 26, 0.55));
}
.preloader__ember {
  position: absolute; left: 50%; top: 50%;
  width: 13px; height: 13px; border-radius: 50%;
  background: radial-gradient(circle, #fff3d6 0%, #ffc53d 38%, #ff7a1a 62%, rgba(255, 61, 0, 0) 76%);
  box-shadow: 0 0 26px 7px rgba(255, 140, 40, 0.5);
  opacity: 0; pointer-events: none;
}

.preloader.is-igniting .preloader__draw { opacity: 1; }
.preloader.is-igniting .preloader__star { animation: none; }
.preloader.is-igniting .preloader__spark { animation: none; opacity: 0; }
/* the one-shot burst at the moment the mark catches */
.preloader.is-igniting.is-bursting .preloader__spark {
  animation: spark-fly 0.95s var(--ease-out) 1 both;
  animation-delay: calc(var(--t, 0s) * 0.34);
}
@keyframes spark-fly {
  0%   { opacity: 0; transform: translate(-50%, -50%) rotate(var(--a)) translateX(34px) scale(1); }
  10%  { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%, -50%) rotate(var(--a)) translateX(var(--d)) scale(0.3); }
}

/* ============ AGE GATE ============ */
/*
  The 18+ door, held between the loader and the site.

  It sits above the preloader (1000) rather than inside it, so the two can
  cross-fade: the curtain drops through the same near-black the gate arrives
  in, and the card simply scales up out of the dark. Nothing about it depends
  on GSAP — the door is compliance, not choreography, and a blocked CDN must
  not be able to open it.

  Outside #smooth-wrapper for the reason the coin stage is: position:fixed
  inside a transformed ancestor resolves against the ancestor.
*/
.agegate {
  position: fixed; inset: 0; z-index: 1100;
  display: grid;
  place-items: center;
  place-items: safe center;   /* a card taller than the viewport keeps its head */
  overflow-y: auto;
  padding: clamp(20px, 5vh, 56px) 20px;
  opacity: 0; visibility: hidden; pointer-events: none;
  /*
    Opaque, and warm rather than flat black — the bloom is the scrim's own,
    rather than the page's showing through it. This replaces a blur, and it is
    opaque rather than merely dark because at every opacity that still let the
    hero through, the sharp headline behind the card read as a rendering fault
    rather than as depth. Smearing it was the whole job the blur was doing, and
    the blur was the most expensive thing on the screen. See the note below.
  */
  background:
    radial-gradient(88% 68% at 50% 42%, rgba(255, 100, 30, 0.06), transparent 64%),
    radial-gradient(125% 95% at 50% 40%, #0b0907, #030201 62%);
  transition: opacity 0.5s var(--ease-out), visibility 0.5s;
}
.agegate.is-open { opacity: 1; visibility: visible; pointer-events: auto; }
html.agegate-open { overflow: hidden; }

/*
  There is deliberately no blur behind this gate any more.

  It started as a backdrop-filter on .agegate and cost about seven frames out
  of every eight — a viewport-sized backdrop re-blurs every frame, and it kept
  doing so even over a page that had been completely frozen. Moving the same
  blur onto the hero as a plain filter bought most of that back, but a blurred
  viewport-sized layer is still the most expensive thing on the screen, and it
  was still the only thing standing between this gate and a flat 60fps.

  An opaque scrim reaches the same place by a cheaper road: the point was never
  the blur, it was that nothing behind the card should compete with it, and a
  scrim that simply covers the page does that for free.
*/

.agegate__card {
  width: min(460px, 100%);
  padding: clamp(30px, 4vw, 44px) clamp(24px, 3.4vw, 40px);
  border-radius: var(--r-panel);
  background: var(--surface-container);
  text-align: center;
  transform: translateY(16px) scale(0.965);
  transition: transform 0.65s var(--ease-out);
}
.agegate.is-open .agegate__card { transform: none; }

.agegate__mark {
  width: 54px; height: 54px; margin: 0 auto 22px;
  filter: drop-shadow(0 0 18px rgba(255, 90, 26, 0.42));
  transition: filter var(--dur-edge) var(--ease-out), opacity var(--dur-edge) var(--ease-out);
}

.agegate__panel[hidden] { display: none; }

.agegate__title {
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(25px, 3.4vw, 34px);
  line-height: 1.06; letter-spacing: -0.03em;
  margin-bottom: 13px; text-wrap: balance;
}
.agegate__body {
  color: var(--on-surface-variant);
  font-size: 15px; max-width: 35ch;
  margin: 0 auto 26px;
  text-wrap: pretty;   /* no one-word last line under a headline this size */
}
.agegate__actions { display: flex; flex-direction: column; gap: 10px; }
.agegate__actions .btn { width: 100%; justify-content: center; }

.agegate__back {
  display: inline-block; margin-top: 16px;
  font-size: 13px; color: var(--on-surface-muted);
  text-decoration: underline; text-underline-offset: 3px;
  transition: color var(--dur-link);
}
.agegate__back:hover { color: var(--on-surface-variant); }

.agegate__note {
  position: relative;
  margin-top: 26px; padding-top: 20px;
  font-size: 12px; letter-spacing: 0.02em;
  color: var(--on-surface-muted);
}
/* the one hairline that is allowed to be a line, and it still fades out at both ends */
.agegate__note::before {
  content: ""; position: absolute; top: 0; left: 14%; right: 14%; height: 1px;
  background: linear-gradient(to right, transparent, rgba(var(--palette-fire-500-rgb), 0.34), transparent);
}
.agegate__note i { font-style: normal; opacity: 0.4; margin: 0 7px; }
/* the line may wrap between the three items, never inside one of them */
.agegate__note span, .agegate__note a { white-space: nowrap; }
.agegate__note a {
  color: var(--on-surface-variant);
  text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: rgba(var(--palette-white-rgb), 0.25);
  transition: color var(--dur-link);
}
.agegate__note a:hover { color: var(--accent-bright); }

/* Saying no puts the fire out: the mark cools and the ring stops travelling. */
.agegate.is-declined .agegate__mark { filter: grayscale(0.9) brightness(0.5); opacity: 0.55; }
.agegate.is-declined .agegate__card::after { opacity: 0.28; animation-duration: 22s; }

/* ============ CURSOR ============ */
.cursor { display: none; }
@media (hover: hover) and (pointer: fine) {
  /* Above the preloader and the age gate: `body.cursor-active` hides the native
     pointer, so a cursor trapped under a fullscreen overlay is no cursor at all.
     pointer-events: none means sitting on top costs the overlay nothing. */
  .cursor { display: block; position: fixed; inset: 0; z-index: 1200; pointer-events: none; }
  .cursor__dot {
    position: absolute; width: 5px; height: 5px; margin: -2.5px;
    background: var(--accent); border-radius: 50%;
  }
  .cursor__ring {
    position: absolute; width: 28px; height: 28px; margin: -14px;
    border-radius: 50%;
    background: rgba(var(--palette-white-rgb), 0.06);
    display: flex; align-items: center; justify-content: center;
    transition: width var(--dur-card) var(--ease-out), height var(--dur-card) var(--ease-out),
                margin var(--dur-card) var(--ease-out), background var(--dur-card) var(--ease-out);
  }
  .cursor__label {
    font-size: 9.5px; font-weight: 500; letter-spacing: 0.08em;
    color: var(--on-surface); opacity: 0; transition: opacity var(--dur-link);
  }
  .cursor.is-hover .cursor__ring {
    width: 48px; height: 48px; margin: -24px;
    background: rgba(var(--palette-white-rgb), 0.1);
    backdrop-filter: blur(4px);
  }
  .cursor.is-hover .cursor__label { opacity: 1; }
  .cursor.is-hover .cursor__dot { opacity: 0; }
  body.cursor-active, body.cursor-active a, body.cursor-active button { cursor: none; }
}

/* ============ HEADER ============ */
.site-header {
  position: fixed; top: 0; left: 0; right: 0; z-index: 500;
  display: flex; align-items: center; gap: 28px;
  height: var(--header-h); padding-inline: clamp(20px, 3vw, 44px);
  transition: background var(--dur-card) var(--ease-out), backdrop-filter var(--dur-card), transform 0.35s var(--ease-out);
}
.site-header.is-scrolled {
  background: rgba(10, 8, 6, 0.74);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
}
.site-header.is-hidden { transform: translateY(-100%); }
/* The header owns a stacking context (z-index: 500), so the burger's own
   z-index is trapped inside it and the X was painting behind the menu's
   backdrop. While the menu is open the whole header goes above the overlay,
   and the scroll-away rule is overridden so the close control cannot be
   parked off-screen. */
.site-header.is-menu-open { z-index: 640; transform: none; }

.logo { display: inline-flex; align-items: center; gap: 11px; }
.logo__mark { width: 32px; height: 32px; object-fit: contain; transition: transform 0.4s var(--ease-out); }
.logo:hover .logo__mark { transform: rotate(90deg); }
/*
  The wordmark is artwork now rather than set type, so it is sized by height:
  that keeps its cap height locked to the mark beside it and lets the width
  fall out of the aspect ratio, instead of the other way round.
*/
.logo__word { height: 13px; width: auto; }

.nav { display: flex; gap: 4px; margin-inline: auto; }
.nav__link {
  font-size: 14.5px; font-weight: 450; color: var(--on-surface-variant);
  padding: 7px 14px; border-radius: var(--r-pill);
  transition: color var(--dur-link), background-color var(--dur-link);
}
.nav__link:hover { color: var(--on-surface); background: rgba(var(--palette-white-rgb), 0.04); }
.nav__link.is-active { color: var(--on-surface); background: rgba(var(--palette-white-rgb), 0.06); }

/* ============ BUTTONS — pills, tonal or solid, no outlines ============ */
.btn {
  display: inline-flex; align-items: center; gap: 9px;
  font-size: 15px; font-weight: 500; letter-spacing: 0.012em;
  padding: 13px 27px; border-radius: var(--r-pill);
  transition: all var(--dur-btn) ease-out;
}
.btn__icon { width: 16px; height: 16px; flex: none; transition: transform var(--dur-btn) ease-out; }
.btn:hover .btn__icon { transform: translateX(2px); }
.btn--portal:hover .btn__icon, .btn--ghost:hover .btn__icon { transform: translate(1px, -1px); }

.btn--primary { background: var(--accent); color: var(--ink); }
.btn--primary:hover { background: var(--accent-hover); }
.btn--primary:active { background: var(--palette-fire-300); }

.btn--ghost, .btn--portal {
  background: var(--fill);
  color: var(--on-surface);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.btn--ghost:hover, .btn--portal:hover { background: var(--fill-hover); }
.btn--portal { min-height: 36px; padding: 7px 17px; font-size: 13.5px; }

/* ============ BURGER / MOBILE MENU ============ */
.burger { display: none; position: relative; z-index: 620; width: 40px; height: 40px; flex-direction: column; align-items: center; justify-content: center; gap: 6px; border-radius: 50%; }
.burger span { width: 20px; height: 1.5px; background: var(--on-surface); border-radius: 2px; transition: transform var(--dur-card) var(--ease-out), opacity var(--dur-link); }
.burger.is-open span:nth-child(1) { transform: translateY(7.5px) rotate(45deg); }
.burger.is-open span:nth-child(2) { opacity: 0; }
.burger.is-open span:nth-child(3) { transform: translateY(-7.5px) rotate(-45deg); }

.mobile-menu {
  position: fixed; inset: 0; z-index: 600; display: flex; align-items: center; justify-content: center;
  background: rgba(10, 8, 6, 0.94); backdrop-filter: blur(18px);
  opacity: 0; visibility: hidden; transition: opacity var(--dur-card) var(--ease-out), visibility var(--dur-card);
}
.mobile-menu.is-open { opacity: 1; visibility: visible; }
.mobile-menu__nav { display: flex; flex-direction: column; gap: 6px; text-align: center; }
.mobile-menu__nav a {
  font-family: var(--font-display); font-size: clamp(24px, 5.6vw, 32px); font-weight: 500;
  letter-spacing: -0.015em; padding: 8px 20px; border-radius: var(--r-pill);
  opacity: 0; transform: translateY(20px);
  transition: color var(--dur-link);
}
.mobile-menu.is-open .mobile-menu__nav a { opacity: 1; transform: none; transition: opacity 0.45s var(--ease-out), transform 0.45s var(--ease-out); }
.mobile-menu__nav a:hover { color: var(--accent); }
.mobile-menu__portal { color: var(--accent); }

/* ============ SECTION DOTS ============ */
.dots {
  position: fixed; left: 28px; top: 50%; transform: translateY(-50%); z-index: 400;
  display: flex; flex-direction: column; gap: 16px;
}
.dots__dot {
  position: relative; width: 8px; height: 8px; border-radius: 50%;
  background: rgba(var(--palette-white-rgb), 0.14);
  transition: background var(--dur-card), transform var(--dur-card) var(--ease-out);
}
.dots__dot:hover { background: rgba(var(--palette-white-rgb), 0.35); }
.dots__dot.is-active { background: var(--accent); transform: scale(1.25); }
.dots__tip {
  position: absolute; left: 22px; top: 50%; transform: translateY(-50%) translateX(-6px);
  font-size: 11px; font-weight: 500; letter-spacing: 0.04em;
  color: var(--on-surface-variant); white-space: nowrap;
  opacity: 0; pointer-events: none;
  transition: opacity var(--dur-link), transform var(--dur-card) var(--ease-out);
}
.dots__dot:hover .dots__tip { opacity: 1; transform: translateY(-50%) translateX(0); }
@media (max-width: 1100px) { .dots { display: none; } }

/* the rail the spark rides, drawn behind the dots */
.dots::before {
  content: ""; position: absolute; left: 50%; top: -4px; bottom: -4px;
  width: 1px; margin-left: -0.5px; z-index: -1;
  background: linear-gradient(to bottom, rgba(255, 140, 40, 0.3), rgba(255, 140, 40, 0.06));
}
.dots__spark {
  position: absolute; left: 50%; top: 0;
  width: 7px; height: 7px; margin-left: -3.5px; border-radius: 50%;
  background: radial-gradient(circle, #fff3d6 0%, #ffc53d 38%, rgba(255, 90, 26, 0) 74%);
  box-shadow: 0 0 15px 4px rgba(255, 140, 40, 0.55);
  pointer-events: none; will-change: transform;
}

/* ============ TYPOGRAPHY HELPERS ============ */
.eyebrow {
  font-size: 12px; font-weight: 500;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--accent);
  display: flex; align-items: center; gap: 12px; margin-bottom: 20px;
}
.eyebrow::before { content: ""; width: 22px; height: 1px; background: var(--accent); }
.eyebrow--light { color: var(--accent-bright); }

.section-title {
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(30px, 3.3vw, 42px); line-height: 1.12; letter-spacing: -0.02em;
  margin-bottom: 22px;
}
.section-title em { font-style: normal; color: var(--accent); }
.lead { color: var(--on-surface-variant); max-width: 46ch; margin-bottom: 26px; font-size: 16.5px; }

.textlink {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 14.5px; font-weight: 500; letter-spacing: 0.01em; color: var(--accent);
  transition: color var(--dur-link);
}
.textlink svg { width: 16px; height: 16px; transition: transform var(--dur-btn) ease-out; }
.textlink:hover { color: var(--accent-bright); }
.textlink:hover svg { transform: translateX(3px); }

/* ============ HERO ============ */
.hero {
  min-height: 100vh; min-height: 100svh;
  display: flex; align-items: center;
  padding-top: calc(var(--header-h) + 40px);
  overflow: hidden;
}
.hero__embers { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 1; }
.hero__glow { position: absolute; border-radius: 50%; filter: blur(90px); z-index: 0; }
.hero__glow--a { width: 560px; height: 560px; right: -6%; top: -12%; background: radial-gradient(circle, rgba(255, 90, 26, 0.16), transparent 65%); }
.hero__glow--b { width: 420px; height: 420px; right: 18%; bottom: -18%; background: radial-gradient(circle, rgba(255, 61, 0, 0.09), transparent 65%); }

.hero__inner {
  position: relative; z-index: 2;
  display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  align-items: center; gap: clamp(30px, 5vw, 70px);
}
.hero__title {
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(34px, 4.3vw, 58px); line-height: 1.06; letter-spacing: -0.025em;
  margin-bottom: 24px; min-height: 2.1em;
}
.hero__line { display: block; }
.hero__title em { font-style: normal; color: var(--accent); }
.hero__caret {
  display: inline-block; width: 0.13em; height: 0.82em; margin-left: 0.1em;
  background: var(--accent); vertical-align: baseline; transform: translateY(0.1em);
  border-radius: 2px;
  animation: caret-blink 0.9s steps(1) infinite;
}
@keyframes caret-blink { 0%, 55% { opacity: 1; } 56%, 100% { opacity: 0; } }
.hero__sub { color: var(--on-surface-variant); font-size: clamp(15px, 1.4vw, 17px); margin-bottom: 36px; }
.hero__ctas { display: flex; flex-wrap: wrap; gap: 12px; }

/* hero star */
.hero__visual { display: flex; justify-content: center; }
.hero__star-wrap { position: relative; width: min(40vh, 360px); aspect-ratio: 1; }
.hero__star-wrap::after { content: ""; position: absolute; inset: 0; } /* long-press shield over the mark */
.hero__star, .hero__star-blur { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
.hero__star-blur { filter: blur(38px) saturate(1.15); opacity: 0.35; transform: scale(1.06); }
.hero__star { filter: drop-shadow(0 0 24px rgba(255, 90, 26, 0.18)); }

.hero__scrollhint {
  position: absolute; left: 50%; bottom: 32px; transform: translateX(-50%); z-index: 3;
  display: flex; flex-direction: column; align-items: center; gap: 10px;
}
.hero__scrollhint-label { font-size: 10.5px; font-weight: 500; letter-spacing: 0.18em; text-transform: uppercase; color: var(--on-surface-muted); }
.hero__scrollhint-line { position: relative; width: 1px; height: 48px; background: rgba(var(--palette-white-rgb), 0.12); overflow: hidden; }
.hero__scrollhint-line i { position: absolute; left: 0; top: -40%; width: 100%; height: 40%; background: var(--accent); animation: scroll-drop 1.8s var(--ease-in-out) infinite; }
@keyframes scroll-drop { 0% { top: -40%; } 60%, 100% { top: 110%; } }

/* ============ SECTION HEAD ============ */
.section-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 30px; margin-bottom: 44px; }
.games__arrows { display: flex; gap: 10px; }
.arrow {
  width: 44px; height: 44px; border-radius: 50%;
  background: var(--fill);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  display: grid; place-items: center;
  transition: all var(--dur-btn) ease-out;
}
.arrow svg { width: 18px; height: 18px; }
.arrow:hover { background: var(--fill-hover); }
.arrow:disabled { opacity: 0.3; pointer-events: none; }

/* ============ GAME CARDS ============ */
/*
  The section takes the colour of whichever game is under the cursor. Same four
  accents the cards already carried; lifted up a level so the atmosphere moves
  rather than just the card.
*/
.games__ambient {
  position: absolute; inset: 4% -6% 0; z-index: 0; pointer-events: none;
  opacity: 0; filter: blur(70px);
  background: radial-gradient(58% 48% at 50% 46%, rgba(var(--tint, 255, 140, 40), 0.15), transparent 72%);
  transition: opacity 0.7s var(--ease-out), background 0.7s var(--ease-out);
}
.games__ambient.is-on { opacity: 1; }
/*
  The glow is deliberately wider than the section so its blur has somewhere to
  fade, and nothing was holding it in: those 6% were the whole reason a phone
  could drag the page sideways off its own right edge. Clipping on the x axis
  alone keeps overflow-y visible, so this stays a plain box rather than
  becoming a scroll container, and the games rail inside still scrolls.
*/
.games { overflow-x: clip; }
.games .container { position: relative; z-index: 1; }

.games__viewport { overflow-x: auto; overflow-y: visible; scrollbar-width: none; margin-inline: calc(var(--gutter) * -1); padding: 44px var(--gutter) 52px; margin-block: -30px; }
.games__viewport::-webkit-scrollbar { display: none; }
.games__track { display: grid; grid-auto-flow: column; grid-auto-columns: clamp(270px, 23.5vw, 330px); gap: 20px; }

.game-card {
  position: relative;
  aspect-ratio: 3 / 3.5;
  border-radius: var(--r-card);
  transition: transform var(--dur-card) var(--ease-out);
  will-change: transform;
}
.game-card:hover { transform: translateY(-4px); }
.game-card::before {
  content: ""; position: absolute; inset: -10%; z-index: -1;
  filter: blur(56px); opacity: 0.8;
  transition: opacity var(--dur-card) ease-out;
}
.game-card:hover::before { opacity: 1; }
.game-card--cc::before   { background: radial-gradient(55% 55% at 50% 48%, rgba(255, 140, 40, 0.2), transparent 72%); }
.game-card--lck::before  { background: radial-gradient(55% 55% at 50% 48%, rgba(255, 61, 46, 0.13), transparent 72%); }
/* Brass rather than fire: FARO is the one game in the catalogue that is not
   lit orange, and the rail should say so before the title does. */
.game-card--faro::before { background: radial-gradient(55% 55% at 50% 48%, rgba(196, 163, 108, 0.18), transparent 72%); }
.game-card--gems::before { background: radial-gradient(55% 55% at 50% 48%, rgba(139, 77, 255, 0.14), transparent 72%); }
.game-card--flip::before { background: radial-gradient(55% 55% at 50% 48%, rgba(53, 196, 216, 0.13), transparent 72%); }
.game-card__link { position: absolute; inset: 0; z-index: 5; border-radius: var(--r-card); }

.game-card__art {
  position: absolute; inset: 0; overflow: hidden;
  border-radius: var(--r-card);
  background: var(--surface-container);

  /* LCKDWN's alarm blends on `screen`, and a blend with nothing to isolate it
     mixes against the nearest stacking context — which `overflow: hidden` does
     not make. That put the compositor to work flattening the page to light two
     lamps inside a 300px tile. Isolating changes nothing to look at and keeps
     every layer in here, including FARO's, composited against this card. */
  isolation: isolate;
}
.game-card__scene, .game-card__photo { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transform: scale(1.02); transition: transform 0.7s var(--ease-out); }
.game-card--cc .game-card__photo { object-position: 0% 62%; }
.game-card--lck .game-card__photo { object-position: 62% center; }
.game-card--faro .game-card__photo { object-position: 50% 38%; }
.game-card:hover .game-card__scene, .game-card:hover .game-card__photo { transform: scale(1.06); }
.game-card__art::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(6, 4, 3, 0.82) 0%, rgba(6, 4, 3, 0.18) 40%, transparent 62%);
}

.game-card__badge {
  position: absolute; top: 14px; left: 14px; z-index: 3;
  font-size: 11px; font-weight: 500; letter-spacing: 0.02em;
  padding: 6px 12px; border-radius: var(--r-pill);
  background: var(--glass);
  backdrop-filter: blur(var(--glass-blur));
  -webkit-backdrop-filter: blur(var(--glass-blur));
  color: var(--on-surface-variant);
}
.game-card__badge--live { color: var(--accent-bright); }

.game-card__body {
  position: relative; z-index: 2; height: 100%;
  display: flex; flex-direction: column; justify-content: flex-end; gap: 11px;
  padding: 16px;
}
.game-card__title {
  font-family: var(--font-display); font-size: 24px; font-weight: 600;
  line-height: 1.1; letter-spacing: -0.015em;
  text-shadow: 0 2px 18px rgba(0, 0, 0, 0.6);
}
.game-card__title sup { font-size: 0.45em; font-weight: 500; color: var(--on-surface-variant); }

.game-card__chips { display: flex; flex-wrap: wrap; gap: 6px; }
.chip {
  display: inline-flex; align-items: center;
  font-size: 11.5px; font-weight: 500; letter-spacing: 0.015em;
  color: rgba(var(--palette-white-rgb), 0.85);
  background: var(--glass);
  backdrop-filter: blur(var(--glass-blur));
  -webkit-backdrop-filter: blur(var(--glass-blur));
  border-radius: var(--r-pill); padding: 6px 12px;
  transition: background var(--dur-link), color var(--dur-link);
  white-space: nowrap;
}
.game-card:hover .chip { background: var(--glass-strong); }
.chip--rtp { color: var(--accent-bright); }
.chip--rtp .count { font-weight: 600; }

/* ============ CARD MICRO-ANIMATIONS ============ */
/*
  Each card animates the thing the game actually is: Captain's Call throws a
  coin, LCKDWN shuts a door, Gems lights a stone, Flip flips a bottle. They sit
  above .game-card__art::after so the gradient does not bury them.
*/

/* Captain's Call — a real two-faced coin, spun on rotateX like the game's */
.game-card__coin {
  position: absolute; z-index: 1;
  left: 50%; top: 42%;
  width: 34%; aspect-ratio: 1; margin-left: -17%;
  transform-style: preserve-3d;
  pointer-events: none;
}
.game-card__coin img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain;
  backface-visibility: hidden; -webkit-backface-visibility: hidden;
  filter: drop-shadow(0 8px 20px rgba(0, 0, 0, 0.6));
}
.game-card__coin img.is-back { transform: rotateX(180deg); }
.game-card__flash {
  position: absolute; inset: 0; z-index: 1; opacity: 0; pointer-events: none;
  background: radial-gradient(60% 44% at 50% 40%, rgba(255, 244, 214, 0.75), rgba(255, 190, 90, 0.16) 48%, transparent 72%);
}

/* LCKDWN — the closed door arrives, and its arrival is the slam */
.game-card__photo--alt { opacity: 0; }
.game-card__alarm {
  position: absolute; inset: 0; z-index: 1; opacity: 0; pointer-events: none;
  background:
    radial-gradient(52% 40% at 12% 26%, rgba(255, 40, 30, 0.5), transparent 62%),
    radial-gradient(52% 40% at 88% 26%, rgba(255, 40, 30, 0.5), transparent 62%),
    linear-gradient(to bottom, rgba(120, 8, 4, 0.42), transparent 55%);
  mix-blend-mode: screen;
}
.game-card__lockword {
  position: absolute; z-index: 2; left: 0; right: 0; top: 36%;
  text-align: center;
  font-family: var(--font-display); font-weight: 800; font-size: clamp(15px, 1.5vw, 20px);
  letter-spacing: 0.24em; color: #ffd7d2;
  text-shadow: 0 0 22px rgba(255, 50, 40, 0.85), 0 2px 12px rgba(0, 0, 0, 0.8);
  opacity: 0; pointer-events: none;
}

/* Gems — the stone lights from inside, and one distant gem goes dark */
/* transition:none because GSAP writes this transform every frame, and the
   inherited 0.7s ease would smear each write into the next. */
.game-card__gem { object-position: center 46%; transition: none; }
.game-card__sheen {
  position: absolute; inset: -20% -60%; z-index: 1; opacity: 0; pointer-events: none;
  background: linear-gradient(72deg, transparent 40%, rgba(255, 246, 214, 0.5) 50%, transparent 60%);
}
.game-card__cursed {
  position: absolute; z-index: 1; left: 14%; top: 24%;
  width: 16%; aspect-ratio: 1; border-radius: 50%;
  background: radial-gradient(circle, #05060a 34%, rgba(5, 6, 10, 0) 72%);
  opacity: 0; pointer-events: none;
}

/* FARO — two cards out of the box, and the second one is gold */
/* The shared flash is not used here. Captain's Call needs one because a spun
   coin catches the light at the top of its arc; a dealt card does not light
   the room it is dealt in. The win is the edge and the bloom, and the game's
   own note is that stopping there is the point. */
/*
  Ported from the game's own table rather than approximated, which is the rule
  for FARO everywhere: the ivory face, the brass inner rule, the index that
  scales with the card. The one deliberate difference is the face — the game
  sets its ranks in Cormorant and this site does not carry it, so the rank is
  in Inter Tight here. A serif loaded for two glyphs is a font request nobody
  is getting paid back for.

  Colours stated literally. They are FARO's, not PyroPlay's, and a brass card
  is the whole reason this is the one tile in a row of fire that is not orange.
*/
/* 35% down and 26% tall is the band of clear felt between the box and the
   point the tile's own gradient starts burying things, measured off the crop
   rather than chosen: the plate is landscape, `cover` scales it by height, so
   what shows is a fixed 723px window on the middle of it and the felt below
   the box is the same felt on every screen. */
.faro-deal {
  position: absolute; z-index: 1; inset-inline: 0; top: 35%; height: 26%;
  display: flex; justify-content: center; gap: 5%;
  pointer-events: none;
}

/* The box is painted into the plate, so it cannot be lit directly. This is
   laid over where it sits in the crop: dead centre, a fifth of the way down. */
.faro-deal__lamp {
  position: absolute; inset: -130% 0 105%; opacity: 0;
  background: radial-gradient(30% 46% at 50% 58%, rgba(255, 228, 176, 0.5), rgba(196, 163, 108, 0.12) 52%, transparent 74%);
}

/* The seat a card lands in. The card is mounted here and flies *from* the box,
   so nothing on the table moves when it arrives. */
.faro-seat { position: relative; height: 100%; aspect-ratio: 1 / 1.4; }

/*
  The gold the winning card throws onto the felt, which is the game's own and
  not a halo behind it.

  Two shadows on the same timing: a tight warm one that hugs the edge, and a
  wide soft one that is the light on the cloth. The element carries no
  background, so the card sits on top of it and only the light gets out — which
  is a box-shadow doing here what the game does with a drop-shadow filter, for
  the same reason. It traces the card. A radial glow would be a round bloom
  behind a rectangular object.
*/
.faro-seat__halo {
  position: absolute; inset: 0; border-radius: 4px; opacity: 0;
  box-shadow:
    0 0 7px rgba(220, 192, 141, 0.75),
    0 0 26px rgba(196, 163, 108, 0.5);
}

.faro-card {
  position: absolute; inset: 0;
  border-radius: 4px;
  background: linear-gradient(168deg, #f4ead9, #e7d8c1 62%, #d3c0a4);
  box-shadow:
    inset 0 0 0 1px rgba(168, 131, 75, 0.55),
    inset 0 0 0 2px rgba(244, 234, 217, 0.9),
    inset 0 0 0 3px rgba(168, 131, 75, 0.3),
    0 6px 10px rgba(0, 0, 0, 0.45);
  color: #15140f;
  overflow: hidden;

  /* Every part of a card scales with the card, which is the whole reason the
     game draws them rather than pictures them. The rail sizes the tile, the
     tile sizes this, and `cqw` is what carries that down to the rank without
     anybody restating the arithmetic each time the rail changes width. */
  container-type: inline-size;
}
.faro-card[data-suit="heart"] { color: #8d1f24; }

.faro-card__index {
  position: absolute; display: grid; justify-items: center; gap: 0.06em;
  font-family: var(--font-display); font-weight: 600;
  font-size: 21cqw; line-height: 0.9;
}
.faro-card__index svg { width: 12cqw; fill: currentColor; }
.faro-card__index--tl { top: 6%; left: 8%; }
.faro-card__index--br { right: 8%; bottom: 6%; transform: rotate(180deg); }

.faro-card__pip {
  position: absolute; top: 50%; left: 50%; width: 36%;
  transform: translate(-50%, -50%); fill: currentColor;
}

/* An engraving is an engraving: it is the one part of a card this site does
   not draw. It bleeds past the card and the card clips it, which is what the
   game does with it too. */
.faro-card__court {
  position: absolute; top: 50%; left: 50%; width: 76%; height: auto;
  transform: translate(-50%, -50%);
}

/*
  The winning card's edge light, drawn the way the game draws it: a warm line
  around the card, brass-200 at the top falling to brass-500 at the bottom, and
  nothing at all on the face.

  That last part is the whole point. A card that wins is a lit card, not a gold
  card — wash the paper and you have replaced the seven of spades and the king
  with two brass rectangles, and the thing the animation was explaining is
  gone. The game renders this stroke always and reveals it by opacity, so
  nothing about the card's geometry changes when it wins; same here.

  The gradient needs a mask to stay a line rather than a filled rectangle, so a
  browser without one gets a flat brass line instead. The wrong version of this
  rule is a solid gold card, which is worth one @supports to never ship.
*/
.faro-card__edge {
  position: absolute; inset: 0; opacity: 0; border-radius: inherit;
  padding: 1.5px;
  background: linear-gradient(180deg, #f0dcb5, #a8834b);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
}

@supports not ((mask-composite: exclude) or (-webkit-mask-composite: xor)) {
  .faro-card__edge {
    background: none;
    box-shadow: inset 0 0 0 1.5px #c4a36c;
  }
}

/* ============ SHOWCASE (Captain's Call) ============ */
.showcase { overflow: hidden; }
.showcase__glow {
  position: absolute; width: 700px; height: 700px; right: -14%; top: 8%;
  background: radial-gradient(circle, rgba(255, 90, 26, 0.07), transparent 65%);
  filter: blur(70px); pointer-events: none;
}
.showcase__inner {
  display: grid; grid-template-columns: minmax(0, 0.94fr) minmax(0, 1.06fr);
  gap: clamp(36px, 5vw, 80px); align-items: center;
}
.showcase__gamelogo { height: 88px; width: auto; margin-bottom: 22px; filter: drop-shadow(0 8px 24px rgba(0, 0, 0, 0.5)); }
.showcase__features { list-style: none; display: flex; flex-direction: column; gap: 16px; margin-bottom: 30px; }

/* The hook and the beats. Short lines carrying the game's voice rather than the
   body's, so the pitch reads the way somebody would say it out loud. The beats
   are the two one-line turns the copy hangs on — the coin going up, and what
   that moment is called. */
.showcase__hook {
  font-family: var(--font-display);
  font-size: clamp(21px, 2.3vw, 29px);
  font-weight: 600;
  letter-spacing: -0.022em;
  color: var(--on-surface);
  margin-bottom: 18px;
}
.showcase__beat {
  font-size: 17px;
  font-weight: 500;
  color: var(--on-surface);
  margin-bottom: 24px;
}
.showcase__beat--accent { color: var(--accent-bright); margin-bottom: 30px; }

/* ---- The Edge band ---- */
.edgeband {
  margin-top: clamp(52px, 6.5vw, 96px);
  padding: clamp(30px, 4vw, 56px);
  border-radius: var(--r-panel);
  background: var(--surface-container);
  display: grid;
  grid-template-columns: minmax(0, 1.02fr) minmax(0, 0.98fr);
  gap: clamp(26px, 4vw, 62px);
  align-items: center;
}
.edgeband__mark {
  display: grid; place-items: center;
  width: 46px; height: 46px;
  border-radius: 50%;
  margin-bottom: 20px;
  color: var(--accent-bright);
  background: var(--fill);
}
.edgeband__mark svg { width: 21px; height: 21px; }
.edgeband__title { margin: 14px 0 0; }
.edgeband__title em { color: var(--on-surface-muted); }
.edgeband__lead { margin-bottom: 26px; max-width: none; }

/* The three-line turn. Each line its own row so the punch lands on its own,
   and the last one is the only thing in the band wearing the accent. */
.edgeband__called { display: flex; flex-direction: column; gap: 4px; }
.edgeband__called span { color: var(--on-surface-muted); font-size: 16px; }
.edgeband__called strong {
  margin-top: 12px;
  font-family: var(--font-display);
  font-size: clamp(19px, 2vw, 25px);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--accent-bright);
}
.showcase__features li { display: flex; gap: 15px; align-items: flex-start; }
.showcase__feat-icon {
  flex: none; width: 42px; height: 42px; border-radius: 50%;
  display: grid; place-items: center;
  color: var(--accent-bright);
  background: var(--fill);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.showcase__feat-icon svg { width: 19px; height: 19px; }
.showcase__features strong { display: block; font-size: 15px; font-weight: 600; letter-spacing: -0.005em; }
.showcase__features span { color: var(--on-surface-variant); font-size: 14.5px; }
.showcase__stats { display: flex; gap: clamp(20px, 3vw, 44px); margin-bottom: 32px; }
.stat strong { display: block; font-family: var(--font-display); font-weight: 600; font-size: clamp(24px, 2.3vw, 32px); letter-spacing: -0.02em; color: var(--on-surface); }
.stat strong .count { color: inherit; font: inherit; letter-spacing: inherit; }
.stat > span { font-size: 11px; font-weight: 500; letter-spacing: 0.1em; text-transform: uppercase; color: var(--on-surface-muted); }

/* demo rig — one full-bleed stage, floating glass UI, ambient bloom */
.showcase__demo { position: relative; perspective: 1200px; }
.demo {
  position: relative; z-index: 2;
  aspect-ratio: 16 / 10.5; overflow: hidden;
  border-radius: var(--r-panel);
  background:
    linear-gradient(to bottom, rgba(6, 9, 16, 0.55), rgba(6, 9, 16, 0.32) 42%, rgba(6, 9, 16, 0.82) 88%),
    url("../assets/cc-hero-v2.webp") center 30% / cover no-repeat;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.45);
  transform-style: preserve-3d;
  will-change: transform;
}
.demo__result {
  position: absolute; top: 15%; left: 0; right: 0; text-align: center; z-index: 3;
  font-family: var(--font-display); font-weight: 600; font-size: clamp(26px, 2.6vw, 38px);
  letter-spacing: -0.015em; color: var(--on-surface);
  text-shadow: 0 0 34px rgba(255, 140, 40, 0.35), 0 2px 20px rgba(0, 0, 0, 0.6);
  transition: color var(--dur-link);
}
.demo__result.is-heads { color: #8ab8ff; text-shadow: 0 0 34px rgba(90, 140, 255, 0.4), 0 2px 20px rgba(0, 0, 0, 0.6); }
.demo__result.is-tails { color: #ff8a80; text-shadow: 0 0 34px rgba(255, 90, 70, 0.4), 0 2px 20px rgba(0, 0, 0, 0.6); }
.demo__result.is-edge  { color: var(--accent-bright); text-shadow: 0 0 40px rgba(255, 157, 61, 0.65), 0 2px 20px rgba(0, 0, 0, 0.6); }

/* ============ THE COIN ============ */
/*
  Four nested elements, one job each, because every one of them wants the
  transform property and they must never fight over it:

    .coin-slot   the anchor in the card. Owns size and position.
    .coin        what Flip carries between the card and the stage. Owns
                 perspective, and nothing else touches its transform.
    .coin__fly   the arc — translateY and scale, or the resting float.
    .coin__spin  the only 3D context. rotateX in flight, rotateY on the rim.
*/
.coin-slot {
  position: absolute; left: 50%; bottom: 36%; z-index: 2;
  width: clamp(72px, 8.5vw, 104px); aspect-ratio: 1;
  margin-left: calc(clamp(72px, 8.5vw, 104px) / -2);
}
/*
  An inline-size container as well as a 3D one. coinBody.js states the
  coin's thickness and radius as shares of its diameter, and cqi is the only
  unit that can spend them: translateZ refuses a percentage, and the coin's
  pixel size changes when Flip carries it to the fullscreen stage.
*/
.coin { position: absolute; inset: 0; perspective: 640px; container-type: inline-size; }
.coin__fly { position: absolute; inset: 0; will-change: transform; }
.coin.is-resting .coin__fly { animation: coin-rest 5200ms var(--ease-in-out) infinite; }
@keyframes coin-rest {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50%      { transform: translateY(-3.5%) rotate(1deg); }
}

.coin__spin {
  position: absolute; inset: 0;
  transform-style: preserve-3d;
  will-change: transform;
}
.coin__face {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: contain;
  backface-visibility: hidden; -webkit-backface-visibility: hidden;
  filter: drop-shadow(0 10px 24px rgba(0, 0, 0, 0.55));
  /* half a thickness in front of centre, so the solid has a middle */
  transform: translateZ(4.750cqi);
}
.coin__face--back { transform: rotateX(180deg) translateZ(4.750cqi); }

/*
  The rim, as a cylinder wall rather than a picture of one.

  What was here before were two flat copies of coin-edge.webp laid over the
  coin and faded in at the angles where a flat band and a real one look
  alike. That is why the edge never quite looked like the coin's own edge,
  and why an edge landing left every later toss spinning a rim: the overlay's
  opacity outlived the pose that asked for it, and no amount of transform
  could take it back.

  The wall lives inside .coin__spin, so the browser occludes and foreshortens
  it along with the faces and there is no handover left to write.

  Its texture is drawn rather than photographed. coin-edge.webp is a picture
  of an ENTIRE rim seen face-on; thirty-six quads each showing the whole of
  it would be thirty-six repetitions of one bright centre. So the milling is
  a repeating gradient in the golds sampled off that file — #3a2404 in the
  grooves through #f6dd93 on the crests — with a second gradient down the
  thickness for the roll of the edge. It tiles across every quad, so the
  milling runs continuously round the coin.
*/
.coin__rim {
  position: absolute; inset: 0;
  transform-style: preserve-3d;
  pointer-events: none;
}
.coin__rim i {
  position: absolute; left: 50%; top: 50%;
  width: 9.099cqi; height: 9.500cqi;
  margin-left: -4.549cqi; margin-top: -4.750cqi;
  background-image:
    linear-gradient(180deg, rgba(0,0,0,0.62) 0%, rgba(0,0,0,0) 26%,
      rgba(255,255,255,0.14) 50%, rgba(0,0,0,0) 74%, rgba(0,0,0,0.68) 100%),
    linear-gradient(90deg, #3a2404 0%, #8a5c05 16%, #d9ad48 46%,
      #f6dd93 54%, #a5761c 78%, #3a2404 100%);
  background-size: 100% 100%, 50% 100%;
  background-repeat: no-repeat, repeat;
  backface-visibility: hidden; -webkit-backface-visibility: hidden;
  /* the per-quad rotateZ is written once, by coinBody.js */
}
.demo__coin-shadow {
  position: absolute; left: 50%; bottom: 33.5%; z-index: 2;
  width: 90px; height: 14px; margin-left: -45px;
  background: radial-gradient(ellipse, rgba(0, 0, 0, 0.5), transparent 70%);
}

/* floating bottom stack */
.demo__bottom {
  position: absolute; left: 16px; right: 16px; bottom: 16px; z-index: 4;
  display: flex; flex-direction: column; align-items: center; gap: 13px;
}
.demo__status {
  font-size: 11.5px; font-weight: 500; letter-spacing: 0.05em;
  color: rgba(var(--palette-white-rgb), 0.66);
  text-shadow: 0 1px 12px rgba(0, 0, 0, 0.8);
}
.demo__history { display: flex; justify-content: center; gap: 6px; overflow: hidden; max-width: 100%; }
.demo__hist-chip {
  display: grid; place-items: center; flex: none;
  width: 28px; height: 28px; border-radius: 50%;
  font-size: 10.5px; font-weight: 600; letter-spacing: 0.02em;
  background: var(--glass);
  backdrop-filter: blur(var(--glass-blur));
  -webkit-backdrop-filter: blur(var(--glass-blur));
  color: var(--on-surface-variant);
  animation: hist-in 0.3s var(--ease-out);
}
.demo__hist-chip--h { color: #8ab8ff; }
.demo__hist-chip--t { color: #ff8a80; }
.demo__hist-chip--bonus { color: #57e694; }
.demo__hist-chip--edge { color: var(--accent-bright); width: auto; padding: 0 13px; border-radius: var(--r-pill); }
@keyframes hist-in { from { transform: translateY(6px); opacity: 0; } to { transform: none; opacity: 1; } }

.demo__controls { display: flex; gap: 8px; width: 100%; }
.demo__btn {
  flex: 1; text-align: center; padding: 12px;
  font-size: 13px; font-weight: 500; letter-spacing: 0.01em;
  border-radius: var(--r-pill);
  background: var(--glass);
  backdrop-filter: blur(var(--glass-blur));
  -webkit-backdrop-filter: blur(var(--glass-blur));
  color: rgba(var(--palette-white-rgb), 0.85);
  transition: background var(--dur-btn) ease-out, color var(--dur-btn) ease-out;
}
.demo__btn.is-called { background: var(--accent); color: var(--ink); font-weight: 600; }

.demo__btn:hover { background: var(--glass-strong); color: var(--on-surface); }
.demo__btn:disabled { opacity: 0.45; pointer-events: none; }

/* ============ COIN STAGE — the fullscreen toss ============ */
/*
  Lives outside #smooth-wrapper on purpose: position:fixed inside a
  transformed ancestor resolves against the ancestor, not the viewport, and
  ScrollSmoother transforms #smooth-content on every frame.
*/
.stage {
  position: fixed; inset: 0; z-index: 800;
  display: grid; place-items: center;
  opacity: 0; visibility: hidden; pointer-events: none;
  /* Near-solid: the page behind is not atmosphere, it is a competing headline. */
  background: radial-gradient(125% 95% at 50% 42%, rgba(5, 8, 16, 0.975), rgba(1, 2, 5, 0.995) 62%);
  transition: opacity 0.55s var(--ease-out), visibility 0.55s;
}
.stage.is-open { opacity: 1; visibility: visible; pointer-events: auto; }

/*
  Sat above centre so the coin clears the captains' faces — they are looking up
  at it, and the whole picture falls apart if it is covering their heads.
  The reveal then needs the middle of the frame, so the coin gives up more.
*/
.stage__slot { transform: translateY(-9%); transition: transform 0.9s var(--ease-out); }
.stage.is-edge .stage__slot { transform: translateY(-17%) scale(0.84); }

/* the stadium, in plates — absent until the art lands, and fine without it */
.stage__sky, .stage__stands {
  position: absolute; left: 0; right: 0; pointer-events: none;
  background-position: center; background-size: cover; background-repeat: no-repeat;
  will-change: transform;
}
.stage__sky {
  top: 0; height: 78%;
  background-image: url("../assets/stadium-sky.webp");
  background-size: cover;
  opacity: 0.5;
  -webkit-mask-image: linear-gradient(to bottom, #000 48%, transparent);
  mask-image: linear-gradient(to bottom, #000 48%, transparent);
}
/*
  Full height with the image at natural aspect, anchored to the floor. `cover`
  in a short box crops the plate and leaves a hard horizontal cut across the
  frame where the element ends; the plate's own alpha above the roofline is the
  only edge that should be visible.
*/
.stage__stands {
  bottom: 0; height: 100%;
  background-image: url("../assets/stadium-stands.webp");
  background-size: 100% auto;
  background-position: center bottom;
  opacity: 0.62;
}
.stage__captains {
  position: absolute; bottom: 0; left: 0; right: 0; height: 46%;
  background: url("../assets/stadium-captains.webp") center bottom / contain no-repeat;
  opacity: 0.75; pointer-events: none; will-change: transform;
}

/* floodlight cones — JS leans them toward the coin as it climbs */
.stage__beam {
  position: absolute; top: -14%; width: 40vmin; height: 125%;
  pointer-events: none; opacity: 0;
  background: linear-gradient(to bottom,
    rgba(255, 228, 176, 0.22), rgba(255, 198, 120, 0.06) 46%, transparent 74%);
  filter: blur(20px);
  transform-origin: 50% 0%;
  clip-path: polygon(42% 0, 58% 0, 100% 100%, 0 100%);
}
.stage__beam--l { left: 4%; }
.stage__beam--r { right: 4%; }

/* the single spotlight The Edge earns */
.stage__spot {
  position: absolute; inset: 0; opacity: 0; pointer-events: none;
  background: radial-gradient(24% 40% at 50% 44%, rgba(255, 238, 198, 0.34), rgba(255, 180, 90, 0.08) 46%, transparent 70%);
}

.stage__embers { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }

.stage__slot { position: relative; width: min(44vmin, 400px); aspect-ratio: 1; }

.stage__count {
  position: absolute; top: 11%; left: 0; right: 0; text-align: center;
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(26px, 5.4vw, 58px); letter-spacing: 0.16em;
  color: rgba(255, 228, 176, 0.92);
  text-shadow: 0 0 44px rgba(255, 150, 50, 0.5);
  opacity: 0; pointer-events: none;
}

.stage__verdict {
  position: absolute; bottom: 19%; left: 0; right: 0; text-align: center;
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(32px, 7.4vw, 84px); letter-spacing: -0.02em; line-height: 1;
  opacity: 0; pointer-events: none;
}
.stage__verdict.is-heads { color: #9cc4ff; text-shadow: 0 0 46px rgba(90, 140, 255, 0.5); }
.stage__verdict.is-tails { color: #ff9a90; text-shadow: 0 0 46px rgba(255, 90, 70, 0.5); }

/* the reveal, held back until the coin has been still for a beat */
.stage__edge {
  position: absolute; inset: 0; z-index: 2;
  display: flex; flex-direction: column; align-items: center; justify-content: flex-end;
  gap: 4px; padding-bottom: 11%;
  opacity: 0; pointer-events: none;
}
.stage__edge-mark {
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(28px, 6.4vw, 70px); letter-spacing: 0.18em;
  color: #f4e2a8; text-shadow: 0 0 54px rgba(255, 180, 80, 0.7);
}
.stage__edge-mark sup { font-size: 0.32em; letter-spacing: 0; vertical-align: super; }
.stage__edge-mult {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(38px, 9.4vw, 104px); letter-spacing: -0.03em; line-height: 1;
  color: var(--accent-bright); text-shadow: 0 0 60px rgba(255, 122, 26, 0.55);
}
.stage__edge-note {
  margin-top: 10px;
  font-size: 11.5px; font-weight: 500; letter-spacing: 0.07em;
  color: var(--on-surface-muted);
}

.stage__again {
  position: absolute; bottom: 7%; left: 50%; transform: translateX(-50%);
  z-index: 3;
  font-size: 14.5px; font-weight: 500; letter-spacing: 0.01em;
  padding: 13px 27px; border-radius: var(--r-pill);
  background: var(--fill); color: var(--on-surface);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  opacity: 0; transition: opacity 0.4s var(--ease-out), background var(--dur-btn) ease-out;
}
.stage__again.is-shown { opacity: 1; }
.stage__again:hover { background: var(--fill-hover); }

.stage__close {
  position: absolute; top: 22px; right: 26px; z-index: 4;
  width: 42px; height: 42px; border-radius: 50%;
  display: grid; place-items: center;
  font-size: 22px; line-height: 1;
  background: var(--fill); color: var(--on-surface-variant);
  transition: all var(--dur-btn) ease-out;
}
.stage__close:hover { background: var(--fill-hover); color: var(--on-surface); }

@media (max-width: 640px) {
  /* twenty-two names still read as "all the same" and cost a third less paint;
     the one that is not a reskin sits at position 18 and survives the cut */
  .wrapwall__name:nth-child(n+23) { display: none; }
  .manifesto__statement { max-width: none; }
  .cadence__list { gap: 6px 18px; }
  .principle { border-radius: var(--r-card); }
  .stage__slot { width: min(62vmin, 300px); }
  .stage__close { top: 14px; right: 14px; }
  /* portrait is tall and narrow: the verdict and the invitation were sitting
     on top of each other, and the invitation was wrapping to two lines */
  .stage__verdict { bottom: 27%; }
  .stage__again { bottom: 9%; font-size: 13.5px; padding: 12px 20px; white-space: nowrap; }
  .stage__edge { padding-bottom: 18%; }
  .stage__edge-note { max-width: 78vw; text-align: center; line-height: 1.5; }
}

/* art panel idle life — a single quiet breathe */
.art-breathe { animation: art-breathe 6s var(--ease-in-out) infinite; }
.art-breathe--late { animation-delay: 3s; }
@keyframes art-breathe { 0%, 100% { opacity: 0.65; } 50% { opacity: 1; } }

/* ============ TECHNOLOGY ============ */
.tech__grid { display: grid; grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr); gap: clamp(36px, 5vw, 80px); align-items: start; }
.tech__chip { margin-top: 44px; max-width: 320px; }
.tech__chip-board { position: relative; border-radius: var(--r-card); padding: 18px; background: var(--surface-container); }
.tech__chip-board > svg:first-child { width: 100%; height: auto; }
/* ---- the core and its four spokes ---- */
.tech__core-plate { fill: #1b1611; stroke: #ff7a1a; stroke-width: 1.6; }
.tech__core-die { fill: #241b12; }

.spoke__rail { stroke: rgba(255, 122, 26, 0.2); stroke-width: 1.6; transition: stroke 0.3s var(--ease-out); }
.spoke__node { fill: #ff8a3a; transition: fill 0.3s var(--ease-out); }

/*
  The travelling pulse is one dash chasing a gap as long as the path itself, so
  only ever one is on the wire.

  The dash and the motion are both set from JS, not from here. A keyframe whose
  value contains var() or calc() is not interpolable — the property flips
  between the two endpoints instead of travelling — and the first version of
  this did exactly that: the animation reported itself as running while
  stroke-dashoffset only ever held `11.4px` or `calc(-152px)`.
*/
.spoke__pulse {
  stroke: #ffc53d; stroke-width: 2.4;
  filter: drop-shadow(0 0 5px rgba(255, 170, 60, 0.85));
  opacity: 0;
}

.spoke.is-lit .spoke__rail { stroke: rgba(255, 197, 61, 0.65); }
.spoke.is-lit .spoke__node { fill: #ffe3a1; }

.tech__chip-mark {
  position: absolute; width: 42px; height: 42px; object-fit: contain;
  left: 50%; top: 50%; transform: translate(-50%, -50%);
  animation: core-breathe 3.4s var(--ease-in-out) infinite;
}
@keyframes core-breathe {
  0%, 100% { filter: drop-shadow(0 0 8px rgba(255, 90, 26, 0.3)); }
  50%      { filter: drop-shadow(0 0 18px rgba(255, 140, 40, 0.62)); }
}

.tech__features { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.tech-card {
  padding: 28px 26px;
  background: var(--surface-container); border-radius: var(--r-card);
  transition: background var(--dur-card) ease-out;
}
.tech-card:hover { background: var(--surface-high); }
.tech-card__icon {
  display: grid; place-items: center; width: 46px; height: 46px; margin-bottom: 20px;
  border-radius: 50%; color: var(--accent-bright);
  background: var(--fill);
  transition: background var(--dur-card) ease-out;
}
.tech-card:hover .tech-card__icon { background: var(--fill-hover); }
.tech-card__icon svg { width: 21px; height: 21px; }
.tech-card h3 { font-family: var(--font-display); font-size: 17px; font-weight: 600; letter-spacing: -0.01em; margin-bottom: 8px; }
.tech-card p { color: var(--on-surface-variant); font-size: 14.5px; }

/* ============ STUDIO / TIMELINE ============ */
.studio__grid { display: grid; grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.5fr); gap: clamp(36px, 4vw, 64px); align-items: start; }
.studio__intro { position: sticky; top: calc(var(--header-h) + 30px); }

.timeline { position: relative; display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; padding-top: 26px; }
.timeline__line { position: absolute; top: 47px; left: 4%; right: 4%; height: 2px; }
.timeline__seg { position: absolute; top: 0; height: 100%; border-radius: 2px; background: rgba(var(--palette-white-rgb), 0.13); overflow: hidden; }
.timeline__seg i { display: block; width: 100%; height: 100%; background: var(--accent); transform-origin: left; transform: scaleX(0); }
.timeline__item { text-align: center; padding: 0 6px; }
.timeline__node {
  position: relative; z-index: 2;
  display: grid; place-items: center; width: 44px; height: 44px; margin: 0 auto 16px;
  border-radius: 50%;
  background: var(--surface-high); color: var(--on-surface-muted);
  transition: color 0.4s, background 0.4s;
}
.timeline__node svg { width: 19px; height: 19px; }
.timeline__node svg.timeline__ring {
  position: absolute; left: 50%; top: 50%;
  width: 52px; height: 52px; max-width: none; max-height: none;
  margin: -26px 0 0 -26px;
  transform: rotate(180deg); pointer-events: none;
}
.timeline__ring circle {
  fill: none; stroke: var(--accent); stroke-width: 2.5; stroke-linecap: round;
}
.timeline__item.is-lit .timeline__node { color: var(--accent-bright); background: var(--surface-higher); }
.timeline__year {
  display: block; font-family: var(--font-display); font-weight: 600; font-size: 19px;
  letter-spacing: -0.01em; color: var(--on-surface-muted); margin-bottom: 5px;
  transition: color 0.4s;
}
.timeline__item.is-lit .timeline__year { color: var(--accent); }

/*
  Everything to the right of the quarter we are in has not happened yet, so it
  is drawn as unfinished rather than merely dim: the rail into it is a dashed
  track the fire has not reached, and its ring never closes. The last tile is
  further out still — an ember breathing, rather than one that has caught.

  The state is also said in words on a small tag, because a claim about the
  future should not depend on a viewer noticing an animation.
*/
.timeline__seg--dashed {
  background: repeating-linear-gradient(to right,
    rgba(var(--palette-white-rgb), 0.15) 0 5px, transparent 5px 11px);
}
.timeline__seg--dashed i { display: none; }
.timeline__item[data-state="next"] .timeline__node,
.timeline__item[data-state="ahead"] .timeline__node {
  background: transparent;
  box-shadow: inset 0 0 0 1px rgba(var(--palette-white-rgb), 0.12);
}
.timeline__tag {
  display: inline-block; margin-top: 11px;
  padding: 3px 9px; border-radius: 999px;
  border: 1px dashed rgba(var(--palette-white-rgb), 0.18);
  font-size: 10px; font-weight: 500; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--on-surface-muted);
}
.timeline__item[data-state="ahead"] .timeline__tag {
  color: var(--accent); border-color: rgba(255, 90, 26, 0.34);
}
/* the one that has actually happened says so in solid, not dashed */
.timeline__tag--live {
  border-style: solid; border-color: rgba(255, 90, 26, 0.45);
  color: var(--accent-bright);
}
/* the ember waiting to catch — one element, opacity and transform only */
@keyframes timeline-breathe {
  0%, 100% { opacity: 0.4; transform: scale(1); }
  50%      { opacity: 0.92; transform: scale(1.07); }
}
.timeline__item[data-state="ahead"] .timeline__node > svg:not(.timeline__ring) {
  color: var(--accent);
  animation: timeline-breathe 3.2s ease-in-out infinite;
}
html.no-motion .timeline__item[data-state="ahead"] .timeline__node > svg:not(.timeline__ring) {
  animation: none; opacity: 0.72;
}
.timeline__item h3 { font-family: var(--font-display); font-size: 15px; font-weight: 600; letter-spacing: -0.005em; margin-bottom: 7px; }
.timeline__item p { font-size: 13px; color: var(--on-surface-variant); }

.careers {
  grid-column: 1 / -1;
  position: relative; overflow: hidden;
  margin-top: 24px; padding: clamp(34px, 4vw, 56px);
  border-radius: var(--r-panel);
  background:
    radial-gradient(640px 320px at 90% 15%, rgba(255, 110, 26, 0.09), transparent 65%),
    var(--surface-container);
  display: flex; flex-direction: column; align-items: flex-start; gap: 6px;
}
.careers__bg { position: absolute; right: -20px; top: 50%; transform: translateY(-50%); width: 340px; opacity: 0.24; pointer-events: none; }
.careers__mark { width: 100%; height: auto; }
.careers__title { font-family: var(--font-display); font-weight: 600; font-size: clamp(26px, 2.9vw, 36px); letter-spacing: -0.02em; }
.careers p { color: var(--on-surface-variant); margin-bottom: 20px; max-width: 42ch; }

/* ============ STANCE (positioning / partnership) ============ */
.stance__grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 16px; margin: 40px 0 34px;
}
.stance__item {
  padding: 26px 24px;
  background: var(--surface-container); border-radius: var(--r-card);
  transition: background var(--dur-card) ease-out;
}
.stance__item:hover { background: var(--surface-high); }
.stance__item h3 {
  font-family: var(--font-display); font-size: 16px; font-weight: 600;
  letter-spacing: -0.01em; margin-bottom: 8px; color: var(--accent-bright);
}
.stance__item p { color: var(--on-surface-variant); font-size: 14.5px; }

/* ============ FOOTER ============ */
.footer { padding: 72px 0 28px; background: linear-gradient(to bottom, transparent, rgba(20, 17, 11, 0.6)); }
.footer__grid { display: grid; grid-template-columns: 1.4fr repeat(4, 0.8fr) 1.2fr; gap: 32px; margin-bottom: 52px; }
.footer__brand p { color: var(--on-surface-variant); font-size: 14px; margin-top: 16px; max-width: 30ch; }
.footer__col { display: flex; flex-direction: column; gap: 10px; }
.footer__col h4, .footer__side h4 {
  font-size: 12px; font-weight: 500;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--on-surface-muted); margin-bottom: 8px;
}
.footer__col a { color: var(--on-surface-variant); font-size: 14px; width: fit-content; transition: color var(--dur-link); }
.footer__col a:hover { color: var(--on-surface); }
.footer__social { display: flex; gap: 8px; margin-bottom: 26px; }
.footer__social a {
  display: grid; place-items: center; width: 38px; height: 38px; border-radius: 50%;
  background: var(--fill); color: var(--on-surface-variant);
  transition: all var(--dur-btn) ease-out;
}
.footer__social a:hover { color: var(--on-surface); background: var(--fill-hover); }
.footer__social svg { width: 16px; height: 16px; }
.footer__bottom {
  display: flex; justify-content: space-between; align-items: center; gap: 16px; flex-wrap: wrap;
  padding-top: 24px;
  color: var(--on-surface-muted); font-size: 13px;
}
.footer__legal { display: flex; gap: 12px; align-items: center; }
.footer__legal i { opacity: 0.4; }
.footer__legal a { transition: color var(--dur-link); }
.footer__legal a:hover { color: var(--on-surface); }

/* ============ REVEAL STATES (JS adds .is-in) ============ */
.reveal { opacity: 0; transform: translateY(24px); }
html.no-motion .reveal, html.no-js .reveal { opacity: 1; transform: none; }

/* ============ MANIFESTO ============ */
.manifesto { position: relative; overflow: hidden; }
.manifesto__mesh { position: absolute; inset: 0; background: var(--grad-mesh); pointer-events: none; }
.manifesto__inner { position: relative; z-index: 1; }
.manifesto__statement { max-width: 17ch; margin-bottom: clamp(38px, 5vw, 70px); }
.manifesto__statement em { color: var(--on-surface-muted); }
.manifesto__resolve { max-width: 58ch; margin-bottom: clamp(54px, 7vw, 100px); }
.manifesto__resolve .lead { max-width: none; font-size: clamp(16px, 1.5vw, 18.5px); margin-bottom: 0; }

/* ---- the wrapper wall ---- */
/*
  The category's argument against itself: a sport or a celebrity bolted to a
  stock casino game, over and over, with the one game that isn't a reskin
  burning in the middle of it.

  The names move on transform and opacity alone. At thirty-five nodes a
  per-name filter or text-shadow is the difference between this section being
  free and this section being the reason a mid-range phone stutters. The single
  blurred glow is the one exception, and it is one element, not thirty-five.
*/
.wrapwall {
  position: relative;
  display: flex; flex-wrap: wrap; justify-content: center; align-items: center;
  gap: clamp(11px, 1.5vw, 24px) clamp(15px, 2.1vw, 36px);
  padding: clamp(12px, 2vw, 28px) 0;
  margin-bottom: clamp(28px, 3.5vw, 50px);
}
/*
  The greys vary by colour, not by opacity, because opacity is the channel the
  scroll owns — a per-name opacity baked in here would be overwritten the
  moment the timeline touches it, and the wall would flatten to one tone.
*/
.wrapwall__name {
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(11px, 1.15vw, 15px);
  letter-spacing: 0.06em; text-transform: uppercase; white-space: nowrap;
  color: rgba(var(--palette-white-rgb), 0.2);
}
.wrapwall__name:nth-child(3n)   { color: rgba(var(--palette-white-rgb), 0.13); }
.wrapwall__name:nth-child(4n+1) { color: rgba(var(--palette-white-rgb), 0.27); }

.wrapwall__ours {
  position: relative; z-index: 2;
  display: inline-flex; align-items: center; gap: 0.5em;
  padding: 0.4em 0.85em 0.4em 0.4em;
  border-radius: 999px;
  background: var(--surface-container);
  box-shadow: inset 0 0 0 1px rgba(255, 90, 26, 0.32);
  font-size: clamp(13px, 1.5vw, 19px);
}
.wrapwall__ourname {
  font-family: var(--font-display); font-weight: 600;
  letter-spacing: 0.01em; white-space: nowrap; color: var(--on-surface);
}
.wrapwall__glow {
  position: absolute; left: 50%; top: 50%;
  width: 360px; height: 360px; margin: -180px 0 0 -180px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 122, 26, 0.45), transparent 66%);
  filter: blur(46px);
  opacity: 0; pointer-events: none;
}
.wrapwall__chip {
  display: grid; place-items: center; flex: none;
  width: 1.95em; height: 1.95em;
  border-radius: clamp(4px, 0.6vw, 8px);
  background:
    radial-gradient(circle at 50% 50%, rgba(16, 9, 4, 0.86) 0 34%, rgba(16, 9, 4, 0) 72%),
    var(--grad-fire);
}
/* the mark burns in full colour, so the chip gives it a dark core to burn
   against — fire on fire is mud, fire on ember reads */
.wrapwall__chip img {
  width: 74%; height: 74%; object-fit: contain;
  filter: drop-shadow(0 1px 3px rgba(12, 6, 2, 0.55));
  opacity: 0;
}
.wrapwall__caption {
  display: block; margin-bottom: clamp(54px, 7vw, 96px);
  font-size: 12.5px; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--on-surface-muted);
}
.wrapwall__caption b { color: var(--accent); font-weight: 500; }
/* no motion engine — the wall states its case standing still */
html.no-js .wrapwall__glow, html.no-motion .wrapwall__glow { opacity: 1; }
html.no-js .wrapwall__chip img, html.no-motion .wrapwall__chip img { opacity: 1; }

/* ---- the cadence ---- */
.cadence__list {
  display: flex; flex-wrap: wrap; gap: 8px 26px;
  font-family: var(--font-display);
  font-size: clamp(17px, 2vw, 26px); font-weight: 500; letter-spacing: -0.02em;
  color: var(--on-surface-variant);
  margin-bottom: 22px;
}
.cadence__close { color: var(--on-surface); }

/* ============ PRINCIPLES ============ */
.principles__grid {
  display: grid; grid-template-columns: minmax(0, 0.6fr) minmax(0, 1.4fr);
  gap: clamp(28px, 4vw, 72px); align-items: start;
}
.principles__aside { position: sticky; top: calc(var(--header-h) + 44px); }
.principles__index { position: relative; height: 1.14em; margin-top: 10px; }
.principles__index span {
  position: absolute; left: 0; top: 0;
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(58px, 8.4vw, 124px); line-height: 0.9; letter-spacing: -0.05em;
  background: var(--grad-fire);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
  /* absolutely positioned, so this padding is free — and without it
     background-clip: text slices the bottom off every numeral */
  padding: 0.14em 0.06em 0.26em;
  opacity: 0; transform: translateY(0.1em);
  transition: opacity 0.34s var(--ease-out), transform 0.34s var(--ease-out);
}
.principles__index span.is-on { opacity: 1; transform: none; }
html.no-js .principles__index span:first-child,
html.no-motion .principles__index span:first-child { opacity: 1; transform: none; }

.principles__rows { display: flex; flex-direction: column; gap: 16px; }
.principle {
  padding: clamp(26px, 3vw, 44px);
  border-radius: var(--r-panel);
  background: var(--surface-container);
  transition: background var(--dur-edge) var(--ease-out);
}
.principle.is-current { background: var(--surface-high); }
.principle__no {
  display: block; margin-bottom: 15px;
  font-family: var(--font-display); font-size: 12px; font-weight: 600;
  letter-spacing: 0.2em; color: var(--on-surface-muted);
  transition: color var(--dur-edge) var(--ease-out);
}
.principle.is-current .principle__no { color: var(--accent); }
.principle__title {
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(21px, 2.5vw, 34px); line-height: 1.08; letter-spacing: -0.028em;
  margin-bottom: 14px;
}
.principle__body { color: var(--on-surface-variant); font-size: 15.5px; max-width: 56ch; }
.principle__body strong { color: var(--on-surface); font-weight: 600; }

/* ============ EXPERIENCE CLOSING LINE ============ */
.tech__earn {
  grid-column: 1 / -1;
  margin-top: clamp(28px, 3vw, 44px);
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(17px, 1.8vw, 23px); letter-spacing: -0.02em;
  color: var(--on-surface-variant);
}
.tech__earn em { font-style: normal; color: var(--accent); }

/* ============ SIGN-OFF ============ */
.signoff {
  position: relative; overflow: hidden; text-align: center;
  padding: clamp(88px, 12vh, 148px) 0 clamp(64px, 8vh, 104px);
}
.signoff__mesh { position: absolute; inset: 0; background: var(--grad-mesh); pointer-events: none; }
.signoff__inner { position: relative; z-index: 1; display: flex; flex-direction: column; align-items: center; }
/* the fuse: an ember falls down it and lights the mark waiting at the bottom */
.signoff__fuse {
  position: relative; width: 1px; height: clamp(52px, 8vh, 84px); margin-bottom: 24px;
  background: linear-gradient(to bottom, transparent, rgba(var(--palette-white-rgb), 0.18));
}
.signoff__fuse i {
  position: absolute; left: 50%; top: 0; width: 7px; height: 7px; margin-left: -3.5px;
  border-radius: 50%;
  background: radial-gradient(circle, #fff3d6 0%, #ffc53d 40%, #ff7a1a 70%, rgba(255, 61, 0, 0) 80%);
  box-shadow: 0 0 15px 3px rgba(255, 140, 40, 0.6);
  opacity: 0;
}
.signoff__mark {
  width: clamp(48px, 6vw, 66px); aspect-ratio: 1; object-fit: contain;
  margin-bottom: clamp(24px, 3vw, 36px);
  transition: filter 0.7s var(--ease-out);
}
.signoff__mark.is-lit { filter: drop-shadow(0 0 26px rgba(255, 140, 40, 0.6)); }
.signoff__lede {
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(20px, 2.5vw, 32px); letter-spacing: -0.028em;
  margin-bottom: clamp(26px, 3vw, 38px);
}
.signoff__creed { display: flex; flex-direction: column; gap: 7px; }
.signoff__creed span { font-size: clamp(15px, 1.45vw, 18px); color: var(--on-surface-variant); }
.signoff__creed span:last-child { color: var(--accent-bright); }
html.no-js .signoff__mark, html.no-motion .signoff__mark { filter: drop-shadow(0 0 22px rgba(255, 140, 40, 0.5)); }


/* ============ DESCENDER SAFETY ============ */
/*
  Two boxes on this site are routinely shorter than the glyphs inside them, and
  both of them clip rather than overflow.

  SplitText masks each line in an overflow:clip wrapper exactly one line-box
  tall. Display type here runs at line-height 0.98-1.12 and the face needs about
  1.21em, so descenders were being cut. The padding grows the clip box (clipping
  is against the padding box); the matching negative margin gives the space
  straight back, so the leading is exactly what it was.
*/
.sline-mask {
  padding-top: 0.18em;    margin-top: -0.18em;
  padding-bottom: 0.24em; margin-bottom: -0.24em;
}

/*
  background-clip: text paints only inside the element's own box, so a glyph
  hanging below it is not drawn at all. These two are the only gradient-filled
  text on the site; both need their box grown past the line box to be painted
  whole.
*/
.statement--grad {
  padding-top: 0.16em;    margin-top: -0.16em;
  padding-bottom: 0.24em; margin-bottom: -0.24em;
}


/* ============ RESPONSIVE ============ */
@media (max-width: 1024px) {
  .principles__grid { grid-template-columns: 1fr; }
  .principles__aside { position: static; }
  /* the sticky numeral has nothing to be sticky against once the rows go full
     width, and each row already carries its own number */
  .principles__index { display: none; }
  /* the wall wraps itself; it just needs fewer rows of it on a narrow page */
  .wrapwall__name:nth-child(n+29) { display: none; }
  .manifesto__statement { max-width: 20ch; }
  .nav { display: none; }
  .btn--portal { margin-left: auto; }
  .burger { display: flex; }
  .hero { padding-bottom: 72px; }
  .hero__scrollhint { display: none; }
  .hero__inner { grid-template-columns: 1fr; text-align: left; }
  .hero__visual { order: -1; margin-top: 20px; }
  .hero__star-wrap { width: min(24vh, 220px); }
  .tech__grid, .showcase__inner, .edgeband { grid-template-columns: 1fr; }
  .studio__grid { grid-template-columns: 1fr; }
  .studio__intro { position: static; }
  .timeline { grid-template-columns: repeat(2, 1fr); gap: 32px 18px; }
  .timeline__line { display: none; }
  .footer__grid { grid-template-columns: repeat(3, 1fr); }
  .footer__brand { grid-column: 1 / -1; }
  .showcase__gamelogo { height: 72px; }
}
@media (max-width: 640px) {
  .btn--portal { display: none; }
  .section-head { flex-direction: column; align-items: flex-start; }
  .games__track { grid-auto-columns: min(78vw, 320px); }
  .games__arrows { display: none; }
  .timeline { grid-template-columns: 1fr; }
  .footer__grid { grid-template-columns: 1fr 1fr; }
  .footer__side { grid-column: 1 / -1; }
  .hero__ctas .btn { width: 100%; justify-content: center; }
  .showcase__stats { flex-wrap: wrap; }
  .showcase__gamelogo { height: 60px; }
  .tech__features { grid-template-columns: 1fr; }
  .careers__bg { width: 240px; opacity: 0.18; }
  /* the demo becomes a portrait stage on phones — room for coin, status, history and controls */
  .demo { aspect-ratio: 3 / 3.9; border-radius: var(--r-card); }
  .demo__result { top: 11%; }
  .demo__coin { bottom: 40%; }
  .demo__coin-shadow { bottom: 37.5%; }
  .demo__bottom { gap: 10px; }
}

/* ============ REDUCED MOTION ============ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; }
  html { scroll-behavior: auto; }
}
