/**
 * Portal stylesheet — single sheet, no preprocessor.
 *
 * Theme palette is applied at runtime by tenants.js via CSS custom
 * properties (var(--brand), var(--canvas), etc.) so this stylesheet is
 * tenant-agnostic.
 *
 * Layout strategy:
 *   - Single column, vertical scroll on mobile
 *   - Hero takes 100svh on first paint
 *   - Device cards reflow:
 *       - <640px : 1 col
 *       - 640-960 : 2 col
 *       - >960px : 4 col
 */

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

:root {
  --brand: #22D3EE;
  --brand-hover: #06B6D4;
  --brand-press: #0891B2;
  --canvas: #050B1A;
  --surface: #0F172A;
  --card: #1E293B;
  --text-primary: #F1F5F9;
  --text-muted: #94A3B8;
  --splash-mid: #0E1A38;
  --splash-end: #020617;
  --brand-a12: #22D3EE1F;
  --brand-a24: #22D3EE3D;
  --brand-a40: #22D3EE66;

  --radius-sm: 12px;
  --radius-md: 18px;
  --radius-lg: 28px;
  --shadow-soft: 0 8px 40px rgba(0, 0, 0, 0.4);
  --shadow-glow: 0 0 60px var(--brand-a40);
}

html, body {
  width: 100%;
  min-height: 100%;
  background: var(--canvas);
  color: var(--text-primary);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
               "Hiragino Sans GB", "Microsoft YaHei", system-ui, sans-serif;
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

body {
  position: relative;
}

/* ─── 3-screen scroll-snap container ─────────────────────────────────
 *
 * main is a vertical scroller; each .screen is a 100svh snap target.
 * Snap is `y mandatory` — any scroll gesture (small flick or hard
 * scroll) magnetically locks the next .screen to fill the viewport,
 * preventing partial-screen mid-states. scroll-snap-stop:always
 * enforces stopping at each screen rather than skipping past on a
 * fast wheel input.
 *
 * Why on main (not html): keeps the fixed topbar / canvas / radial
 * background outside the scroller. */
/* Three-tier viewport-height fallback so we always get the correct
   visible height regardless of browser:
     1. 100vh        — universal (Chrome 79+, every TV browser)
     2. var(--svh)   — JS-set on every resize/orientation, exactly
                       window.innerHeight, even on Chrome <108 that
                       lacks the svh CSS unit
     3. 100svh       — modern browsers (Chrome 108+)
   Each line overrides the previous on supporting browsers. */
.snap-scroller {
  scroll-snap-type: y mandatory;
  height: 100vh;
  height: var(--svh, 100vh);
  height: 100svh;
  overflow-y: auto;
  overflow-x: hidden;
  scroll-behavior: smooth;
  scrollbar-width: none;
}
.snap-scroller::-webkit-scrollbar { display: none; }

.screen {
  scroll-snap-align: start;
  scroll-snap-stop: always;
  min-height: 100vh;
  min-height: var(--svh, 100vh);
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  position: relative;
  width: 100%;
}

/* Background layers — radial splash + canvas particles + subtle grain */
.bg-layer {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.bg-radial {
  background:
    radial-gradient(ellipse 80% 60% at 50% 20%, var(--splash-mid) 0%, transparent 60%),
    radial-gradient(ellipse 100% 80% at 50% 100%, var(--splash-end) 0%, transparent 70%),
    var(--canvas);
}

#bg-canvas {
  width: 100%;
  height: 100%;
  display: block;
  opacity: 1;
}

main, header {
  position: relative;
  z-index: 1;
}

/* ─── Top bar (logo on left, language on right) ─── */
.topbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 28px;
  background: linear-gradient(to bottom, rgba(0, 0, 0, 0.5), transparent);
}

.brand-mark {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-weight: 600;
  font-size: 16px;
  color: var(--text-primary);
  text-decoration: none;
}

.brand-mark img {
  height: 32px;
  width: auto;
  border-radius: 6px;
}

.lang-switch {
  display: inline-flex;
  gap: 4px;
  background: rgba(0, 0, 0, 0.3);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 999px;
  padding: 4px;
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}

.lang-btn {
  appearance: none;
  border: none;
  background: transparent;
  color: var(--text-muted);
  font: inherit;
  font-size: 13px;
  padding: 6px 14px;
  border-radius: 999px;
  cursor: pointer;
  transition: color .15s, background .15s;
}

.lang-btn:hover { color: var(--text-primary); }
.lang-btn.active {
  background: var(--brand-a24);
  color: var(--text-primary);
}

/* ─── Focus indicators for D-pad / keyboard navigation ────────────
 *
 * TV remotes can only navigate via focus → critical that the focused
 * element is unambiguously visible. Standard outline is reserved for
 * the cards themselves (which need a stronger glow); pills, tabs and
 * thumbs use a thicker brand-color outline. */

.brand-mark:focus,
.lang-btn:focus,
.showcase-tab:focus,
.showcase-cta:focus,
.showcase-thumb:focus,
.web-row a:focus,
.device-action:focus {
  outline: 2px solid var(--brand);
  outline-offset: 3px;
}

