/* =============================================================
   FANATIK Site v2.7 — App Tour
   4-panel grid (desktop ≥960w) / horizontal scroll-snap carousel (<960w).

   Replaces the v2.1 scroll-pinned 3-screen pattern per CEO directive
   (May 13 2026). The new layout is simpler, lighter, and slots into
   the IA between #the-quiz and #founding-preview as a "see what's in
   the app" pause beat — not a sustained focus moment.

   Palette tokens — locked v2 brand:
     --black     #000000
     --off-black #0A0A0A
     --lime      #D3FE4C
     --white     #FFFFFF
     --mute      rgba(255,255,255,0.55)
     --mute-deep rgba(255,255,255,0.35)

   Type:
     Inter 400 / 700 / 900
     JetBrains Mono 700 for eyebrow + captions
   ============================================================= */

/* Scoped tokens — partial is safe to embed without polluting :root. */
.app-tour {
  --black: #000000;
  --off-black: #0a0a0a;
  --lime: #d3fe4c;
  --white: #ffffff;
  --mute: rgba(255, 255, 255, 0.55);
  --mute-deep: rgba(255, 255, 255, 0.35);

  /* Phone-mockup geometry.
     Source PNGs are 780×1688 (iPhone Pro Max aspect 0.462).
     On mobile we target ~480-560px tall; on desktop ~640-720px.
     Width derives from aspect-ratio so we never distort the screenshot.
     The 1px lime hairline border + 32px corner radius give the
     "broadcast screenshot in a frame" register, not "iPhone marketing." */
  --mockup-aspect: 780 / 1688;
  --mockup-h-mobile: clamp(480px, 64vw, 560px);
  --mockup-h-tablet: clamp(560px, 56vw, 640px);
  --mockup-h-desktop: clamp(620px, 38vw, 720px);
  --mockup-radius: 32px;
  --mockup-stroke: 1px;

  /* Section block padding inherits the v2.7 rhythm bump.
     Falls back to the same clamp() the rest of the page uses if
     --section-py isn't defined (e.g. partial loaded standalone). */
  padding-block: var(--section-py, clamp(80px, 10vw, 160px));
  /* v2.11.2 alignment: inline padding now uses the brand spacing scale
     so the left edge of .app-tour__header (and the desktop .app-tour__panels)
     lands at the same x as .the-quiz__inner and .cabinet__header.
     Was: padding-inline: clamp(20px, 5vw, 64px);  — at 1440w that resolved
     to ~72px, which is fine for the panels but mismatched the quiz/cabinet
     rhythm. var(--space-3) maps to 24px (matches the quiz/cabinet mobile);
     the desktop override below restores generous breathing room. */
  padding-inline: var(--space-3);

  /* v2.12.0 — surface shift: off-black + horizontal scanline grain.
     Quiz stays pure black (#060606); app-tour rises to the off-black
     tier (#0A0A0A) with a 2-3px repeating scanline overlay at 0.018
     opacity. Reads as a "broadcast screen preview" register vs the
     quiz's "studio" register. Reinforced by the §03 · APP section-
     frame above. The scanline is baked into the background-image so
     it sits behind all content without z-index machinery.
     Was: background: var(--black); */
  background: #0A0A0A;
  background-image: repeating-linear-gradient(
    to bottom,
    transparent 0,
    transparent 2px,
    rgba(255, 255, 255, 0.018) 2px,
    rgba(255, 255, 255, 0.018) 3px
  );
  color: var(--white);
  font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  width: 100%;
  max-width: 100%;
  box-sizing: border-box;
  /* Belt-and-braces: clip horizontal overflow from the mobile carousel
     so the page doesn't gain a horizontal scrollbar. */
  overflow-x: clip;
}

.app-tour *,
.app-tour *::before,
.app-tour *::after {
  box-sizing: border-box;
}

/* Lime period — shared utility across the brand. */
.app-tour .period,
.app-tour__subtitle .period,
.app-tour-slab__sub .period,
.app-tour-slab__word .period {
  color: var(--lime) !important;
  font-weight: 900;
}

/* ---------- Header ---------------------------------------------------- */
.app-tour__header {
  /* v2.11.2 alignment: use the brand --max-width token (1280px, same value
     as the previous literal) so this inner container shares the exact same
     ceiling as .the-quiz__inner, .cabinet__header, .cabinet__grid, and
     .footer__inner — guarantees identical left edges across sections. */
  max-width: var(--max-width, 1280px);
  margin: 0 auto clamp(40px, 5vw, 72px);
  display: flex;
  flex-direction: column;
  /* v2.11.4 — CEO directive: centre the app-tour header proper (eyebrow +
     "INSIDE." title + subtitle), balanced left/right via auto margins on the
     inner container, balanced top/bottom via --section-py block padding
     (80-160px clamp). */
  align-items: center;
  text-align: center;
  gap: clamp(8px, 1vw, 14px);
}

