/* ═══════════════════════════════════════════════════════════════════
   KWIETMOB — SEASON ZERO · MUNICH
   A title card, a transmission, three quiet statements.
   Mobile-first. Near-black + warm off-white, aligned with the
   Season Zero app tokens. Subtle grain, cinematic reveals.
   ═══════════════════════════════════════════════════════════════════ */

/* ── RESET ─────────────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* Author display rules must never resurrect [hidden] elements */
[hidden] { display: none !important; }

/* ── TOKENS (mirrors mobile/src/theme/tokens.ts) ───────────────── */

:root {
  --bg:            #0A0A0A;
  --bg-deep:       #050505;

  --text:          #ECE8DF;
  --text-2:        #A9A498;
  --text-dim:      #6E6A60;
  --text-faint:    #4A473F;

  --silver:        #C8C3B6;

  --line:          rgba(236, 232, 223, 0.10);
  --line-strong:   rgba(236, 232, 223, 0.22);
  --glow:          rgba(200, 195, 182, 0.10);

  --black:         #000000;

  --sans:          'Space Grotesk', 'Helvetica Neue', sans-serif;
  --mono:          'Space Mono', 'Courier New', monospace;

  --ease:          cubic-bezier(0.16, 1, 0.3, 1);

  /* Shared horizontal page gutter */
  --gutter:        clamp(1.4rem, 5.5vw, 4.5rem);
  /* Vertical distance between scenes — vast on purpose */
  --scene:         clamp(7rem, 22vh, 14rem);
  /* Content measure for wide screens */
  --measure:       70rem;
}

/* ── BASE / SCROLL STAGE ───────────────────────────────────────────
   The document scroller (the viewport) is the one and only vertical
   scroll container, so wheel, touch, keyboard and find-in-page all
   drive it natively. Snapping is native CSS, y-mandatory, on every
   breakpoint; the scenes below define the snap positions.

   Scene heights use 100svh — the SMALL viewport height — which iOS
   Safari keeps constant whether its toolbars are expanded or
   collapsed. Nothing recalculates height during a gesture, so snap
   positions can never shift mid-scroll.

   No global scroll-behavior: smooth — it stalls hash navigation in
   background tabs. In-page anchors scroll smoothly via script.js.  */
html {
  scroll-snap-type: y mandatory;
  background: var(--bg-deep);
  scrollbar-width: thin;
  scrollbar-color: rgba(236, 232, 223, 0.14) transparent;
}

/* A cinema has no scrollbar — lock the page while the title card runs */
html.is-intro:not(.intro-done) { overflow: hidden; }

body {
  background: var(--bg-deep);
  color: var(--text);
  font-family: var(--sans);
  font-weight: 300;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
  min-height: 100vh;
}

/* Every cinematic scene is exactly one composed frame: it fills the
   stable viewport and is a hard snap stop in both directions. */
.hero,
.transmission,
.statement,
.mission,
.enter,
.ending {
  min-height: 100vh;
  min-height: 100svh;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}

/* The credits rest at the very end of the reel */
.footer { scroll-snap-align: end; }

/* Atmosphere — a barely-lit room, drifting almost imperceptibly */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  background:
    radial-gradient(ellipse 90% 60% at 50% 0%, #0E0E0E 0%, rgba(10,10,10,0) 60%),
    radial-gradient(ellipse 120% 90% at 50% 55%, #0A0A09 0%, #040404 90%);
  z-index: -2;
  pointer-events: none;
  animation: drift 80s ease-in-out infinite alternate;
}

@keyframes drift {
  from { transform: translate3d(0, 0, 0) scale(1.02); }
  to   { transform: translate3d(0, -1.2%, 0) scale(1.05); }
}

/* Film grain — texture, not effect */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  opacity: 0.05;
  mix-blend-mode: overlay;
  z-index: 1;
  pointer-events: none;
}

::selection {
  background: rgba(236, 232, 223, 0.18);
  color: var(--text);
}

a { color: inherit; }

img { max-width: 100%; display: block; }

/* Visible focus for keyboard users — quiet but unmistakable */
:focus { outline: none; }
:focus-visible {
  outline: 1px solid var(--text-2);
  outline-offset: 5px;
}

.mark {
  user-select: none;
  -webkit-user-drag: none;
  /* Source PNG is a cream mark on a solid black square — screen-blend
     drops the black pixels against the dark page background. */
  mix-blend-mode: screen;
}