/* Split rules — :focus-visible was added to Chrome in 86 (Oct 2020).
   Including it in the same selector list as :focus causes Chrome 79
   on Android TV to discard the entire rule, leaving the card's focus
   state visually identical to its blurred state. Two separate rules
   so newer browsers still get focus-visible specificity. */
.device-card:focus {
  border-color: var(--brand);
  outline: none;
  transform: translateY(-4px);
  box-shadow:
    0 22px 60px rgba(0, 0, 0, 0.55),
    0 0 0 3px var(--brand),
    0 0 60px var(--brand-a40);
}
.device-card:focus-visible {
  border-color: var(--brand);
  outline: none;
  transform: translateY(-4px);
  box-shadow:
    0 22px 60px rgba(0, 0, 0, 0.55),
    0 0 0 3px var(--brand),
    0 0 60px var(--brand-a40);
}

/* Suppress default outline only when we've replaced it with our own */
.device-card { outline: none; }

/* ─── Hero (Screen 1) — hidden in current layout, kept in DOM in case
       we want to bring back the promo splash later. ─── */
.hero {
  display: none !important;
}

/* ─── Promo split-hero variant ───────────────────────────────────────
 *
 * Three explicit responsive states (driven by the `.promo-split`
 * container query so the layout responds to its own width, not just
 * the viewport — works inside any future container too):
 *
 *   ≥ 960px  desktop : 2-column, text left + carousel right with
 *                      coverflow side cards visible.
 *   640-959  tablet  : single column stacked, carousel on top, text
 *                      below; carousel still has coverflow but tighter.
 *   ≤ 639px  phone   : single column stacked, carousel single-card
 *                      only (no side peeks — they'd just clip).
 *
 * All sizing is fluid (clamp + cqw) within each state so transitions
 * between breakpoints are smooth, no magic numbers.
 */

body.has-promo .hero {
  padding: clamp(72px, 8vh, 100px) clamp(16px, 3vw, 32px) clamp(32px, 5vh, 60px);
  flex-direction: column;          /* the promo-split is the only child */
  justify-content: center;
  align-items: center;
}

body.has-promo .hero-logo,
body.has-promo .hero-name,
body.has-promo .hero-tagline,
body.has-promo .hero > .hero-cta { display: none !important; }

.promo-split {
  display: grid;
  grid-template-columns: 1fr;
  grid-template-areas: "carousel" "text";
  gap: clamp(20px, 4vw, 48px);
  width: min(1360px, 100%);
  margin: 0 auto;
  animation: promoIn 700ms cubic-bezier(.16,.84,.34,1) 100ms both;
}

