/* ═══════════════════════════════════════════════════════
   MOBILE (≤920px) — the OLD hero reel: PLAY, Next pills, the vocab strip,
   the window that resizes per screen. Off in ring mode (index.html turns this
   <link> to media="not all"; lantern-hero-ring-phone.css takes over).
   Shared phone rules (Install, the wall, the send button) stay in
   lantern-hero-mobile.css.
   ═══════════════════════════════════════════════════════ */
/* the ring's own layers: shown only where the ring files are on */
.car-sides,
.car-back,
.car-frame { display: none; }
#hero .sh-page { display: none; }
#hero .hero-copy-sh { display: none; }
@media (max-width: 920px) {
  /* un-hide stage (lantern-v3.css sets display:none at 920px); the transform
     also neutralises every desktop per-phase stage slide */
  #hero .hero-stage {
    display: block !important;
    grid-column: 1 !important;
    grid-row: 2 !important;
    height: auto !important;
    margin-right: 0 !important;
    overflow: visible !important;
    transform: none !important;
  }
  body.hero-p2 #hero .hero-stage,
  body.hero-p3 #hero .hero-stage,
  body.hero-imm #hero .hero-stage,
  body.hero-p5 #hero .hero-stage { margin-top: 13px !important; }

  /* two-row hero: copy (auto) above, stage (remaining) below */
  #hero .hero-inner {
    grid-template-columns: 1fr !important;
    grid-template-rows: 134px auto 1fr !important;  /* copy (fixed) · browser · spacer */
    align-items: start !important;
    gap: var(--m-vgap) !important;
    height: 100% !important;
  }
  /* Ukrainian Immerse title needs three lines: that screen alone gets a 22px
     taller copy row (the browser drops by the same 22px only there). */
  html.lang-uk body.hero-imm #hero .hero-inner { grid-template-rows: 156px auto 1fr !important; }

  /* all phase copies: row 1, bottom-aligned so browser Y stays constant */
  #hero .hero-copy,
  #hero .hero-copy-p2,
  #hero .hero-copy-p5 {
    grid-column: 1 !important;
    grid-row: 1 !important;
    align-self: end !important;
    /* width:100%, NOT 90vw — the column is 100vw-48px (#hero's padding), and a
       wider 1fr child inflates the track and biases every centred descendant right */
    width: 100% !important; max-width: none !important;
    padding: 0;
    min-width: 0;
  }

  /* the same -12px settle every phase's copy carries, so top→title gap is identical */
  body.hero-p2 #hero .hero-copy-p2 { transform: translateY(-12px) !important; }

  /* phase titles wrap to their authored two lines (the <br> shows), filling the
     134px copy row uniformly so browser-Y stays constant */
  #hero .hero-copy-p2 h2, #hero .hero-copy-p5 h2 {
    display: block !important; font-weight: 700;
  }
  #hero .hero-copy-p2 h2 br,
  #hero .hero-copy-p5 h2 br { display: inline !important; }
  /* Ukrainian Immerse: the authored <br> would orphan one word — wrap naturally */
  html.lang-uk #hero .hero-copy-imm h2 br { display: none !important; }
  /* phase title+subhead left-aligned to match the Home h1; the browser stays centred */
  #hero .hero-copy-p2, #hero .hero-copy-imm, #hero .hero-copy-p5 { text-align: left !important; }
  #hero .hero-copy-imm .p2-sub { margin-left: 0 !important; margin-right: 0 !important; }
  /* the active phase copy is TOP-aligned so the top→title gap is identical on
     every screen; browser-Y is driven by the fixed 134px row, not the copy */
  body.hero-p2 #hero .hero-copy-p2,
  body.hero-imm #hero .hero-copy-imm, body.hero-p5 #hero .hero-copy-p5 { align-self: start !important; }

  /* compact Home title: .ln spans collapse to inline, vw-scaled font */
  #hero .hero-copy h1 { display: block !important; font-size: clamp(15px, 4.6vw, 30px) !important; line-height: 1.1; margin-bottom: 0; white-space: nowrap; }
  #hero .hero-copy h1 .ln,
  #hero .hero-copy h1 .ln > .i { display: inline !important; transform: none !important; overflow: visible; }
  /* subhead under each headline, clamped to 3 lines so browser + cards still fit */
  #hero .hero-copy .hsub {
    display: -webkit-box !important; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden;
    margin: var(--m-vgap) auto 0 !important; max-width: none;   /* fill the copy column, matching the browser width */
    font-size: var(--fs-read) !important; line-height: 1.45;
  }

  /* -- HOME: the real reading browser is the mobile Home screen. Home breaks out
     of the fixed 134px copy row, which exists only to hold browser-Y constant
     across P2-P5. -- */
  body:not(.hero-p2):not(.hero-p3):not(.hero-imm):not(.hero-p5):not(.hero-simp) #hero .hero-stage {
    opacity: 1; pointer-events: auto;
    /* +6px on the 12px grid gap so sub→browser matches the title→sub rhythm */
    margin-top: 6px !important;
  }
  body:not(.hero-p2):not(.hero-p3):not(.hero-imm):not(.hero-p5):not(.hero-simp) #hero .hero-inner {
    grid-template-rows: auto auto auto !important;  /* copy · browser · CTA dock; no 1fr spacer */
    /* no 120px Next-pill reserve: mobile Home shows no pill, and the reserve
       pushed the one-screen hero past the fold */
    padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 8px) !important;
    /* split the slack above/below the stack; `safe` falls back to start on a short
       phone instead of pushing the H1 up under the fixed topbar */
    align-content: safe center !important;
    /* the fixed topbar sits inside the centring box — reserve its height so the
       gaps above and below the stack come out equal */
    padding-top: var(--m-topbar) !important;
  }
  body:not(.hero-p2):not(.hero-p3):not(.hero-imm):not(.hero-p5):not(.hero-simp) #hero .hero-copy {
    align-self: start !important;
  }
  #hero .hero-copy { text-align: left; }

  /* no wrapping card — Home copy sits directly on the page */
  .hh-card { width: 100%; }
  /* h1.hh-h1 / .hsub.hh-sub out-specify the compact .hero-copy h1 / .hsub rules
     above: Home's title and sub read in full, left-aligned.
     margin-top 44px: a zone break from the topbar wordmark, larger than the
     H1→sub gap, so the headline groups with its subhead. */
  #hero .hero-copy h1.hh-h1 { display: block !important; text-align: left; white-space: normal !important; font-size: clamp(30px, 9.2vw, 36px) !important; line-height: 1.14 !important; letter-spacing: -.02em; margin: 44px 0 0 !important; }
  /* Ukrainian a step smaller so line 1 («Покращуй англійську,») fits down to 320px */
  html.lang-uk #hero .hero-copy h1.hh-h1 { font-size: clamp(21px, 7.3vw, 29px) !important; }
  /* once PLAY hides the logo (home-live), drop the zone break: uniform top→title */
  body.home-live #hero .hero-copy h1.hh-h1 { margin-top: 2px !important; }
  /* 17px/1.45 like every phase's .p2-sub; balance evens the three-line rag */
  #hero .hero-copy .hsub.hh-sub { display: block !important; -webkit-line-clamp: unset !important; overflow: visible !important; text-align: left; max-width: none !important; margin: 10px 0 0 !important; font-size: var(--fs-read) !important; line-height: 1.45; text-wrap: balance; }

  /* SHORT VIEWPORTS (SE, or any phone with the address bar showing): shrink the
     H1 zone break so the Send CTA stays above the fold; the JS window cap does the
     rest. Height-based on purpose. */
  @media (max-height: 740px) {
    /* 20px still reads as a zone break: it stays larger than the ~21px H1→sub ink gap */
    #hero .hero-copy h1.hh-h1 { margin-top: 20px !important; }
  }

  /* the phone shows no ▶ caption: the button says it, and the dock keeps one
     thing to press per row. Desktop keeps its caption (lantern-hero.css). */
  .hh-playlabel { display: none !important; }

  .hh-play { width: 66px; height: 66px; }
  .hh-play svg { width: 24px; height: 24px; }
  .hh-play::before { inset: -13px; }

  /* CTA dock — note + "Send to yourself", in grid row 3 right under the browser
     (reparented into .hero-inner in JS). Static, not fixed: one block with the browser. */
  .hh-dock {
    grid-column: 1; grid-row: 3;
    align-self: start; justify-self: center;
    /* 100% of the padded column, capped — a vw width overflowed the track off-centre */
    width: 100%; max-width: 360px; margin-top: 8px;
    flex-direction: column; align-items: center; gap: 12px;
    display: none;
  }
  .hh-dock .m-hcta-note { margin: 0; }
  /* shown only on the Home screen */
  body:not(.hero-p2):not(.hero-p3):not(.hero-imm):not(.hero-p5):not(.hero-simp) .hh-dock {
    display: flex !important;
  }
  /* …and fades out once PLAY fires. Faded, not display:none, so row 3 keeps its
     height and the browser doesn't jump. */
  body.home-live .hh-dock {
    opacity: 0; visibility: hidden; pointer-events: none;
    transition: opacity .32s ease, visibility 0s linear .32s;
  }

  /* every phase keeps its subhead: the short data-m copy is written for 2 lines at
     17px, which the fixed 134px copy row is sized for — the clamp keeps a longer
     locale from stretching it to 3 */
  #hero .hero-copy-p2 .p2-sub,
  #hero .hero-copy-p5 .p2-sub {
    display: -webkit-box !important; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
    margin: var(--m-vgap) auto 0 !important; max-width: none;   /* fill the copy column, matching the browser width */
    font-size: var(--fs-read) !important; line-height: 1.45;
  }
  #hero .hero-copy-p2 h2,
  #hero .hero-copy-p5 h2,
  #hero .hero-copy-imm h2 { font-size: clamp(24px, 8vw, 31px) !important; margin-bottom: 0 !important; line-height: 1.12 !important; }
  /* the Ukrainian Immerse title is the longest — a step smaller */
  html.lang-uk #hero .hero-copy-imm h2 { font-size: clamp(22px, 7.2vw, 28px) !important; }
  /* no per-screen eyebrow on mobile */
  #hero .hero-copy-p2 .p2-eyebrow,
  #hero .hero-copy-imm .p2-eyebrow,
  #hero .hero-copy-p5 .p2-eyebrow { display: none !important; }

  /* exit: vertical nudge instead of desktop horizontal slide */
  body.hero-p2 #hero .hero-copy { transform: translateY(-12px) !important; }
  body.hero-p3 #hero .hero-copy-p2 { transform: translateY(-12px) !important; }

  /* hero: don't vertical-centre — let copy + stage stack from top. */
  #hero { align-items: flex-start !important; padding: 0 var(--gut, 20px) 60px !important; }
  /* reel screens (hero-p2 stays on <body> from Simplify on) own the whole viewport,
     or the fixed bottom cluster rides over the next section on a tall phone */
  body.hero-p2 #hero { min-height: 100vh !important; min-height: 100svh !important; }
  #hero .hero-inner {
    width: 100% !important;
    box-sizing: border-box !important;
    align-self: stretch !important;
    min-height: calc(85vh - var(--nav, 56px));
    /* svh = viewport with the browser toolbar shown (the safe floor); 85% so
       short Home content leaves no dead gap before the next section */
    min-height: calc(85svh - var(--nav, 56px));
    padding: calc(var(--nav, 56px) - 8px) 0 calc(env(safe-area-inset-bottom,0px) + 120px) !important;
  }

  /* float: lantern-v3.css sets display:none at 920px — un-hide, in normal flow */
  #hero .float { display: block !important; position: relative !important; top: auto !important; left: auto !important; z-index: auto !important; }
  #hero .floatwrap { animation: none !important; transform: none !important; filter: none !important; }

  /* browser: flat, full-width, no 3D perspective, no bottom crop */
  #hero .browser,
  body.hero-p2 #hero .browser,
  body.hero-p3 #hero .browser {
    position: relative !important;
    /* fills the padded column (100vw-48px) — see .hero-copy above */
    width: 100% !important; max-width: none !important; min-height: 0 !important;
    transform: none !important; clip-path: none !important;
    /* off-tier on purpose: fake browser-chrome shadow, not a UI elevation tier */
    box-shadow: 0 10px 28px -8px rgba(var(--ink-rgb),.18) !important;
  }

  /* browser page. Its children are position:absolute, so .page never grows on its
     own: lantern-mobile-window.js sets an inline min-height per screen — the CSS
     values are the pre-JS fallback, and the transition makes the morph. The article
     reads left-aligned like a real page. */
  #hero .browser .page { font-size: 14px !important; line-height: 1.6 !important; padding: 16px !important; min-height: 330px !important; transition: min-height 1s var(--ease-out) 0.12s; text-align: left !important; }
  /* url pill: -2px height (1px off top+bottom padding) */
  #hero .browser .url { padding: 3px 11px !important; }
  /* Home fallback: one short paragraph, cropped to content */
  body.at-hero:not(.hero-p2):not(.hero-p3):not(.hero-imm):not(.hero-p5):not(.hero-simp) #hero .browser .page {
    min-height: 250px !important;
  }
  /* bottom padding > top: the article is bottom-anchored, so the heavier bottom
     makes top and bottom read equal */
  #hero .browser .page-en,
  #hero .browser .ex-page { padding: 8px 20px 26px !important; }
  #hero .browser .page > p:first-child,
  #hero .browser .page h3 { font-size: 15px !important; }
  #hero .browser .page-en > p:first-child { margin-bottom: 11px !important; }
  /* the article is taller than the window, so something clips: from Simplify on
     (body.hero-p2) every layer anchors to the BOTTOM so each phase's payoff stays
     whole and the article's title clips off the top. Home keeps the top-anchor —
     its payoff is the title. */
  body.hero-p2 #hero .browser .page-en,
  body.hero-p2 #hero .browser .ex-page,
  body.hero-p2 #hero .browser .imm-page { top: auto !important; bottom: 0 !important; }

  /* base highlight geometry on mobile; only the demo-SAVED words go blue */
  #hero .browser .hl { border-radius: var(--r-xs); padding: 0 2px; }
  #hero .browser .hl.saved { background: #e3edfd; color: #2f6fd6; }
  /* resting cue: the same two lemmas as RESTING_MARKS (lantern-hero-words.js), static, so the demo ADDS
     the other two. :not(.saved) — this selector outranks .hl.saved; the padding
     matches .hl above so nothing reflows when PLAY drops these rules. */
  body:not(.hero-p2):not(.hero-p3):not(.hero-imm):not(.hero-p5):not(.hero-simp):not(.home-live) #hero .browser .page-en > p .hl[data-w="devoted"]:not(.saved),
  body:not(.hero-p2):not(.hero-p3):not(.hero-imm):not(.hero-p5):not(.hero-simp):not(.home-live) #hero .browser .page-en > p .hl[data-w="legacy"]:not(.saved) {
    background: #bfdbfe; color: var(--ink, #1a1714); border-radius: var(--r-xs); padding: 0 2px;
  }

  /* ── Simplify's scroll cue: screen 2 keeps screen 1's frame (isSimplify in
     lantern-mobile-window.js) and the article slides up inside it — a scroll, so a
     scrollbar shows it. ≤920px only: desktop's window really does grow. */
  #hero .browser .hh-sbar {
    display: block; position: absolute; top: 0; right: 0; bottom: 0; width: 10px;
    background: rgba(var(--ink-rgb), .045);
    opacity: 0; pointer-events: none; z-index: 4;
  }
  /* the up-arrow a real scrollbar parks at the top of its track */
  #hero .browser .hh-sbar s {
    position: absolute; left: 50%; top: 4px; transform: translateX(-50%);
    width: 0; height: 0;
    border-left: 3.5px solid transparent; border-right: 3.5px solid transparent;
    border-bottom: 4px solid rgba(var(--ink-rgb), .34);
  }
  /* thumb:track ratio ≈ how much of the article the frozen frame shows */
  #hero .browser .hh-sbar i {
    position: absolute; left: 2px; right: 2px; top: 14px; height: 58%;
    border-radius: 3px; background: rgba(var(--ink-rgb), .34);
  }
  /* travel matches .hero-extra's reveal (1s var(--ease-out) .12s); `top`, not
     transform, so the thumb lands on the track floor at any window size */
  body.hero-p2 #hero .browser .hh-sbar { animation: hhSbarShow 1s ease 0.12s 1 both; }
  body.hero-p2 #hero .browser .hh-sbar i { animation: hhSbarRide 1s var(--ease-out) 0.12s 1 both; }
  /* no fade-out: the page stays scrolled, so the bar stays parked */
  @keyframes hhSbarShow { 0% { opacity: 0 } 12%, 100% { opacity: 1 } }
  @keyframes hhSbarRide { from { top: 14px } to { top: calc(100% - 58% - 3px) } }
  @media (prefers-reduced-motion: reduce) {
    body.hero-p2 #hero .browser .hh-sbar,
    body.hero-p2 #hero .browser .hh-sbar i { animation: none; }
  }

  /* word cards on mobile — row 1 = EN word (sized inline by mCardSpec()), row 2 =
     translation + practice ring; no CEFR badge. `width` transitions because
     layoutMobileRow() re-specs every card when a 5th word is saved. */
  #hero .hw-card .wordcard.wordcard-m {
    padding: 9px 11px !important; border-radius: var(--r-lg) !important;
    transition: width .32s var(--ease-out), transform .3s cubic-bezier(.2,.7,.2,1), box-shadow .3s;
  }
  #hero .hw-card .wordcard-m .w { line-height: 1.05 !important; }
  #hero .hw-card .wordcard-m .wbot { display: flex !important; align-items: center; justify-content: space-between; gap: 8px; margin-top: 6px !important; }
  /* .wm-ol — a neighbour overlaps the right edge: pack ring + gloss hard LEFT so
     the covered strip is whitespace, not a half-eaten ring */
  #hero .hw-card .wordcard-m.wm-ol .wbot { flex-direction: row-reverse; justify-content: flex-end; }
  /* no nowrap/ellipsis on purpose: the gloss wraps, and layoutMobileRow() measures
     the real card height */
  #hero .hw-card .wordcard-m .tr { font-size: var(--fs-eyebrow) !important; margin-top: 0 !important; min-width: 0; }
  #hero .hw-card .wordcard-m .wd-prog { width: 20px !important; height: 20px !important; }
  /* the two smaller tiers (M_TIERS in lantern-hero-words.js): ring and gloss step
     down together. .wm-sm = 100px, .wm-xs = 84px (last resort, SE). */
  #hero .hw-card .wordcard.wordcard-m.wm-sm,
  #hero .hw-card .wordcard.wordcard-m.wm-xs { padding: 7px 9px !important; border-radius: var(--r-md) !important; }
  #hero .hw-card .wordcard-m.wm-sm .wbot { gap: 5px; margin-top: 5px !important; }
  #hero .hw-card .wordcard-m.wm-xs .wbot { gap: 4px; margin-top: 5px !important; }
  #hero .hw-card .wordcard-m.wm-sm .tr { font-size: var(--fs-caption) !important; }
  #hero .hw-card .wordcard-m.wm-sm .wd-prog { width: 18px !important; height: 18px !important; }
  #hero .hw-card .wordcard-m.wm-xs .tr { font-size: var(--fs-micro) !important; }
  #hero .hw-card .wordcard-m.wm-xs .wd-prog { width: 15px !important; height: 15px !important; }
  /* cramped tiers only: clip the gloss instead of letting it run under the ring */
  #hero .hw-card .wordcard-m.wm-sm .tr,
  #hero .hw-card .wordcard-m.wm-xs .tr { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

  /* word deck: compact right-rail — visible P2 onwards */
  #worddeck { position: fixed; top: 68px; right: 12px; width: 110px; }
  .wd-label { font-size: 9px; margin-bottom: 5px; }
  .wd-card { padding: 5px 9px; border-radius: var(--r-md); margin-top: -17px; }
  /* the small cards carry the gloss, not the level badge */
  .wd-card .wd-tr { display: block !important; }
  .wd-card .wd-side .cefr-b { display: none !important; }

  /* word popup: compact on mobile */
  .popup.hw-popup { width: min(256px, calc(100vw - 32px)) !important; padding: 12px 14px !important; }
  .popup.hw-popup .w { font-size: var(--fs-read) !important; }
  .popup.hw-popup hr { margin: 8px 0 !important; }
  .popup.hw-popup .def { font-size: var(--fs-sm) !important; line-height: 1.4 !important; }
  .popup.hw-popup .ex { display: none !important; }
  .popup.hw-popup .save { margin-top: 9px !important; }
  .popup.hw-popup .savebtn { padding: 9px 14px !important; font-size: var(--fs-sm) !important; }

  /* P2-P5: worddeck = horizontal-scroll vocab strip pinned near the bottom, with a
     right edge-fade as the "more" cue. pan-x + overscroll containment keep a
     sideways pan from fighting the page scroll. */
  body.hero-p2 #worddeck {
    position: fixed !important;
    bottom: calc(env(safe-area-inset-bottom, 0px) + 20px) !important;
    left: var(--gut, 20px) !important;
    right: var(--gut, 20px) !important;
    top: auto !important;
    width: auto !important;
    transform: none !important;
    transition: top var(--dur-3) var(--ease-out), bottom var(--dur-3) var(--ease-out);
  }
  body.hero-p2 #worddeck.show { display: block !important; }
  body.hero-p2 .wd-label {
    display: block !important; margin: 0 0 6px 2px !important;
    font-family: var(--mono); font-size: 9px; letter-spacing: .14em; text-transform: uppercase;
    color: var(--amber-deep); opacity: .9;
  }
  body.hero-p2 #wd-stack {
    display: flex !important; flex-direction: row !important; flex-wrap: nowrap !important;
    justify-content: flex-start !important; gap: 5px !important;
    overflow-x: auto !important; overflow-y: visible !important;
    scroll-behavior: smooth; scrollbar-width: none;
    touch-action: pan-x; overscroll-behavior-x: contain;
    -webkit-mask: linear-gradient(90deg, #000 88%, transparent);
            mask: linear-gradient(90deg, #000 88%, transparent);
    padding: 3px 14px 4px 0;
  }
  body.hero-p2 #wd-stack::-webkit-scrollbar { display: none; }
  /* chip = word + gloss, width fits the word (62-132px). The desktop progress ring
     (.wd-side) is dropped; progress is an underline via ::after instead. */
  body.hero-p2 .wd-card {
    flex: 0 0 auto !important;
    width: auto !important; min-width: 62px !important; max-width: 132px !important;
    margin: 0 !important; padding: 7px 10px 9px !important; gap: 0 !important;
    overflow: hidden !important;
    box-shadow: var(--shadow-1) !important;
  }
  /* entrance: scale in place — desktop's translateX would overlap the next chip */
  body.hero-p2 .wd-card:not(.in):not(.preset) {
    transform: scale(0.85) !important;
  }
  body.hero-p2 .wd-card .wd-side { display: none !important; }
  body.hero-p2 .wd-card .wd-main { width: 100% !important; }
  body.hero-p2 .wd-card .wd-w {
    font-size: var(--fs-eyebrow) !important; line-height: 1.1 !important;
    white-space: nowrap !important; overflow: hidden !important; text-overflow: ellipsis !important;
    display: block !important;
  }
  body.hero-p2 .wd-card .wd-tr {
    font-size: var(--fs-micro) !important; line-height: 1.15 !important; margin-top: 2px !important;
    white-space: nowrap !important; overflow: hidden !important; text-overflow: ellipsis !important;
  }
  /* progress underline: amber fill sized to --wd-prog-frac (set by lantern-v3.js
     setProg) over a faint track; background-size animates the growth */
  body.hero-p2 .wd-card::after {
    content: ''; position: absolute; left: 10px; right: 10px; bottom: 4px; height: 2px;
    border-radius: 2px;
    background: linear-gradient(90deg, var(--amber, #F07010) 0, var(--amber, #F07010) 100%)
                  left center / calc(var(--wd-prog-frac, 0) * 100%) 100% no-repeat,
                rgba(var(--ink-rgb),.12);
    transition: background-size var(--dur-4) var(--ease-out);
  }
  /* the in-flight mastery clone draws its own bar */
  body.hero-p2 .wd-card.mr-fly::after { display: none !important; }
  /* upright row: drop the desktop rail's rotation scatter */
  body.hero-p2 #worddeck .wd-card.in {
    transform: none !important; animation: none !important;
  }

  /* scroll-cue arrow: hidden */
  .scroll-cue { display: none; }

  body.hero-p5 #hero .hx-hud { position: relative; bottom: auto; left: auto; right: auto; }
  /* P5: let menus + bubbles overflow above the browser frame */
  body.hero-p5 #hero .browser { overflow: visible !important; }
  body.hero-p5 #hero .browser .page { overflow: visible !important; }

  /* ── P1 word demo on mobile: un-gate the cards + the demo "cursor" ──
     lantern-v3.css hides .hw-card/.hw-cursor under 1000px; the mobile
     demo (lantern-hero-words.js MOBILE mode) needs both back */
  .hw-card { display: block !important; }
  /* rested mobile cards glide when the row re-centres (centreMobileRow in
     lantern-hero-words.js); transform/opacity keep their fly-in timing */
  #hero .hw-card { transition: transform .45s var(--ease-out), opacity .35s ease, left .42s var(--ease-out), top .42s var(--ease-out); }
  /* rested cards breathe with a gentle ~3px float, desynced by per-card --cbdur.
     The left/top glide is re-stated because lantern-v3.css's
     `#hero .hw-card.rested` transition out-specifies the rule above — without it
     settled cards teleport when the row re-centres. No transform here: it belongs
     to card-bob-m, and the fold-to-deck FLIP writes its own inline transition. */
  #hero .hw-card.rested {
    animation: card-bob-m var(--cbdur, 4.6s) ease-in-out infinite !important;
    transition: opacity .35s ease, left .42s var(--ease-out), top .42s var(--ease-out);
  }
  @keyframes card-bob-m {
    0%   { transform: translate3d(0, 0, 0); }
    33%  { transform: translate3d(.5px, -3px, 0); }
    66%  { transform: translate3d(-.5px, -1.5px, 0); }
    100% { transform: translate3d(0, 0, 0); }
  }
  .hw-cursor { display: block !important; }
  /* the pointer is a fingertip, not a mouse arrow */
  .hw-cursor .hwc-ico svg { display: none; }
  .hw-cursor .hwc-ico::before {
    content: ""; position: absolute; left: -11px; top: -11px;
    width: 22px; height: 22px; border-radius: var(--r-circle);
    background: rgba(var(--ink-rgb),.30);
    border: 1.5px solid rgba(255,255,255,.9);
    box-shadow: var(--shadow-1);
  }

}