.app-tour__eyebrow {
  font-family: 'JetBrains Mono', ui-monospace, 'Menlo', monospace;
  font-weight: 700;
  font-size: clamp(11px, 1.2vw, 13px);
  letter-spacing: 0.14em;
  color: var(--mute);
  margin: 0;
  text-transform: uppercase;
}

.app-tour__title {
  font-family: 'Inter', system-ui, sans-serif;
  font-weight: 900;
  font-size: clamp(36px, 7vw, 80px);
  line-height: 0.94;
  letter-spacing: -0.035em;
  color: var(--white);
  margin: 0;
  text-transform: uppercase;
}

.app-tour__subtitle {
  font-family: 'Inter', system-ui, sans-serif;
  font-weight: 400;
  font-size: clamp(15px, 1.8vw, 18px);
  line-height: 1.45;
  color: var(--mute);
  margin: 0;
  max-width: 48ch;
}

/* ---------- Panels container ----------------------------------------- */
/* Mobile-first: horizontal scroll-snap carousel.
   Edge-to-edge bleed using negative inline margins so the first/last
   panel can sit flush with the viewport edge when scrolled. */
.app-tour__panels {
  list-style: none;
  /* v2.11.2 alignment: bleed math now tracks the new var(--space-3) inline
     section padding so the first/last panel still sits flush with the
     viewport edge on mobile. Was: margin: 0 calc(clamp(20px, 5vw, 64px) * -1)
     + padding-inline: clamp(20px, 5vw, 64px); */
  margin: 0 calc(var(--space-3) * -1); /* negate section padding */
  padding-inline: var(--space-3);       /* re-add for first panel */
  display: flex;
  flex-direction: row;
  gap: clamp(16px, 3vw, 28px);
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  /* v2.11.2 alignment: scroll-padding tracks the new --space-3 section
     padding so snap points land at the same edge as the inner column. */
  scroll-padding-inline: var(--space-3);
  /* iOS momentum scroll. */
  -webkit-overflow-scrolling: touch;
  /* Hide scrollbar in WebKit while keeping scroll behaviour. */
  scrollbar-width: thin;
  scrollbar-color: var(--mute-deep) transparent;
}

.app-tour__panels::-webkit-scrollbar {
  height: 4px;
}
.app-tour__panels::-webkit-scrollbar-thumb {
  background: var(--mute-deep);
  border-radius: 999px;
}
.app-tour__panels::-webkit-scrollbar-track {
  background: transparent;
}

/* ---------- Individual panel ----------------------------------------- */
.app-tour__panel {
  flex: 0 0 auto;
  /* Mobile width: panel + peek of next panel so the user gets a visual
     scroll affordance. Width clamps so it never gets cramped or oversize. */
  width: clamp(260px, 75vw, 340px);
  scroll-snap-align: start;
  scroll-snap-stop: always;

  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: clamp(16px, 2.2vw, 24px);

  margin: 0;
  padding: 0;
}

/* ---------- Phone mockup --------------------------------------------- */
/* Minimal frame: 1px lime hairline at the brand accent, 32px radius.
   The screenshot fills the mockup edge-to-edge — no internal padding
   that would create a fake bezel. This is the "screenshot in a frame"
   register, not "iPhone marketing render." */
.app-tour__mockup {
  margin: 0;
  padding: 0;
  position: relative;
  width: 100%;
  height: var(--mockup-h-mobile);
  background: var(--off-black);
  border: var(--mockup-stroke) solid var(--lime);
  border-radius: var(--mockup-radius);
  overflow: hidden;
  isolation: isolate;
  /* Subtle outer glow + shadow — lime tinted, very low opacity.
     Confined enough not to violate the 30% lime cap rule. */
  box-shadow:
    0 0 0 1px rgba(211, 254, 76, 0.06),
    0 20px 60px rgba(0, 0, 0, 0.55);
}

.app-tour__shot {
  display: block;
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Anchor at top so the home countdown / arena hub / leaderboard top
     row are visible even if the mockup container is shorter than the
     780×1688 source aspect would otherwise crop. */
  object-position: top center;
  /* Smooth fade-in when the lazy-loader swaps data-lazy-src → src. */
  opacity: 0;
  transition: opacity 320ms ease-out;
  will-change: opacity;
}

.app-tour__shot.is-loaded {
  opacity: 1;
}