@keyframes promoIn {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Stack order in single-column states: image first (it's the hero),
   text below */
.promo-text     { grid-area: text; }
.promo-carousel { grid-area: carousel; }

/* ─── Desktop: 2-column split ── */
@media (min-width: 1200px) {
  .promo-split {
    grid-template-columns: minmax(0, 0.78fr) minmax(0, 1.4fr);
    grid-template-areas: "text carousel";
    gap: clamp(48px, 6cqw, 96px);
    align-items: center;
  }
  .promo-text { align-items: flex-start; text-align: left; }
}

/* ── Left column: brand text ── */
.promo-text {
  display: flex;
  flex-direction: column;
  align-items: center;             /* default centered for stacked states */
  text-align: center;
  gap: clamp(12px, 1.5vh, 18px);
}

.promo-badge {
  display: inline-flex;
  align-items: center;
  padding: clamp(5px, 0.6vw, 6px) clamp(12px, 1.4vw, 14px);
  font-size: clamp(11px, 0.9vw, 13px);
  font-weight: 600;
  letter-spacing: 0.08em;
  color: var(--brand);
  background: var(--brand-a12);
  border: 1px solid var(--brand-a40);
  border-radius: 999px;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}

.promo-headline {
  /* Fluid headline — caps at 72px on big desktops, scales down
     gracefully through tablet + phone to 32px minimum. */
  font-size: clamp(32px, 7vw, 72px);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -0.02em;
  margin: 0;
  background: linear-gradient(180deg, var(--text-primary) 0%, var(--brand) 200%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

.promo-subhead {
  font-size: clamp(15px, 1.8vw, 20px);
  color: var(--text-muted);
  margin: 0;
  font-weight: 500;
}

.promo-bullets {
  list-style: none;
  margin: clamp(4px, 1vh, 12px) 0 clamp(8px, 1.5vh, 16px);
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(6px, 0.9vh, 10px);
}

.promo-bullets li {
  font-size: clamp(13px, 1vw, 15px);
  color: var(--text-primary);
  display: flex;
  align-items: center;
  gap: 10px;
}

.promo-bullets li::before {
  content: "";
  flex: 0 0 auto;
  width: 6px;
  height: 6px;
  border-radius: 999px;
  background: var(--brand);
  box-shadow: 0 0 12px var(--brand);
}

.promo-cta { margin-top: 8px; }

/* ── Right column: 3D rotating carousel ── */
.promo-carousel {
  display: flex;
  align-items: center;
  justify-content: center;
  /* Phone/tablet: full column width; clip side-card peek so cards
     don't crash into adjacent layout. Desktop overrides below. */
  overflow: hidden;
  width: 100%;
}

/* Stage = perspective container; track holds the rotating 3D group.
   Sizing is fluid: in stacked states the stage takes up to ~520px
   (looks decent on phone/tablet); on desktop it expands to fill its
   column. Aspect ratio always 16:9 so the image isn't cropped. */
.carousel-stage {
  width: 100%;
  max-width: 520px;
  aspect-ratio: 16 / 9;
  perspective: 1400px;
  position: relative;
}

@media (min-width: 1200px) {
  .promo-carousel { overflow: visible; }   /* let side cards peek */
  .carousel-stage { max-width: 780px; perspective: 1600px; }
}

.carousel-track {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
}

/* Coverflow — 3 fixed slots (left / center / right). data-slot is set
   by JS and rotated every 3.5s; CSS transitions slide cards between
   slots in 700ms. Center card large + flat + bright; side cards
   smaller + dimmed + angled. Since all 3 cards display the same
   source image, the slot "wrap-around" is visually invisible. */
.carousel-card {
  position: absolute;
  inset: 0;
  border-radius: clamp(12px, 1.5vw, 20px);
  overflow: hidden;
  border: 1px solid var(--brand-a24);
  background: var(--card);
  transition: transform 700ms cubic-bezier(.65, 0, .35, 1),
              opacity 700ms,
              filter 700ms,
              box-shadow 700ms;
  backface-visibility: hidden;
  opacity: 0;          /* before JS assigns slot */
}

.carousel-card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.carousel-card[data-slot="center"] {
  transform: translateX(0) rotateY(0deg) scale(1);
  opacity: 1;
  filter: none;
  z-index: 3;
  box-shadow: 0 28px 70px rgba(0, 0, 0, 0.65),
              0 0 80px var(--brand-a40);
}

/* Default (stacked / phone) side-card behavior: invisible.
   Phone has no horizontal room for cover-flow peeks — single card
   only. Larger states override below. */
.carousel-card[data-slot="left"],
.carousel-card[data-slot="right"] {
  transform: translateX(0) rotateY(0deg) scale(1);
  opacity: 0;
  z-index: 1;
}

/* Tablet (640-959px): tight cover-flow, side cards small but
   visible to convey rotation, fully contained inside stage */
@media (min-width: 640px) {
  .carousel-card[data-slot="left"] {
    transform: translateX(-22%) rotateY(24deg) scale(0.72);
    opacity: 0.45;
    filter: brightness(0.6);
    box-shadow: 0 14px 32px rgba(0, 0, 0, 0.5);
  }
  .carousel-card[data-slot="right"] {
    transform: translateX(22%) rotateY(-24deg) scale(0.72);
    opacity: 0.45;
    filter: brightness(0.6);
    box-shadow: 0 14px 32px rgba(0, 0, 0, 0.5);
  }
}

/* Desktop (≥ 960px): generous cover-flow, peeks past stage edges
   into the column gap (overflow: visible above lets it bleed) */
@media (min-width: 1200px) {
  .carousel-card[data-slot="left"] {
    transform: translateX(-26%) rotateY(26deg) scale(0.76);
    opacity: 0.55;
    filter: brightness(0.65);
    box-shadow: 0 18px 40px rgba(0, 0, 0, 0.55);
  }
  .carousel-card[data-slot="right"] {
    transform: translateX(26%) rotateY(-26deg) scale(0.76);
    opacity: 0.55;
    filter: brightness(0.65);
    box-shadow: 0 18px 40px rgba(0, 0, 0, 0.55);
  }
}

/* Respect prefers-reduced-motion: pin first card to center, no
   transitions, no slot cycling (JS sees the media query and skips
   setInterval). */
@media (prefers-reduced-motion: reduce) {
  .carousel-card[data-slot] { transition: none; }
}

.hero-logo {
  width: 84px;
  height: 84px;
  border-radius: 18px;
  margin-bottom: 24px;
  box-shadow: var(--shadow-glow);
  animation: float 6s ease-in-out infinite;
  object-fit: cover;
}

@keyframes float {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-10px); }
}

.hero-name {
  font-size: clamp(36px, 6vw, 64px);
  font-weight: 700;
  letter-spacing: -0.02em;
  margin-bottom: 12px;
  background: linear-gradient(180deg, var(--text-primary) 0%, var(--brand) 200%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

.hero-tagline {
  font-size: clamp(15px, 1.6vw, 18px);
  color: var(--text-muted);
  margin-bottom: 56px;
  max-width: 600px;
}

.hero-cta {
  appearance: none;
  border: 1px solid var(--brand-a40);
  background: var(--brand-a12);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  color: var(--text-primary);
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.05em;
  padding: 14px 28px;
  border-radius: 999px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  transition: background .2s, border-color .2s, transform .2s, box-shadow .2s;
}

.hero-cta:hover {
  background: var(--brand-a24);
  border-color: var(--brand);
  transform: translateY(-2px);
  box-shadow: 0 12px 40px var(--brand-a40);
}

.hero-cta::after {
  content: "";
  display: inline-block;
  width: 12px;
  height: 12px;
  border-right: 2px solid var(--brand);
  border-bottom: 2px solid var(--brand);
  transform: rotate(45deg);
  animation: bounceArrow 1.6s ease-in-out infinite;
}

@keyframes bounceArrow {
  0%, 100% { transform: rotate(45deg) translate(-2px, -2px); opacity: .5; }
  50%      { transform: rotate(45deg) translate(2px, 2px);   opacity: 1; }
}

/* ─── Screen 2: client UI showcase ──────────────────────────────────
 *
 * UX:
 *   1. pill tabs at top  → choose TV or Phone
 *   2. mockup of chosen device shows in center, large
 *   3. thumbnail strip below → click to switch which screenshot is shown
 *
 * The non-active mockup is display:none so only one device fills the
 * stage at a time. Phone slide #3 is landscape (mobile_2); when active,
 * .is-rotated on the bezel triggers a -90° rotation to mimic landscape.
 */

.showcase {
  padding: clamp(64px, 7vh, 88px) clamp(16px, 3vw, 32px) clamp(24px, 3vh, 40px);
  gap: clamp(16px, 2.5vh, 28px);
}

.showcase-text {
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(8px, 1vh, 14px);
  max-width: 720px;
}

.showcase-eyebrow {
  display: inline-flex;
  padding: 5px 14px;
  font-size: clamp(11px, 0.9vw, 13px);
  font-weight: 600;
  letter-spacing: 0.08em;
  color: var(--brand);
  background: var(--brand-a12);
  border: 1px solid var(--brand-a40);
  border-radius: 999px;
}

.showcase-headline {
  font-size: clamp(28px, 4.5vw, 48px);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.1;
  background: linear-gradient(180deg, var(--text-primary) 0%, var(--brand) 220%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

.showcase-subhead {
  font-size: clamp(14px, 1.5vw, 18px);
  color: var(--text-muted);
}

/* ─── Pill tabs (TV / Phone selector) ─── */
.showcase-tabs {
  display: inline-flex;
  gap: 4px;
  background: rgba(0, 0, 0, 0.3);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 999px;
  padding: 4px;
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}

.showcase-tab {
  appearance: none;
  border: none;
  background: transparent;
  color: var(--text-muted);
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  padding: 8px 22px;
  border-radius: 999px;
  cursor: pointer;
  transition: color .2s, background .2s;
}

.showcase-tab:hover { color: var(--text-primary); }
.showcase-tab.is-active {
  background: var(--brand-a24);
  color: var(--text-primary);
  box-shadow: 0 4px 16px var(--brand-a24);
}

/* Stage holds the active mockup + the thumbnail strip. Layout
   adapts to the active device:
     TV active    → column (mockup top, thumbs below) — TV bezel is
                    landscape so thumbs fit naturally below it.
     Phone active → row (mockup left, thumbs stacked vertically on
                    the right) — phone bezel is portrait/tall so the
                    space to its right takes a vertical thumb stack. */
.showcase-stage {
  position: relative;
  width: min(1100px, 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(12px, 2vh, 24px);
  flex-direction: column;
}

.showcase-stage[data-active-device="tv"]    .device-mock--phone { display: none; }
.showcase-stage[data-active-device="phone"] .device-mock--tv    { display: none; }

.showcase-stage[data-active-device="phone"] {
  flex-direction: row;
  gap: clamp(16px, 2vw, 32px);
  /* Reserve vertical space so the portrait bezel + landscape-swap
     form both have room. */
  min-height: clamp(360px, 50vh, 500px);
}

/* Thumbs orientation: row by default; column when phone is active so
   they stack vertically beside the portrait bezel. */
.showcase-stage[data-active-device="phone"] .showcase-thumbs {
  flex-direction: column;
}

/* ─── Thumbnail strip (3 thumbs of active device's screenshots) ─── */
.showcase-thumbs {
  display: flex;
  gap: clamp(8px, 1vw, 12px);
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  max-width: 100%;
}

/* ─── Thumbnail micro-previews ────────────────────────────────────
 * Thumbs are SECONDARY navigation — small, unobtrusive, like
 * carousel-dot indicators with a hint of preview content. They
 * should NEVER compete visually with the mockup hero.
 *
 * Aspect ratio matches the source orientation so previews aren't
 * cropped weirdly:
 *   TV thumbs (default)            16:9 landscape (matches tv_*.jpg)
 *   Phone thumbs (data-device=phone): 9:19.5 portrait (matches mobile_*)
 *   Phone .is-landscape (mobile_2): 16:9 landscape (the playback shot) */
.showcase-thumb {
  appearance: none;
  border: 1.5px solid rgba(255, 255, 255, 0.18);
  background: transparent;
  padding: 0;
  border-radius: 6px;
  overflow: hidden;
  cursor: pointer;
  width: clamp(40px, 5vw, 56px);
  height: calc(clamp(40px, 5vw, 56px) * 9 / 16);
  flex-shrink: 0;
  transition: border-color .2s, opacity .2s, transform .2s;
  opacity: 0.85;
}
.showcase-thumbs[data-device="phone"] .showcase-thumb {
  /* Mini-phone aspect — narrower and taller than TV thumbs */
  width: calc(clamp(36px, 4.5vw, 48px));
  height: calc(clamp(36px, 4.5vw, 48px) * 19.5 / 9);
}
.showcase-thumbs[data-device="phone"] .showcase-thumb.is-landscape {
  /* Mobile_2 is landscape playback — keep it landscape even in phone strip */
  width: calc(clamp(40px, 5vw, 56px));
  height: calc(clamp(40px, 5vw, 56px) * 9 / 16);
}
.showcase-thumb:hover { opacity: 1; }
.showcase-thumb.is-active {
  border-color: var(--brand);
  opacity: 1;
}
.showcase-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Download CTA at bottom of screen 2 — taps into screen 3. */
.showcase-cta {
  margin-top: clamp(8px, 1vh, 16px);
}

/* ─── TV mock: 16:9 black bezel + glow ─── */
.device-mock--tv {
  /* Width-driven sizing using min() — Chrome 79+. The frame's height
     is derived via calc() (pre-aspect-ratio fallback) using the same
     expression. CSS aspect-ratio property landed in Chrome 88; for
     TV browsers (Chrome 79 on Android TV) we have to do the math
     manually so the bezel doesn't collapse to a 15px sliver. */
  --tv-w: min(720px, 80vw);
  width: var(--tv-w);
  display: flex;
  flex-direction: column;
  align-items: center;
}

.device-mock--tv .device-mock__frame {
  width: 100%;
  /* 16:9 derived height — calc lets us replicate aspect-ratio without
     the property. min(...) recomputes alongside --tv-w on resize. */
  height: calc(var(--tv-w) * 9 / 16);
  background: #0a0a0a;
  border-radius: clamp(8px, 1vw, 14px);
  padding: clamp(6px, 0.8vw, 10px);
  box-shadow:
    0 30px 80px rgba(0, 0, 0, 0.7),
    0 0 60px var(--brand-a24),
    inset 0 0 0 1px rgba(255, 255, 255, 0.08);
}

.device-mock--tv .device-mock__screen {
  width: 100%;
  height: 100%;
  border-radius: clamp(4px, 0.5vw, 6px);
  overflow: hidden;
  position: relative;
  background: #000;
}

.device-mock--tv .device-mock__stand {
  width: 28%;
  height: clamp(10px, 1.4vh, 16px);
  margin-top: clamp(4px, 0.6vh, 8px);
  background: linear-gradient(180deg, #1a1a1a 0%, #0a0a0a 100%);
  border-radius: 0 0 8px 8px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.6);
  /* trapezoid stand: clip wider top, narrow bottom for monitor look */
  clip-path: polygon(8% 0, 92% 0, 78% 100%, 22% 100%);
  background: #1a1a1a;
}

/* ─── Phone mock: 9:19.5 portrait with notch on top.
 *
 * Two CSS vars define the portrait dimensions. When the active slide
 * is landscape (mobile_2 — phone in landscape video playback), the
 * .is-landscape class on the bezel SWAPS width/height (so the bezel
 * physically becomes a landscape rectangle). Notch + screen radius
 * adapt for the new orientation. The image does NOT rotate; its
 * native landscape orientation now matches the rotated bezel.
 *
 * width/height transition gives a satisfying physical "rotate" feel
 * without using transform: rotate (which would also rotate the image
 * inside, defeating the point). */
.device-mock--phone {
  --bezel-w: clamp(175px, 23vh, 230px);
  --bezel-h: clamp(380px, 50vh, 500px);
  width: var(--bezel-w);
  height: var(--bezel-h);
  flex-shrink: 0;
  transition: width 600ms cubic-bezier(.65, 0, .35, 1),
              height 600ms cubic-bezier(.65, 0, .35, 1);
}

.device-mock--phone.is-landscape {
  width: var(--bezel-h);
  height: var(--bezel-w);
}

/* Silver iPhone aesthetic — narrow brushed-silver bezel with cool
   metallic gradient. Thin highlight line on the outer edge sells
   the metallic feel; black inner shadow line defines the screen edge. */
.device-mock--phone .device-mock__frame {
  width: 100%;
  height: 100%;
  background: linear-gradient(135deg, #e8e8ec 0%, #c0c2c8 50%, #989aa0 100%);
  border-radius: clamp(22px, 2.2vw, 32px);
  padding: clamp(3px, 0.35vw, 5px);
  position: relative;
  box-shadow:
    0 24px 60px rgba(0, 0, 0, 0.5),
    0 0 50px var(--brand-a24),
    inset 0 0 0 0.5px rgba(255, 255, 255, 0.7),
    inset 0 0 0 1px rgba(0, 0, 0, 0.18);
}

.device-mock--phone .device-mock__notch {
  position: absolute;
  top: clamp(10px, 1vw, 14px);
  left: 50%;
  transform: translateX(-50%);
  width: 30%;
  height: clamp(14px, 1.6vw, 20px);
  background: #000;
  border-radius: 999px;
  z-index: 2;
  transition: top 600ms cubic-bezier(.65, 0, .35, 1),
              left 600ms cubic-bezier(.65, 0, .35, 1),
              width 600ms cubic-bezier(.65, 0, .35, 1),
              height 600ms cubic-bezier(.65, 0, .35, 1),
              transform 600ms cubic-bezier(.65, 0, .35, 1);
}

/* Landscape orientation — notch moves to the left side (acts as the
   "top" relative to a phone rotated -90°). Width/height swap. */
.device-mock--phone.is-landscape .device-mock__notch {
  top: 50%;
  left: clamp(10px, 1vw, 14px);
  transform: translateY(-50%);
  width: clamp(14px, 1.6vw, 20px);
  height: 30%;
}

.device-mock--phone .device-mock__screen {
  width: 100%;
  height: 100%;
  border-radius: clamp(18px, 2vw, 28px);
  overflow: hidden;
  position: relative;
  background: #000;
}

/* ─── Mock slides (cross-fade) ─── */
.mock-slide {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 700ms ease-in-out;
  display: block;
}

.mock-slide.is-active {
  opacity: 1;
}

/* Landscape slides display inside a now-landscape bezel (the bezel
   itself swaps width/height when active). object-fit: cover fits
   the landscape image to the landscape screen naturally, no letterbox. */

/* Larger viewports: TV mockup can grow */
@media (min-width: 1100px) {
  .device-mock--tv    { max-width: 760px; }
}

/* ─── Landscape layout for screen 2 (TV browsers, laptops, landscape
 * mobile / tablet). Two-column grid: text + controls on the left,
 * device mockup + thumbs on the right. Lets us use horizontal space
 * on wide viewports (TV 960×484) instead of stacking everything
 * vertically and crowding the mockup out.
 *
 * Threshold: landscape orientation + ≥640 CSS px width. Excludes
 * portrait mobile + portrait tablet (768×1024) which keep vertical
 * stack. Activates on TV (960×484), laptops, mobile landscape. */
/* ─── Landscape layout (TV browsers, laptops, landscape mobile/tablet)
 *
 * Two-column composition:
 *   [ marketing copy + tabs + CTA ]   [ device mockup ]
 *                                     [ thumb strip   ]
 *
 * The left column is wrapped in .showcase-side so it can be vertically
 * centered as a unit. The right column places the mockup as the visual
 * hero and stages the thumb strip directly underneath as natural
 * navigation, not orphan content.
 *
 * Threshold: landscape orientation + ≥640 CSS px width — covers TV
 * (960×484 CSS), laptops, mobile landscape. Portrait viewports keep
 * the original vertical stack. */
@media (orientation: landscape) and (min-width: 640px) {
  .showcase {
    display: grid;
    grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.05fr);
    /* Right column: tabs (top) → stage (mockup + thumbs, fills rest).
       Stage handles the mockup ↔ thumbs arrangement internally based
       on the active device, so the grid stays a clean 2×2. */
    grid-template-rows: auto 1fr;
    grid-template-areas:
      "side  tabs"
      "side  stage";
    column-gap: clamp(36px, 6vw, 96px);
    row-gap: clamp(10px, 1.8vh, 18px);
    padding: clamp(64px, 9vh, 96px) clamp(28px, 4vw, 64px) clamp(24px, 3vh, 40px);
    width: min(1280px, 100%);
    margin: 0 auto;
  }

  .showcase-side {
    grid-area: side;
    align-self: center;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: clamp(18px, 3vh, 32px);
    text-align: left;
    max-width: 480px;
  }
  .showcase-side .showcase-text {
    align-items: flex-start;
    text-align: left;
    max-width: none;
    gap: clamp(10px, 1.6vh, 18px);
  }
  .showcase-side .showcase-cta  { margin-top: 0; align-self: flex-start; }

  .showcase-tabs   { grid-area: tabs;   justify-self: center; align-self: end; }
  .showcase-stage  { grid-area: stage;  align-self: center; justify-self: center; }

  /* Mockup as visual hero: bigger, more dominant than the text column. */
  .device-mock--tv {
    --tv-w: min(580px, 52vw);
    width: var(--tv-w);
    max-width: 100%;
  }
  .device-mock--tv .device-mock__frame {
    width: 100%;
    height: calc(var(--tv-w) * 9 / 16);
  }
  .device-mock--phone {
    --bezel-h: clamp(320px, 64vh, 480px);
    --bezel-w: clamp(148px, 30vh, 222px);
  }
}

/* ─── Short landscape — TV browsers (~484 px CSS height) and laptops
 * with chrome bars. Strong hero typography on the left, bigger
 * mockup + readable thumbs on the right. Sized aggressively in vh so
 * the visual weight scales correctly at low viewport heights. */
@media (orientation: landscape) and (max-height: 640px) {
  .showcase {
    padding: clamp(48px, 10vh, 72px) clamp(28px, 4vw, 56px) clamp(12px, 2vh, 24px);
    column-gap: clamp(32px, 5vw, 72px);
    row-gap: clamp(8px, 1.4vh, 14px);
  }
  .showcase-side { gap: clamp(16px, 3vh, 26px); max-width: 460px; }
  .showcase-eyebrow  {
    padding: 5px 14px;
    font-size: clamp(11px, 2vh, 13px);
    letter-spacing: 0.08em;
  }
  /* Headline: aggressive vh scaling so it feels like a real hero on
     a 484-tall viewport, not a paragraph caption. */
  .showcase-headline {
    font-size: clamp(28px, 7.5vh, 48px);
    line-height: 1.04;
    letter-spacing: -0.02em;
  }
  .showcase-subhead  {
    font-size: clamp(13px, 2.8vh, 17px);
    line-height: 1.4;
  }
  .showcase-tab      { padding: 7px 22px; font-size: clamp(12px, 2.4vh, 14px); }
  .showcase-cta      { padding: 12px 26px; font-size: clamp(13px, 2.6vh, 15px); }
  /* On compact viewports thumbnails are too small to be meaningful —
     swap them for numbered pill indicators (1/2/3). Reads at a glance,
     functions as pure navigation rather than pretending to be a preview.
     Selectors match the specificity of data-device rules above so they
     reliably override the image-thumb sizing. */
  .showcase-thumbs[data-device]   {
    gap: 8px;
    counter-reset: thumb-num;
  }
  .showcase-thumbs[data-device] .showcase-thumb,
  .showcase-thumbs[data-device="phone"] .showcase-thumb,
  .showcase-thumbs[data-device="phone"] .showcase-thumb.is-landscape {
    counter-increment: thumb-num;
    width: clamp(24px, 4.5vh, 30px);
    height: clamp(24px, 4.5vh, 30px);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: clamp(11px, 2vh, 13px);
    font-weight: 600;
    color: var(--text-muted);
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.18);
    opacity: 1;
  }
  .showcase-thumbs[data-device] .showcase-thumb img { display: none; }
  .showcase-thumbs[data-device] .showcase-thumb::before { content: counter(thumb-num); }
  .showcase-thumbs[data-device] .showcase-thumb.is-active {
    background: var(--brand-a24);
    color: var(--brand);
    border-color: var(--brand);
  }
  /* Phone tab: stack numbered pills vertically beside the bezel */
  .showcase-stage[data-active-device="phone"] .showcase-thumbs {
    flex-direction: column;
  }

  /* Mockup as hero, sized so frame + thumbs strip both fit within
     100vh = 540 (Chrome 79 fallback) without clipping. Math:
     padding (84) + gap (14) + frame (~250) + thumbs (~70) = 418 → fits. */
  .device-mock--tv   { --tv-w: min(440px, 46vw); }
  .device-mock--phone {
    --bezel-h: clamp(240px, 65vh, 320px);
    --bezel-w: clamp(110px, 30vh, 148px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .mock-slide { transition: none; }
}

/* ─── Device grid (Screen 3) ──────────────────────────────────────
 * device-grid + web-row are visually centered in the viewport (the
 * .screen flex defaults of justify-content: center handle this).
 * Footer is absolute-positioned at the bottom so it doesn't push the
 * grid up — what the user sees centered is the cards themselves. */
.devices {
  padding: clamp(72px, 8vh, 100px) clamp(16px, 3vw, 32px) clamp(72px, 10vh, 100px);
  gap: clamp(20px, 3vh, 32px);
}

.devices .device-grid,
.devices .web-row,
.devices .footer {
  width: 100%;
  max-width: 1200px;
  margin-left: auto;
  margin-right: auto;
}

.devices .footer {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
}

.device-grid {
  display: grid;
  gap: clamp(12px, 2vw, 20px);
  /* Default 2 cols so even narrow phones (≥320px) show 4 cards in
     a 2×2 grid without scrolling. Wider screens get more columns. */
  grid-template-columns: repeat(2, 1fr);
}

@media (min-width: 1200px) { .device-grid { grid-template-columns: repeat(4, 1fr); } }

.device-card {
  position: relative;
  background: linear-gradient(180deg, var(--card) 0%, var(--surface) 100%);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: var(--radius-lg);
  padding: 32px 24px 24px;
  text-align: center;
  text-decoration: none;
  color: var(--text-primary);
  transition: transform .25s, border-color .25s, box-shadow .25s;
  overflow: hidden;
  isolation: isolate;
  cursor: pointer;
}

.device-card::before {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(135deg, var(--brand-a40), transparent 50%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  opacity: 0;
  transition: opacity .25s;
  z-index: -1;
}

.device-card:hover {
  transform: translateY(-4px);
  border-color: var(--brand-a24);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5), 0 0 40px var(--brand-a12);
}

.device-card:hover::before { opacity: 1; }

.device-icon {
  width: 56px;
  height: 56px;
  margin: 0 auto 18px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--brand-a12);
  border-radius: 16px;
  color: var(--brand);
}

.device-icon svg { width: 28px; height: 28px; }

.device-title {
  font-size: 17px;
  font-weight: 600;
  margin-bottom: 6px;
}

.device-meta {
  font-size: 12px;
  color: var(--text-muted);
  min-height: 18px;     /* avoid jump while loading */
  margin-bottom: 18px;
}

.device-action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  font-size: 13px;
  font-weight: 600;
  color: var(--brand);
  border: 1px solid var(--brand-a40);
  background: transparent;
  border-radius: 999px;
  padding: 8px 18px;
  transition: background .2s;
}

.device-card:hover .device-action {
  background: var(--brand-a24);
}

.device-action[aria-disabled="true"] {
  color: var(--text-muted);
  border-color: rgba(255, 255, 255, 0.1);
  cursor: not-allowed;
}

/* ─── Web fallback row ─── */
.web-row {
  text-align: center;
  margin-top: clamp(20px, 3vh, 40px);
  font-size: 14px;
  color: var(--text-muted);
}

.web-row a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--brand);
  text-decoration: none;
  font-weight: 600;
  margin-left: 8px;
}

.web-row a:hover { text-decoration: underline; }

/* ─── Footer (absolute-positioned at bottom of screen 3) ─── */
.footer {
  text-align: center;
  padding: 18px 16px 22px;
  font-size: 12px;
  color: var(--text-muted);
  border-top: 1px solid rgba(255, 255, 255, 0.04);
  width: 100%;
}

.footer p + p { margin-top: 6px; }

/* ─── iOS guide ─── */
.ios-page {
  max-width: 720px;
  margin: 0 auto;
  padding: 100px 20px 60px;
}

.ios-header {
  text-align: center;
  margin-bottom: 48px;
}

.ios-title {
  font-size: clamp(28px, 4vw, 40px);
  font-weight: 700;
  margin-bottom: 12px;
}

.ios-subtitle {
  color: var(--text-muted);
  font-size: 15px;
}

.step {
  background: linear-gradient(180deg, var(--card) 0%, var(--surface) 100%);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: var(--radius-md);
  padding: 28px;
  margin-bottom: 24px;
  position: relative;
  overflow: hidden;
  opacity: 0;
  animation: stepIn .5s ease-out forwards;
  animation-delay: calc(var(--i, 1) * 80ms);
}

@keyframes stepIn {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}

.step-num {
  display: inline-block;
  font-size: 12px;
  font-weight: 700;
  color: var(--brand);
  background: var(--brand-a12);
  padding: 4px 10px;
  border-radius: 999px;
  margin-bottom: 10px;
  letter-spacing: 0.05em;
}

.step h3 {
  font-size: 18px;
  font-weight: 600;
  margin-bottom: 10px;
}

.step p {
  color: var(--text-muted);
  font-size: 15px;
  line-height: 1.6;
  margin-bottom: 18px;
}

.step p a, .step p b {
  color: var(--text-primary);
  font-weight: 600;
  text-decoration: none;
}

.step img {
  width: 100%;
  max-width: 420px;
  display: block;
  margin: 0 auto;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-soft);
}

.back-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--brand);
  text-decoration: none;
  font-size: 14px;
  margin-bottom: 24px;
  padding: 8px 14px;
  border-radius: 999px;
  border: 1px solid var(--brand-a24);
  transition: background .2s;
}

.back-btn:hover { background: var(--brand-a12); }

/* ─── Compact device cards for short landscape (TV browsers, laptops
 * with chrome bars). Default card sizing assumes a tall desktop
 * viewport; on TV (CSS 484h) the same padding / font sizes balloon
 * each card past the fold even in 2×2 grid. Tighten everything for
 * a clean two-row view. */
@media (orientation: landscape) and (max-height: 640px) {
  .devices {
    padding: clamp(48px, 9vh, 72px) clamp(16px, 2.5vw, 32px) clamp(8px, 1.5vh, 16px);
    gap: clamp(8px, 1.4vh, 14px);
  }
  .device-grid    { gap: clamp(10px, 1.6vw, 16px); }
  .device-card    { padding: clamp(12px, 2vh, 18px) clamp(12px, 1.6vw, 20px); border-radius: 18px; }
  .device-icon    { width: clamp(32px, 5vh, 44px); height: clamp(32px, 5vh, 44px); margin: 0 auto clamp(6px, 1vh, 10px); border-radius: 10px; }
  .device-icon svg { width: clamp(18px, 2.6vh, 22px); height: clamp(18px, 2.6vh, 22px); }
  .device-title   { font-size: clamp(13px, 2.4vh, 15px); margin-bottom: 2px; }
  .device-meta    { font-size: clamp(10px, 1.8vh, 12px); margin-bottom: clamp(6px, 1.2vh, 12px); min-height: 0; }
  .device-action  { font-size: clamp(11px, 1.8vh, 12px); padding: 4px 12px; }
  .web-row        { font-size: clamp(11px, 2vh, 13px); margin-top: clamp(8px, 1.5vh, 14px); }
  .footer         { padding: 12px 16px 16px; font-size: clamp(10px, 1.8vh, 11px); }
}

/* ─── Mobile tuning ─── */
@media (max-width: 640px) {
  .topbar { padding: 12px 16px; }
  .hero { padding: 80px 16px 40px; }
  .devices { padding: 60px 12px 60px; }
  /* 2-col cards on phones — tighter padding so titles + meta fit
     comfortably in narrow columns */
  .device-card { padding: 18px 12px 14px; }
  .device-icon { width: 44px; height: 44px; margin-bottom: 12px; }
  .device-icon svg { width: 22px; height: 22px; }
  .device-title { font-size: 15px; margin-bottom: 4px; }
  .device-meta  { font-size: 11px; margin-bottom: 12px; }
  .device-action { font-size: 12px; padding: 6px 14px; }
  .ios-page { padding: 80px 16px 40px; }
  .step { padding: 22px 18px; }
}