/* ── TYPE UTILITIES ────────────────────────────────────────────── */

.tag {
  font-family: var(--mono);
  font-size: clamp(0.56rem, 1.4vw, 0.66rem);
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--text-dim);
}

/* ═══════════════════════════════════════════════════════════════
   OPENING SEQUENCE
   ───────────────────────────────────────────────────────────────
   States on <html>, added cumulatively, never removed:
     .is-intro     pre-paint: black screen, everything hidden
     .intro-title  the headline fades in, alone
     .intro-done   the page reveals itself around the title
     .intro-skip   user interrupted — everything resolves fast
   Without JS none of these classes exist and the page is simply
   visible. Reduced motion never enters the sequence at all.
   ═══════════════════════════════════════════════════════════════ */

/* .veil — hero elements that wait for the title before appearing */
.veil { opacity: 1; }

html.is-intro .veil {
  opacity: 0;
  transform: translateY(12px);
}

html.is-intro.intro-done .veil {
  opacity: 1;
  transform: none;
  transition: opacity 1.6s var(--ease), transform 1.6s var(--ease);
  transition-delay: var(--d, 0s);
}

/* The title card itself — settles fully, then holds a silent beat
   before the page is allowed to arrive (timing in script.js) */
html.is-intro .hero-title {
  opacity: 0;
  transform: scale(1.035);
  filter: blur(7px);
  transition: opacity 1.4s var(--ease), transform 1.4s var(--ease), filter 1.4s var(--ease);
}

html.is-intro.intro-title .hero-title {
  opacity: 1;
  transform: none;
  filter: blur(0);
}

/* The world arrives with a barely-there camera settle */
html.is-intro .hero {
  transform: scale(1.012);
  transition: transform 2.2s var(--ease);
}

html.is-intro.intro-done .hero { transform: none; }

/* Below the fold stays dark until the sequence has finished */
html.is-intro main,
html.is-intro footer { opacity: 0; }

html.is-intro.intro-done main,
html.is-intro.intro-done footer {
  opacity: 1;
  transition: opacity 1.2s ease 0.2s;
}

/* Skip: resolve everything quickly, no staggering */
html.intro-skip .hero-title,
html.intro-skip .veil,
html.intro-skip main,
html.intro-skip footer {
  transition-duration: 0.5s !important;
  transition-delay: 0s !important;
}

/* ── SCROLL REVEALS ────────────────────────────────────────────────
   .reveal         — fades + rises when .in-view is added
   .reveal-trigger — invisible trigger, animates .reveal-line children
   .mask           — overflow-hidden wrapper for sliding lines        */

.reveal {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 1.2s var(--ease), transform 1.2s var(--ease);
  transition-delay: var(--d, 0s);
}

.reveal.in-view {
  opacity: 1;
  transform: translateY(0);
}

.mask {
  display: block;
  overflow: hidden;
}

.reveal-line {
  display: block;
  transform: translateY(112%);
  transition: transform 1.35s var(--ease);
  transition-delay: var(--d, 0s);
}

.in-view .reveal-line,
.reveal-line.in-view {
  transform: translateY(0);
}

/* ═══════════════════════════════════════════════════════════════
   1. TITLE CARD / HERO — centered, symmetric, film poster
   ═══════════════════════════════════════════════════════════════ */

.hero {
  min-height: 100vh;
  min-height: 100svh;
  display: grid;
  grid-template-rows: auto 1fr auto;
  justify-items: center;
  text-align: center;
  padding: calc(1.5rem + env(safe-area-inset-top)) var(--gutter)
           calc(1.6rem + env(safe-area-inset-bottom));
}

.hero-mark {
  width: clamp(28px, 4vw, 36px);
  opacity: 0.9;
}

.hero-core {
  align-self: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(1.5rem, 4.5vh, 2.4rem);
}

/* Sized so the title stands as one line on desktop and stacks into a
   two-line monument on phones (text-wrap: balance keeps it even). */
.hero-title {
  font-family: var(--sans);
  font-weight: 300;
  font-size: clamp(2.1rem, 8.6vw, 4.6rem);
  line-height: 1.18;
  letter-spacing: 0.16em;
  /* compensate trailing tracking so the line optically centers */
  padding-left: 0.16em;
  text-transform: uppercase;
  text-wrap: balance;
  color: var(--text);
}