/* ---------- Caption --------------------------------------------------- */
.app-tour__caption {
  /* Inter 800 ALL CAPS with lime period — matches the brand register
     used on the home tile labels. Mono is reserved for chyron/eyebrow. */
  font-family: 'Inter', system-ui, sans-serif;
  font-weight: 800;
  font-size: clamp(20px, 2.2vw, 28px);
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--white);
  text-transform: uppercase;
  margin: 0;
}

/* ---------- Tablet (≥640w) — slightly larger mockup, no layout change */
@media (min-width: 640px) {
  .app-tour__panel {
    width: clamp(300px, 60vw, 380px);
  }
  .app-tour__mockup {
    height: var(--mockup-h-tablet);
  }
}

/* ---------- Desktop (≥960w) — 4-col grid, carousel goes inert -------- */
@media (min-width: 960px) {
  .app-tour__panels {
    /* Switch from horizontal flex-scroll to 4-column grid.
       Re-zero the negative margin we used for mobile bleed. */
    margin: 0 auto;
    /* v2.11.2 alignment: token-driven to stay in lockstep with the header
       and every other --max-width container on the page. */
    max-width: var(--max-width, 1280px);
    padding-inline: 0;
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: clamp(20px, 2.4vw, 32px);
    overflow: visible;
    scroll-snap-type: none;
  }

  .app-tour__panel {
    width: 100%;
    flex: initial;
    scroll-snap-align: initial;
  }

  .app-tour__mockup {
    height: var(--mockup-h-desktop);
  }

  /* v2.11.2 alignment: at ≥960w the inline section padding bumps to
     var(--space-5) (48px) so it matches the .cabinet's tablet+ rhythm
     (var(--space-7) var(--space-5)) and the .the-quiz tablet override.
     With .app-tour__header and the 4-col panels both capped at
     var(--max-width) and centred via margin: 0 auto, the inner column
     left edge now lands at exactly the same x-coordinate as
     .the-quiz__inner and .cabinet__header at every viewport width above
     the inner cap. Was: padding-inline: clamp(48px, 5vw, 96px);
     The 96px peak (on ≥1920w) pulled the app-tour edge inward past the
     quiz/cabinet edge — that was the visible CEO-screenshot mismatch. */
  .app-tour {
    padding-inline: var(--space-5);
  }
}

/* ---------- Reduced-motion: no fade transitions, no scroll-snap ------ */
@media (prefers-reduced-motion: reduce) {
  .app-tour__shot {
    transition: none;
    opacity: 1;
  }
  .app-tour__panels {
    /* Collapse the horizontal carousel into a static stack on mobile.
       Vertical panels are easier to read with reduced motion preference
       and bypass the scroll-snap motion that some vestibular users
       find disorienting. */
    scroll-snap-type: none;
  }
  @media (max-width: 959px) {
    .app-tour__panels {
      flex-direction: column;
      overflow: visible;
      margin-inline: 0;
      padding-inline: 0;
    }
    .app-tour__panel {
      width: 100%;
    }
  }
}

/* ---------- Forced-colors / high-contrast safety --------------------- */
@media (forced-colors: active) {
  .app-tour__mockup {
    border-color: CanvasText;
    box-shadow: none;
  }
  .app-tour .period {
    color: LinkText;
  }
  .app-tour__caption {
    color: CanvasText;
  }
  /* Belt-and-braces: ensure the shot is visible even if opacity
     transitions don't run under forced-colors. */
  .app-tour__shot {
    opacity: 1;
  }
}

/* ---------- Print: drop the carousel, render as a 2×2 grid ----------- */
@media print {
  .app-tour__panels {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 16px;
    overflow: visible;
  }
  .app-tour__mockup {
    height: auto;
    aspect-ratio: var(--mockup-aspect);
    box-shadow: none;
  }
  .app-tour__shot {
    opacity: 1;
    position: relative;
    height: auto;
  }
}

/* =============================================================
   v2.8 BROADCAST · F2-owned overrides (2026-05-14)
   -------------------------------------------------------------
   The v2.8 inline CSS (index.html lines 552-889) introduces a
   scroll-pinned stage with a phone mockup, animated slabs, and
   a 4-column step-index strip. These overrides patch the bugs
   surfaced by the audit. They live here as the durable home for
   v2.8 scroll-pinned overrides; F1 may later move the inline
   block in here wholesale, in which case these rules continue
   to apply with no rewrite.
   ============================================================= */

/* BUG-010 · Phone at-rest scale bump from 0.7 → 0.95 desktop, 1.0 mobile.
   At 0.7 the phone resolves to ~174×378px on a 1440w viewport (≈12% of
   width — looks like a sticker, not a hero element). Scroll-driven JS
   should oscillate around the new at-rest base, not from 0.7 floor.
   The JS in app-tour.js maps scroll progress to --phoneScale; F3 will
   adjust the JS range to (0.85 → 1.05 → 0.92) to match the new base. */
