/* ==========================================================================
   Eye Routine — product page styles (LOCAL DRAFT, working copy only)
   --------------------------------------------------------------------------
   Scoped, additive stylesheet for /apps/eye-routine/.
   The approved APPSTAR header + footer keep the standard light "Quiet
   Publisher" brand frame (appstar-v8-19.css). Only the product content
   inside .er-main switches to the Eye Routine dark-navy visual identity.
   Nothing here overrides the shared site CSS for any other page.
   Prefix: er-  (Eye Routine)
   ========================================================================== */

:root {
  --er-bg: #060A22;
  --er-bg-2: #0B1140;
  --er-panel: #0E1545;
  --er-line: rgba(255, 255, 255, 0.10);
  --er-line-soft: rgba(255, 255, 255, 0.06);
  --er-text: #ECEEF8;
  --er-muted: #A8AFCE;
  --er-muted-soft: #828AAD;
  --er-blue: #4F8DF6;
  --er-blue-strong: #2F80EC;
  --er-amber: #FED400;
}

/* Dark navy product canvas — applied only to the Eye Routine main content */
.er-main {
  background: var(--er-bg);
  color: var(--er-text);
}

.er-container {
  width: min(1040px, calc(100% - 40px));
  margin: 0 auto;
}

/* ---- Hero ---------------------------------------------------------------- */
.er-hero {
  /* No gradient band — the hero shares the flat dark page background (--er-bg)
     so it reads uniform with the sections below. Header styling is untouched.
     Compact-but-premium vertical rhythm to match the reference. */
  padding: 62px 0 66px;
}

.er-hero-layout {
  display: grid;
  /* Text-dominant, mascot balances the right. A 260px mascot + 32px gap leaves
     a ~748px text column at the 1040px container — still wide enough for the
     subtitle's longer second line at ~46px to stay on one line. */
  grid-template-columns: minmax(0, 1fr) 260px;
  gap: 32px;
  align-items: center;
}

.er-app-icon {
  width: 132px;
  height: 132px;
  border-radius: 28px;
  display: block;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.45);
}

/* ==========================================================================
   Hero mascot (LOCAL EXPERIMENT — avatar test)
   --------------------------------------------------------------------------
   Reproduces the app's eyes mascot, animating ONLY the eyes. The container's
   box matches the mascot SVG's 212x92 viewBox, so SVG coordinates map straight
   to container percentages. No tile, border, or background — just the mascot.

   States:
     • default  → full static mascot (eyes_mascot.svg). Fallback for no-JS /
       offline / reduced-motion.
     • .is-animated (JS, when the Lottie blink is live) → the accent-lines +
       smile SVG (eyes removed) plus the background-free Lottie eyes, which are
       absolutely positioned to land exactly on the original eye centres.

   Lottie box maths (comp 1920x1080; eyes at comp x=600 & x=1320, y=540 →
   SVG eye centres 71.05 & 139.80, y≈38.99). Uniform scale s = 68.754/720 =
   0.095492 maps the eye centres exactly. Full comp → 183.34 x 103.13 SVG units,
   placed at SVG (13.76, -12.58):
     left  = 13.76/212  =  6.49%
     top   = -12.58/92  = -13.67%
     width = 183.34/212 = 86.48%
     height= 103.13/92  = 112.10%
   ========================================================================== */
.er-hero-mascot {
  display: flex;
  justify-content: flex-end; /* sit toward the right edge of the hero */
}

.er-mascot {
  position: relative;
  width: 260px;                /* balances the right side without dominating */
  aspect-ratio: 212 / 92;      /* matches the mascot SVG viewBox */
  overflow: visible;           /* the eye comp extends slightly above the box */
}

.er-mascot-fallback,
.er-mascot-accents {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

/* Accent/smile layer and Lottie eyes are hidden until the blink is live. */
.er-mascot-accents,
.er-mascot-lottie {
  display: none;
}

.er-mascot-lottie {
  position: absolute;
  left: 6.49%;
  top: -13.67%;
  width: 86.48%;
  height: 112.10%;
}

.er-mascot-lottie svg {
  display: block;
}

.er-mascot.is-animated .er-mascot-fallback {
  display: none;
}

.er-mascot.is-animated .er-mascot-accents,
.er-mascot.is-animated .er-mascot-lottie {
  display: block;
}

/* Belt-and-braces: under reduced-motion always keep the full static mascot. */
@media (prefers-reduced-motion: reduce) {
  .er-mascot.is-animated .er-mascot-fallback {
    display: block;
  }
  .er-mascot.is-animated .er-mascot-accents,
  .er-mascot.is-animated .er-mascot-lottie {
    display: none;
  }
}

.er-kicker {
  margin: 0 0 14px;
  color: var(--er-blue);
  font-size: 12px;
  font-weight: 650;
  letter-spacing: .14em;
  text-transform: uppercase;
}

/* Hero title — large, premium, separate "Eye Routine" */
.er-hero h1 {
  margin: 0 0 14px;
  font-size: clamp(40px, 5vw, 56px);
  line-height: 1.03;
  letter-spacing: -.03em;
  font-weight: 700;
  color: #fff;
}

/* Subtitle — the dominant hero statement: large, bold, near-white, two lines.
   Close to APPSTAR homepage headline strength. No max-width cap — the exact
   two-line split comes from the desktop .er-sub-break, and the wide text column
   keeps the long second line on one line. */
.er-hero-copy {
  margin: 0;
  color: #F4F6FE;
  font-size: clamp(30px, 4.4vw, 46px);
  line-height: 1.08;
  font-weight: 680;
  letter-spacing: -.02em;
}

/* Forced exact 2-line split only on wide screens, where the long second line
   fits the text column; below 1040px it wraps naturally (no overflow). */
.er-sub-break { display: none; }
/* Tablet-portrait-only break (after "screen breaks and") — see the tablet media
   query below. Hidden everywhere by default so desktop keeps its 2-line split
   and phone wraps naturally. */
.er-sub-break-tablet { display: none; }
/* iPhone XR-only controlled line breaks (shown only in the XR media query below).
   Hidden everywhere else so SE/tablet/desktop wrap exactly as before — no text
   duplication, just an optional <br>. */
.er-xr-br { display: none; }
/* Shared mobile break — shows on BOTH iPhone SE and XR (≤430px) for break points
   the two share; XR keeps its existing break, SE gains the same one. SE-only break
   shows only ≤390px. One <br> renders per device; no text is duplicated. */
.er-mob-br { display: none; }
.er-se-br { display: none; }
.er-lg-br { display: none; }   /* large-mobile-only break (iPhone 14 Pro Max etc.) */
.er-pixel7-br { display: none; }   /* Pixel 7-only break (412px) */
@media (max-width: 430px) { .er-mob-br { display: inline; } }
@media (min-width: 411px) and (max-width: 413px) { .er-pixel7-br { display: inline; } }
@media (max-width: 390px) {
  .er-se-br { display: inline; }
  .er-sub-break { display: inline; }   /* hero lead 2-line split on iPhone SE too */
}
@media (min-width: 430px) and (max-width: 480px) { .er-lg-br { display: inline; } }
@media (min-width: 1040px) {
  .er-sub-break { display: inline; }
}

/* Supporting paragraph — small, quiet, ~2 lines, sits close under the subtitle */
.er-hero-sub {
  max-width: 660px;
  margin: 16px 0 0;
  color: #8B96BC;
  font-size: 15.5px;
  line-height: 1.6;
}

/* ---- Section scaffolding ------------------------------------------------- */
.er-section {
  padding: 70px 0;
  border-top: 1px solid var(--er-line-soft);
}

.er-section-label {
  margin: 0 0 14px;
  color: var(--er-blue);
  font-size: 12px;
  font-weight: 650;
  letter-spacing: .13em;
  text-transform: uppercase;
}

.er-section h2 {
  margin: 0 0 18px;
  max-width: 720px;
  font-size: clamp(26px, 3vw, 34px);
  line-height: 1.12;
  letter-spacing: -.02em;
  font-weight: 700;
  color: #fff;
}

.er-section-copy {
  max-width: 680px;
  margin: 0;
  color: var(--er-muted);
  font-size: 17px;
  line-height: 1.72;
}

/* ==========================================================================
   What's Inside — stable feature slider as a horizontal viewport + track (same
   interaction feel as "A look at the app"). All slides sit side-by-side in the
   track; navigating translates the track on the X axis only — fixed section
   height (487px desktop), no reflow, the next section never moves. The arrows
   reuse the site .er-arrow component.
   ========================================================================== */
.er-wi-slider {
  position: relative;
  margin-top: 30px;
  padding: 0 52px;            /* side gutters hold the arrows, like the carousel */
}

/* Soft side fades so the slide content dissolves into the page background at the
   viewport edges (same idea as the "A look at the app" carousel) — not a hard
   rectangular clip. They sit over the scroll viewport's left/right edges, above
   the sliding content but below the arrows (z 3), and never block swipe/scroll
   or the buttons (pointer-events: none). Gradient is the exact page bg → its own
   transparent form (rgba so the fade never goes muddy/grey). */
.er-wi-slider::before,
.er-wi-slider::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: 100px;              /* desktop fade width */
  z-index: 2;
  pointer-events: none;
}
.er-wi-slider::before {
  left: 52px;                /* the scroll viewport's left edge (the gutter) */
  background: linear-gradient(to right, var(--er-bg), rgba(6, 10, 34, 0));
}
.er-wi-slider::after {
  right: 52px;               /* the scroll viewport's right edge */
  background: linear-gradient(to left, var(--er-bg), rgba(6, 10, 34, 0));
}