.hero-tag {
  display: inline-flex;
  align-items: center;
  gap: 0.9em;
  color: var(--text-dim);
}

/* Small live dot next to the season tag */
.hero-tag::before {
  content: '';
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--silver);
  opacity: 0.7;
  animation: beacon 5s ease-in-out infinite;
}

@keyframes beacon {
  0%, 100% { opacity: 0.25; }
  50%      { opacity: 0.8; }
}

/* Poster credit line: coordinates left, cue center, spacer right */
.hero-foot {
  width: 100%;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: end;
}

.hero-coords {
  justify-self: start;
  font-size: 0.54rem;
  color: var(--text-faint);
  display: none;
}

@media (min-width: 680px) {
  .hero-coords { display: block; }
}

/* A faint standing line with a light that keeps flowing downward —
   the only instruction on the screen */
.scroll-cue {
  grid-column: 2;
  display: block;
  width: 1px;
  height: clamp(3rem, 8vh, 4.2rem);
  background:
    linear-gradient(180deg, transparent 0%, var(--text-2) 45%, transparent 85%)
      0 0 / 100% 300% no-repeat,
    linear-gradient(180deg, rgba(236, 232, 223, 0.16), transparent)
      0 0 / 100% 100% no-repeat;
  animation: cue 3.6s cubic-bezier(0.4, 0, 0.2, 1) infinite;
}

@keyframes cue {
  0%   { background-position: 0 100%, 0 0; }
  100% { background-position: 0 -100%, 0 0; }
}

/* ═══════════════════════════════════════════════════════════════
   2. TRANSMISSION — the film owns the scene
   Full-bleed on mobile, a framed screen on desktop.
   ═══════════════════════════════════════════════════════════════ */

/* The film owns a full scene of its own */
.transmission {
  min-height: 100vh;
  min-height: 100svh;
  padding: clamp(4.5rem, 12vh, 8rem) 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* On phones the idle screen stands as a portrait monolith;
   once the film plays, the frame cuts to widescreen. */
.film-frame {
  position: relative;
  width: 100%;
  aspect-ratio: 3 / 4;
  background: var(--black);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  overflow: hidden;
}

.film-frame.is-playing { aspect-ratio: 16 / 9; }

@media (min-width: 760px) {
  .transmission { padding-inline: var(--gutter); }

  /* The frame is capped by width AND by the height the scene actually
     has, so the composed frame always fits exactly one viewport at the
     unchanged 16:9 ratio. On tall viewports the height term is never
     the smallest value, so the rendered size is bit-identical to
     before; it only engages where the frame would otherwise overflow. */
  .film-frame {
    aspect-ratio: 16 / 9;
    max-width: min(
      76rem,
      100%,
      calc((100svh - 2 * clamp(4.5rem, 12vh, 8rem)) * 16 / 9)
    );
    border: 1px solid var(--line);
  }
}

/* Optional poster frame behind the play state (set video.poster) */
.film-frame.has-poster {
  background-size: cover;
  background-position: center;
}

.film-frame.has-poster::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 90% 80% at 50% 50%, rgba(0,0,0,0.25) 0%, rgba(0,0,0,0.72) 100%);
}

.film-frame.is-playing::before { display: none; }

/* Idle state — the channel exists, the signal hasn't arrived */
.film-idle {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(0.9rem, 2.5vh, 1.3rem);
  text-align: center;
  padding: 2rem;
}

.film-mark {
  width: clamp(30px, 5vw, 42px);
  opacity: 0.25;
  mix-blend-mode: screen;
}

.film-label {
  color: var(--text-2);
  letter-spacing: 0.34em;
  padding-left: 0.34em;
}

.film-note {
  font-size: clamp(0.48rem, 1.2vw, 0.55rem);
  color: var(--text-faint);
}

/* Drifting scanline — barely-there proof the channel is live */
.film-scan {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
}

.film-scan::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: -20%;
  height: 18%;
  background: linear-gradient(180deg, transparent, rgba(236, 232, 223, 0.03), transparent);
  animation: scan 9s cubic-bezier(0.4, 0, 0.2, 1) infinite;
}

@keyframes scan {
  0%, 52%  { transform: translateY(0); }
  100%     { transform: translateY(780%); }
}