.app-tour--v28 .app-tour-phone-wrap {
  --phoneScale: 0.95;
}

@media (max-width: 640px) {
  /* Mobile: phone already fills more relative width, so 1.0 at rest
     keeps the screen edge close to the slab columns. */
  .app-tour--v28 .app-tour-phone-wrap {
    --phoneScale: 1.0;
  }
}

/* BUG-011 · Slab container clipping — COUNTDOWN/ROOMS/RANKINGS/FRIENDS
   extend past viewport at 1440w because the slab __word is
   clamp(64px, 14vw, 240px) and translates 80% → 0% → -80%.
   At 14vw the word is ~200px wide; at 80% translate the right edge
   sits at +0.8 × viewport-width past the centre, beyond the
   right viewport edge. Two-fer fix:
     1. overflow: hidden on the slabs container so the offstage
        slab doesn't trigger a horizontal page scrollbar.
     2. tighten the translate range used by F3's JS to 50% → 0% → -50%
        so each slab edge stays inside the viewport at peak offset.
   F3 reads `--slabTranslateMax: 50%` (set below) and clamps the JS
   range to that value. */
.app-tour--v28 .app-tour-slabs {
  overflow: hidden;
  /* JS-readable token — F3 uses getComputedStyle on .app-tour-slabs
     to pick up this value.
     FW2 fix #11 (CDO/CPO): tightened from 50% → 40% because the
     audit confirmed the slab clipping persists at 50% on 1440w
     idle (clipped "COUNTDOWN" reads as a CSS bug, not as a "slide
     in via scrub" affordance). 40% keeps each slab edge inside
     the viewport at peak offset across 1280-1920w. Forced-colors /
     no-JS fallback simply keeps the slabs centred (overflow hidden
     does the clipping work). */
  --slabTranslateMax: 40%;
}

/* BUG-044 · Step-index columns should size to content, not equal-width.
   "01" is 1/4 of "RANKINGS" wide; forcing 1fr 1fr 1fr 1fr makes the
   "01" column visually empty and pushes "FRIENDS" to feel cramped at
   1280w. Switch to auto-fit so each column hugs its content.
   Keep the strip's `justify-content: space-between` so the spacing
   reads as a broadcast strip, not a left-aligned list. */
.app-tour--v28 .app-tour-step-index {
  /* From `display: flex; justify-content: space-between;` inline ->
     a grid with auto-sized columns separated by gap. The gap matches
     the inline 12px; on mobile narrows to 6px via existing override. */
  display: grid;
  grid-template-columns: repeat(4, max-content);
  justify-content: space-between;
  align-items: end;
}

.app-tour--v28 .app-tour-step-index__item {
  /* Override the inline `flex: 1` so columns size to content. */
  flex: initial;
  min-width: 0;
}

@media (max-width: 640px) {
  /* Mobile: 4 items of varying widths on a 320-414w viewport will
     collide. Allow shrinking via minmax + use the gap as the visual
     anchor between items. */
  .app-tour--v28 .app-tour-step-index {
    grid-template-columns: repeat(4, minmax(0, auto));
  }
}

/* Reduced-motion: at-rest phone scale is the final scale, no
   scroll-driven animation. Inline rule already forces `scale(1)`;
   we leave that intact but make the override scoped so an external
   F3 extension doesn't accidentally re-enable transition. */
@media (prefers-reduced-motion: reduce) {
  .app-tour--v28 .app-tour-phone-wrap {
    --phoneScale: 1;
  }
  .app-tour--v28 .app-tour-slabs {
    /* Don't translate slabs; let them cross-fade in-place. F3 will
       collapse the X-axis range to zero under reduced-motion. */
    --slabTranslateMax: 0%;
  }
}

/* Forced-colors safety: keep slab/phone visible in Windows
   High Contrast mode even if the scroll animation never advances. */
@media (forced-colors: active) {
  .app-tour--v28 .app-tour-slab {
    opacity: 1 !important;
  }
}

/* F3 cross-dep — BUG-013 static fallback.
   2026-05-14 REVERT: the previous version used `display: block` on
   the panels (broke the original horizontal flex layout, each panel
   rendered full-bleed and the app screen images covered the viewport
   — visible CEO regression). Disable the fallback entirely for now;
   the scroll-pinned stage always renders, and prefers-reduced-motion
   is handled by the inline CSS in index.html (locks --phoneScale to 1
   and clears slab translate). If we need a true no-JS fallback we'll
   wire it in v2.8.1 with proper layout preservation. */
/* .app-tour--fallback .app-tour__panels { ... } — intentionally removed */
/* .app-tour--fallback .app-tour-stage { ... } — intentionally removed */