/* The track IS a native horizontal scroll container (same mechanics as the
   "A look at the app" .er-carousel). The browser handles trackpad/touch swipe
   natively; overscroll-behavior-x: contain stops the back/forward gesture, and
   vertical scroll passes through to the page. Scrollbar hidden. */
.er-wi-stage {
  display: flex;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
  scrollbar-width: none;        /* Firefox */
  -ms-overflow-style: none;     /* legacy IE/Edge */
}
.er-wi-stage::-webkit-scrollbar { display: none; width: 0; height: 0; }  /* WebKit/Blink */

.er-wi-slide {
  flex: 0 0 100%;               /* one slide = one viewport width */
  scroll-snap-align: start;     /* each slide is a snap point */
  min-height: 487px;           /* fixed-height stage (the screen-break-timer ref) */
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-top: 6px;
}

/* Shared visual area — centres each slide's scene in the wide stage. */
.er-wi-visual {
  margin-top: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 55px;
  width: 100%;
  min-width: 0;
}

/* ---- Shared heading: number / title / subtitle (identical on every slide) -- */
.er-slide-heading {
  position: relative;
  text-align: center;
  width: 100%;
}

.er-slide-num {
  position: absolute;
  left: 16%;         /* sits left of the centred title, like the reference */
  top: 4px;
  color: var(--er-muted);
  font-size: 21px;
  font-weight: 500;
  letter-spacing: .02em;
}

.er-slide-title {
  margin: 0;
  color: #D6DEF8;
  font-size: clamp(23px, 2.9vw, 31px);
  font-weight: 500;
  letter-spacing: .13em;
  line-height: 1.2;
}

.er-slide-sub {
  margin: 13px 0 0;
  color: #6687D3;
  font-size: 13px;
  line-height: 1.65;
  letter-spacing: .04em;
}

/* Slide-03 arrows feel: vertically align the shared arrows with the visual. */
.er-wi-slider .er-arrow {
  top: 56%;
}
.er-wi-slider .er-arrow:disabled {
  opacity: .3;
  cursor: default;
}

/* ---- Slide 01: voice-guided routine -------------------------------------- */
/* Heading is the shared number/title/subtitle (same as slides 02/03). The
   visual stacks the large wave with the sound toggle centred just below it. */
.er-voice-scene {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 15px;                  /* small gap between wave and the sound button */
  width: 100%;
  min-width: 0;
}

/* The real animated voice wave (Lottie). Large + prominent, contain-scaled so
   nothing is clipped; aspect-ratio reserves the full height. The visible wave
   art fills ~93% of this wrapper width, so the wrapper is sized generously on
   desktop to fill the span between the slider arrows (small, balanced gaps —
   like the Figma reference). The 16:9-ish padding is transparent, never cropped.
   Base value here stays mobile-safe; desktop enlarges it below. */
.er-voicewave {
  width: 100%;                /* definite size resolves to the column → no overflow */
  max-width: 578px;
  min-width: 0;
  aspect-ratio: 2000 / 640;   /* source canvas aspect — height scales with width */
  margin: 0 auto;
}
/* Desktop: grow the wave to fill the space between the arrows. clamp() keeps it
   responsive; the height stays within budget so the section height is unchanged. */
@media (min-width: 821px) {
  .er-voicewave {
    max-width: clamp(620px, 70vw, 880px);
  }
}
.er-voicewave-lottie {
  width: 100%;
  height: 100%;
}

/* Sound/mute toggle — small, subtle, centred below the wave. */
.er-voice-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  color: #8EB1F7;
  -webkit-appearance: none;
  appearance: none;
  opacity: .9;
  transition: opacity .2s ease;
}
.er-voice-toggle:hover { opacity: 1; }

.er-voice-ico {
  display: block;
  width: 24px;
  height: 24px;
}
/* Default = sound on (show the "on" icon); muted shows the "off" icon. */
.er-voice-ico-off { display: none; }
.er-voice-toggle.is-muted .er-voice-ico-on { display: none; }
.er-voice-toggle.is-muted .er-voice-ico-off { display: block; }

/* ---- Slide 02: screen break timer scene -------------------------------------
   CSS/SVG countdown ring (left) + feature copy (right) form ONE centered group
   (.er-timer-scene). The copy aligns to the timer digits (set on desktop). */
.er-timer-scene {
  display: flex;
  align-items: center;        /* base/mobile: centred; desktop aligns to digits */
  justify-content: center;
  gap: 55px;
  width: 100%;
  min-width: 0;
}

.er-timer-ring {
  position: relative;
  flex: 0 0 auto;
  width: 164px;
  height: 164px;
}

/* Subtle low-opacity glow behind the ring. */
.er-timer-ring::before {
  content: "";
  position: absolute;
  inset: -14px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(134,163,245,0.10) 0%, rgba(134,163,245,0) 68%);
  pointer-events: none;
}

.er-timer-ring-svg {
  display: block;
  width: 100%;
  height: 100%;
}