.film-frame.is-playing .film-scan,
.film-frame.is-playing .film-idle { display: none; }

/* Play state — a breathing ring, nothing else */
.film-play {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(1.2rem, 3.5vh, 1.7rem);
  background: none;
  border: none;
  cursor: pointer;
  color: var(--text);
  transition: background-color 0.5s ease;
}

.film-play:hover,
.film-play:focus-visible { background-color: rgba(236, 232, 223, 0.03); }

.film-play:active .film-ring { transform: scale(0.96); animation: none; }

.film-ring {
  width: clamp(80px, 12vw, 106px);
  aspect-ratio: 1;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  animation: breathe 5.5s ease-in-out infinite;
  transition: transform 0.35s ease, border-color 0.35s ease,
              background-color 0.35s ease;
}

@keyframes breathe {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.045); }
}

.film-play:hover .film-ring,
.film-play:focus-visible .film-ring {
  border-color: var(--silver);
  background-color: rgba(236, 232, 223, 0.05);
  animation: none;
}

.film-tri {
  width: 0;
  height: 0;
  border-top: 8px solid transparent;
  border-bottom: 8px solid transparent;
  border-left: 13px solid var(--text);
  margin-left: 4px;
}

.film-play-label {
  color: var(--text-dim);
  letter-spacing: 0.34em;
  padding-left: 0.34em;
}

.film-frame video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: var(--black);
}

.film-loading {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--mono);
  font-size: 0.56rem;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--text-dim);
  background: var(--black);
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.3s ease;
}

.film-loading.visible { opacity: 1; }

/* ═══════════════════════════════════════════════════════════════
   3. STATEMENT — one thought, oversized, left-anchored
   ═══════════════════════════════════════════════════════════════ */

/* Grid (not flex) for the vertical centering: the block child keeps
   its block-layout width resolution, so `max-width` + `margin: 0 auto`
   place it exactly where they did before. */
.statement {
  padding: var(--scene) var(--gutter);
  display: grid;
  align-content: center;
}

.statement-block {
  /* width:100% restores the block-layout width resolution inside the
     centering grid — an auto margin would otherwise shrink-to-fit the
     block. Rendered geometry is identical to plain block layout. */
  width: 100%;
  max-width: var(--measure);
  margin: 0 auto;
}

.statement-block .reveal-line {
  font-family: var(--sans);
  font-weight: 300;
  font-size: clamp(2.5rem, 12.5vw, 6.75rem);
  line-height: 1.02;
  letter-spacing: 0.015em;
  text-transform: uppercase;
  color: var(--text-dim);
}

/* The last line is the arrival — full light */
.statement-block .mask:last-child .reveal-line {
  color: var(--text);
}

/* ═══════════════════════════════════════════════════════════════
   4. MISSION 001 — a name, nothing more
   ═══════════════════════════════════════════════════════════════ */

.mission {
  padding: var(--scene) var(--gutter);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: clamp(1.5rem, 4.5vh, 2.2rem);
}

.mission-rule {
  width: 1px;
  height: clamp(2.6rem, 8vh, 4rem);
  background: linear-gradient(180deg, transparent, var(--line-strong));
}

.mission-tag { color: var(--text-dim); }

.mission-title {
  font-family: var(--sans);
  font-weight: 300;
  font-size: clamp(2.05rem, 9.2vw, 5.2rem);
  line-height: 1.1;
  letter-spacing: 0.18em;
  padding-left: 0.18em;
  text-transform: uppercase;
  color: var(--text);
}

.mission-note { color: var(--text-dim); }

/* ═══════════════════════════════════════════════════════════════
   5. APP ENTRY — one strong action
   ═══════════════════════════════════════════════════════════════ */

.enter {
  padding: var(--scene) var(--gutter);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
}

.enter-support {
  font-family: var(--sans);
  font-weight: 300;
  font-size: clamp(0.78rem, 2.2vw, 0.95rem);
  letter-spacing: 0.22em;
  padding-left: 0.22em;
  text-transform: uppercase;
  color: var(--text-2);
  margin-bottom: clamp(2.4rem, 7vh, 3.6rem);
}