.er-timer-readout {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.er-timer-time {
  font-size: 45px;
  line-height: 54px;
  font-weight: 400;
  letter-spacing: .01em;
  color: #FFFFFF;
  /* keep each digit the same width so the countdown never jitters/reflows */
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

.er-timer-label {
  margin-top: 2px;
  font-size: 9px;
  line-height: 11px;
  font-weight: 300;
  letter-spacing: .04em;
  color: #86A3F5;
}

.er-timer-copy {
  flex: 0 0 auto;
  width: 176px;
  text-align: left;
  /* hidden while the countdown runs (space stays reserved → no layout shift);
     fades in gently a beat after 00:00 (.is-shown added by JS). The tiny 5px
     rise is transform-only (no layout shift); it settles to the exact approved
     position (translateY 0). */
  opacity: 0;
  transform: translateY(5px);
  transition: opacity 950ms ease-out, transform 950ms ease-out;
}
.er-timer-copy.is-shown {
  opacity: 1;
  transform: translateY(0);
}

/* Heartbeat pulse on the ring once per second during the countdown. Transform
   only → no layout shift, no reflow, permanent scale unchanged. Calm + premium:
   amplitude softened ~20% (1.03 → 1.024, final 1.045 → 1.036), ease-in-out. */
@keyframes er-timer-pulse {
  0%   { transform: scale(1); }
  45%  { transform: scale(1.024); }
  100% { transform: scale(1); }
}
@keyframes er-timer-pulse-final {
  0%   { transform: scale(1); }
  45%  { transform: scale(1.036); }
  100% { transform: scale(1); }
}
.er-timer-ring.is-pulse {
  animation: er-timer-pulse 230ms ease-in-out;
}
.er-timer-ring.is-pulse-final {
  animation: er-timer-pulse-final 300ms ease-in-out;
}

.er-timer-copy-head {
  margin: 0;
  color: #DAA125;
  font-weight: 800;
  font-size: 24px;
  line-height: 29px;
}

.er-timer-copy-line {
  margin: 18px 0 0;
  color: #EDF1FD;
  font-weight: 400;
  font-size: 15px;
  line-height: 1.55;
}

/* Desktop: scale the WHOLE timer group up and prominent (ring large/dominant)
   and align the copy to the timer digits — the eye reads the timer first, then
   the copy. Scoped to slide 02 only; mobile keeps the base sizes. The group
   stays within the fixed stage so the section height never changes. */
@media (min-width: 821px) {
  /* vertically centre the (larger) group in the stage + align ring with arrows */
  .er-wi-visual:has(.er-timer-ring) {
    margin-top: 60px;
  }
  .er-timer-scene {
    align-items: flex-start;   /* lets the copy align to the digits, not ring top */
    gap: 128px;                /* ring → copy gap (scaled with the group) */
  }
  .er-timer-ring {
    width: 290px;
    height: 290px;
  }
  .er-timer-time {
    font-size: 84px;
    line-height: 92px;
  }
  .er-timer-label {
    margin-top: 5px;
    font-size: 15px;
    line-height: 18px;
  }
  .er-timer-copy {
    width: 230px;
    /* push the copy down so the yellow headline top lines up with the TOP of
       the timer digits (digits sit centred in the 290px ring). */
    margin-top: 98px;
  }
  .er-timer-copy-head {
    font-size: 33px;
    line-height: 40px;
  }
  .er-timer-copy-line {
    font-size: 19px;
    margin-top: 23px;
  }
}

/* ---- Slide 03: visual focus exercises scene ---------------------------------
   The tight-crop Focus Ladder Lottie (1544×406, background layer stripped) plays
   autoplay + loop with NO controls. Contain ('meet') scaling + aspect-ratio box
   render the full canvas with no crop and no horizontal stretch — uniform scale,
   nothing clipped. Large on desktop so the letters fill the space between the
   arrows like the Figma reference; width:100% lets it scale down on mobile. */
.er-focus {
  flex: 1 1 auto;
  min-width: 0;
  width: 100%;
  max-width: 780px;
  margin: 0 auto;
}

/* aspect-ratio matches the tight-crop canvas (1544/406 ≈ 3.8), so the height is
   always proportional to the width — no stretch/squash, no cropping. The JSON is
   now exported transparent (no background layer), so no blend/overlay workaround
   is needed — the letters sit directly on the page. */
.er-focus-anim {
  width: 100%;
  margin: 0 auto;
  aspect-ratio: 1544 / 406;
}

.er-focus-lottie {
  width: 100%;
  height: 100%;
}

/* Desktop: drop the (short) animation to the vertical centre of the stage so the
   top/bottom gaps are balanced (scoped to slide 03 only; mobile keeps base). */
@media (min-width: 821px) {
  .er-wi-visual:has(.er-focus) {
    margin-top: 98px;
  }
}

/* iPad Air / tablet portrait only (760–900px): the desktop (min-width:821px)
   centring above doesn't apply at 820px, so the short letters animation sat
   high with a big empty gap below, and read a touch large. Give the visual
   wrapper a fixed height and let its existing flex centring (display:flex /
   align-items:center / justify-content:center) sit the animation in the middle
   of the slide area, and trim it 8% (no prior scale on this slide → 1.0 × 0.92).
   Scoped to slide 03 (.er-focus) only — no other slide, Gabor, desktop, or
   phone is affected. */
@media (min-width: 760px) and (max-width: 900px) {
  /* Let the focus visual fill the whole area below the heading; the wrapper
     already uses display:flex / align-items:center / justify-content:center
     (flex-direction:column on tablet), so the animation is centred both ways.
     The heading/subtitle and section heading stay put. */
  .er-wi-visual:has(.er-focus) {
    flex: 1 1 auto;
    height: auto;
    margin-top: 0;
  }
  /* Root cause of "too high": .er-focus is flex:1 1 auto, so in the column
     wrapper it grew to the full height and pinned the animation to the TOP.
     flex:0 0 auto keeps it at content height so the wrapper can centre it. */
  .er-focus {
    flex: 0 0 auto;
  }
  /* Size unchanged — kept at the previous 0.92. Position handled by flex above. */
  .er-focus-anim {
    transform: scale(0.92);
    transform-origin: center center;
  }
}

/* Screen break timer (slide 02) — iPad Air portrait only (760–820px). The
   max-width:820px rule stacks this slide into a column (timer over text); here
   we restore the desktop-style timer-LEFT / text-RIGHT row and centre the whole
   group in the visual stage area. Capped at 820px so iPad Pro (834px, which
   already gets the good min-width:821px row layout) is untouched. Selectors are
   scoped under .er-wi-visual:has(.er-timer-ring) so only slide 02 is affected
   and the column rule is overridden by specificity. */
@media (min-width: 760px) and (max-width: 820px) {
  /* Fill the area below the heading and centre the (large) group vertically in
     it — the wrapper is flex-direction:column (tablet base) + justify/align
     centre, so the row sits in the middle of the visual stage. */
  .er-wi-visual:has(.er-timer-ring) {
    flex: 1 1 auto;
    height: auto;
    margin-top: 0;
  }
  /* Horizontal row: large timer LEFT, text RIGHT. align-items:flex-start (not
     centre) so the text aligns to the TOP of the timer digits via the copy's
     margin-top below — the timer + text read as one composition, with the eye
     moving timer → text. The whole scene is centred in the stage by the
     flex:1 1 auto wrapper above. */
  .er-wi-visual:has(.er-timer-ring) .er-timer-scene {
    flex-direction: row;
    align-items: flex-start;
    justify-content: center;
    gap: 64px;
  }
  /* Strong left anchor — matches the desktop/reference timer scale (was 164px).
     Group ≈ 290 + 64 + 230 = 584px, centred in the ~700px stage → ~58px clear of
     the arrows, no crop. */
  .er-wi-visual:has(.er-timer-ring) .er-timer-ring {
    width: 290px;
    height: 290px;
  }
  .er-wi-visual:has(.er-timer-ring) .er-timer-time {
    font-size: 84px;
    line-height: 92px;
  }
  .er-wi-visual:has(.er-timer-ring) .er-timer-label {
    margin-top: 5px;
    font-size: 15px;
    line-height: 18px;
  }
  /* Left-aligned text block beside the timer, scaled to match (was 176px auto).
     margin-top aligns the "Small breaks." top with the TOP of the 00:00 digits
     (digits are centred in the 290px ring → top ≈ 103px). Block content ≈ 184px,
     so it ends ≈ 282px — just above the ring's lower edge, as intended. */
  .er-wi-visual:has(.er-timer-ring) .er-timer-copy {
    width: 230px;
    max-width: none;
    text-align: left;
    margin-top: 98px;
  }
  .er-wi-visual:has(.er-timer-ring) .er-timer-copy-head {
    font-size: 33px;
    line-height: 40px;
  }
  .er-wi-visual:has(.er-timer-ring) .er-timer-copy-line {
    font-size: 19px;
    margin-top: 23px;
  }
}

/* Voice-guided visual routine (slide 01) — iPad Air portrait only (760–820px).
   Treat the wave + sound icon as ONE composition: fill the area below the
   heading and centre the whole group vertically in it (the wrapper is column +
   align/justify centre, and .er-voice-scene doesn't flex-grow, so it stays at
   content height and is centred). Capped at 820px so iPad Pro (834px) is
   untouched; scoped to slide 01 (.er-voice-scene) only. */
@media (min-width: 760px) and (max-width: 820px) {
  .er-wi-visual:has(.er-voice-scene) {
    flex: 1 1 auto;
    height: auto;
    margin-top: 0;
  }
  /* +10% wave ↔ sound-icon gap (15px → 16.5px) — subtle but visible. */
  .er-wi-visual:has(.er-voice-scene) .er-voice-scene {
    gap: 16.5px;
  }
}

/* Helpful Break Tips — iPad Air portrait only (760–820px). The max-width:820px
   rule stacks copy-over-phone; here we restore a two-column row (tip text LEFT,
   iPhone RIGHT) and centre the whole group. Scoped to .er-section:has(.er-break
   tip) so only this section is affected and the column-stack is overridden by
   specificity. Capped at 820px so iPad Pro (834px) is untouched. */
@media (min-width: 760px) and (max-width: 820px) {
  /* Two-column row, centred as one composition. The ~56px top margin ≈ the
     section's 70px bottom padding, so the group sits balanced between the intro
     paragraph and the bottom divider — not too high, not too low. */
  .er-section:has(.er-breaktip) .er-breaktip {
    flex-direction: row;
    align-items: center;
    justify-content: center;
    gap: 0;
    max-width: 700px;
    margin: 56px auto 0;
  }
  /* Left text block, vertically centred against the phone. gap:0 + a small
     negative margin tuck it ~20px into the iPhone block so the two read as ONE
     composition; z-index keeps the text on top. The text is centred in a 350px
     block, so the ~20px overlap falls in the block's side whitespace and never
     covers the visible phone body. */
  .er-section:has(.er-breaktip) .er-breaktip-copy {
    width: auto;
    max-width: 350px;
    flex: 0 1 auto;
    margin-right: -20px;
    position: relative;
    z-index: 1;
    /* Move ONLY the text block up ~90px and left ~16px (to the green-box spot)
       without shifting the phone — transform doesn't affect layout, so the
       iPhone stays exactly where it is. A slight overlap into the phone block's
       edge is preserved. */
    transform: translate(-16px, -90px);
  }
  /* Slightly larger tip text — subtle but visible (lead 21→24px, sub 17→18px). */
  .er-section:has(.er-breaktip) .er-breaktip-lead {
    font-size: 24px;
  }
  .er-section:has(.er-breaktip) .er-breaktip-sub {
    font-size: 18px;
  }
  /* iPhone on the right at its current size (343px), never cropped. */
  .er-section:has(.er-breaktip) .er-breaktip-phone {
    flex: 0 0 auto;
  }
  /* Balanced 2-line intro (avoids the lone "habit." on its own line):
     "…everyday tip" / "to help you build a calmer screen habit." */
  .er-section:has(.er-breaktip) .er-section-copy {
    max-width: 450px;
  }
}

/* ---- Slide 04: reaction focus exercises scene -------------------------------
   The transparent Station Jump Tracker Lottie (1920×1080, 16:9, connected points
   with moving red/green/blue/white targets) plays autoplay + loop with NO
   controls. Contain ('meet') scaling + a 16:9 aspect-ratio box render the full
   canvas with no crop and no stretch — uniform scale, nothing clipped. The width
   is capped so the 16:9 height fits the fixed slider stage with balanced top/
   bottom gaps; width:100% lets it scale down proportionally on mobile. */
.er-react {
  flex: 1 1 auto;
  min-width: 0;
  width: 100%;
  max-width: 760px;
  margin: 0 auto;
}

/* aspect-ratio matches the JSON canvas (1920/1080 = 16:9), so the height is
   always proportional to the width — no stretch/squash, no cropping. The JSON is
   transparent (no background layer), so it sits directly on the page with no
   blend/overlay workaround. */
.er-react-anim {
  width: 100%;
  margin: 0 auto;
  aspect-ratio: 1920 / 1080;
}

.er-react-lottie {
  width: 100%;
  height: 100%;
}

/* Desktop: give slide 04 a fixed-height media region (the post-heading stage
   space) and let the larger 16:9 wrapper sit centred inside it. Because the
   Station JSON is transparent with its dots/lines in the middle ~72% of the
   canvas, the wrapper can be a touch taller than the region — its empty top/
   bottom margins overflow harmlessly (nothing visible there, nothing clipped,
   layout height stays 487px so Break Tips never moves) while the dots themselves
   fill the central area and reach close to the arrows. align-items:center on
   .er-wi-visual keeps the wrapper vertically centred → balanced top/bottom. */
@media (min-width: 821px) {
  .er-wi-visual:has(.er-react) {
    margin-top: 13px;
    height: 383px;
  }
}

/* iPad Air / tablet portrait only (760–900px): the Station Jump Tracker dots
   sit in the central ~72% of their transparent 16:9 canvas, so they read small
   next to the Gabor slide whose grey rectangle fills its whole box. The box is
   already full stage width, so we scale the animation ~22% (its empty margins
   are transparent → no crop; the dots stay centred and clear of the arrows).
   Scoped to .er-react only — the Gabor slide and all other slides are untouched,
   and desktop (≥901px) + phone (<760px) keep their existing sizes. */
@media (min-width: 760px) and (max-width: 900px) {
  .er-react-anim {
    transform: scale(1.10);
    transform-origin: center center;
  }
}

/* ---- Slide 05: Gabor-style focus patterns scene ----------------------------
   The real Comp_gabor_lr_drift Lottie shown truthfully: the JSON's own grey
   background layer fills the 1920×1080 canvas, so the visible rectangle IS the
   genuine grey Gabor stimulus — NOT restyled onto navy, NOT recoloured, NO
   blend, NO glow, NO fake-CSS pattern. The preview is sized modestly (large
   enough to read, not huge) so a centred supporting caption fits below it inside
   the fixed stage. Contain ('meet') + 16:9 aspect-ratio box → uniform scale,
   no crop, no clip, no stretch. width:100% lets it scale down on mobile. */
.er-gabor {
  flex: 0 1 auto;
  min-width: 0;
  width: 100%;
  max-width: 630px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* aspect-ratio matches the JSON canvas (1920/1080 = 16:9) so the grey rectangle
   is always proportional — never stretched or cropped. No border-radius/overflow
   clip: the full rectangle stays visible, exactly like the reference. */
.er-gabor-anim {
  width: 100%;
  aspect-ratio: 1920 / 1080;
}

.er-gabor-lottie {
  width: 100%;
  height: 100%;
}

/* Supporting caption centred under the preview (neutral product copy). */
.er-gabor-cap {
  margin: 12px 0 0;
  text-align: center;
  color: var(--er-muted);
  font-size: 13px;
  line-height: 1.6;
  letter-spacing: .04em;
}

/* Desktop: centre the preview + caption column vertically in the stage so the
   top/bottom gaps stay balanced (scoped to slide 05; mobile keeps base). */
@media (min-width: 821px) {
  .er-wi-visual:has(.er-gabor) {
    margin-top: 11px;
  }
}

/* iPad Mini portrait only (~768px wide): the Gabor preview reads too large and
   too close to the horizontal edges. Trim it 10% (max-width 630px → 567px); it
   stays centred (margin:0 auto), height scales with the 16:9 aspect-ratio (no
   crop), and the caption is unchanged. Bounded 740–790px so iPad Air portrait
   (820px), desktop, phone, and the other slides are untouched. */
@media (min-width: 740px) and (max-width: 790px) {
  .er-gabor {
    max-width: 567px;
  }
}

/* ==========================================================================
   Helpful Break Tips — copy left, realistic iPhone right (reference layout).
   ========================================================================== */
/* Two-column composition measured from landing_page.svg. The column is 760px
   centred on the page (SVG x260→1020). Phone bbox 649→992 (W343, inset 28px
   from the right). Text block centred at x≈492 (left 47px, W370) and vertically
   centred against the phone — it reads beside the phone, never below it.
   Phone (H430) sets the row height; both children are absolutely placed so the
   short text block can sit centred over the taller phone. */
.er-breaktip {
  position: relative;
  max-width: 760px;
  min-height: 430px;
  margin: 48px auto 0;
}

.er-breaktip-copy {
  position: absolute;
  top: 35%;            /* SVG: text centre ≈65px above phone centre */
  left: 47px;          /* SVG: text left edge ≈307, column left ≈260 */
  transform: translateY(-50%);
  width: 370px;        /* SVG: text block W≈370 */
  text-align: center;
  margin: 0;
  padding: 0;
}

.er-breaktip-lead {
  margin: 0;
  color: #EDF1FD;
  font-size: clamp(21px, 2.4vw, 26px);
  font-weight: 400;            /* Inter Regular — not bold */
  line-height: 1.4;
}

.er-breaktip-sub {
  margin: 12px 0 0;
  color: #6687D3;
  /* Inter ExtraLight: no specific Inter weight file is loaded, so 200 requests
     ExtraLight and the browser falls back to the lightest available weight. */
  font-size: clamp(17px, 2vw, 21px);
  font-weight: 200;
  line-height: 1.5;
}

.er-breaktip-phone {
  position: absolute;
  top: 0;
  right: 28px;         /* SVG: phone right edge ≈992, column right ≈1020 */
}

.er-breaktip-phone img {
  display: block;
  width: 343px;        /* SVG: phone rect W=343 (1:1) */
  max-width: 100%;
  height: auto;
  /* Single subtle shadow that follows the transparent phone shape (down + right)
     — replaces the old big 80px/0.55 blur that read as a dark halo/glow. */
  filter: drop-shadow(15px 15px 20px rgba(0, 0, 0, 0.20));
}

/* ---- Privacy-friendly — product reassurance block (dark, on-brand) -------
   Replaces the old light-blue card with a calm, dark navy section that matches
   the rest of the page: blue section label + white headline (shared styles),
   two benefit columns, and a clean, flat Eye Routine icon on the right (no ring,
   no shadow). All selectors are scoped under .er-privacy so nothing else on the
   page is affected. */
/* Generous, premium vertical rhythm so the block reads as a full landing-page
   section (not a footer strip) between the app-preview section and the footer.
   Scoped to .er-privacy only — the shared .er-section padding is untouched. */
.er-section.er-privacy {
  padding-top: 108px;
  padding-bottom: 120px;
}

/* Keep the headline compact (stable left edge, stays on one line) so the wider
   two-column row beneath it clearly extends further right than the headline. */
.er-privacy h2 {
  max-width: 680px;
}

.er-privacy-grid {
  margin-top: 54px;
  display: grid;
  /* Three evenly-distributed zones spanning the FULL content width: left text
     at the left edge, middle text centred, icon at the right edge. Equal 1fr
     tracks + per-item justify-self (rules below) do the distribution, so the
     left→middle gap and the middle→icon gap read visually similar. */
  grid-template-columns: minmax(220px, 1fr) minmax(260px, 1fr) minmax(150px, 1fr);
  align-items: center;
  column-gap: 24px;
  row-gap: 36px;
}

/* Place each block within its zone: left text → left edge, middle text →
   centre, icon → right edge. */
.er-privacy-grid > .er-privacy-col:nth-child(1) { justify-self: start; }
.er-privacy-grid > .er-privacy-col:nth-child(2) { justify-self: center; }

.er-privacy-col-title {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  font-size: 13px;
  font-weight: 700;               /* Inter Bold */
  letter-spacing: .12em;
  text-transform: uppercase;
}

.er-privacy-col-title--dont { color: #fff; }
.er-privacy-col-title--get  { color: var(--er-blue); }   /* #4F8DF6 */

.er-privacy-mark {
  display: block;
  flex: none;
  width: 18px;
  height: auto;
  opacity: .9;                    /* present but not dominant */
}

.er-privacy-list {
  margin: 18px 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  row-gap: 13px;
}

.er-privacy-list li {
  color: var(--er-muted);         /* #A8AFCE */
  font-weight: 400;               /* Inter Regular */
  font-size: 15px;
  line-height: 1.5;
}

/* Right-hand product visual: the Eye Routine icon shown cleanly (no orbit ring),
   pinned to the right edge of the row and vertically centred against the text. */
.er-privacy-visual {
  justify-self: end;
  align-self: center;
}

.er-privacy-orbit {
  display: grid;
  place-items: center;
  /* No ring / orbit / stroke / glow disc — just a clean centred wrapper so the
     product icon reads naturally instead of like a badge. */
}

.er-privacy-icon {
  display: block;
  /* Clean, flat icon — no shadow, glow, ring, filter, crop, mask, or object-fit.
     Uses the original full Eye Routine icon PNG at its natural appearance. */
  width: 150px;
  height: 150px;
}

.er-privacy-note {
  margin: 48px 0 0;
  max-width: 760px;
  color: var(--er-muted);
  font-size: 14.5px;
  line-height: 1.7;
}

.er-privacy-link {
  color: var(--er-blue);
  font-weight: 700;
}

.er-privacy-link:hover {
  color: #79A9F9;
}

/* Tablet / mobile: stack the two columns, drop the icon below them (smaller,
   centred). No horizontal overflow, full list readability. */
@media (max-width: 820px) {
  .er-privacy-grid {
    grid-template-columns: 1fr 1fr;
    column-gap: 28px;
    row-gap: 34px;
  }
  .er-privacy-visual {
    grid-column: 1 / -1;
    justify-self: center;
    padding-left: 0;
  }
}

@media (max-width: 560px) {
  .er-privacy-grid {
    grid-template-columns: 1fr;
    row-gap: 30px;
  }
  .er-privacy-icon { width: 132px; height: 132px; }
}

/* Privacy-Friendly — small + medium mobile (≤430px: iPhone SE + XR). In the single-column layout the
   base rule centres the 2nd column (WHAT YOU GET) while the 1st (WHAT WE DON'T
   DO) is left-aligned, which reads inconsistent. Left-align the 2nd column to
   match the first so both blocks share the same left edge. */
@media (max-width: 430px) {
  .er-privacy-grid > .er-privacy-col:nth-child(2) { justify-self: start; }

  /* Spacing rhythm on iPhone SE:
     • list → next block gaps are already equal (the single-column grid row-gap).
     • icon → privacy copy = headline → first block: the grid's top gap is 54px,
       so set the note's top gap to 54px (was 48px).
     • privacy copy → footer divider = section top divider → label: the section
       padding-top is 108px, so match the bottom padding to 108px (was 120px). */
  .er-privacy-note { margin-top: 54px; }
  .er-section.er-privacy { padding-bottom: 108px; }
}

/* PRIVACY-FRIENDLY — iPad Air portrait only (760–820px). The max-width:820px
   rule above puts the two text columns on row 1 and drops the icon to a centred
   row 2 (which makes the grid tall and pushes the policy copy down toward the
   footer). Here we restore a single 3-column ROW — left text / middle text /
   icon on the right — so the note (a sibling already below the grid) sits right
   under the row, inside the privacy section. Placed after the 820/560 rules so
   it wins for 760–820px; capped at 820px so iPad Pro (834px) is untouched. */
@media (min-width: 760px) and (max-width: 820px) {
  .er-privacy-grid {
    grid-template-columns: minmax(180px, 1fr) minmax(210px, 1fr) minmax(140px, auto);
    align-items: center;
    column-gap: 28px;
    row-gap: 0;
  }
  /* Icon back in the right column of the SAME row (not spanning/below). */
  .er-privacy-visual {
    grid-column: auto;
    justify-self: end;
  }
  /* Nudge WHAT YOU GET left (centre → start) so noticeably more of it (~30%)
     sits under the headline; left/right gaps stay roughly balanced and the icon
     column is unaffected. */
  .er-privacy-grid > .er-privacy-col:nth-child(2) {
    justify-self: start;
  }
  /* Clearly more breathing room above the policy copy (48px → 80px) so it
     separates from the row but still belongs to the privacy section (the 120px
     section bottom padding keeps it well clear of the footer). */
  .er-privacy-note {
    margin-top: 80px;
  }
}

/* ---- Product screenshots: horizontal carousel ---------------------------
   Prepared portrait phone screenshots in one horizontal, scroll-snapping row.
   The <img> keeps its natural phone proportions (width:100%; height:auto) so
   nothing is stretched or cropped. ~3 visible on desktop, ~2 tablet, ~1 mobile
   (see responsive overrides). Swipe/trackpad scrolling + snap are CSS-only;
   the prev/next arrows use a small amount of JavaScript. */
.er-carousel-wrap {
  --er-gutter: 52px;
  position: relative;
  margin-top: 12px;
  /* side gutters reserve space so the arrows sit OUTSIDE the screenshot row;
     the edge fades align to the same gutter so they hug the card cut-offs */
  padding: 0 var(--er-gutter);
}

.er-carousel {
  display: flex;
  gap: 20px;
  /* vertical padding gives the card shadow room (the horizontal-scroll
     container would otherwise clip it) */
  padding: 6px 2px 16px;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-padding-left: 2px;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
  /* Scrollbar fully hidden (Firefox / legacy IE) — scrolling still works */
  scrollbar-width: none;
  -ms-overflow-style: none;
}

/* Scrollbar fully hidden (WebKit / Blink) */
.er-carousel::-webkit-scrollbar {
  display: none;
  width: 0;
  height: 0;
}

/* ---- Edge fades ---------------------------------------------------------- */
.er-fade {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 60px;
  z-index: 2;
  pointer-events: none; /* do not block swipe/scroll or the arrows */
}

.er-fade-left {
  left: var(--er-gutter);
  background: linear-gradient(to right, var(--er-bg), rgba(6, 10, 34, 0));
}

.er-fade-right {
  right: var(--er-gutter);
  background: linear-gradient(to left, var(--er-bg), rgba(6, 10, 34, 0));
}

/* ---- Carousel arrows (web-style chevrons, sit OUTSIDE the screenshots) --- */
.er-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 3; /* above the edge fades */
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 999px;
  background: rgba(10, 14, 42, 0.45);
  color: rgba(207, 224, 255, 0.85);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  transition: background .2s ease, color .2s ease, border-color .2s ease;
}

.er-arrow span {
  display: block;
  margin-top: -2px; /* optically centre the chevron glyph */
}

.er-arrow:hover {
  background: rgba(22, 30, 74, 0.70);
  color: #fff;
  border-color: rgba(255, 255, 255, 0.22);
}

/* placed in the wrap's side gutters → clear of every phone screenshot */
.er-arrow-prev { left: 6px; }
.er-arrow-next { right: 6px; }

.er-shot {
  margin: 0;
  /* ~3 screenshots visible at once on desktop (two 20px gaps) */
  flex: 0 0 auto;
  width: calc((100% - 40px) / 3);
  scroll-snap-align: center;
  border-radius: 22px;
  overflow: hidden;
  border: 1px solid var(--er-line);
  background: var(--er-bg-2);
  /* very subtle bottom shadow only — no heavy dark block under the phone */
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.22);
  /* Premium showcase: side cards sit slightly smaller and softer; the
     centred card (.is-active, set by JS) comes forward. transform: scale
     is visual only, so phone proportions, snap and layout are unchanged. */
  transform: scale(0.9);
  transform-origin: center center;
  opacity: 0.7;
  transition: transform .35s ease, opacity .35s ease, box-shadow .35s ease;
}

.er-shot.is-active {
  transform: scale(1);
  opacity: 1;
  /* Primary focused card: outline becomes a slightly brighter, clearer brand
     blue (low opacity, still dark-premium — not neon) vs the dim white side
     borders, plus a very soft blue glow. Black depth softened from 0.28 → 0.20
     so there's no harsh bottom shadow. Border width unchanged (no layout jump). */
  border-color: rgba(143, 181, 255, 0.20);
  box-shadow:
    0 8px 22px rgba(0, 0, 0, 0.20),
    0 0 26px rgba(59, 130, 246, 0.10);
}

/* <picture> wraps each screenshot <img> (WebP source + PNG fallback). picture
   defaults to display:inline, so make it block to keep the exact prior layout. */
.er-shot picture {
  display: block;
}
.er-shot img {
  display: block;
  width: 100%;
  height: auto;
}

@media (prefers-reduced-motion: reduce) {
  .er-carousel {
    scroll-behavior: auto;
  }
  .er-shot {
    transition: none;
  }
}

/* ==========================================================================
   Dark product header (LOCAL DRAFT — Eye Routine pages only)
   --------------------------------------------------------------------------
   Re-skins the shared .site-header to the Eye Routine dark navy identity.
   Scoped by .er-header (on the <header>) and .er-body (on the <body>) so the
   APPSTAR homepage header stays white and unchanged. Positioning is left to
   the shared CSS, so the header keeps its sticky behaviour (top:0, z-index).
   ========================================================================== */

/* Dark page canvas so the sticky header never flashes white during overscroll
   / rubber-band scrolling (applied on the dark product page only). */
.er-body {
  background: var(--er-bg);
}

/* Opaque dark navy header with a subtle gradient that echoes the product
   hero (a soft blue bloom toward the top-right over the navy base). The
   gradient is painted on the sticky header element itself, so it is fully
   opaque — page content scrolls cleanly underneath, and because the header
   stays pinned the gradient never shifts, jumps or flashes during scroll. */
.er-header.site-header {
  background:
    radial-gradient(150% 320% at 88% -180%, rgba(79, 141, 246, 0.20), transparent 60%),
    linear-gradient(180deg, #0A1031, var(--er-bg));
  border-bottom: 1px solid var(--er-line-soft);
}

/* White APPSTAR logo on the dark header is served as a real asset
   (apps/eye-routine/assets/appstar-white-logo.svg — the brand "White version"
   with the colour star + white wordmark), so no CSS colour treatment is
   needed here. */

/* Nav link states (dark header): inactive softer white, active full white.
   Active item is marked aria-current="page" on each Eye Routine page. Subtle —
   colour only, no underline/weight change, so there's no layout shift. */
.er-header .nav-links {
  color: rgba(255, 255, 255, 0.60);
}

.er-header .nav-links a:hover {
  color: rgba(255, 255, 255, 0.92);
}

.er-header .nav-links a[aria-current="page"] {
  color: #fff;
}

/* Mobile hamburger bars → white on the dark header */
.er-header .menu-mark span {
  background: #fff;
}

/* Mobile full-screen menu → dark themed to match the product pages */
.er-header .mobile-menu-overlay {
  background: var(--er-bg);
  border-top-color: var(--er-line-soft);
}

.er-header .mobile-menu-content a {
  color: rgba(255, 255, 255, 0.60);
  border-bottom-color: var(--er-line-soft);
  /* Lighter than the heavy shared base (clamp(32–42px)/700) so the links don't
     compete with the APPSTAR logo: ~15% smaller + one weight step down. Same
     font family, padding (tap area), dividers and colours are kept. Scoped to
     .er-header so the APPSTAR popup is unaffected; applies on all phone widths. */
  font-size: clamp(27px, 7.6vw, 35px);
  font-weight: 600;
}

.er-header .mobile-menu-content a[aria-current="page"] {
  color: #fff;
}

/* Menu button: keep the keyboard focus ring (:focus-visible) but drop the
   persistent outline after a mouse/touch click. Keyboard accessibility stays. */
.er-header .mobile-menu-button:focus:not(:focus-visible) {
  outline: none;
}

/* ==========================================================================
   Dark product footer (LOCAL DRAFT — Eye Routine pages only)
   --------------------------------------------------------------------------
   Re-skins the shared .site-footer to dark navy. Scoped by .er-footer on the
   <footer> so the APPSTAR homepage footer stays white and unchanged. Legal
   company text is unchanged — only colours are restyled.
   ========================================================================== */
.er-footer.site-footer {
  background: var(--er-bg);
  /* Single subtle divider above the footer (1px, 8% white) — like the APPSTAR
     footer. Shows on all layouts; the dark --line-soft would be invisible here. */
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}

.er-footer .footer-inner {
  color: var(--er-muted);
}

.er-footer .footer-legal {
  color: var(--er-muted);
}

.er-footer .footer-links a {
  color: rgba(255, 255, 255, 0.60);
}

.er-footer .footer-links a:hover {
  color: rgba(255, 255, 255, 0.92);
}

/* Active footer link — same feeling as the header nav active state (full white,
   colour only, no underline/weight change → no layout shift). Set per page with
   aria-current="page" on the current section's footer link, so on the landing
   page neither Support nor Privacy is active. */
.er-footer .footer-links a[aria-current="page"] {
  color: #fff;
}

/* ==========================================================================
   Eye Routine privacy page — dark product background with the legal copy in a
   clean white card. Scoped to .er-legal-page / .er-legal-card, which are used
   ONLY on apps/eye-routine/privacy/. The legal text keeps the shared light-page
   colours (dark headings, grey body, APPSTAR-blue links), which already read
   well on white. No product-page element uses these classes, so it is unaffected.
   ========================================================================== */
.er-legal-card {
  max-width: 780px;
  margin: 0;
  background: #FFFFFF;
  border: 1px solid #E5EAF5;
  border-radius: 24px;
  padding: clamp(28px, 5vw, 64px);
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.35);
}

/* ---- Responsive ---------------------------------------------------------- */
@media (max-width: 820px) {
  .er-hero-layout {
    grid-template-columns: 1fr;
    gap: 28px;
    text-align: left;
  }
  /* stacked: text first, mascot below, left-aligned with the text */
  .er-hero-mascot {
    justify-content: flex-start;
  }
  /* What's Inside slider on mobile: slides size to their stacked content; the
     track height is the tallest slide, so switching still never reflows. */
  .er-wi-slider {
    padding: 0 40px;
  }
  /* Smaller, subtler side fades on mobile (aligned to the 40px gutter). */
  .er-wi-slider::before { left: 40px; width: 44px; }
  .er-wi-slider::after { right: 40px; width: 44px; }
  .er-wi-slide {
    min-height: 0;
  }
  .er-wi-visual {
    flex-direction: column;
    gap: 22px;
  }
  .er-slide-wave {
    width: 100%;
    max-width: 320px;
  }
  /* Slide 02 stacks ring over copy — centre the copy block when stacked. */
  .er-timer-scene {
    flex-direction: column;
    align-items: center;
    gap: 22px;
  }
  .er-timer-copy {
    width: auto;
    max-width: 320px;
    text-align: center;
  }
  /* Break Tips: drop the absolute two-column composition and stack copy/phone */
  .er-breaktip {
    position: static;
    min-height: 0;
    max-width: 420px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 30px;
  }
  .er-breaktip-copy {
    position: static;
    transform: none;
    top: auto;
    left: auto;
    width: 100%;
    max-width: 420px;
  }
  .er-breaktip-phone {
    position: static;
    right: auto;
  }
  /* Tablet: ~2 screenshots visible */
  .er-shot {
    width: calc((100% - 20px) / 2);
  }
}


@media (max-width: 640px) {
  .er-hero {
    padding: 56px 0 52px;
  }
  .er-app-icon {
    width: 104px;
    height: 104px;
    border-radius: 24px;
  }
  .er-mascot {
    width: 200px;
  }
  .er-section {
    padding: 54px 0;
  }
  .er-hero-copy {
    font-size: 16.5px;
  }
  /* Mobile: one centred screenshot is the focus, with a sliver of the next
     peeking to signal the row scrolls. Arrows are hidden here (the gutters
     would crowd a phone) — users swipe instead. Edge fades stay, now hugging
     the screen edges (gutter → 0). */
  .er-carousel-wrap {
    --er-gutter: 0px;
  }
  .er-carousel {
    gap: 14px;
  }
  .er-shot {
    width: 82%;
  }
  .er-fade {
    width: 40px;
  }
  .er-arrow {
    display: none;
  }
}

/* ==========================================================================
   HERO — iPad Air / tablet portrait only (768–1024px).
   Placed last so it overrides the generic max-width:820px stacking rule within
   the 768–820 overlap. Desktop (≥1040px, where .er-sub-break shows) and phone
   (<768px) are untouched. Only the hero is affected here. */
@media (min-width: 768px) and (max-width: 1024px) {
  /* Two columns: a controlled ~460px text column + the mascot filling the rest,
     vertically centred — so the mascot stays on the RIGHT and never drops below
     the text on iPad Air portrait. */
  .er-hero-layout {
    grid-template-columns: minmax(0, 460px) minmax(0, 1fr);
    gap: 32px;
    align-items: center;
    text-align: left;
  }

  /* Larger mascot than the stacked tablet version (260px); fills its column up
     to a calm cap, never cropped (aspect-ratio + overflow stay intact). */
  .er-hero-mascot {
    justify-content: center;
  }
  .er-mascot {
    /* ~12% smaller than the previous tablet size for more right-side breathing
       room (was width:100% / max-width:340px). */
    width: 88%;
    max-width: 299px;
  }

  /* Force the 3-line headline split (routines, / screen breaks and / focus
     exercises.) and size it to fit comfortably inside the ~460px text column. */
  .er-sub-break,
  .er-sub-break-tablet {
    display: inline;
  }
  .er-hero-copy {
    font-size: 30px;
    line-height: 1.14;
  }

  /* Keep the body paragraph within the text column so it never widens the row
     or pushes the mascot down. */
  .er-hero-sub {
    max-width: 460px;
  }
}

/* Small + medium mobile (≤430px: iPhone SE, XR, Pixel…): the hero mascot is a
   full-mascot Lottie (face + pupils) whose pupils are scroll-driven (see the JS).
   The static upward-gaze SVG (.er-mascot-se) is used ONLY as the no-JS /
   reduced-motion fallback (replacing the straight-eye fallback) and is hidden once
   the Lottie is live (.is-animated). Scoped to ≤430px → tablet / iPad / desktop
   unaffected. */
.er-mascot-se { display: none; }   /* hidden everywhere by default */

@media (max-width: 430px) {
  .er-mascot-se {
    display: block;
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
  }
  /* Swap the straight-eye fallback for the upward-gaze one (no-JS state only). */
  .er-mascot-fallback { display: none; }
  /* Once the Lottie is live, hide the static fallback. */
  .er-mascot.is-animated .er-mascot-se { display: none; }
  /* The scroll Lottie already includes the face/accents/smile, so hide the
     separate accents SVG, and let the 212×92 Lottie fill the mascot box exactly
     (override the old eyes-only Lottie offsets). */
  .er-mascot.is-animated .er-mascot-accents { display: none; }
  .er-mascot-lottie {
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
  }

  /* Centre the mascot under the (left-aligned) hero copy — overrides the generic
     max-width:820px flex-start. Horizontal only; does not affect the Lottie
     scroll logic (it reads the mascot's vertical position). */
  .er-hero-mascot {
    justify-content: center;
  }

  /* Body copy rhythm: keep the full wording but let the browser balance the
     wrap so the final line is no longer an isolated short line. CSS-only;
     gracefully ignored on browsers without text-wrap support. */
  .er-hero-sub {
    text-wrap: pretty;
  }
}

/* WHAT'S INSIDE intro copy: the shorter iPhone SE variant is hidden by default;
   the full copy shows on every other width (swapped at ≤390px below). Slide
   TITLES and SUBTITLES are handled in JS (single node), not CSS-toggled spans. */
.er-inside-copy-se { display: none; }

/* WHAT'S INSIDE slider — small + medium mobile (≤430px: iPhone SE + XR). Halve the
   side fade overlays so the slide visual reads wider, and stack the slide number
   above the centred title so "05" never overlaps long titles (e.g. Gabor-style
   focus patterns). Scoped to ≤430px → tablet / iPad / desktop unaffected. */
@media (max-width: 430px) {
  /* Shorter, less-repetitive WHAT'S INSIDE intro copy on SE. (Slide titles and
     subtitles are swapped in JS — see applyTitles().) */
  .er-inside-copy-full { display: none; }
  .er-inside-copy-se { display: inline; }

  /* One-line, centred titles: tighten the wide tracking just enough that the
     longest short title ("Voice-Guided Routine") stays on a single line at the
     SE width, while keeping the font premium (not shrunk). */
  .er-slide-title { letter-spacing: .02em; }

  /* One shared visual-stage rhythm: the same gap below the heading on every
     slide, so visuals sit at a consistent optical position (each keeps its own
     size). Timer stays in its mobile stacked composition from the ≤820 rules. */
  /* Treat each slide's visual as ONE grouped block, vertically centred in the
     usable area below the subtitle: the wrapper grows to fill that area and its
     single grouped child (wave+icon / timer+text / letters / dots / Gabor+caption)
     is centred and must NOT stretch. Same rhythm on all 5 slides → consistent
     breathing room below the subtitle and above the bottom divider. */
  .er-wi-visual { margin-top: 26px; flex: 1 1 auto; }
  .er-wi-visual > * { flex: 0 0 auto; }
  /* Fade ONLY inside the slider's 40px side gutters. Move those gutters from the
     slider onto each SLIDE (so the centred content size is unchanged: 335 − 80 =
     255px, exactly as before), let the scroll viewport span the full width, and
     mask only its outer 40px. Slides now scroll THROUGH the gutters and fade
     there, while the central content/animation stays fully clean — no hard edges. */
  .er-wi-slider::before,
  .er-wi-slider::after { display: none; }
  .er-wi-slider { padding-left: 0; padding-right: 0; }
  .er-wi-slide  { padding-left: 40px; padding-right: 40px; }
  .er-wi-stage {
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 40px, #000 calc(100% - 40px), transparent 100%);
            mask-image: linear-gradient(to right, transparent 0, #000 40px, #000 calc(100% - 40px), transparent 100%);
  }

  /* Slide numbers: visible but SUBTLE on iPhone SE — small + low opacity, stacked
     centred ABOVE the title (override the base absolute position so it can never
     overlap the title). Quiet slide context, not competing with the title. */
  .er-wi-slider .er-slide-num {
    position: static;
    display: block;
    left: auto;
    top: auto;
    font-size: 12px;
    opacity: .45;
    margin: 0 0 4px;
  }

  /* Slider arrows: visible + usable on iPhone SE (override the ≤640px display:none).
     `top` is a % of .er-wi-slider (position:relative); its height is constant (the
     stage stretches every slide to the tallest), so a fixed % = the SAME Y on all
     5 slides, no drift. 36% lands in the EMPTY zone above the centred animation
     (between the subtitle and the animation top) — moved up clearly from the old
     52% which sat down by the animation. Arrows stay in the side gutters (x≈6px),
     above the fade (z-index 3) and outside the masked stage, never clipped, and
     clear of the centred visual horizontally. 36px hit area kept. */
  .er-wi-slider .er-arrow {
    display: inline-flex !important;
    top: 36%;
    /* Light treatment: chevron only — no disc, border, ring, or shadow. */
    background: transparent;
    border: 0;
    box-shadow: none;
    opacity: .65;                      /* lighter again (was .72, .8 before) — plain chevron */
    color: rgba(225, 235, 255, 0.95);  /* keep the chevron bright under the opacity */
    /* Larger, comfortable touch target (was 36px) without reducing it. */
    width: 44px;
    height: 44px;
  }
  /* Keep the (now-transparent, larger) hit box centred on the SAME chevron x as
     before, so the visible arrow doesn't shift: was 36px @ left/right:6 (centre
     24px) → now 44px @ left/right:2 (centre 24px). Vertical is unchanged (top:36%
     + translateY(-50%)). */
  .er-wi-slider .er-arrow-prev { left: 2px; }
  .er-wi-slider .er-arrow-next { right: 2px; }
  /* No disc on tap/hover either. */
  .er-wi-slider .er-arrow:hover {
    background: transparent;
    border-color: transparent;
  }

  /* Slide 01 — wave ~+11% (transform only; sound icon stays below, group centred,
     hero mascot logic untouched). */
  .er-voicewave { transform: scale(1.11); transform-origin: center; }

  /* Slide 04 — dots/targets ~+13% so they fill the visual stage better (centred,
     not cropped; arrows are hidden on SE so no overlap). */
  .er-react-anim { transform: scale(1.13); transform-origin: center center; }

  /* Slide 05 — hide the Gabor caption on SE to drop the heavy text block below
     the animation (animation + grey background kept). */
  .er-gabor-cap { display: none; }
}

/* A LOOK AT THE APP — small + medium mobile (≤430px) baseline. The screenshot phone reads too
   large/heavy here, so shrink each carousel shot ~30% (the ≤640px mobile width
   is 82% → 82 × 0.70 ≈ 57%). Width-only: .er-shot img is width:100%/height:auto,
   so the phone scales proportionally (no crop, no distortion) and the carousel
   keeps the active shot centred. Does NOT touch the Helpful Break Tips mockup
   (.er-breaktip-phone) or any wider breakpoint. */
@media (max-width: 430px) {
  .er-shot { width: 57%; }

  /* The ≤640px rule `.er-arrow { display:none }` hides ALL arrows on mobile; the
     WHAT'S INSIDE arrows are re-enabled under .er-wi-slider, but these carousel
     arrows were never re-enabled — so they were invisible on iPhone SE. Show
     them here as plain chevrons (same clean treatment as WHAT'S INSIDE): no
     disc/border/shadow, ~.58 opacity, 44px hit area. The base `top:50%` +
     `translateY(-50%)` keeps them vertically centred on the screenshot row, and
     `left/right:6px` flanks the centred shot. z-index 3 sits above the fades and
     the wrap isn't overflow-clipped, so nothing else hides them. */
  .er-carousel-wrap .er-arrow {
    display: inline-flex !important;
    background: transparent;
    border: 0;
    box-shadow: none;
    opacity: .58;
    color: rgba(225, 235, 255, 0.95);
    width: 44px;
    height: 44px;
  }
  .er-carousel-wrap .er-arrow:hover {
    background: transparent;
    border-color: transparent;
  }
}

/* A LOOK AT THE APP — medium mobile (iPhone XR ~414px, Pixel, etc.) only.
   The shared ≤430px rule above shrinks the screenshot to 57% (the SE 30% cut).
   On the wider XR viewport that's more than needed, so use a gentler reduction
   here (82% → 67% ≈ 18%). SE (≤390px) is excluded by min-width:391 and keeps
   57%. Aspect ratio preserved (img is width:100%/height:auto); stays centred. */
@media (min-width: 391px) and (max-width: 430px) {
  .er-shot { width: 67%; }

  /* iPhone XR intentional line rhythm: enable the controlled breaks and the hero
     lead's after-"routines," split. One text version only (these are bare <br>s,
     not duplicated copy). SE (≤390) and tablet/desktop keep their own wrapping. */
  .er-xr-br { display: inline; }
  .er-sub-break { display: inline; }

  /* Helpful Break Tips: trim the iPhone mockup ~11% (343px → 305px) so it's less
     dominant on XR. Width-only; height:auto keeps the aspect ratio (no crop), and
     the stacked column keeps it centred. */
  .er-breaktip-phone img { width: 305px; }

  /* Privacy-Friendly: trim the icon ~10% (132px → 119px) so the section reads a
     touch shorter. Centred as before; still no shadow/glow/ring. */
  .er-privacy-icon { width: 119px; height: 119px; }
}