.enter-cta {
  display: inline-block;
  border: 1px solid var(--line-strong);
  color: var(--text);
  font-family: var(--mono);
  font-size: clamp(0.62rem, 1.7vw, 0.74rem);
  letter-spacing: 0.3em;
  padding: clamp(1.05rem, 3vh, 1.3rem) clamp(2.2rem, 7vw, 3.4rem);
  padding-left: calc(clamp(2.2rem, 7vw, 3.4rem) + 0.3em);
  text-transform: uppercase;
  text-decoration: none;
  background: none;
  cursor: pointer;
  transition: border-color 0.55s ease, background-color 0.55s ease,
              color 0.55s ease;
}

.enter-cta:hover,
.enter-cta:focus-visible {
  border-color: var(--text);
  background-color: var(--text);
  color: var(--bg-deep);
}

/* Coming-soon: quiet, static, clearly not broken */
.enter-cta.is-disabled {
  color: var(--text-dim);
  border-color: var(--line);
  cursor: default;
  pointer-events: auto;
}

.enter-cta.is-disabled:hover,
.enter-cta.is-disabled:focus-visible {
  border-color: var(--line);
  background: none;
  color: var(--text-dim);
}

.enter-note {
  margin-top: clamp(1.3rem, 3.5vh, 1.8rem);
  color: var(--text-faint);
}

/* ═══════════════════════════════════════════════════════════════
   6. ENDING + FOOTER
   ═══════════════════════════════════════════════════════════════ */

.ending {
  padding: clamp(3.5rem, 10vh, 6rem) var(--gutter) clamp(6rem, 18vh, 11rem);
  display: grid;
  align-content: center;
  text-align: center;
}

.ending-line {
  font-family: var(--sans);
  font-weight: 300;
  font-size: clamp(0.95rem, 3.2vw, 1.4rem);
  letter-spacing: 0.34em;
  padding-left: 0.34em;
  text-transform: uppercase;
  color: var(--text-2);
}

.footer {
  border-top: 1px solid var(--line);
  margin: 0 var(--gutter);
  padding: clamp(1.8rem, 4.5vh, 2.4rem) 0
           calc(clamp(2rem, 5vh, 2.8rem) + env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.3rem;
}

@media (min-width: 680px) {
  .footer {
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
    gap: 2rem;
  }
}

.footer-brand {
  display: inline-flex;
  align-items: center;
  gap: 0.9em;
  font-size: 0.54rem;
  letter-spacing: 0.24em;
  color: var(--text-faint);
}

.footer-brand .mark { width: 20px; opacity: 0.55; }

.footer-coords {
  font-size: 0.54rem;
  letter-spacing: 0.24em;
  color: var(--text-faint);
}

.footer-links {
  display: inline-flex;
  align-items: center;
  gap: clamp(1.4rem, 4vw, 2.2rem);
}

.footer-links a {
  font-family: var(--mono);
  font-size: 0.54rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--text-faint);
  text-decoration: none;
  transition: color 0.4s ease;
}

.footer-links a:hover,
.footer-links a:focus-visible { color: var(--text-2); }

/* ═══════════════════════════════════════════════════════════════
   MOBILE EXECUTION — the scroll cue carries a travelling blurred
   bloom on phones, so the glowing line reads with the same
   presence as on desktop. Desktop (≥ 760px) is untouched.
   (Scene snapping lives in the base scroll-stage rules above and
   applies to every breakpoint.)
   ═══════════════════════════════════════════════════════════════ */

@media (max-width: 759px) {
  .scroll-cue { position: relative; }

  /* Soft bloom that travels with the light — same gradient, same
     animation, same timing as the line it amplifies */
  .scroll-cue::before {
    content: '';
    position: absolute;
    top: 0;
    bottom: 0;
    left: -3px;
    width: 7px;
    background:
      linear-gradient(180deg, transparent 0%, rgba(236, 232, 223, 0.75) 45%, transparent 85%)
        0 0 / 100% 300% no-repeat,
      linear-gradient(180deg, rgba(236, 232, 223, 0.10), transparent)
        0 0 / 100% 100% no-repeat;
    filter: blur(4px);
    animation: cue 3.6s cubic-bezier(0.4, 0, 0.2, 1) infinite;
  }
}

/* ═══════════════════════════════════════════════════════════════
   REDUCED MOTION — content is never gated behind animation
   ═══════════════════════════════════════════════════════════════ */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001s !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001s !important;
  }

  .reveal,
  .reveal-line,
  .veil,
  .hero-title,
  main,
  footer {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
  }
}
