/* ─── Ironi — marketing landing page (Ironclad) ────────────────────
   Consumes the shared tokens from base.css (:root). Desktop mirrors the
   approved design; smaller breakpoints stack it into a phone-friendly page. */

#landing {
  --lp-muted: #a7adb7;
  --lp-faint: #949ba6;
  --accent-ink-text: #ccff00;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-ui);
  /* clip, not hidden: a hidden box is still a scroll container, so jumping to
     a section or focusing a control could slide the whole page sideways by
     however far the hero glow overhangs. hidden stays as the fallback. */
  overflow-x: hidden;
  overflow-x: clip;
  min-height: 100vh;
}
#landing .mono { font-family: var(--font-mono); }
#landing .volt { color: var(--accent-ink-text); }
#landing .good { color: var(--good); }
#landing .dim { color: var(--lp-muted); }
/* Base anchor colour at ZERO-id specificity (:where strips the #landing id) so
   the button classes below (.lp-cta-sm, .lp-band-btn, …) actually win. With the
   old `#landing a` rule the id beat the classes: volt CTAs rendered white text
   and the CTA-band button went black-on-black. */
:where(#landing) a { color: var(--text); text-decoration: none; }
#landing h1, #landing h2, #landing h3 { margin: 0; }

/* The scroll progress bar was removed from the markup, but its declaration
   block was left behind with no selector in front of it — three orphan
   declarations and a closing brace, which is why this file's braces did not
   balance and why the minified twin carried a stray `scaleX(0); }`. Nothing
   in public/ renders a progress bar any more, so the block is gone. */

/* ── Nav (fixed; gains a glass background once you scroll) ──
   Fixed, not sticky: #landing's overflow-x hidden breaks position: sticky.
   #landing gets matching top padding so the hero doesn't start underneath. */
#landing { padding-top: calc(60px + var(--safe-top)); }
/* Anchor landing: every section that can be an anchor target needs the same
   clearance under the FIXED nav, not just the ones built from `.lp-section`.
   `#features`, `#log-sets` and `#progress` are `.lp-fscreen` sections and were
   missing it, so `/#features` from the nav or the footer scrolled the heading
   underneath the bar. Targeting `section[id]` covers those, the feature screens
   added since, and any future one, so the rule cannot fall out of date again. */
.lp-section, .lp-hero, #landing section[id] { scroll-margin-top: calc(70px + var(--safe-top)); }
.lp-nav {
  position: fixed; top: 0; left: 0; right: 0; z-index: 50;
  padding: calc(14px + var(--safe-top)) 0 14px;
  border-bottom: 1px solid transparent;
  transition: background 0.35s ease, border-color 0.35s ease;
}
.lp-nav.scrolled {
  background: rgba(12, 13, 16, 0.78);
  -webkit-backdrop-filter: blur(16px) saturate(1.4);
  backdrop-filter: blur(16px) saturate(1.4);
  border-bottom-color: var(--line);
}
.lp-nav-inner {
  display: flex; align-items: center; gap: 40px;
  max-width: 1280px; margin: 0 auto; padding: 0 56px;
}
.lp-brand { display: flex; align-items: center; gap: 11px; }
.lp-mono {
  width: 32px; height: 32px; border-radius: 9px;
  display: block; object-fit: cover;
  border: 1px solid var(--line); flex: none;
}
.lp-word { font: 700 16px var(--font-ui); letter-spacing: -0.2px; white-space: nowrap; }
/* The gap gives way before the labels do: locales with long nav words (ru, de)
   otherwise squeezed the CTA until its own label clipped. */
.lp-nav-links { display: flex; gap: clamp(17px, 2.1vw, 30px); margin-left: 20px; }
.lp-nav-links a { font: 500 14px var(--font-ui); color: var(--lp-muted); }
.lp-nav-links a:hover { color: var(--text); }
/* Active page (set by scripts/sync-chrome.js + build-blog.js) */
.lp-nav-links a.is-active { color: var(--accent-ink-text); position: relative; }
.lp-nav-links a.is-active::after { content: ''; position: absolute; left: 0; right: 0; bottom: -6px; height: 2px; border-radius: 2px; background: var(--accent); }
/* When the JS slider is live it parks under the active link, so the static bar
   would be a second one. The scroll helpers add .nav-slider-on to hand the
   indicator over; no-JS visitors never get the class and keep the static bar. */
.lp-nav-links.nav-slider-on a.is-active::after { content: none; }
.lp-nav-spacer { flex: 1; }
.lp-login { font: 600 14px var(--font-ui); color: var(--lp-muted); white-space: nowrap; }
.lp-login:hover { color: var(--text); }
.lp-login-drawer { display: none; }
/* Outlined, not filled: the hero's store card is the page's one filled action,
   and two accent fills on one screen cancel each other out. Apple does the
   same — quiet nav, loud hero.
   One nav control family: this button, the theme toggle, the language picker
   and the hamburger all sit on the same faint wash, behind the same hairline
   border, at the same 12px radius and the same 40px height. The CTA is the
   loud one through full-strength ink and a heavier weight, never through a
   different plate. */
.lp-cta-sm {
  display: inline-flex; align-items: center; justify-content: center;
  flex: none; height: 40px; box-sizing: border-box;
  background: rgba(255, 255, 255, 0.04); color: var(--text);
  border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 12px;
  padding: 0 18px; font: 700 14px var(--font-ui); white-space: nowrap;
}
.lp-cta-sm:hover { border-color: rgba(255, 255, 255, 0.22); background: rgba(var(--accent-rgb), .08); }

/* ── Mobile nav menu (hamburger) ──
   .lp-menu / .lp-menu-row are display:contents on desktop, so the wrapped
   links + lang picker + Log in participate in the bar's flex layout exactly
   as before. ≤1000px they become a slide-down panel under the fixed bar. */
.lp-menu, .lp-menu-row { display: contents; }
/* The drawer's own close button only exists once the menu is a panel. */
.lp-menu-close { display: none; }
.lp-burger {
  display: none; align-items: center; justify-content: center;
  width: 44px; height: 44px; flex: none; padding: 0;
  background: rgba(255,255,255,0.04); color: var(--text);
  border: 1px solid rgba(255,255,255,0.1); border-radius: 12px;
  cursor: pointer; transition: border-color 0.15s ease;
}
.lp-burger:hover { border-color: rgba(255,255,255,0.22); }
.lp-burger .i-close { display: none; }
.lp-nav.menu-open .lp-burger .i-menu { display: none; }
.lp-nav.menu-open .lp-burger .i-close { display: block; }

/* ── Hero ── */
.lp-hero {
  position: relative; max-width: 1280px; margin: 0 auto; padding: 64px 56px 56px;
  display: grid; grid-template-columns: 1.05fr 0.95fr; gap: 56px; align-items: center;
}
.lp-hero-glow {
  position: absolute; left: -120px; top: -80px; width: 520px; height: 520px;
  border-radius: 50%; background: radial-gradient(circle, rgba(var(--accent-rgb),.12), transparent 65%);
  pointer-events: none;
}
.lp-hero-glow2 {
  position: absolute; right: -160px; top: 32%; width: 460px; height: 460px;
  border-radius: 50%; background: radial-gradient(circle, rgba(127,212,255,.07), transparent 65%);
  pointer-events: none;
}
.lp-hero-grid {
  position: absolute; inset: -60px 0 0; pointer-events: none;
  background-image:
    linear-gradient(rgba(255,255,255,.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.045) 1px, transparent 1px);
  background-size: 56px 56px;
  -webkit-mask-image: radial-gradient(ellipse 80% 70% at 60% 0%, #000, transparent 72%);
  mask-image: radial-gradient(ellipse 80% 70% at 60% 0%, #000, transparent 72%);
}
.lp-fdot {
  position: absolute; width: 5px; height: 5px; border-radius: 50%;
  background: var(--accent); opacity: 0.3; pointer-events: none;
}
.lp-hero-copy { position: relative; }
/* Hero type scale is modelled on Apple's product pages: a 64px/1.06 headline
   with 19px support copy at desktop, stepping down at each breakpoint. */
#landing .lp-hero h1 { font: 700 64px/1.06 var(--font-ui); letter-spacing: -2.6px; margin: 0; }
.lp-hero p {
  font: 500 19px/1.55 var(--font-ui); color: var(--lp-muted); max-width: 520px; margin: 26px 0 0;
  /* Two even lines on a phone instead of a one-word orphan on the last line. */
  text-wrap: balance;
}
/* Third line, quieter still: who this is for, not what it does. Compound
   selector so it beats the plain `.lp-hero p` rule above regardless of
   source order. */
.lp-hero p.lp-hero-audience {
  margin-top: 10px; color: var(--lp-faint); font: 500 16px/1.5 var(--font-ui);
  max-width: 460px;
}
.lp-btn-primary {
  background: var(--accent); color: var(--ink); border-radius: 13px;
  padding: 13px 26px; font: 700 15px var(--font-ui);
  box-shadow: var(--shadow-cta);
}
.lp-btn-primary:hover { background: var(--accent-pressed); }
.lp-btn-ghost {
  border: 1px solid var(--line2); border-radius: 13px; padding: 13px 24px;
  font: 600 14px var(--font-ui); color: var(--text);
}
.lp-btn-ghost:hover { border-color: var(--text); }
/* The supplied store artwork is a matched 500:148 pair. Keep its full
   border and lettering visible at every breakpoint. */
.lp-store-row { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-top: 34px; }
.lp-store-row > a { flex: 0 1 auto; min-width: 0; }
.lp-hero-title-line { display: block; }
.lp-hero-title-line--accent { color: var(--accent); }
.lp-hero-track-icon { width: .95em; height: .68em; margin-left: .12em; vertical-align: -.02em; fill: currentColor; }
/* 48px tall (500x148 artwork), the size leading app sites use on desktop. */
.lp-store-row > :is(.lp-app-store-badge, .lp-play-badge) { width: 162px; }
.lp-band-actions > :is(.lp-app-store-badge, .lp-play-badge) { width: 162px; max-width: 100%; }
.lp-app-store-badge, .lp-play-badge {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px;
}
.lp-app-store-badge img, .lp-play-badge img { display: block; width: 100%; height: auto; }
.lp-app-store-badge:hover img, .lp-play-badge:hover img { filter: brightness(1.12); }
/* Quiet trust row under the two CTAs: three small facts, not a badge.
   Smaller and fainter than the audience line above the buttons so it never
   competes with them, and no rating stars, because we are not quoting a
   rating. Each beat carries its own themed glyph (dumbbell / clipboard-check
   / shield-check, all hand-drawn to the site's existing stroke language —
   viewBox 24, stroke-width 2, round caps/joins — since nothing matching
   already shipped anywhere on the page to reuse), so the row still reads as
   one consistent icon language while each icon backs its own fact instead of
   one glyph repeating three times.
   Beats separate with a hairline divider on one line (desktop, and mobile
   rows wide enough to hold two); the divider color drops to transparent at
   the mobile breakpoint below instead of being removed, so the layout box
   size never shifts and a wrap never leaves an orphan line poking out.
   margin-top matches .lp-store-row's own margin-top (34px) rather than a new
   number, so the gap under the CTAs reads at the same rhythm as the gap
   above them and the trust row reads as its own quiet block, not a fourth
   line hugging the buttons. */
.lp-hero p.lp-hero-proof {
  display: flex; align-items: center; flex-wrap: wrap; row-gap: 8px;
  max-width: none; margin-top: 34px;
  color: var(--lp-faint); font: 500 13px/1.4 var(--font-ui);
}
.lp-hero-proof-beat { display: inline-flex; align-items: center; gap: 6px; padding: 0 14px; border-left: 1px solid var(--line); }
.lp-hero-proof-beat:first-child { padding-left: 0; border-left: none; }
.lp-hero-proof-beat svg { width: 13px; height: 13px; flex: none; opacity: .8; }
.lp-hero-proof-n { color: var(--lp-muted); font-weight: 600; font-variant-numeric: tabular-nums; }
/* phone mock — --pp/--rx/--ry are scroll-parallax + cursor-tilt vars set from JS */
.lp-phone-wrap {
  position: relative; display: flex; justify-content: center;
  height: 644px; min-height: 644px;
  transform: perspective(900px) translateY(var(--pp, 0px))
             rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
  will-change: transform;
}
/* ── Device frame ──
   Modelled on a real iPhone Pro, measured off the owner's reference shot and
   held as ratios of the frame's outer width so both mocks scale identically:
     graphite band   1.6% of the width   (5px at 314)
     black bezel     2.2%                (7px)
     outer radius   17%                  (53px)
     screen radius   outer − band − bezel, so all three curves are concentric
     aspect          0.488, the device's own
   The band is a real gradient, not a flat ring: a transparent border filled by
   a border-box background layer, with the pure-black bezel painted as a
   padding-box layer on top of it. One element, two clips, no extra markup. */
.lp-phone {
  position: relative; z-index: 1; box-sizing: border-box;
  --frame-band: 5px;
  --frame-bezel: 7px;
  --frame-radius: 53px;
  width: 314px; max-width: 100%;
  border: var(--frame-band) solid transparent;
  padding: var(--frame-bezel);
  border-radius: var(--frame-radius);
  background:
    linear-gradient(#000, #000) padding-box,
    linear-gradient(160deg, #565a5f 0%, #2f3237 20%, #212326 46%, #34373c 68%,
                    #4d5158 86%, #232528 100%) border-box;
  /* The chamfer: a 1px rim brighter than the band itself is the whole reason a
     titanium edge reads as metal rather than as a painted stroke. Then the
     ambient cast under the device. */
  box-shadow: 0 0 0 1px rgba(255,255,255,.34), 0 58px 104px -30px rgba(0,0,0,.9),
              0 20px 46px -24px rgba(0,0,0,.72);
  animation: floaty 6s ease-in-out infinite;
  transform-style: preserve-3d;
}
/* Offsets are measured from the padding box, so the band's own thickness has
   to be added back for the buttons to clear it by a consistent 3px. */
.lp-side-controls {
  position: absolute; top: 20%; left: calc(-1 * (var(--frame-band) + 3px)); z-index: 0;
  display: flex; flex-direction: column; gap: 8px;
  pointer-events: none;
}
.lp-side-button {
  display: block; width: calc(var(--frame-band) + 3px); box-sizing: border-box;
  background: linear-gradient(90deg, #5b5f66, #34373c 55%, #212326);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.16), 0 1px 3px rgba(0,0,0,.6);
}
.lp-side-controls--left .lp-side-button { border-radius: 3px 0 0 3px; }
.lp-side-button--action { height: 22px; margin-bottom: 2px; }
.lp-side-button--volume { height: 38px; }
.lp-side-button--power {
  position: absolute; top: 28%; right: calc(-1 * (var(--frame-band) + 3px)); z-index: 0;
  height: 74px; border-radius: 0 3px 3px 0;
  background: linear-gradient(270deg, #5b5f66, #34373c 55%, #212326);
  pointer-events: none;
}
/* Fake 3D slab: two full-silhouette layers stacked behind the front face
   (~18px depth). Because each layer keeps the phone's rounded outline, the
   visible edge follows the corner CURVES too — a flat rotateY(-90deg) side
   wall couldn't cover the corners and left a gap there. Visible during the
   intro spin and as a thin continuous rim on desktop cursor tilt. */
/* inset is negative by the band width so the slabs match the OUTER silhouette,
   not the bezel opening. */
.lp-phone::before {
  content: ''; position: absolute; inset: calc(-1 * var(--frame-band));
  border-radius: inherit;
  background: #17191e;
  transform: translateZ(-9px);
}
.lp-phone::after {
  content: ''; position: absolute; inset: calc(-1 * var(--frame-band));
  border-radius: inherit;
  background: linear-gradient(160deg, #202329, #121316);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.05);
  transform: translateZ(-18px);
}
@keyframes floaty { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-10px); } }
.lp-screen {
  position: relative; z-index: 1;
  height: 620px; min-height: 620px;
  /* Concentric by construction: outer radius minus everything outside the
     glass, so the band, the bezel and the screen share one centre of curvature
     at every corner. overflow:hidden makes the screen content obey it too. */
  border-radius: calc(var(--frame-radius) - var(--frame-band) - var(--frame-bezel));
  overflow: hidden; background: var(--bg);
  display: flex; flex-direction: column;
  /* Faint glass edge: the one hint of depth a real screen has against its
     bezel, now that there is no notch doing that job visually. */
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.05);
}
/* No notch: a clean top edge, time on the left and signal/wifi/battery on
   the right, same two-column status row every real phone renders. */
.lp-status {
  display: flex; align-items: center; justify-content: space-between;
  height: 42px; box-sizing: border-box; padding: 7px 18px 5px;
  font: 600 12px var(--font-ui);
}
.lp-status .lp-time {
  font: 600 13px var(--font-mono);
  letter-spacing: .3px;
  font-variant-numeric: tabular-nums;
}
.lp-sig { display: inline-flex; align-items: center; gap: 6px; color: rgba(255,255,255,.92); }
.lp-sig .lp-cell { width: 17px; height: 11px; }
.lp-sig .lp-wifi { width: 16px; height: 12px; }
.lp-sig .lp-batt { width: 25px; height: 12px; }
.lp-appbar { padding: 6px 18px 0; display: flex; justify-content: space-between; align-items: center; font: 600 12px var(--font-ui); }
.lp-appbar .mono { font: 700 11px var(--font-mono); }
.lp-pips { padding: 12px 18px 0; display: flex; gap: 4px; }
.lp-pips i { flex: 1; height: 4px; border-radius: 2px; background: #2a2d34; }
.lp-pips i.on { flex: 2; background: var(--accent); }
.lp-exhead { padding: 16px 20px 0; }
.lp-exhead .mono { font: 400 10px var(--font-mono); }
.lp-exhead .lp-sets-done { margin-top: 8px; color: var(--lp-muted); }
.lp-exhead .ex { font: 700 22px var(--font-ui); letter-spacing: -0.5px; margin-top: 5px; }
.lp-target-chip {
  display: inline-flex; margin-top: 8px; padding: 5px 9px;
  border: 1px solid rgba(255,255,255,.1); border-radius: 999px;
  background: var(--panel); color: var(--lp-muted); font: 500 9px var(--font-mono);
}
.lp-sets { padding: 14px 16px 0; display: flex; flex-direction: column; gap: 8px; }
.lp-set.done {
  background: var(--panel); border-radius: 13px; padding: 11px 14px;
  display: flex; align-items: center; gap: 10px; color: var(--lp-muted);
}
.lp-set.done .chk {
  width: 20px; height: 20px; border-radius: 6px; background: var(--accent); color: var(--ink);
  display: flex; align-items: center; justify-content: center; font: 700 12px var(--font-ui);
}
.lp-set.done .val { margin-left: auto; font: 500 15px var(--font-mono); }
.lp-set.now {
  background: linear-gradient(150deg, #22252c, #15171b);
  border: 1.5px solid var(--accent); border-radius: 15px; padding: 14px;
}
.lp-set.now .lbl { font: 400 10px var(--font-mono); color: var(--accent-ink-text); }
.lp-coach-pill {
  display: inline-flex; align-items: center; gap: 6px; margin-top: 10px;
  padding: 6px 9px; border-radius: 999px;
  background: rgba(var(--accent-rgb),.1); color: var(--accent-ink-text);
  font: 600 9.5px var(--font-ui);
}
.lp-coach-pill svg { width: 13px; height: 13px; flex: none; }
.lp-lasttime { margin-top: 8px; color: var(--lp-muted); font: 400 9px var(--font-mono); }
.lp-steppers { display: flex; gap: 10px; margin-top: 10px; }
.lp-steppers .fld { flex: 1; background: var(--bg); border-radius: 11px; padding: 8px 0; text-align: center; }
.lp-steppers .t { font: 400 8px var(--font-mono); }
.lp-stepper-row { display: flex; align-items: center; gap: 4px; margin-top: 4px; padding: 0 4px; }
.lp-stepper-row .n { flex: 1; min-width: 0; }
.lp-stepbtn {
  width: 32px; height: 32px; border-radius: 10px;
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  background: #24272e; color: var(--lp-muted); font: 500 18px var(--font-mono);
}
.lp-steppers .n { font: 700 24px var(--font-mono); }
.lp-log {
  background: var(--accent); color: var(--ink); border-radius: 11px; padding: 12px;
  text-align: center; font: 700 14px var(--font-ui); margin-top: 10px;
}
.lp-set.next { display: flex; align-items: center; gap: 10px; padding: 10px 4px; opacity: .72; }
.lp-set.next .box {
  width: 18px; height: 18px; border: 1.5px solid var(--lp-muted);
  border-radius: 5px; flex: none;
}
.lp-set.next .mono { font-size: 9px; }
.lp-set.next .up { margin-left: auto; }

/* ── Sections ── */
.lp-section { max-width: 1280px; margin: 0 auto; padding: 90px 56px 40px; }
.lp-section--tight { padding-top: 40px; padding-bottom: 40px; }
.lp-head-center { text-align: center; max-width: 640px; margin: 0 auto; }
.lp-kicker { font: 600 11px var(--font-mono); color: var(--accent-ink-text); letter-spacing: 3px; }
.lp-head-center h2 { font: 700 38px/1.1 var(--font-ui); letter-spacing: -1.4px; margin: 16px 0 0; }

/* shared feature cards (still used by secondary public pages) */
.lp-feature-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-top: 56px; }
.lp-feature-grid.cols-3 { grid-template-columns: repeat(3, 1fr); }
.lp-feature {
  position: relative; overflow: hidden;
  background: var(--panel); border: 1px solid var(--line); border-radius: 22px;
  padding: 32px; min-height: 230px; display: flex; flex-direction: column;
  transition: transform 0.3s ease, border-color 0.3s ease;
}
.lp-feature::after {
  content: ''; position: absolute; inset: 0; pointer-events: none; opacity: 0;
  background: radial-gradient(420px circle at var(--mx, 50%) var(--my, 50%),
              rgba(var(--accent-rgb),.07), transparent 65%);
  transition: opacity 0.35s ease;
}
.lp-feature-head { display: flex; align-items: center; gap: 12px; }
.lp-feature .ic {
  flex: none; width: 38px; height: 38px; border-radius: 11px;
  display: flex; align-items: center; justify-content: center;
  transition: transform 0.3s ease;
}
.lp-feature .ic svg { width: 19px; height: 19px; }
.lp-feature h3 { font: 700 19px/1.25 var(--font-ui); letter-spacing: -0.3px; margin: 0; min-width: 0; }
.lp-feature p { font: 400 14px/1.6 var(--font-ui); color: var(--lp-muted); margin: 14px 0 0; }
.lp-feature-link { font: 600 13px var(--font-ui); color: var(--lp-muted); margin-top: 18px; transition: color 0.25s ease; }
@media (hover: hover) {
  .lp-feature:hover { transform: translateY(-4px); border-color: rgba(var(--accent-rgb),.28); }
  .lp-feature:hover::after { opacity: 1; }
  .lp-feature:hover .ic { transform: scale(1.08) rotate(-3deg); }
  .lp-feature:hover .lp-feature-link { color: var(--text); }
}
/* Mobile: stack the feature cards (the /about values grid used to force three
   squeezed columns via an inline style) and let each card hug its content. */
@media (max-width: 900px) {
  .lp-feature-grid, .lp-feature-grid.cols-3 { grid-template-columns: 1fr; gap: 14px; margin-top: 32px; }
  .lp-feature { min-height: 0; padding: 26px 22px; }
}

/* product feature bento */
/* ── Feature screens ─────────────────────────────────────────────────────────
   One feature per viewport: copy on one side, the cut-out photograph on the
   other, sides alternating down the page. The headline is display-size but
   LIGHT, and its second clause drops to --dim — scale and tone carry the
   emphasis, so there is no accent colour, no all-caps kicker, and no card or
   border around any of it. */
.lp-fscreen {
  max-width: 1280px; margin: 0 auto; padding: 40px 56px;
  min-height: calc(100svh - 60px);
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 88px; align-items: center;
}
/* Mirror: the photograph runs off the LEFT edge of the viewport so the hand
   reads as reaching in from outside the page. It is positioned against the
   section (max-width 1280, centred), so `50% - 50vw` lands exactly on the
   viewport edge at any width. Source order stays copy-then-photo, so the
   reading order is unchanged. */
/* The photo is pulled out of grid flow below (position: absolute, top: 0,
   bottom: 0, for the full-bleed edge crop), so it always renders at exactly
   this section's own height, and the grid container only has ONE in-flow
   track left: the copy column. An early fix pinned that track to `start` to
   kill an oversized gap before/after this section — but the real source of
   that gap was the base .lp-fscreen's viewport-height min-height, which is
   sized for a full phone mock, not this shorter hand shot: against that
   height the photo (object-fit: contain, bottom-anchored) rendered small and
   low with empty space above it, and pinning the copy to `start` only made
   the mismatch between the two obvious (copy pinned high, photo sitting
   low). Give the section its own min-height instead, sized to exactly the
   photo's rendered height at its own 42vw render width (1049x879 source, so
   height = width * 879/1049) — short enough to keep the same tight
   inter-section rhythm the `start` fix was chasing, and tall enough that the
   absolute photo box now fills it edge to edge with no letterboxing. With
   that, the base .lp-fscreen's align-items: center goes back to centring the
   copy against the photo's actual visual height, no override needed here. */
/* The gap above this section must match the page rhythm: neighbours meet at
   40px bottom padding + 112px top padding (see .lp-fscreen--wide). This
   section's own 40px top padding cannot grow without distorting the
   absolute-photo geometry above, so the missing 72px is margin instead. */
.lp-fscreen--flip { position: relative; min-height: calc(42vw * 879 / 1049); margin-top: 72px; }
.lp-fscreen--flip .lp-fscreen-copy { grid-column: 2; padding-left: 24px; }
.lp-fscreen--flip .lp-fscreen-photo {
  /* The shadow lives on the FIGURE and the mask on the IMG, deliberately.
     `filter` renders first and `mask` clips the result, so with both on one
     element the drop-shadow was sliced off flat at that element's box — which
     is the straight vertical edge that showed to the right of the phone.
     Split across two elements, the mask only feathers the artwork and the
     shadow is free to fall outside it. */
  filter: drop-shadow(54px 6px 58px rgba(0, 0, 0, 0.82));
  position: absolute; top: 0; bottom: 0;
  /* Narrower than half the viewport, and pulled off the left edge, so the shot
     reads smaller and leaves real air between it and the copy column. */
  left: calc(50% - 50vw); width: 42vw; margin: 0;
}
.lp-fscreen--flip .lp-fscreen-photo img {
  width: 100%; height: 100%; max-height: none;
  object-fit: contain;
  /* Bottom-anchored: the wrist is cropped straight in the source, so that cut
     has to land ON the screen edge. Floated in the middle it reads as a
     mistake; at the edge it reads as the arm continuing off-screen. */
  object-position: left bottom;
  /* Feather the two edges that meet the page: the left (where it runs off the
     viewport) and the bottom (where the wrist is cropped). Two masks combined
     with intersect, so only the corner is doubly faded. */
  -webkit-mask-image:
    linear-gradient(to right, transparent 0%, #000 11%),
    linear-gradient(to top, transparent 0%, #000 9%);
  -webkit-mask-composite: source-in;
  mask-image:
    linear-gradient(to right, transparent 0%, #000 11%),
    linear-gradient(to top, transparent 0%, #000 9%);
  mask-composite: intersect;
}
.lp-section-eyebrow {
  margin: 0 0 16px; color: var(--lp-muted);
  font: 400 21px/1.2 var(--font-ui); letter-spacing: -.2px;
}
#landing .lp-fscreen h2 {
  margin: 0; font: 400 48px/1.08 var(--font-ui); letter-spacing: -1.7px;
}
.lp-h2-quiet { color: var(--lp-muted); }
.lp-fscreen-copy p {
  max-width: 460px; margin: 20px 0 0; color: var(--lp-muted);
  font: 400 17px/1.6 var(--font-ui);
}
.lp-fscreen-copy .lp-quote { max-width: 520px; margin-top: 28px; }

/* ── Log sets ──────────────────────────────────────────────────────────────
   Second section, right after the hero, and the one place on the page that is
   neither a split nor a photograph. The hero above it is copy-left /
   phone-right; repeating that shape immediately underneath made the page feel
   like one idea told twice. So this screen is centred instead, and the visual
   is a WIDE LEDGER BAND rather than a device: the tracker's own set list laid
   out at desk width, wider than the copy above it, no phone frame anywhere.
   The band earns the width — at ≥861px the live set becomes a single
   horizontal line that runs label → last time → reps → weight → Log, so the
   reader's eye lands on the Log button at the end of the sentence the heading
   just made. Below that it folds back to the stacked phone shape.
   It is still the honest app layout: the rows reuse the exact classes the
   hero phone mock draws (.lp-target-chip/.lp-set/.lp-steppers/.lp-log), only
   re-scaled for a surface that is read from a metre away instead of held. */
.lp-fscreen--ledger {
  /* padding-top/bottom match the base .lp-fscreen's 40px (not a wider,
     ledger-only value): this section is content-height, not viewport-height,
     so any extra here adds directly to the gap before and after it instead
     of being absorbed into empty screen space the way it would on a
     min-height: 100svh screen. */
  min-height: 0; grid-template-columns: minmax(0, 1fr);
  gap: 44px; padding-top: 40px; padding-bottom: 40px;
  text-align: center; align-items: start;
}
.lp-fscreen--ledger .lp-fscreen-copy { max-width: 680px; margin: 0 auto; }
#landing .lp-fscreen--ledger h2 { text-wrap: balance; }
.lp-fscreen--ledger .lp-fscreen-copy p {
  max-width: 520px; margin-left: auto; margin-right: auto;
}
.lp-ledger {
  width: 100%; max-width: 880px; margin: 0 auto; text-align: left;
  background: var(--bg); border: 1px solid var(--line); border-radius: 22px;
  overflow: hidden;
  box-shadow: 0 30px 70px -32px rgba(0,0,0,.6);
}
.lp-ledger-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; padding: 17px 22px; border-bottom: 1px solid var(--line);
}
.lp-ledger-head .ex {
  font: 700 20px var(--font-ui); letter-spacing: -0.4px; min-width: 0;
}
.lp-ledger-head .lp-target-chip { margin-top: 0; flex: none; font-size: 10px; }
.lp-ledger-rows {
  display: flex; flex-direction: column; gap: 10px; padding: 16px 18px 18px;
}
/* Phone-scale type would disappear on a 940px band, so the ledger nudges the
   whole set of sizes up one step. Same layout, read from further away. */
.lp-ledger .lp-set.done { padding: 13px 16px; }
.lp-ledger .lp-set.done .mono { font-size: 11px; }
.lp-ledger .lp-set.done .val { font-size: 17px; }
.lp-ledger .lp-set.next { padding: 11px 6px; }
.lp-ledger .lp-set.next .mono { font-size: 11px; }
.lp-ledger .lp-set.now { padding: 14px 16px; }
.lp-ledger .lp-set.now .lbl { font-size: 11px; }
.lp-ledger .lp-lasttime { font-size: 11px; }
.lp-ledger .lp-steppers .t { font-size: 9px; }
/* Between the phone stack and the wide row the fields get very wide; cap the
   stepper run so − value + stays one control instead of drifting to opposite
   ends of a 300px box. */
.lp-ledger .lp-stepper-row { max-width: 190px; margin-left: auto; margin-right: auto; }
/* Two companion beats after the ledger: honest, compact recreations of the
   rest timer (app/src/screens/today/RestBar.svelte) and the PR celebration
   (app/src/screens/today/PrCelebration.svelte), so the section reads as one
   story — logging is fast, and it also carries you through the rest and
   rewards the effort — instead of one lone wide band with empty flanks
   either side. They sit in the DOM right after the ledger, so every width
   reads them in that same order. Three tiers from here down: mobile keeps
   the stack (ledger, then beats stacked below); 768–1100px turns the beats
   into a row under the ledger (≥861px rule below); ≥1101px has room to flank
   the ledger instead, one beat on each side (see the ≥1101px block after the
   768–1100px one). */
.lp-log-composition { width: 100%; }
.lp-log-beats {
  display: flex; flex-direction: column; gap: 14px;
  width: 100%; max-width: 880px; margin: 20px auto 0;
}
.lp-log-beat {
  display: flex; align-items: center; gap: 16px;
  padding: 18px 20px; border-radius: 18px;
  background: var(--bg); border: 1px solid var(--line);
  text-align: left;
}
.lp-log-beat-visual {
  position: relative; flex: none; width: 44px; height: 44px;
  display: flex; align-items: center; justify-content: center;
}
.lp-log-ring { width: 44px; height: 44px; }
.lp-log-ring-bg { fill: none; stroke: var(--line); stroke-width: 2.5; }
.lp-log-ring-fg { fill: none; stroke: var(--accent); stroke-width: 2.5; stroke-linecap: round; }
.lp-log-ring-time {
  position: absolute; font-size: 9px; font-weight: 600;
  color: var(--lp-muted); letter-spacing: -0.2px;
}
.lp-log-beat-badge {
  width: 44px; height: 44px; border-radius: 50%;
  background: var(--accent); color: var(--ink);
}
.lp-log-beat-badge svg { width: 22px; height: 22px; }
.lp-log-beat-copy { min-width: 0; }
.lp-log-beat-title { margin: 0; font: 700 15px var(--font-ui); letter-spacing: -0.2px; color: var(--text); }
.lp-log-beat-note { margin: 4px 0 0; font: 400 13px/1.4 var(--font-ui); color: var(--lp-muted); }
/* Capped at 1100px: this single-line "SET · NOW" row (label → last time →
   steppers → Log, ~660px of fixed-width children) assumes the ledger has its
   own full ~880px band to itself, which is only true from 861px up to the
   point the ≥1101px block below narrows the ledger into a flanked column.
   Past that the ledger falls back to the stacked phone-card form the ≥1101px
   block below inherits unstyled — the same shape it already uses under
   861px, which is exactly what a narrower column needs. */
@media (min-width: 861px) and (max-width: 1100px) {
  /* One line, ending in the Log button. */
  .lp-ledger .lp-set.now {
    display: flex; align-items: center; gap: 22px; padding: 14px 14px 14px 18px;
  }
  .lp-ledger-meta { flex: 1 1 auto; min-width: 0; }
  .lp-ledger-meta .lp-lasttime { margin-top: 5px; }
  .lp-ledger .lp-steppers { flex: none; width: 300px; margin-top: 0; }
  .lp-ledger .lp-log {
    flex: none; margin-top: 0; min-width: 148px; padding: 15px 24px;
  }
}
/* 768–1100px: wide enough for the two beats to sit side by side, not wide
   enough to flank the ledger without cramping it (see the ≥1101px block
   below) — so this band keeps the below-the-ledger row the section has
   always shown at this width. Split out from the ≥861px block above so the
   flanking layout can override just the composition, not the ledger's own
   internal single-line breakpoint. */
@media (min-width: 768px) and (max-width: 1100px) {
  .lp-log-beats { flex-direction: row; margin-top: 24px; }
  .lp-log-beat { flex: 1 1 0; }
}
/* ≥1101px: the stretched-alone band was the actual complaint, so once there
   is room for a real three-column composition, the two beats move to either
   side of the ledger instead of underneath it — dominant ledger in the
   middle, narrowed now that it has flanks, beats vertically centred against
   it and visibly subordinate. `.lp-log-beats` turns to `display: contents`
   so its two children (rest-timer, then PR-celebration — unchanged DOM
   order, the same order mobile and the 768–1100px tier still read top to
   bottom / left to right) become direct grid items instead, no HTML
   reordering needed. */
@media (min-width: 1101px) {
  .lp-log-composition {
    display: grid;
    grid-template-columns: minmax(180px, 240px) minmax(440px, 620px) minmax(180px, 240px);
    justify-content: center; align-items: center; gap: 40px;
  }
  .lp-ledger { grid-column: 2; grid-row: 1; }
  .lp-log-beats { display: contents; }
  .lp-log-beats .lp-log-beat {
    grid-row: 1; flex-direction: column; align-items: center;
    text-align: center; gap: 12px; padding: 22px 18px;
  }
  .lp-log-beats .lp-log-beat:first-child { grid-column: 1; }
  .lp-log-beats .lp-log-beat:last-child { grid-column: 3; }
  .lp-log-beat-copy { text-align: center; }
}
/* Phone: the band is now only as wide as the screen, so the padding and the
   stepper chrome come back down or the two number fields stop fitting at
   320px with a two-decimal load in them. */
@media (max-width: 640px) {
  .lp-fscreen--ledger { gap: 26px; }
  .lp-ledger-head { padding: 14px 15px; flex-wrap: wrap; gap: 8px; }
  .lp-ledger-head .ex { font-size: 18px; }
  .lp-ledger-rows { padding: 12px 11px 14px; gap: 8px; }
  .lp-ledger .lp-set.done { padding: 11px 12px; }
  .lp-ledger .lp-set.now { padding: 12px 11px; }
  .lp-ledger .lp-set.next { padding: 10px 4px; }
  .lp-ledger .lp-steppers { gap: 8px; }
  .lp-ledger .lp-stepbtn { width: 28px; height: 28px; font-size: 16px; }
  .lp-ledger .lp-steppers .n { font-size: 20px; }
  .lp-log-beats { gap: 10px; margin-top: 16px; }
  .lp-log-beat { padding: 14px 16px; border-radius: 16px; }
}
/* ── The centred screen ──
   Symmetrical instead of split, so it does not read as a repeat of the screens
   either side. The strip blows up the numbers the phone in the photo shows. */
.lp-fscreen--wide {
  /* Extra top padding is the gap between this screen and the trainer screen
     above it; the 1fr photo row absorbs it, so the screen still fits. */
  padding-top: 112px;
  grid-template-columns: minmax(0, 1fr);
  /* auto copy, then the photo takes ALL remaining height. Without the 1fr row
     the stacked layout grew past the viewport and the screen stopped being one
     screen. minmax(0, 1fr) so the row may shrink below the image's size. */
  grid-template-rows: auto minmax(0, 1fr);
  gap: 28px; text-align: center; align-items: stretch;
}
.lp-fscreen--wide .lp-fscreen-copy { max-width: 780px; margin: 0 auto; }
.lp-fscreen--wide .lp-fscreen-copy p { max-width: 560px; margin-left: auto; margin-right: auto; }
/* ── Progress chart ──
   Drawn rather than photographed: the subject is a line going up, so the
   screen draws one. Absolute inside its row because an inline SVG carries an
   intrinsic size from its viewBox, and that would grow the row and push the
   screen past a single viewport. */
.lp-chart { position: relative; display: block; min-height: 0; margin: 0; }
.lp-chart svg {
  position: absolute; inset: 0;
  display: block; width: 100%; height: 100%; overflow: visible;
}
.lp-chart-grid line { stroke: var(--line); stroke-width: 1; vector-effect: non-scaling-stroke; }
.lp-chart-axis line { stroke: var(--line2); stroke-width: 1; vector-effect: non-scaling-stroke; }
/* Labels live in HTML, not in the SVG. The chart scales non-uniformly to fill
   its row, and `vector-effect: non-scaling-size` is not reliably supported, so
   SVG <text> came out squashed — badly so on a phone, where the horizontal
   stretch is largest. Positioned by percentage against the same viewBox the
   gridlines use. */
.lp-chart-labels {
  position: absolute; inset: 0; pointer-events: none;
}
.lp-chart-labels span {
  position: absolute; left: 0; width: 6.5%;
  transform: translateY(-50%); text-align: right;
  color: var(--lp-muted); font: 400 13px/1 var(--font-ui);
  font-variant-numeric: tabular-nums;
}
.lp-chart-dot { filter: drop-shadow(0 0 12px rgba(var(--accent-rgb), 0.65)); }

/* Numbers sit directly under the sentence and overlap the top of the shot, so
   they read as part of the copy while costing the screen almost no height.
   The shadow is what keeps them legible over the plate in BOTH themes: a dark
   halo on the dark page, a white halo on the light one. */
.lp-fscreen--wide .lp-spec-strip {
  position: relative; z-index: 2;
  margin: 34px 0 14px;
  text-shadow: 0 2px 14px rgba(12, 13, 16, 0.9), 0 0 34px rgba(12, 13, 16, 0.75);
}
.lp-spec-strip {
  display: flex; justify-content: center; flex-wrap: wrap;
  gap: 20px 64px; margin: 34px 0 0;
}
.lp-spec-strip div { min-width: 0; }
.lp-spec-strip dt {
  font: 400 44px/1 var(--font-ui); letter-spacing: -1.6px; color: var(--text);
  font-variant-numeric: tabular-nums;
}
.lp-spec-unit { font-size: 24px; letter-spacing: -0.6px; margin-left: 2px; }
.lp-spec-strip dd {
  margin: 8px 0 0; color: var(--lp-muted);
  font: 400 15px/1.4 var(--font-ui);
}
.lp-fscreen-photo { margin: 0; display: flex; justify-content: center; }

/* ── The full-bleed screen ──
   The photograph runs the whole viewport width and the headline sits ON it,
   in the dark half the shot was framed for. No column, no card, no crop. */
.lp-fscreen--bleed { position: relative; margin: 96px 0 0; }
.lp-bleed-photo { position: relative; margin: 0; }
.lp-bleed-photo img { display: block; width: 100%; height: auto; }
/* Dissolve the top and bottom edges into the page so the band has no seam.
   Explicit rgba stops on purpose: interpolating to `transparent` goes through
   transparent BLACK and leaves a grey haze across the middle of the photo. */
.lp-bleed-photo::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(
    to bottom,
    rgba(12, 13, 16, 1) 0%,
    rgba(12, 13, 16, 0) 13%,
    rgba(12, 13, 16, 0) 74%,
    rgba(12, 13, 16, 1) 100%
  );
}
.lp-bleed-copy {
  position: absolute; inset: 0;
  display: flex; align-items: center;
  pointer-events: none;
}
.lp-bleed-inner {
  max-width: 1280px; width: 100%; margin: 0 auto; padding: 0 56px;
  pointer-events: auto;
}
.lp-bleed-inner .lp-section-eyebrow { margin-bottom: 16px; }
/* Flush right, but INSIDE a block that stays on the dark left half of the
   shot. Right-aligning the full-width inner threw the headline across the
   subject's face, where it is both unreadable and in the way. */
#landing .lp-fscreen--bleed h2 {
  max-width: 520px; margin: 0;
  font: 400 48px/1.08 var(--font-ui); letter-spacing: -1.7px;
  text-align: right;
}
.lp-bleed-inner .lp-section-eyebrow { max-width: 520px; text-align: right; }
.lp-bleed-inner p {
  max-width: 520px; margin: 20px 0 0; color: var(--lp-muted);
  font: 400 17px/1.6 var(--font-ui); text-align: right;
}
/* The photos ship as cut-outs on transparent, so they are `contain`: the
   subject floats at full height instead of being cropped into a band. */
.lp-fscreen-photo img {
  display: block; width: 100%; height: auto;
  max-height: calc(100svh - 160px);
  object-fit: contain;
}

/* Secondary features: plain text in three columns. No card, no border, no
   mock — they are here to be read, not to compete with the feature screens. */
.lp-more {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 40px 48px; max-width: 1000px;
}
.lp-more h3 {
  margin: 0; padding-top: 18px; border-top: 1px solid var(--line);
  font: 600 18px/1.3 var(--font-ui); letter-spacing: -.3px;
}
.lp-more p {
  margin: 8px 0 0; color: var(--lp-muted);
  font: 400 15px/1.6 var(--font-ui);
}


/* Mirrors the real in-app "AI Coach's take" card (.finish-coach.live in
   style.css): panel row, volt gradient sparkle badge, mono uppercase volt
   title, plain body copy. Keep in sync if the app card is redesigned. */
/* The AI's written feedback IS the product, so it is set as a pull-quote —
   no card, no border, no badge. It types itself in, the way the app streams
   it. Reduced motion (or no JS) leaves the full static reply visible. */
/* Fixed height on purpose: the skeleton, the typing text and the settled text
   are all different heights, and the column is vertically centred, so any
   change shifted the whole screen every loop. */
.lp-quote { max-width: 520px; margin: 30px 0 0; min-height: 152px; }
.lp-review-title {
  font: 600 12px var(--font-mono); letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--accent-ink-text); margin: 0 0 14px;
}
.lp-review-text {
  margin: 0; color: var(--text);
  font: 400 30px/1.32 var(--font-ui); letter-spacing: -0.7px;
  min-height: 3.96em;
}
/* Chat-loading skeleton (same look as the app's .skel-text rows). Hidden
   unless the JS loop puts the quote in its loading phase. */
.lp-review-skel { display: none; flex-direction: column; gap: 12px; padding: 6px 0 8px; }
.lp-review-skel i {
  height: 20px; border-radius: 8px;
  background: linear-gradient(90deg, rgba(255,255,255,.07) 25%, rgba(255,255,255,.13) 46%, rgba(255,255,255,.07) 64%);
  background-size: 200% 100%;
}
.lp-review-skel i:nth-child(1) { width: 96%; }
.lp-review-skel i:nth-child(2) { width: 88%; }
.lp-review-skel i:nth-child(3) { width: 64%; }
.lp-quote.loading .lp-review-skel { display: flex; }
.lp-quote.loading .lp-review-text { display: none; }
/* Blinking volt caret while the reply is "typing" (mirrors the app's
   air-caret). Steps(1) so it snaps like a terminal cursor. */
.lp-review-text.typing::after {
  content: ''; display: inline-block; width: 11px; height: 1.02em;
  margin-left: 5px; vertical-align: -0.13em;
  background: var(--accent); border-radius: 2px;
}
@media (prefers-reduced-motion: no-preference) {
  .lp-review-skel i { animation: lp-skel-shimmer 1.2s linear infinite; }
  .lp-review-text.typing::after { animation: lp-caret 0.75s steps(1) infinite; }
}
@keyframes lp-skel-shimmer { to { background-position: -200% 0; } }
@keyframes lp-caret { 50% { opacity: 0; } }

.lp-report-ui {
  display: grid; grid-template-rows: 1fr auto; gap: 18px;
  padding: 18px; border-radius: 20px;
  background: rgba(12,13,16,.58); border: 1px solid rgba(255,255,255,.08);
}
/* Simple stock-style progress line (matches the app's line charts). */
.lp-report-line { min-height: 150px; display: flex; align-items: stretch; }
.lp-report-line svg { width: 100%; height: 150px; display: block; }
/* Binary workout heatmap, matching the in-app Reports heatmap: flat rounded
   cells, trained = solid volt, rest = faint. No glow — it read as noise. */
.lp-report-heat { display: grid; grid-template-columns: repeat(14, 1fr); gap: 6px; }
.lp-report-heat i { aspect-ratio: 1; border-radius: 5px; background: rgba(255,255,255,.055); border: 1px solid rgba(255,255,255,.04); }
.lp-report-heat i.on { background: var(--accent); border-color: var(--accent); }

.lp-voice-ui { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 18px; }
.lp-mic-orb {
  width: 78px; height: 78px; border-radius: 24px; display: flex; align-items: center; justify-content: center;
  color: var(--ink); background: var(--accent);
  box-shadow: 0 18px 42px -18px rgba(var(--accent-rgb),.75);
}
.lp-mic-orb svg { width: 34px; height: 34px; }
.lp-wave { display: flex; align-items: center; gap: 6px; height: 46px; }
.lp-wave i { width: 6px; border-radius: 99px; background: rgba(var(--accent-rgb),.72); }
.lp-wave i:nth-child(1), .lp-wave i:nth-child(7) { height: 16px; }
.lp-wave i:nth-child(2), .lp-wave i:nth-child(6) { height: 28px; }
.lp-wave i:nth-child(3), .lp-wave i:nth-child(5) { height: 40px; }
.lp-wave i:nth-child(4) { height: 22px; }
.lp-voice-bubble {
  padding: 12px 16px; border-radius: 14px;
  background: rgba(255,255,255,.06); border: 1px solid rgba(255,255,255,.1);
  font: 700 18px var(--font-mono);
}



/* dashboard showcase */
#progress { position: relative; }
/* giant outlined word drifting IN FRONT of the showcase card's top edge
   (z-index above it); --px is scroll-linked from JS so it slides sideways as
   you scroll past. Stroke-only with no fill so the card stays readable. */

/* ── Cinematic video band ── */
.lp-cine {
  position: relative; margin-top: 90px; height: 420px; overflow: hidden;
  display: flex; align-items: center; text-align: center;
  /* The video sits at 50% opacity, so the band must paint its own ground —
     on the light page the white background showed through and washed it out.
     --bg is re-pinned dark inside this island. */
  background: var(--bg);
}
/* The full-bleed band already runs edge to edge, so the cinematic band butts
   straight onto it: two dark bands with a page-coloured gap between them read
   as a mistake. */
.lp-fscreen--bleed + .lp-cine { margin-top: 0; }
.lp-cine-video {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; opacity: 0.5; filter: saturate(0.7) brightness(0.75);
}
.lp-cine-scrim {
  position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(180deg, var(--bg), rgba(12,13,16,.3) 30%,
              rgba(12,13,16,.3) 70%, var(--bg));
}
/* Same shape as the full-bleed feature band: media edge to edge, the headline
   sitting on it in the content column, left-aligned. Two bands doing the same
   job should look like the same thing. */
.lp-cine-copy { position: relative; width: 100%; }
.lp-cine-inner { max-width: 1280px; margin: 0 auto; padding: 0 56px; }
#landing .lp-cine-copy h2 {
  margin: 0; font: 400 48px/1.08 var(--font-ui); letter-spacing: -1.7px;
  text-shadow: 0 2px 30px rgba(0,0,0,.55);
}

/* AI teaser */
.lp-ai {
  position: relative; overflow: hidden;
  border: 1px solid rgba(255,255,255,.09); border-radius: 28px; padding: 48px;
  display: grid; grid-template-columns: minmax(0, .9fr) minmax(300px, .7fr);
  align-items: center; gap: 44px;
  background:
    radial-gradient(circle at 82% 18%, rgba(var(--accent-rgb),.16), transparent 34%),
    linear-gradient(135deg, rgba(22,24,29,.96), rgba(12,13,16,.82));
  box-shadow: 0 24px 80px rgba(0,0,0,.34);
}
.lp-ai::before {
  content: ''; position: absolute; inset: 20px; pointer-events: none;
  border: 1px solid rgba(var(--accent-rgb),.08); border-radius: 22px;
}
.lp-ai-copy { position: relative; z-index: 1; max-width: 620px; }
#landing .lp-ai-copy h2 {
  margin: 0; font: 400 48px/1.08 var(--font-ui); letter-spacing: -1.7px;
}
.lp-ai-lede {
  font: 400 17px/1.6 var(--font-ui); color: var(--lp-muted);
  margin: 20px 0 0; max-width: 480px;
}
.lp-ai-join {
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid rgba(var(--accent-rgb),.34); border-radius: 13px; padding: 14px 22px;
  font: 700 14px var(--font-ui); color: var(--accent-ink-text); white-space: nowrap;
  margin-top: 28px; background: rgba(var(--accent-rgb),.06);
  transition: color .2s ease, border-color .2s ease, background .2s ease, transform .2s ease;
}
.lp-ai-join:hover {
  color: var(--ink); border-color: var(--accent); background: var(--accent);
  transform: translateY(-1px);
}
.lp-ai-device {
  position: relative; z-index: 1; display: flex; justify-content: center; align-items: center;
  min-height: 590px; perspective: 950px;
}
.lp-ai-orbit {
  position: absolute; inset: 54px 0 auto 50%; width: min(360px, 84vw); aspect-ratio: 1;
  transform: translateX(-50%); border-radius: 50%; pointer-events: none;
  background: radial-gradient(circle, rgba(var(--accent-rgb),.28), rgba(var(--accent-rgb),.08) 38%, transparent 68%);
  filter: blur(18px); opacity: .66;
}
/* The device is the HERO's phone, reused wholesale and scaled in proportion
   (314→266 wide, 620→526 tall) so both shots read as the same object. Only the
   four frame ratios and the screen height are re-stated at this size; the band
   gradient, the bezel, the side buttons and the concentric screen radius all
   fall out of the shared .lp-phone rules. */
.lp-ai-device .lp-phone {
  width: 266px;
  --frame-band: 4px;
  --frame-bezel: 6px;
  --frame-radius: 45px;
}
.lp-ai-device .lp-screen { height: 526px; min-height: 526px; padding: 0; }
.lp-ai-title {
  padding: 4px 16px 12px; color: var(--text);
  font: 600 15px/1.2 var(--font-ui); letter-spacing: -0.2px;
}
/* Composer, so the screen reads as a chat you can actually type into. */
.lp-ai-composer {
  flex: none; display: flex; align-items: center; gap: 8px;
  margin: 0 12px 14px; padding: 6px 6px 6px 14px;
  border: 1px solid var(--line); border-radius: 999px; background: var(--panel2);
}
.lp-ai-input {
  flex: 1; min-width: 0; color: var(--lp-faint);
  font: 400 12.5px var(--font-ui); white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis;
}
.lp-ai-send {
  flex: none; width: 30px; height: 30px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--accent); color: var(--ink);
}
.lp-ai-send svg { width: 15px; height: 15px; }

/* The phone turns in on scroll: a quarter turn, from edge-on to facing you.
   It needs its own element because .lp-phone already owns a floaty idle
   animation, and an animation's transform beats an inline one, so the rotation
   would never land. */
.lp-ai-flip {
  transform-style: preserve-3d;
  transform: rotateY(calc((1 - var(--spin, 1)) * 90deg));
}
/* Real thickness, so the turn reads as a solid object rather than a sheet of
   paper: a back face sits 11px behind the front, and side slabs bridge the two
   so the edge is visible while it turns. */
.lp-ai-device .lp-phone { transform-style: preserve-3d; }
/* Depth is EXTRUDED, not panelled: ten copies of the frame's own rounded
   silhouette stepped back in Z. A flat side panel is a rectangle and can never
   follow a 36px corner radius, which is why the edge kept breaking at the top
   and bottom of the phone. Stacking the real shape follows every curve for
   free. The stack fades out as the phone squares up, because face-on it would
   still project as a sliver alongside the frame. `--spin` inherits from
   .lp-ai-flip. */
.lp-ai-device .lp-phone { transform-style: preserve-3d; }
.lp-ai-slab {
  position: absolute; inset: calc(-1 * var(--frame-band)); border-radius: inherit;
  background: #1c1f25; pointer-events: none;
  transform: translateZ(calc(var(--i) * -1.2px));
  opacity: calc(1 - var(--spin, 1));
}
/* Back face closes the extrusion and carries the shading. */
.lp-ai-device .lp-phone::after {
  content: ''; position: absolute; inset: calc(-1 * var(--frame-band));
  border-radius: inherit;
  background: linear-gradient(120deg, #2b2f38, #0d0f12 68%);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.06);
  transform: translateZ(-13px);
  opacity: calc(1 - var(--spin, 1));
}

.lp-ai-thread {
  /* Bottom-aligned, the way a real thread sits: messages stack up from the
     composer, not down from the header. */
  margin-top: auto;
  display: flex; flex-direction: column; gap: 10px;
  padding: 13px 14px 22px;
}
.lp-ai-msg, .lp-ai-reply, .lp-ai-typing {
  opacity: 0; transform: translateY(12px);
}
/* Mirrors .cc-msg.user in CoachScreen.svelte: panel fill, hairline border,
   one squared corner on the sending side. */
.lp-ai-msg--user {
  align-self: flex-end; max-width: 82%;
  padding: 10px 13px; border-radius: 16px 16px 4px 16px;
  background: var(--panel2); border: 1px solid var(--line); color: var(--text);
  font: 400 12.5px/1.5 var(--font-ui);
}
/* Mirrors .cc-coach-block: the trainer has NO bubble, just the volt sparkle
   chip beside plain text. */
.lp-ai-reply {
  align-self: flex-start; max-width: 94%;
  display: flex; gap: 9px; align-items: flex-start;
}
.lp-ai-spark {
  flex: none; width: 22px; height: 22px; border-radius: 7px; margin-top: 2px;
  background: var(--accent); color: var(--ink);
  display: flex; align-items: center; justify-content: center;
}
.lp-ai-spark svg { width: 12px; height: 12px; }
.lp-ai-reply p {
  margin: 0; min-width: 0; padding-top: 2px;
  color: var(--text); font: 400 12.5px/1.6 var(--font-ui);
}
.lp-ai-typing {
  align-self: flex-start;
  width: 54px; height: 30px; display: flex; align-items: center; justify-content: center; gap: 5px;
  border-radius: 16px 16px 16px 4px; background: var(--panel2);
  border: 1px solid var(--line);
}
.lp-ai-typing i {
  width: 5px; height: 5px; border-radius: 50%; background: var(--accent);
  animation: lp-ai-dot 1s ease-in-out infinite;
}
.lp-ai-typing i:nth-child(2) { animation-delay: .14s; }
.lp-ai-typing i:nth-child(3) { animation-delay: .28s; }

@media (prefers-reduced-motion: no-preference) {
  .lp-ai-phone {
    animation: lp-ai-float 6s ease-in-out infinite;
    will-change: transform;
  }
  .lp-ai-orbit {
    animation: lp-ai-glow 6s ease-in-out infinite;
    will-change: opacity, transform;
  }
  .lp-ai-msg, .lp-ai-reply {
    animation: lp-ai-reveal 12s cubic-bezier(.16, 1, .3, 1) infinite;
    animation-delay: calc(var(--step) * .9s);
    will-change: opacity, transform;
  }
  .lp-ai-typing {
    animation: lp-ai-typing 12s cubic-bezier(.16, 1, .3, 1) infinite;
    animation-delay: calc(var(--step) * .9s);
    will-change: opacity, transform;
  }
}
@keyframes lp-ai-reveal {
  0%, 7% { opacity: 0; transform: translateY(12px); }
  13%, 84% { opacity: 1; transform: translateY(0); }
  92%, 100% { opacity: 0; transform: translateY(-5px); }
}
@keyframes lp-ai-typing {
  0%, 6% { opacity: 0; transform: translateY(12px); }
  12%, 27% { opacity: 1; transform: translateY(0); }
  36%, 100% { opacity: 0; transform: translateY(-5px); }
}
@keyframes lp-ai-dot {
  0%, 80%, 100% { opacity: .35; transform: translateY(0); }
  35% { opacity: 1; transform: translateY(-3px); }
}
@keyframes lp-ai-float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-10px); }
}
@keyframes lp-ai-glow {
  0%, 100% { opacity: .5; transform: translateX(-50%) scale(.96); }
  50% { opacity: .76; transform: translateX(-50%) scale(1.04); }
}

/* CTA band */
/* Closing screen. No filled slab, no glow: the page ends on the same quiet
   type as the screens above it, with the two ways in side by side. */
.lp-band { position: relative; padding: 24px 0 8px; text-align: center; }
#landing .lp-band h2 {
  margin: 0; font: 400 48px/1.08 var(--font-ui); letter-spacing: -1.7px;
}
.lp-band p {
  max-width: 520px; margin: 20px auto 0; color: var(--lp-muted);
  font: 400 17px/1.6 var(--font-ui);
}
.lp-band-actions {
  margin-top: 34px; display: flex; gap: 14px;
  align-items: center; justify-content: center; flex-wrap: wrap;
}
.lp-band-btn {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 16px 28px; border-radius: 14px;
  border: 1px solid var(--line2); background: transparent; color: var(--text);
  font: 700 16px var(--font-ui); letter-spacing: -0.2px;
}
.lp-band-btn:hover { border-color: var(--text); background: rgba(var(--accent-rgb), .08); }

/* SEO content section — editorial ledger: standfirst lede, then ruled rows
   that each read top to bottom like every other section on the page (mono
   topic stamp, then heading, then prose flowing underneath), not the old
   side-by-side split. */
.lp-seo .lp-seo-inner { max-width: 940px; margin: 0 auto; }
.lp-seo-head { max-width: 680px; padding-bottom: 48px; }
#landing .lp-seo h2 {
  font: 400 44px/1.1 var(--font-ui); letter-spacing: -1.5px;
  color: var(--text); margin: 0;
}
.lp-seo-lede { font: 400 17px/1.7 var(--font-ui); color: var(--lp-muted); margin: 34px 0 0; }
.lp-seo-row { border-top: 1px solid var(--line); padding: 36px 0; }
/* Quiet sentence-case label, not a neon all-caps stamp — the same eyebrow
   voice the feature screens use. */
.lp-seo-tag {
  display: block; color: var(--lp-muted);
  font: 400 15px/1.3 var(--font-ui); letter-spacing: -0.1px; text-transform: lowercase;
}
.lp-seo-tag::first-letter { text-transform: uppercase; }
.lp-seo h3 {
  font: 500 19px/1.35 var(--font-ui); letter-spacing: -0.3px;
  color: var(--text); margin: 10px 0 0;
}
/* Prose sits under the heading, capped to a comfortable reading measure like
   every other section's copy column, instead of stretching the full row.
   ch resolves against the inherited 16px base font here (not the 15px the
   paragraph itself sets), so 88ch lands near 700px - meaningfully wider
   than a typical copy column, short of running edge to edge in the 940px
   section container. */
.lp-seo-body { margin-top: 20px; max-width: 88ch; }
.lp-seo p { font: 400 15px/1.8 var(--font-ui); color: var(--lp-muted); margin: 0; }
/* Emphasis is weight and colour, not a highlighter pen. */
.lp-seo mark { background: none; color: var(--text); font-weight: 600; }
.lp-seo-cta {
  border-top: 1px solid var(--line); padding-top: 32px;
  display: flex; align-items: center; justify-content: space-between;
  gap: 20px; flex-wrap: wrap;
}
.lp-seo-cta-note { font: 400 11px var(--font-mono); color: var(--lp-faint); letter-spacing: 2px; }
/* .lp-band-actions normally sits under a heading (.lp-band, further down the
   page) with its own 34px top margin; here it sits inline next to the note
   instead, so that margin would just push it out of vertical alignment. */
.lp-seo-cta .lp-band-actions { margin-top: 0; }

/* FAQ */
#landing .lp-faq h2 {
  font: 400 44px/1.1 var(--font-ui); letter-spacing: -1.5px;
  color: var(--text); margin: 0 0 28px;
}
/* Hairline-ruled list, not a stack of cards: the rule is the only chrome. */
.lp-faq-item {
  background: none; border: 0; border-top: 1px solid var(--line);
  border-radius: 0; margin: 0;
}
.lp-faq-item:last-of-type { border-bottom: 1px solid var(--line); }
.lp-faq-item summary {
  font: 500 18px/1.4 var(--font-ui); color: var(--text);
  padding: 22px 44px 22px 0; cursor: pointer; list-style: none;
  position: relative; user-select: none;
}
.lp-faq-item summary::-webkit-details-marker { display: none; }
.lp-faq-item summary::after {
  content: '+'; position: absolute; right: 4px; top: 50%;
  transform: translateY(-50%);
  font: 400 20px var(--font-mono); color: var(--accent-ink-text);
  transition: transform .2s ease;
}
/* Chevron rotate. [open] alone covers no-JS: the native attribute flips the
   instant the browser toggles the disclosure. Where the open/close script
   below is running it sets [data-expanded] synchronously on click, before
   the close animation finishes and the [open] attribute itself lags behind
   — so the icon always agrees with the click, not with the animation. */
.lp-faq-item[open] summary::after,
.lp-faq-item[data-expanded="true"] summary::after { transform: translateY(-50%) rotate(45deg); }
.lp-faq-item[data-expanded="false"] summary::after { transform: translateY(-50%) rotate(0deg); }
.lp-faq-item p {
  font: 400 16px/1.7 var(--font-ui); color: var(--lp-muted);
  max-width: 720px; margin: 0; padding: 0 44px 24px 0;
}
@media (hover: hover) {
  .lp-faq-item summary:hover { color: var(--accent-ink-text); }
}

/* footer */
.lp-footer {
  max-width: 1280px; margin: 0 auto; padding: 50px 56px;
  display: flex; align-items: center; gap: 30px;
  border-top: 1px solid var(--line); color: var(--lp-muted); flex-wrap: wrap;
}
.lp-footer a { font: 500 13px var(--font-ui); }
.lp-footer a:hover { color: var(--text); }
.lp-footer-logo {
  width: 44px; height: 44px; border-radius: 13px;
  display: inline-flex; align-items: center; justify-content: center; flex: none;
}
.lp-flinks a.is-active { color: var(--accent-ink-text); }
.lp-footer .mono { font: 400 12px var(--font-mono); margin-left: auto; }
.lp-flinks { display: flex; align-items: center; gap: 30px; flex-wrap: wrap; }
.lp-social { display: flex; align-items: center; gap: 18px; }
.lp-social a {
  color: var(--lp-muted); display: inline-flex; transition: color .15s ease;
}
/* --accent-ink-text is the page's one accent-for-text token: volt on dark,
   the ink black on light so it still reads as the accent against a white
   footer (same swap .lp-nav-links a.is-active and .lp-faq-item summary
   already use). The old `var(--volt)` here was never defined in this
   stylesheet (only blog.css defines --volt), so the hover silently did
   nothing on the landing page footer. */
.lp-social a:hover,
.lp-social a:focus-visible { color: var(--accent-ink-text); }
.lp-social svg { width: 18px; height: 18px; display: block; }

/* ─── Scroll motion ──────────────────────────────────────────────────────────
   Sections fade + rise into place as they enter the viewport; the showcase
   chart draws its line; hero glows parallax gently on scroll. All gated behind
   prefers-reduced-motion and driven by transform/opacity only (compositor-cheap,
   no scroll-jacking). The .reveal/.in classes are applied from index.html JS. */

/* Smooth anchor scrolling — only on the landing (data-authed="0"), so the app's
   own view transitions are untouched. */
html[data-authed="0"] { scroll-behavior: smooth; }
html[data-authed="0"].landing-scroll-active { scroll-behavior: auto; }

@media (prefers-reduced-motion: no-preference) {
  /* The trainer shot slides in from off the left edge as its screen arrives.
     One move, one long decelerating ease (Apple never bounces a product shot),
     transform + opacity only so it stays on the compositor. */
  /* The chart is SCROLL-LINKED: --draw is written from the scroll handler as
     the screen travels up the viewport, so the reader's own scrolling is what
     moves the line. No transition on the clip — a transition would lag behind
     the finger. The axes and grid fade in once on arrival, and the dot rides
     the tip of the line (its cx/cy come from the path in JS). */
  #landing .lp-chart .lp-chart-draw {
    clip-path: inset(0 calc((1 - var(--draw, 0)) * 100%) 0 0);
  }
  #landing .lp-chart .lp-chart-grid,
  #landing .lp-chart .lp-chart-axis,
  #landing .lp-chart .lp-chart-labels {
    opacity: 0;
    transition: opacity 0.7s cubic-bezier(0.22, 0.61, 0.36, 1);
  }
  #landing .lp-chart .lp-chart-labels { transition-delay: 0.12s; }
  #landing .lp-chart .lp-chart-dot {
    opacity: 0;
    transition: opacity 0.4s cubic-bezier(0.22, 0.61, 0.36, 1);
  }
  #landing .lp-chart.is-drawn .lp-chart-grid,
  #landing .lp-chart.is-drawn .lp-chart-axis,
  #landing .lp-chart.is-drawn .lp-chart-labels,
  #landing .lp-chart.is-drawn .lp-chart-dot { opacity: 1; }

  #landing .lp-fscreen--flip .lp-fscreen-photo.reveal {
    opacity: 0;
    transform: translate3d(-14%, 0, 0);
    transition: opacity 0.7s cubic-bezier(0.22, 0.61, 0.36, 1),
                transform 0.9s cubic-bezier(0.22, 0.61, 0.36, 1);
    will-change: opacity, transform;
  }
  #landing .lp-fscreen--flip .lp-fscreen-photo.reveal.in {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

/* This block was missing the closing brace above it, so every rule to the end
   of the file — the light theme, the mobile breakpoints, the ripple ink and
   the reduced-motion overrides themselves — was nested inside
   `prefers-reduced-motion: no-preference` and silently dropped for anyone who
   asks for less motion. */
@media (prefers-reduced-motion: no-preference) {
  #landing .reveal {
    opacity: 0;
    transform: translateY(30px);
    transition: opacity 0.8s cubic-bezier(0.16, 1, 0.3, 1),
                transform 0.8s cubic-bezier(0.16, 1, 0.3, 1);
    will-change: opacity, transform;
  }
  #landing .reveal.in { opacity: 1; transform: none; }

  /* Above-the-fold hero copy is the page's LCP element — an opacity-0 start
     makes LCP wait out the whole fade. Hero reveals slide only, never fade. */
  #landing .lp-hero-copy > .reveal,
  #landing .pg-hero .reveal { opacity: 1; }

  /* Staggered entrance for grouped product tiles. */
  #landing .lp-hero-copy > *:nth-child(2) { transition-delay: 0.06s; }
  #landing .lp-hero-copy > *:nth-child(3) { transition-delay: 0.12s; }
  #landing .lp-hero-copy > *:nth-child(4) { transition-delay: 0.18s; }
  #landing .lp-hero-copy > *:nth-child(5) { transition-delay: 0.24s; }

  /* The hero phone has NO entrance animation on purpose. It is the product
     shot a first-time visitor must read at a glance, so it paints in place on
     the first frame; only the slow `floaty` idle plays. */
  #landing .lp-phone-wrap { perspective: 1100px; }

  /* Scroll-driven layers: --py/--px set from JS (compositor-only). */
  #landing .lp-hero-glow,
  #landing .lp-hero-glow2,
  #landing .lp-hero-grid,

  /* Ambient floating dots in the hero. */
  #landing .lp-fdot { animation: lp-drift 10s ease-in-out infinite; }

  /* "AI coach" in the headline gets a slow volt shimmer.
     Clip with clip-path, NOT overflow:hidden — overflow:hidden on an
     inline-block moves its baseline to the box bottom edge, which lifts
     the volt word out of line with the rest of the headline. */
  #landing .lp-hero h1 .volt {
    position: relative;
    display: inline-block;
    clip-path: inset(0);
    color: var(--accent-ink-text);
    isolation: isolate;
  }
  #landing .lp-hero h1 .volt::after {
    content: '';
    position: absolute;
    inset: -10% -42%;
    background: linear-gradient(100deg, transparent 42%, rgba(244,255,190,0.38) 50%, transparent 58%);
    transform: translateX(-120%);
    animation: lp-shine 5s linear infinite;
    mix-blend-mode: screen;
    pointer-events: none;
  }


  /* Phone mock logging loop: freshly logged rows + the next active card pop
     in; the Log button presses down just before each transition. */
  #landing .lp-set.pop { animation: lp-pop 0.45s cubic-bezier(0.22, 1, 0.36, 1); }
  #landing .lp-log { transition: transform 0.2s ease, background 0.2s ease; }
  #landing .lp-log.press { transform: scale(0.95); background: var(--accent-pressed); }
  #landing .lp-pips i { transition: background 0.4s ease, flex 0.4s ease; }
  #landing .lp-mic-orb { animation: lp-product-float 5.8s ease-in-out infinite; }
  #landing .lp-wave i { animation: lp-wave-pulse 1.2s ease-in-out infinite; }
  #landing .lp-wave i:nth-child(2),
  #landing .lp-wave i:nth-child(6) { animation-delay: 0.08s; }
  #landing .lp-wave i:nth-child(3),
  #landing .lp-wave i:nth-child(5) { animation-delay: 0.16s; }
  #landing .lp-wave i:nth-child(4) { animation-delay: 0.24s; }
}

@keyframes lp-drift {
  0%, 100% { transform: translate(0, 0); }
  33% { transform: translate(9px, -18px); }
  66% { transform: translate(-7px, 12px); }
}
/* from-only so each row settles at its own natural opacity (done rows are .7) */
@keyframes lp-pop {
  from { opacity: 0; transform: translateY(10px) scale(0.97); }
}
@keyframes lp-product-float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-7px); }
}
@keyframes lp-wave-pulse {
  0%, 100% { opacity: .45; transform: scaleY(.72); }
  50% { opacity: 1; transform: scaleY(1); }
}
@keyframes lp-shine { to { transform: translateX(120%); } }
@keyframes lp-sheen { to { transform: skewX(-18deg) translateX(520%); } }

/* Nothing theme-specific left: the card is painted from --accent/--ink, which
   both themes already define correctly. */

/* Lock the hero to the viewport at the widths where it's a two-column grid
   (≥1001px — below that .lp-hero collapses to one column, see the Tablet
   block right below, where copy stacks above a full phone mock and is
   expected to scroll like any marketing page; forcing that stack into one
   screen would mean shrinking everything to illegibility).
   Above 1000px the hero instead reads as one "fold": height matches the
   viewport exactly, minus the same nav clearance #landing already reserves
   above it (60px + safe-top), and a single row makes BOTH columns centre in
   that full height independently via align-items:center, rather than
   centring against whichever column's own content happened to be taller
   (the previous behaviour). dvh tracks the browser's actually visible
   viewport, matching the app's own vh/dvh fallback in App.svelte, so mobile
   browser chrome collapsing/expanding never causes a jump; vh is the
   fallback for browsers that don't parse dvh.
   minmax(0, 1fr), not a plain 1fr, for the same reason the Tablet block
   below already uses minmax(0, 1fr) on the COLUMN axis: a plain 1fr track's
   minimum comes from its tallest item's min-content contribution, and
   .lp-phone-wrap's own min-height:644px (see the base rule above — pinned,
   not changed here) would otherwise floor the ROW at 644px regardless of
   how little space is actually available, pushing the row — and the
   fixed-height .lp-hero around it — past the viewport. minmax(0, 1fr)
   overrides that automatic floor so the row always matches the space
   .lp-hero actually has.
   Placed AFTER the base .lp-hero/.lp-phone-wrap rules above (not next to
   them) on purpose: an earlier attempt sat right after .lp-hero's own base
   rule, and the later, unconditional .lp-phone-wrap transform declaration
   (same specificity) cascaded on top and silently dropped the scale below.
   Same specificity, source order decides, so this block has to be the LAST
   word on these two selectors among the desktop-width rules. */
@media (min-width: 1001px) {
  .lp-hero {
    height: calc(100vh - 60px - var(--safe-top));
    height: calc(100dvh - 60px - var(--safe-top));
    min-height: 740px;
    grid-template-rows: minmax(0, 1fr);
  }
  /* The phone mock's internals are all fixed-pixel (a recreated iPhone
     chrome — see the "stable fixed geometry" invariant on .lp-screen and
     .lp-phone-wrap above, untouched here), so it cannot reflow to a
     shorter height on its own. On a short viewport (a 1280x700 laptop is
     the case most likely to clip) it scales down as one rigid unit via
     transform instead, which only repaints: the wrap keeps its own 644px
     box, and the row above now sizes to the space actually available
     rather than 644px, so align-items:center centres that box within the
     SMALLER row, symmetrically overflowing both edges by the same amount.
     Scaling around the box's own centre (the transform-origin default)
     shrinks that symmetric overflow away evenly, and because the scale
     factor is deliberately the row's height divided by the box's own
     644px, the shrunk result lands exactly filling the row: no overflow,
     no gap, still centred at the same point. Never scales UP past natural
     size on a tall viewport (clamp's upper bound). Floors at 0.6 so it
     never shrinks past legibility; a viewport shorter than the floor
     allows gets a little natural overflow of its own rather than an
     unreadable phone. */
  .lp-phone-wrap {
    --phone-fit: calc((100vh - 60px - var(--safe-top) - 120px) / 644px);
    --phone-fit: calc((100dvh - 60px - var(--safe-top) - 120px) / 644px);
    --phone-scale: clamp(0.6, var(--phone-fit), 1);
    transform: perspective(900px) translateY(var(--pp, 0px))
               rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg))
               scale(var(--phone-scale));
  }
}
@media (min-width: 1001px) and (max-width: 1150px) {
  #landing .lp-hero h1 { font-size: 54px; }
  .lp-store-row > .lp-app-store-badge, .lp-store-row > .lp-play-badge { width: 162px; }
}

/* ── Tablet ── */
@media (max-width: 1000px) {
  /* minmax(0, 1fr), not 1fr: a plain 1fr column floors at the phone mock's
     314px min-content width, which pushes the whole hero past a 320px
     viewport and clips the copy and the store badge on the right. */
  .lp-hero { grid-template-columns: minmax(0, 1fr); gap: 32px; }
  #landing .lp-hero h1 { font-size: 50px; letter-spacing: -2px; margin-top: 22px; }
  .lp-hero p { font-size: 18px; }
  /* kill scroll parallax in single-column layout (JS also guards this) */
  .lp-phone-wrap { --pp: 0px !important; --rx: 0deg !important; --ry: 0deg !important; }
  /* Copy (the AI punch line) stays first on mobile; phone mock follows it. */
  .lp-phone-wrap { height: 644px; min-height: 644px; margin-top: 8px; }
  .lp-more { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 32px 40px; }
  .lp-fscreen {
    grid-template-columns: 1fr; gap: 28px; min-height: 0;
    padding: 56px 20px; align-items: start;
  }
  /* Stacked screens drop min-height, so a 1fr photo row would collapse to zero
     and the shot would disappear. Put both photos back in normal flow. */
  .lp-fscreen--wide { grid-template-rows: auto auto; padding-top: 56px; }
  /* The chart's SVG is absolutely positioned so it contributes no intrinsic
     height. That is what keeps this screen inside one viewport on desktop, but
     in the stacked layout the row it filled collapses to zero and the line
     disappears. Give the figure a height of its own here. */
  .lp-chart { height: 38vh; min-height: 230px; }
  .lp-fscreen--wide .lp-fscreen-photo { position: relative; }
  .lp-fscreen--wide .lp-fscreen-photo img {
    position: static; width: 100%; height: auto; max-height: 52vh;
  }
  /* Stacked: the photo goes back in flow, under its copy. */
  .lp-fscreen--flip .lp-fscreen-copy { grid-column: 1; padding-left: 0; }
  .lp-fscreen--flip .lp-fscreen-photo {
    position: static; width: auto; left: auto;
  }
  .lp-fscreen--flip .lp-fscreen-photo { filter: drop-shadow(0 26px 40px rgba(0, 0, 0, 0.75)); }
  /* The hand reaches in from off the left edge, so on a phone the shot runs to
     that edge rather than sitting inset in the column. */
  .lp-fscreen--flip .lp-fscreen-photo {
    margin-left: -20px; margin-right: -20px;
  }
  .lp-fscreen--flip .lp-fscreen-photo img {
    height: auto; max-height: 58vh; object-position: left bottom;
    /* Bottom fade only: the left edge is the viewport edge here, so feathering
       it would eat the wrist the shot is meant to run off. */
    -webkit-mask-image: linear-gradient(to top, transparent 0%, #000 10%);
    -webkit-mask-composite: source-over;
    mask-image: linear-gradient(to top, transparent 0%, #000 10%);
    mask-composite: add;
  }
  #landing .lp-fscreen h2 { font-size: 40px; letter-spacing: -1.4px; }
  .lp-fscreen-photo img { max-height: 58vh; }
  .lp-fscreen--bleed { margin-top: 64px; }
  .lp-bleed-copy { position: static; padding: 28px 0 44px; }
  .lp-bleed-inner { padding: 0 20px; }
  .lp-bleed-photo img { height: 46vh; min-height: 300px; object-fit: cover; object-position: 72% 50%; }
  #landing .lp-fscreen--bleed h2 { font-size: 40px; letter-spacing: -1.4px; }
  .lp-ai { grid-template-columns: 1fr; }
  .lp-ai-device { min-height: 590px; }

  /* Bar keeps brand + CTA + hamburger; everything else lives in a right-side
     drawer (sidebar) that slides in over a dimmed backdrop. */
  .lp-burger { display: inline-flex; }
  /* Brand absorbs the free space; the CTA sits right beside the burger. */
  .lp-brand { margin-right: auto; }
  .lp-cta-sm { margin-left: 0; }
  /* Solid, not glass: translucent fixed layers over the hero's composited
     layers ghost badly on mobile Chrome; opaque also reads more decisive. */
  .lp-nav.menu-open {
    background: transparent;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    border-bottom-color: transparent;
  }
  /* Dimmed backdrop behind the drawer. It's a pseudo of .lp-nav, so clicks on
     it hit-test as the nav element itself — the outside-click close handler
     checks `e.target === nav` for exactly this. */
  .lp-nav.menu-open::before {
    content: ''; position: fixed; inset: 0; z-index: 1;
    background: rgba(6, 7, 9, 0.55);
  }
  .lp-nav-inner { position: relative; z-index: 2; }
  .lp-menu {
    display: flex; flex-direction: column;
    position: fixed; top: 0; right: 0; bottom: 0; left: auto;
    width: min(320px, 85vw);
    background: #0e0f13;
    border-left: 1px solid var(--line);
    box-shadow: -28px 0 60px -18px rgba(0, 0, 0, 0.7);
    padding: calc(74px + var(--safe-top)) 24px 24px;
    overflow-y: auto; overscroll-behavior: contain;
    transform: translateX(102%);
    visibility: hidden;
    transition: transform 0.28s cubic-bezier(0.2, 0.8, 0.3, 1),
                visibility 0s linear 0.28s;
  }
  .lp-nav.menu-open .lp-menu {
    transform: none; visibility: visible;
    transition: transform 0.28s cubic-bezier(0.2, 0.8, 0.3, 1);
  }
  /* Page scroll locks while the drawer is open (class set by the nav script). */
  html.lp-drawer-open { overflow: hidden; }
  .lp-nav-spacer { display: none; }
  .lp-menu-close {
    position: absolute; top: calc(14px + var(--safe-top)); right: 18px;
    width: 44px; height: 44px; display: inline-flex;
    align-items: center; justify-content: center;
    background: none; border: 0; color: var(--text); cursor: pointer;
  }
  /* The CTA leaves the bar and becomes the drawer's last action. */
  .lp-menu .lp-cta-sm {
    order: 99; width: 100%; height: auto; text-align: center;
    margin: 18px 0 0; padding: 15px 20px; font-size: 15px;
  }
  .lp-nav-links { display: flex; flex-direction: column; gap: 0; margin-left: 0; }
  .lp-nav-links a {
    font: 600 16px var(--font-ui); color: var(--text);
    padding: 15px 2px; border-bottom: 1px solid var(--line);
  }
  .lp-nav-links .lp-login-drawer { display: block; }
  .lp-menu-row {
    display: flex; align-items: center; justify-content: space-between;
    gap: 14px; margin-top: auto; padding-top: 16px;
  }
  .lp-menu-row .lp-login-original { display: none; }
  .lp-menu-row .lang-pick { margin-right: 0; }
  .lp-menu-row .lang-pick-label { display: inline; }
  /* Anchor the language dropdown to the button's LEFT edge inside the panel —
     right-anchored it spills off the left side of the phone screen. */
  /* The picker sits at the drawer's bottom-RIGHT now: anchor the menu to the
     button's right edge so it opens inward. Left-anchored it spills past the
     drawer and forces a horizontal scrollbar. */
  .lp-menu-row .lang-pick-menu {
    top: auto; left: auto; bottom: calc(100% + 8px); right: 0;
    max-width: calc(min(320px, 85vw) - 48px);
  }
  .lp-nav.menu-open .lp-nav-links a,
  .lp-nav.menu-open .lp-menu-row {
    animation: lp-menu-item-in 0.32s cubic-bezier(0.2, 0.8, 0.3, 1) backwards;
  }
  .lp-nav.menu-open .lp-nav-links a:nth-child(1) { animation-delay: 0.03s; }
  .lp-nav.menu-open .lp-nav-links a:nth-child(2) { animation-delay: 0.06s; }
  .lp-nav.menu-open .lp-nav-links a:nth-child(3) { animation-delay: 0.09s; }
  .lp-nav.menu-open .lp-nav-links a:nth-child(4) { animation-delay: 0.12s; }
  .lp-nav.menu-open .lp-nav-links a:nth-child(5) { animation-delay: 0.15s; }
  .lp-nav.menu-open .lp-nav-links a:nth-child(6) { animation-delay: 0.18s; }
  .lp-nav.menu-open .lp-nav-links a:nth-child(7) { animation-delay: 0.21s; }
  .lp-nav.menu-open .lp-menu-row { animation-delay: 0.24s; }
}
@keyframes lp-menu-item-in {
  from { opacity: 0; transform: translateX(14px); }
  to { opacity: 1; transform: translateX(0); }
}
@media (prefers-reduced-motion: reduce) {
  .lp-menu { transition: none !important; }
  .lp-nav.menu-open .lp-menu,
  .lp-nav.menu-open .lp-nav-links a,
  .lp-nav.menu-open .lp-menu-row { animation: none !important; transition: none !important; }
  .lp-ai-phone, .lp-ai-orbit,
  .lp-ai-msg, .lp-ai-reply, .lp-ai-typing,
  .lp-ai-typing i {
    animation: none !important;
  }
  .lp-ai-phone { transform: none; }
  .lp-ai-msg, .lp-ai-reply {
    opacity: 1; transform: none;
  }
  .lp-ai-typing { display: none; }
}

/* ── Mobile ── */
@media (max-width: 640px) {
  #landing { padding-top: calc(56px + var(--safe-top)); }
  .lp-nav { padding: calc(12px + var(--safe-top)) 0 12px; }
  .lp-nav-inner { padding: 0 20px; gap: 14px; }
  .lp-menu { padding: calc(70px + var(--safe-top)) 20px 20px; }
  .lp-fdot { display: none; }
  .lp-hero { padding: 28px 20px 8px; gap: 28px; }
  .lp-store-row { margin-top: 28px; gap: 10px; }
  /* Stacked, both full width, exactly like an onboarding choice card. Same
     width as the hero phone (314px) and on the same axis, so the CTAs and
     the device read as one column rather than three loose objects. */
  #landing .lp-hero h1 { font-size: 42px; letter-spacing: -1.5px; margin-top: 22px; text-wrap: balance; text-align: center; }
  .lp-hero p { font-size: 17px; text-align: center; margin-left: auto; margin-right: auto; }
  .lp-hero p.lp-hero-audience { font-size: 15px; }
  /* Dividers turn transparent rather than removed, so the box the beats sit
     in never resizes when the row wraps to two lines at narrow widths.
     margin-top matches .lp-store-row's own mobile margin-top (28px) above,
     same reasoning as the desktop rule: reuse the CTA row's own gap rather
     than a new number. */
  .lp-hero p.lp-hero-proof { justify-content: center; font-size: 12.5px; margin-top: 28px; }
  .lp-hero-proof-beat { padding: 0 10px; border-left-color: transparent; }
  .lp-hero-proof-beat:first-child { padding-left: 10px; }
  /* Three equal columns so Free / AI / 1 tap line up instead of rag-wrapping. */
  .lp-section { padding: 56px 20px 24px; }
  .lp-head-center h2 { font-size: 28px; letter-spacing: -0.9px; }
  .lp-section-eyebrow { font-size: 17px; margin-top: 0; }
  .lp-more { grid-template-columns: 1fr; gap: 26px; }
  .lp-fscreen { padding: 44px 20px; gap: 24px; }
  #landing .lp-fscreen h2 { font-size: 34px; letter-spacing: -1.1px; }
  .lp-fscreen-copy p { font-size: 17px; margin-top: 16px; }
  .lp-section-eyebrow { font-size: 17px; margin-bottom: 12px; }
  .lp-fscreen-photo img { max-height: 46vh; }
  .lp-fscreen--bleed { margin-top: 52px; }
  #landing .lp-fscreen--bleed h2 { font-size: 34px; letter-spacing: -1.1px; }
  .lp-bleed-inner p { font-size: 17px; margin-top: 16px; }
  .lp-report-line { min-height: 112px; }
  .lp-report-line svg { height: 112px; }
  .lp-report-heat { grid-template-columns: repeat(7, 1fr); }
  .lp-ai {
    grid-template-columns: 1fr; gap: 28px; padding: 30px 22px;
    border-radius: 22px;
  }
  .lp-ai::before { inset: 12px; border-radius: 18px; }
  #landing .lp-ai-copy h2 { font-size: 34px; letter-spacing: -1.1px; }
  .lp-ai-lede { font-size: 16px; }
  /* Same width as the phone mock below it (266px), and centred on the same
     axis, so the two read as one column instead of two loose objects. */
  .lp-ai-join {
    /* display:flex, not inline-flex: auto margins only centre a block-level
       box, and inline-flex left the button off the phone's axis. */
    display: flex; width: 266px; max-width: 100%;
    margin: 28px auto 0; text-align: center;
  }
  .lp-ai-device { min-height: 565px; width: 100%; }
  .lp-ai-phone { width: min(248px, 92vw); border-radius: 36px; }
  .lp-ai-thread { gap: 8px; padding-top: 12px; }
  .lp-ai-msg { font-size: 12.5px; }
  .lp-band { padding: 16px 0 4px; }
  /* Keep store artwork readable without stretching it across the screen. */
  .lp-band-actions { flex-direction: row; gap: 10px; }
  .lp-band-actions > :is(.lp-app-store-badge, .lp-play-badge) { width: 162px; }
  #landing .lp-band h2 { font-size: 34px; letter-spacing: -1.1px; }
  /* The editorial headings were still at their 44px desktop size on a phone,
     which forced "A workout tracker built" to wrap mid-phrase. */
  #landing .lp-seo h2,
  #landing .lp-faq h2 { font-size: 32px; letter-spacing: -1px; }
  .lp-seo-lede { font-size: 16px; margin-top: 24px; }
  .lp-faq-item summary { font-size: 16px; padding: 18px 40px 18px 0; }
  .lp-faq-item p { font-size: 15px; padding-right: 40px; }
  .lp-band h2 { font-size: 27px; }
  .lp-seo-head { padding-bottom: 36px; }
  .lp-seo h2 { font-size: 26px; letter-spacing: -0.8px; }
  /* The break is load-bearing now: it separates the dark clause from the grey
     one. Hiding it ran "built" straight into "for real training". */
  .lp-seo-lede { font-size: 15.5px; }
  .lp-seo-row { padding: 28px 0; }
  .lp-seo-body { margin-top: 14px; max-width: none; }
  .lp-seo-cta { flex-direction: column-reverse; align-items: stretch; text-align: center; }
  .lp-footer {
    flex-direction: column; align-items: stretch;
    gap: 0; padding: 10px 20px 44px;
  }
  .lp-footer-logo { margin-bottom: 10px; }
  /* Two columns: ten single links stacked one per row made the footer longer
     than most of the sections above it. */
  .lp-flinks { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 20px; }
  .lp-flinks a { display: flex; align-items: center; min-height: 48px; padding: 0 2px; border-bottom: 1px solid var(--line); font-size: 14px; }
  .lp-footer .mono { margin: 20px 0 0; color: var(--lp-faint); }
  .lp-social { padding-top: 20px; }
  .lp-cine { height: 300px; margin-top: 56px; }
  .lp-cine-inner { padding: 0 20px; }
  #landing .lp-cine-copy h2 { font-size: 34px; letter-spacing: -1.1px; }
}

/* ─── Language picker (custom dropdown, all marketing navs) ─────────────── */
.lang-pick { position: relative; flex: none; margin-right: 14px; }
.lang-pick-btn {
  /* Same 40px as .lp-theme-toggle right next to it, so the two nav controls
     read as one family instead of the picker looking thinner. */
  display: flex; align-items: center; gap: 8px; height: 40px; padding: 0 12px;
  box-sizing: border-box;
  background: rgba(255,255,255,0.04); color: #8a8f98;
  border: 1px solid rgba(255,255,255,0.1); border-radius: 12px;
  font: 600 13px/1 'Source Sans 3', system-ui, sans-serif; cursor: pointer;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.lang-pick-btn:hover, .lang-pick-btn[aria-expanded="true"] { color: #f2f3f5; border-color: rgba(255,255,255,0.22); }
.lang-pick-chev { transition: transform 0.15s ease; }
.lang-pick-btn[aria-expanded="true"] .lang-pick-chev { transform: rotate(180deg); }
.lang-pick-menu {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 60;
  min-width: 196px; max-height: min(62vh, 430px); overflow-y: auto;
  background: #16181d; border: 1px solid rgba(255,255,255,0.1);
  border-radius: 14px; padding: 6px;
  box-shadow: 0 18px 50px -12px rgba(0,0,0,0.65);
}
.lang-pick-menu [data-code] {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; padding: 10px 12px; border: 0; border-radius: 9px;
  background: transparent; color: #8a8f98; text-align: left; cursor: pointer;
  font: 600 13px/1 'Source Sans 3', system-ui, sans-serif;
  transition: color 0.12s ease, background 0.12s ease;
}
.lang-pick-menu [data-code]:hover { color: #f2f3f5; background: rgba(255,255,255,0.05); }
.lang-pick-menu [data-code].active { color: #ccff00; }
.lang-pick-check { display: none; line-height: 0; }
.lang-pick-menu .active .lang-pick-check { display: block; }
@media (max-width: 720px) {
  .lang-pick { margin-right: 10px; }
  .lang-pick-label { display: none; }
  .lang-pick-btn { padding: 8px 10px; gap: 6px; }
}

/* ─── Pricing ────────────────────────────────────────────────────────────── */
.lp-price-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 20px;
  max-width: 880px; margin: 56px auto 0;
}
.lp-price {
  display: flex; flex-direction: column; padding: 32px 28px;
  background: var(--panel); border: 1px solid var(--line); border-radius: 24px;
}
.lp-price.pro {
  background: linear-gradient(155deg, #1b1d23, #111216);
  border: 1.5px solid var(--accent); position: relative; overflow: hidden;
}
.lp-price.pro::before {
  content: ''; position: absolute; top: -70px; right: -70px;
  width: 240px; height: 240px; pointer-events: none;
  background: radial-gradient(circle, rgba(var(--accent-rgb),0.13), transparent 70%);
}
.lp-price-name {
  font: 700 12px var(--font-mono); letter-spacing: 2px;
  text-transform: uppercase; color: var(--lp-muted);
}
.lp-price.pro .lp-price-name { color: var(--accent-ink-text); }
.lp-price-amount { display: flex; align-items: baseline; gap: 7px; margin-top: 16px; }
.lp-price-amount .n { font: 700 46px var(--font-mono); letter-spacing: -1.5px; color: var(--text); }
.lp-price-amount .per { font: 400 13px var(--font-mono); color: var(--lp-muted); }
.lp-price-alt { margin-top: 7px; font: 400 12px var(--font-mono); color: var(--lp-faint); }
.lp-price-tag { margin: 16px 0 0; font: 400 15px/1.5 var(--font-ui); color: var(--lp-muted); }
.lp-price .lp-checks { margin: 22px 0 30px; }
.lp-price .lp-checks div { font-size: 14px; }
.lp-price-cta {
  display: block; margin-top: auto; padding: 14px; text-align: center;
  border-radius: 14px; font: 700 15px var(--font-ui);
  transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}
.lp-price-cta.ghost { border: 1px solid var(--line2); color: var(--text); }
.lp-price-cta.ghost:hover { border-color: var(--accent); color: var(--accent-ink-text); }
.lp-price-cta.solid {
  background: var(--accent); color: var(--ink);
  box-shadow: 0 12px 30px -10px rgba(var(--accent-rgb),0.5);
}
.lp-price-cta.solid:hover { background: var(--accent-pressed, #b8e600); }
.lp-price-note {
  margin-top: 18px; text-align: center;
  font: 400 12px var(--font-mono); color: var(--lp-faint); letter-spacing: 0.04em;
}
@media (max-width: 900px) {
  .lp-price-grid { grid-template-columns: 1fr; gap: 16px; margin-top: 32px; max-width: 480px; }
  .lp-price { padding: 26px 22px; }
  .lp-price-amount .n { font-size: 38px; }
}

/* Plans: Free lifetime first, then three Pro commitment lengths (6-month featured). */
.lp-plan-head {
  max-width: 640px; margin: 26px auto 0; text-align: center;
  font: 500 15px/1.55 var(--font-ui); color: var(--lp-muted);
}
/* Two cards: Free + Pro. The Pro card carries interval tabs. */
.lp-plans {
  display: grid; grid-template-columns: 1fr 1.1fr; gap: 18px;
  max-width: 880px; margin: 22px auto 0; align-items: stretch;
}
/* Interval tabs inside the Pro card (Monthly default / 6 months / Yearly). */
.lp-int-tabs {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px;
  margin: 16px 0 4px; padding: 4px; border-radius: 12px;
  background: rgba(12,13,16,.66); border: 1px solid var(--line);
}
.lp-int-tab {
  appearance: none; border: 0; cursor: pointer; border-radius: 9px;
  /* .lp-int-tabs is a grid row, so all three tabs stretch to match the
     tallest (the two-line "-28%"/"-52%" options). Centering the tab's own
     column content keeps the single-line "Monthly" label sitting at the
     same visual middle instead of pinned to the top of that taller box. */
  display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 2px;
  padding: 8px 4px; background: transparent; color: var(--lp-muted);
  font: 700 11px var(--font-mono); letter-spacing: 0.4px;
  transition: color 0.15s ease, background 0.15s ease;
}
.lp-int-tab:hover { color: var(--text); }
.lp-int-tab.active { background: var(--accent); color: var(--ink); }
.lp-int-save { font: 700 9.5px var(--font-mono); font-style: normal; color: var(--accent-ink-text); }
.lp-int-tab.active .lp-int-save { color: var(--ink); }
.lp-plan {
  display: flex; flex-direction: column; text-align: center; padding: 30px 22px;
  background: var(--panel); border: 1px solid var(--line); border-radius: 20px;
}
/* Free stays respectable but quiet: dimmer panel; the price slot reads
   volt "Free" (not a number) per Nidhanshu 2026-07-12. */
.lp-plan.free { background: rgba(22, 24, 29, 0.55); }
.lp-plan.free .lp-plan-amount .n { color: var(--accent-ink-text); }
/* Paid non-featured cards (Monthly / Yearly) read Pro-family: faint volt
   frame + a whisper of volt wash — clearly above Free, below the star. */
.lp-plan:not(.free):not(.feat) {
  border-color: rgba(var(--accent-rgb),0.2);
  background:
    linear-gradient(165deg, rgba(var(--accent-rgb),0.05), rgba(var(--accent-rgb),0) 48%),
    var(--panel);
}
.lp-plan:not(.free):not(.feat) .lp-price-cta.ghost { border-color: rgba(var(--accent-rgb),0.32); }
.lp-plan:not(.free):not(.feat) .lp-price-cta.ghost:hover { border-color: var(--accent); }
/* Featured Pro card = the star: volt frame + glow, volt-tinted gradient,
   lifted above the row, bigger Source Sans 3 price. */
.lp-plan.feat {
  background:
    linear-gradient(155deg, rgba(var(--accent-rgb),0.09), rgba(var(--accent-rgb),0.025) 38%, rgba(var(--accent-rgb),0) 62%),
    linear-gradient(155deg, #1b1d23, #101115);
  border: 1.5px solid var(--accent); position: relative; overflow: hidden;
  padding-top: 34px; padding-bottom: 34px;
  box-shadow:
    0 0 0 1px rgba(var(--accent-rgb),0.16),
    0 22px 55px -22px rgba(var(--accent-rgb),0.4),
    0 26px 50px -26px rgba(0,0,0,0.7);
}
.lp-plan.feat::before {
  content: ''; position: absolute; top: -70px; right: -70px;
  width: 220px; height: 220px; pointer-events: none;
  background: radial-gradient(circle, rgba(var(--accent-rgb),0.16), transparent 70%);
}
/* Faint diagonal sheen sweeping the featured card (reduced-motion gated). */
@media (prefers-reduced-motion: no-preference) {
  .lp-plan.feat::after {
    content: ''; position: absolute; top: -20%; bottom: -20%; left: -55%;
    width: 45%; pointer-events: none;
    background: linear-gradient(105deg, transparent,
      rgba(var(--accent-rgb),0.045) 40%, rgba(255,255,255,0.06) 50%,
      rgba(var(--accent-rgb),0.045) 60%, transparent);
    transform: translateX(0) skewX(-16deg);
    animation: lp-plan-sheen 7s ease-in-out infinite;
  }
  @keyframes lp-plan-sheen {
    0%, 58% { transform: translateX(0) skewX(-16deg); }
    92%, 100% { transform: translateX(360%) skewX(-16deg); }
  }
}
.lp-plan-badge {
  align-self: center; margin-bottom: 12px; padding: 5px 13px;
  background: var(--accent); color: var(--ink); border-radius: 100px;
  font: 700 10px var(--font-mono); letter-spacing: 1.5px;
  box-shadow: 0 6px 18px -6px rgba(var(--accent-rgb),0.55);
}
.lp-plan-name { font: 700 12px var(--font-mono); letter-spacing: 2px; color: var(--lp-muted); }
.lp-plan.feat .lp-plan-name { color: var(--accent-ink-text); }
/* Launch-offer eyebrow: "LAUNCH OFFER · 70% OFF". Volt accent, small caps. */
.lp-plan-offer {
  display: flex; align-items: baseline; justify-content: center; gap: 5px;
  margin-top: 12px; font: 700 10px var(--font-mono); letter-spacing: 1.2px;
  color: var(--accent-ink-text); text-transform: uppercase;
}
.lp-plan-offer .lp-off-pct { color: var(--accent-ink-text); }
.lp-plan-amount { display: flex; align-items: baseline; justify-content: center; gap: 6px; margin-top: 10px; }
.lp-plan-amount .anchor {
  font: 400 18px var(--font-mono); letter-spacing: -0.5px; color: var(--lp-faint);
  text-decoration: line-through; text-decoration-color: rgba(255,255,255,0.32);
}
.lp-plan-amount .n { font: 700 40px var(--font-mono); letter-spacing: -1.5px; color: var(--text); }
.lp-plan.feat .lp-plan-amount .n { font-size: 46px; }
.lp-plan.feat .lp-plan-amount .anchor { font-size: 20px; }
.lp-plan-amount .per { font: 400 13px var(--font-mono); color: var(--lp-muted); }
.lp-plan-sub { margin: 8px 0 18px; font: 400 12px var(--font-mono); color: var(--lp-faint); }
/* Feature check-rows inside plan cards. Free = full tracker list (dim checks);
   featured Pro = the 3 AI features (volt checks); Monthly/Yearly = one compact
   "Everything in Free + AI coach" row. Left-aligned block inside the centered
   card; CTA stays pinned to the bottom via margin-top:auto. */
.lp-plan-feats {
  margin: 0 0 24px; padding-top: 16px; text-align: left;
  border-top: 1px solid var(--line);
  display: flex; flex-direction: column; gap: 9px;
  position: relative; z-index: 1;
}
.lp-plan-feats div {
  display: flex; align-items: flex-start; gap: 8px;
  font: 400 13px/1.45 var(--font-ui); color: var(--lp-muted);
}
.lp-plan-feats svg { flex: none; width: 14px; height: 14px; margin-top: 2px; color: var(--accent-ink-text); }
.lp-plan.free .lp-plan-feats svg { color: var(--lp-faint); }
.lp-plan.feat .lp-plan-feats div { color: var(--text); }
.lp-plan.feat .lp-plan-feats { border-top-color: rgba(var(--accent-rgb),0.14); }
.lp-plan:not(.free):not(.feat) .lp-plan-feats { border-top-color: rgba(var(--accent-rgb),0.1); }
.lp-plan .lp-price-cta { margin-top: auto; position: relative; z-index: 1; }
.lp-plans-more { margin-top: 26px; text-align: center; }
.lp-plans-more a {
  display: inline-flex; align-items: baseline; gap: 6px;
  font: 500 14px var(--font-ui); color: var(--lp-muted);
  border-bottom: 1px solid var(--line2);
  padding-bottom: 2px;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.lp-plans-more a:hover { color: var(--accent-ink-text); border-color: var(--accent); }
@media (max-width: 1024px) {
  .lp-plans { grid-template-columns: repeat(2, 1fr); max-width: 640px; }
  .lp-plan.feat { transform: none; }
}
@media (max-width: 900px) {
  .lp-plans { grid-template-columns: 1fr; gap: 14px; max-width: 480px; }
  .lp-plan { padding: 26px 22px; }
  /* Stacked: the featured Pro card leads the column. */
  .lp-plan.feat { transform: none; order: -1; padding-top: 30px; padding-bottom: 30px; }
  .lp-plan-amount .n { font-size: 36px; }
  .lp-plan.feat .lp-plan-amount .n { font-size: 42px; }
}

/* ─── Testimonials ("Loved on Google Play") ────────────────────────────────
   Review cards are native Ironclad dark cards (panel bg, line border,
   Source Sans 3) with amber review stars for the familiar rating look.
   Self-contained inline SVGs (star + 4-color Play triangle) via <use>.
   The aggregate rating header + "Posted on Google Play" footers stay
   hidden in the markup until the app is live on Google Play. */
.gp-defs { position: absolute; width: 0; height: 0; overflow: hidden; }
.gp-widget {
  --gp-font: var(--font-ui, 'Source Sans 3', system-ui, sans-serif);
  --gp-ink: var(--text); --gp-grey: var(--lp-faint); --gp-amber: #FBBC04;
  --gp-empty: rgba(255, 255, 255, 0.18); --gp-blue: #1a73e8;
  max-width: 1080px; margin: 44px auto 0;
}

/* Rating header (hidden until live on Google Play) */
.gp-rating {
  display: flex; align-items: center; gap: 28px; flex-wrap: wrap;
  background: var(--panel); border: 1px solid var(--line); border-radius: 16px;
  padding: 22px 26px;
  font-family: var(--gp-font);
}
.gp-rating-brand { display: flex; align-items: center; gap: 12px; }
.gp-brand-logo { width: 34px; height: 34px; flex: none; }
.gp-rating-brand-txt { display: flex; flex-direction: column; line-height: 1.2; }
.gp-rating-name { font: 600 17px var(--gp-font); color: var(--gp-ink); letter-spacing: -0.1px; }
.gp-rating-sub { font: 400 13px var(--gp-font); color: var(--gp-grey); }
.gp-rating-score { display: flex; align-items: center; gap: 14px; }
.gp-score-num { font: 500 46px/1 var(--gp-font); color: var(--gp-ink); letter-spacing: -1px; }
.gp-score-meta { display: flex; flex-direction: column; gap: 4px; }
.gp-stars { display: flex; gap: 2px; }
.gp-count { font: 400 13px var(--gp-font); color: var(--gp-grey); }
.gp-count-num { font-weight: 500; color: var(--gp-ink); }
.gp-write {
  margin-left: auto; display: inline-flex; align-items: center;
  background: var(--gp-blue); color: #fff; text-decoration: none;
  font: 500 14px var(--gp-font); letter-spacing: 0.2px;
  padding: 10px 22px; border-radius: 100px; white-space: nowrap;
  transition: background 0.2s ease, box-shadow 0.2s ease;
}

/* Stars (shared) */
.gp-star { width: 18px; height: 18px; fill: var(--gp-amber); }
.gp-star.off { fill: var(--gp-empty); }

/* Review grid */
.gp-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; margin-top: 18px;
}
.gp-review {
  display: flex; flex-direction: column;
  background: var(--panel); border: 1px solid var(--line); border-radius: 16px;
  padding: 20px 20px 16px;
  font-family: var(--gp-font);
  transition: transform 0.25s ease, border-color 0.25s ease;
}
.gp-rev-head { display: flex; align-items: center; gap: 12px; }
.gp-avatar {
  width: 40px; height: 40px; flex: none; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: #fff; font: 500 18px var(--gp-font); user-select: none;
}
img.gp-avatar { object-fit: cover; display: block; }
.gp-rev-id { display: flex; flex-direction: column; line-height: 1.25; }
.gp-rev-name { font: 600 15px var(--gp-font); color: var(--gp-ink); }
.gp-rev-date { font: 400 11px var(--font-mono, 'Source Sans 3', sans-serif); color: var(--gp-grey); }
.gp-rev-stars { display: flex; gap: 2px; margin: 14px 0 10px; }
.gp-rev-stars .gp-star { width: 16px; height: 16px; }
.gp-rev-body { margin: 0; font: 400 14px/1.55 var(--gp-font); color: var(--lp-muted); flex: 1; }
.gp-rev-foot {
  display: flex; align-items: center; gap: 6px; margin-top: 16px;
  font: 400 12px var(--gp-font); color: var(--gp-grey);
}
.gp-foot-logo { width: 14px; height: 14px; flex: none; }

@media (hover: hover) {
  .gp-review:hover { transform: translateY(-3px); border-color: var(--line2, var(--line)); }
  .gp-write:hover { background: #1b66c9; box-shadow: 0 1px 3px rgba(26,115,232,.5); }
}

@media (max-width: 900px) {
  .gp-grid { grid-template-columns: 1fr; }
  .gp-rating { gap: 18px 22px; padding: 20px; }
  .gp-write { margin-left: 0; width: 100%; justify-content: center; }
}

/* ─── Simple pricing cards (Zoho-pricing-inspired, /pricing page) ──────────
   Name / big centered price / billing line / CTA / divider / check list.
   Pro = volt-tinted card with a dashed volt border + MOST POPULAR line.
   Interval toggle (.pz-tabs reuses .lp-int-tab* behavior) sits ABOVE the
   grid, centered. Approved here first; roll out to landing + app after. */
.pz-toggle-row { display: flex; justify-content: center; margin-top: 26px; }
.pz-tabs { width: min(420px, 100%); margin: 0; }
.pz-plans {
  display: grid; grid-template-columns: 1fr 1fr; gap: 18px;
  max-width: 800px; margin: 26px auto 0; align-items: stretch;
}
/* Free card sits 10px lower than Pro (so it's ~10px shorter) with both card
   bottoms aligned - the stretched grid row is sized by the Pro card. */
.pz-card:not(.pz-pro) { margin-top: 10px; }
.pz-card {
  display: flex; flex-direction: column; text-align: center;
  padding: 30px 28px; border-radius: 20px;
  background: var(--panel); border: 1px solid var(--line);
}
.pz-pro {
  background:
    linear-gradient(170deg, rgba(var(--accent-rgb),0.07), rgba(var(--accent-rgb),0.02) 45%, rgba(var(--accent-rgb),0) 70%),
    var(--panel);
  border: 1.5px dashed rgba(var(--accent-rgb),0.55);
}
.pz-popular {
  font: 700 10px var(--font-mono); letter-spacing: 2px; color: var(--accent-ink-text);
  margin-bottom: 14px;
}
.pz-popular::before, .pz-popular::after { content: '·'; margin: 0 8px; opacity: .7; }
.pz-name { font: 700 12px var(--font-mono); letter-spacing: 2px; color: var(--lp-muted); }
.pz-pro .pz-name { color: var(--text); }
.pz-offer {
  margin-top: 14px; font: 700 10px var(--font-mono); letter-spacing: 1.2px;
  color: var(--accent-ink-text); text-transform: uppercase;
}
.pz-amount {
  display: flex; align-items: baseline; justify-content: center; gap: 7px;
  margin-top: 10px;
}
.pz-amount .anchor {
  font: 400 17px var(--font-mono); color: var(--lp-faint);
  text-decoration: line-through; text-decoration-color: rgba(255,255,255,0.32);
}
.pz-amount .n { font: 700 44px var(--font-mono); letter-spacing: -1.5px; color: var(--text); }
.pz-card:not(.pz-pro) .pz-amount .n { color: var(--accent-ink-text); }
.pz-amount .per { font: 400 13px var(--font-mono); color: var(--lp-muted); }
.pz-per { margin-top: 8px; font: 400 12.5px var(--font-mono); color: var(--lp-faint); min-height: 1.4em; }
.pz-cta {
  display: block; margin: 18px auto 0; padding: 13px 20px; width: min(240px, 100%);
  text-align: center; border-radius: 13px; font: 700 14px var(--font-ui);
  transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}
.pz-cta.ghost { border: 1px solid var(--line2); color: var(--text); }
.pz-cta.ghost:hover { border-color: var(--accent); color: var(--accent-ink-text); }
.pz-cta.solid {
  background: var(--accent); color: var(--ink);
  box-shadow: 0 12px 30px -10px rgba(var(--accent-rgb),0.45);
}
.pz-cta.solid:hover { background: var(--accent-pressed, #b8e600); }
.pz-divider { height: 1px; background: var(--line); margin: 24px 0 18px; }
.pz-pro .pz-divider { background: rgba(var(--accent-rgb),0.16); }
.pz-feats-label {
  text-align: left; margin-bottom: 12px;
  font: 700 13px var(--font-ui); color: var(--accent-ink-text);
}
.pz-feats { display: flex; flex-direction: column; gap: 10px; text-align: left; }
.pz-feats div {
  display: flex; align-items: flex-start; gap: 9px;
  font: 400 13.5px/1.5 var(--font-ui); color: var(--lp-muted);
}
.pz-pro .pz-feats div { color: var(--text); }
.pz-feats svg {
  flex: none; width: 16px; height: 16px; margin-top: 1px; padding: 2px;
  color: var(--ink); background: var(--accent); border-radius: 50%;
}
.pz-card:not(.pz-pro) .pz-feats svg { background: rgba(255,255,255,0.22); color: var(--bg); }
/* "See all features" — sits right under the Free card's last feature point
   and anchors to the #compare table. */
.pz-more {
  display: block; margin-top: 12px; text-align: left;
  font: 500 13px var(--font-ui); color: var(--accent-ink-text);
}
.pz-more:hover { text-decoration: underline; }
@media (max-width: 820px) {
  /* Tighten hero → tabs on mobile. #plans (id selector) outranks the generic
     .lp-section mobile padding that later-loading sheets re-assert. */
  #plans { padding-top: 0; }
  #plans .pz-toggle-row { margin-top: 12px; }
}
@media (max-width: 760px) {
  .pz-plans { grid-template-columns: 1fr; max-width: 460px; gap: 14px; margin-top: 20px; }
  .pz-card { padding: 26px 22px; }
  /* Stacked: Pro leads; no vertical offset in one column. */
  .pz-pro { order: -1; }
  .pz-card:not(.pz-pro) { margin-top: 0; }
  .pz-amount .n { font-size: 38px; }
}

/* ─── /pricing page (public/pricing.html) ──────────────────────────────────
   Detailed pricing + feature-comparison page. Reuses the landing plan cards
   (.lp-plans), FAQ (.lp-faq-item) and band; adds the comparison table. The
   wide table always scrolls inside its own wrapper, never the page. */
.pr-tablewrap {
  max-width: 880px; margin: 40px auto 0;
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  border: 1px solid var(--line); border-radius: 18px; background: var(--panel);
}
.pr-table { width: 100%; min-width: 560px; border-collapse: collapse; }
.pr-table th, .pr-table td {
  padding: 13px 18px; border-top: 1px solid var(--line);
  text-align: left; font: 400 14px/1.5 var(--font-ui); color: var(--text);
}
.pr-table thead th {
  border-top: 0; padding-top: 16px; padding-bottom: 14px;
  font: 700 11px var(--font-mono); letter-spacing: 1.5px;
  text-transform: uppercase; color: var(--lp-muted);
}
.pr-table thead th.pro { color: var(--accent-ink-text); }
.pr-table th.c, .pr-table td.c { text-align: center; width: 96px; }
.pr-table .grp td {
  font: 700 11px var(--font-mono); letter-spacing: 1.5px;
  text-transform: uppercase; color: var(--accent-ink-text);
  background: rgba(var(--accent-rgb),0.04); padding-top: 14px; padding-bottom: 12px;
}
.pr-table td .sub { display: block; margin-top: 2px; font: 400 12px/1.5 var(--font-ui); color: var(--lp-muted); }
.pr-table svg.ok { width: 16px; height: 16px; color: var(--accent-ink-text); vertical-align: -3px; }
.pr-table tr.ai svg.ok { filter: drop-shadow(0 0 6px rgba(var(--accent-rgb),0.45)); }
.pr-table .no { color: var(--lp-faint); font: 400 14px var(--font-mono); }
.pr-head-note {
  max-width: 640px; margin: 14px auto 0; text-align: center;
  font: 400 12px var(--font-mono); color: var(--lp-faint); letter-spacing: 0.04em;
}
@media (max-width: 900px) {
  .pr-tablewrap { margin-top: 28px; }
  .pr-table th, .pr-table td { padding: 12px 14px; }
}
@media (max-width: 640px) {
  /* Fit the viewport instead of side-scrolling: feature names wrap, the two
     check columns shrink, type steps down a notch. */
  .pr-tablewrap { margin-top: 20px; border-radius: 14px; }
  .pr-table { min-width: 0; }
  .pr-table th, .pr-table td { padding: 11px 10px; font-size: 13px; }
  .pr-table td:first-child { padding-left: 14px; }
  .pr-table th.c, .pr-table td.c { width: 46px; }
  .pr-table td .sub { font-size: 11.5px; }
  .pr-table svg.ok { width: 14px; height: 14px; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   IRONCLAD LIGHT — marketing hybrid (opt-in, data-theme="light" on <html>)
   ---------------------------------------------------------------------------
   A no-flash head script stamps data-theme="light" BEFORE this stylesheet
   loads. Dark stays byte-identical (data-theme absent or "dark"): every rule
   below is scoped under :root[data-theme="light"], so nothing here applies to
   the default dark theme.

   Treatment: nav, hero, section headings, SEO prose, FAQ, pricing cards,
   testimonials chrome and footer flip LIGHT via token overrides. The app-UI
   showcases stay DARK, framed as intentional dark cards on the light page:
   the hero phone mock + slab, the product-feature tiles, the reports showcase
   + real screenshot, the cinematic video band, and the AI teaser band. Volt
   stays a bright FILL everywhere; volt used as TEXT/stroke in a light section
   darkens to olive (--accent-ink-text) so it reads on white.
   ═══════════════════════════════════════════════════════════════════════════ */

:root[data-theme="light"] {
  color-scheme: light;

  --bg: #f5f6f8;
  --bg2: #eceef1;
  --panel: #ffffff;
  --panel2: #eceef1;
  --bg-elev: #eceef1;
  --card: #ffffff;
  --card-2: #eceef1;

  --line: rgba(12, 13, 16, 0.10);
  --line2: rgba(12, 13, 16, 0.18);
  --control-outline: rgba(12, 13, 16, 0.45);
  --border: rgba(12, 13, 16, 0.10);
  --border-soft: rgba(12, 13, 16, 0.08);
  --border-strong: rgba(12, 13, 16, 0.18);

  --text: #17181c;
  --text-muted: #5c6270;
  --dim: #5c6270;
  --text-faint: #656b75;
  --dim2: #656b75;

  /* Official Ironi light accent. Volt #ccff00 is dark-theme-only: on white it
     fails contrast, so light theme uses Ironi green #4d8000 instead.
     White ink sits on the green fill; unfilled accent ink stays near-black. */
  --accent: #4d8000;
  --accent-rgb: 77, 128, 0;
  --accent-pressed: #416d00;
  --accent-glow: rgba(77, 128, 0, 0.22);
  --accent-text: #ffffff;
  --ink: #ffffff;
  --accent-ink-text: #0c0d10;

  --good: #1d9e50;
  --bad: #d64545;
  --danger: #d64545;
  --warm: #c97a2b;
  --warm-glow: rgba(201, 122, 43, 0.16);
  --push: #0c0d10;
  --pull: #2b8fc9;
  --legs: #c97a2b;

  --shadow-card: 0 1px 0 rgba(255, 255, 255, 0.6) inset, 0 12px 28px -18px rgba(12, 13, 16, 0.28);
  --shadow-cta: 0 10px 24px -10px rgba(12, 13, 16, 0.35);
}

/* Landing-scoped muted/faint greys need a darker value on white. */
:root[data-theme="light"] #landing {
  --lp-muted: #566072;
  --lp-faint: #656b75;
  /* #landing pins --accent-ink-text to volt for the dark default; re-point it
     to the light-theme readable ink here (this scoped rule wins on the
     #landing element itself, and dark islands re-reset it on their subtree). */
  --accent-ink-text: #0c0d10;
  background: var(--bg);
  color: var(--text);
}

/* Drop the dark volt/amber body glow for a clean light wash. */
:root[data-theme="light"] body {
  background:
    radial-gradient(1200px 600px at 50% -10%, rgba(12, 13, 16, 0.04), transparent 60%),
    var(--bg);
}

/* ── Dark islands: app-UI showcases keep the dark palette. Re-declare the dark
   tokens locally so every descendant using var() renders dark, then frame each
   so it reads as an intentional dark card on the light page. The light theme
   turns --accent black, so the islands re-pin the full volt accent set —
   inside them volt fills/text on dark are correct. ── */
:root[data-theme="light"] .lp-phone,
:root[data-theme="light"] .lp-ledger,
:root[data-theme="light"] .lp-fscreen--bleed,
:root[data-theme="light"] .lp-cine,
:root[data-theme="light"] .lp-ai,
/* Two more islands, for the same reason: the cardio band redraws the route
   exactly as the app's cardio share card draws it (volt polyline on ink, no
   map tiles), and the share cards ARE that artwork — both are 1080px canvases
   the app renders on #0c0d10, so a light version of either would be a picture
   of something Ironi never makes. */
:root[data-theme="light"] .lp-cardio-band,
:root[data-theme="light"] .lp-share-card {
  --accent: #ccff00;
  --accent-rgb: 204, 255, 0;
  --accent-pressed: #b8e600;
  --accent-text: #0c0d10;
  --ink: #0c0d10;
  --bg: #0c0d10;
  --bg2: #08090b;
  --panel: #16181d;
  --panel2: #1e2127;
  --bg-elev: #1e2127;
  --card: #16181d;
  --card-2: #1e2127;
  --line: rgba(255, 255, 255, 0.08);
  --line2: rgba(255, 255, 255, 0.14);
  --border: rgba(255, 255, 255, 0.08);
  --border-strong: rgba(255, 255, 255, 0.14);
  --text: #f2f3f5;
  --text-muted: #8a8f98;
  --dim: #8a8f98;
  --text-faint: #5e636c;
  --dim2: #5e636c;
  --lp-muted: #a7adb7;
  --lp-faint: #949ba6;
  --accent-ink-text: #ccff00;
  --accent-glow: rgba(var(--accent-rgb), 0.22);
  --good: #5be08a;
  --gp-empty: rgba(255, 255, 255, 0.18);
  /* Re-declaring a custom prop does NOT retroactively change inherited
     `color` on descendants — only NEW var() reads. So set `color` here too,
     otherwise island headings inherit the page's dark ink over their dark bg. */
  color: var(--text);
}

/* The interval-tab strip inside the (light) Pro card uses a hardcoded dark
   fill; lighten it so it sits inside the white card. */
:root[data-theme="light"] .lp-int-tabs {
  background: rgba(12, 13, 16, 0.05);
  border-color: var(--line);
}
/* Shadows are tuned per theme. rgba(0,0,0,.82) is right against a near-black
   page and reads as a dirty smudge on a near-white one, so light theme uses a
   tighter, much softer cast. */
:root[data-theme="light"] .lp-fscreen--flip .lp-fscreen-photo {
  filter: drop-shadow(30px 6px 36px rgba(12, 13, 16, 0.26));
}
:root[data-theme="light"] .lp-fscreen--wide .lp-fscreen-photo img {
  filter: drop-shadow(0 0 34px rgba(12, 13, 16, 0.26));
}
:root[data-theme="light"] .lp-fscreen--wide .lp-spec-strip {
  text-shadow: 0 2px 14px rgba(245, 246, 248, 0.95), 0 0 34px rgba(245, 246, 248, 0.85);
}
/* No fade on the light page: ramping a dark photograph into white reads as a
   grey smear, not a dissolve. The band keeps crisp edges and sits as a
   deliberate dark island, the same way the cinematic band does. */
:root[data-theme="light"] .lp-bleed-photo::after { background: none; }
/* CTA band button is a dark chip on the volt band → keep its label bright volt. */
/* The band button is a plain outline on the page now, not a dark chip on a
   volt fill, so it takes the page's ink. Tinted with the accent it measured
   4.41:1 on white, just under AA. */
:root[data-theme="light"] .lp-band-btn { color: var(--text); }

/* Framing so the dark tiles/bands read as deliberate on the light page. */
:root[data-theme="light"] .lp-ai {
  box-shadow: 0 24px 64px -30px rgba(12, 13, 16, 0.40);
}
/* The ledger is a recreation of the app's own dark logging screen, so it stays
   dark on the light page for the same reason the phone shots do: its active
   row is a volt-on-near-black control that has no light-theme equivalent in
   the product. Softer cast, because a dark-page shadow smudges on white. */
:root[data-theme="light"] .lp-ledger {
  box-shadow: 0 26px 60px -30px rgba(12, 13, 16, 0.42);
}

/* ── Nav (light) ── */
:root[data-theme="light"] .lp-nav.scrolled {
  background: rgba(255, 255, 255, 0.82);
  border-bottom-color: var(--line);
}
:root[data-theme="light"] .lp-nav-links a { color: #566072; }
:root[data-theme="light"] .lp-nav-links a:hover,
:root[data-theme="light"] .lp-login:hover { color: var(--text); }
:root[data-theme="light"] .lp-login { color: #566072; }
:root[data-theme="light"] .lp-word { color: var(--text); }
:root[data-theme="light"] .lp-nav-links a.is-active { color: var(--accent-ink-text); }
:root[data-theme="light"] .lp-nav-links a.is-active::after { background: var(--accent-ink-text); }
/* Same wash/border pair the toggle, picker and burger take on the light page,
   so the nav keeps reading as one control family in both themes. */
:root[data-theme="light"] .lp-cta-sm {
  background: rgba(12, 13, 16, 0.04);
  border-color: rgba(12, 13, 16, 0.12);
}
:root[data-theme="light"] .lp-cta-sm:hover {
  border-color: rgba(12, 13, 16, 0.28);
  background: rgba(var(--accent-rgb), .10);
}
:root[data-theme="light"] .lp-burger {
  background: rgba(12, 13, 16, 0.04);
  color: var(--text);
  border-color: rgba(12, 13, 16, 0.12);
}
:root[data-theme="light"] .lp-burger:hover { border-color: rgba(12, 13, 16, 0.28); }

/* ── Hero (light) ── */
:root[data-theme="light"] .lp-hero-grid {
  background-image:
    linear-gradient(rgba(12, 13, 16, 0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(12, 13, 16, 0.05) 1px, transparent 1px);
}
:root[data-theme="light"] .lp-hero-glow { background: radial-gradient(circle, rgba(114, 148, 0, 0.10), transparent 65%); }
:root[data-theme="light"] .lp-hero-glow2 { background: radial-gradient(circle, rgba(43, 143, 201, 0.08), transparent 65%); }

/* ── Section eyebrows / volt-as-text in light sections ── */
:root[data-theme="light"] .lp-kicker { color: var(--accent-ink-text); }
:root[data-theme="light"] .lp-seo-tag { color: var(--accent-ink-text); }
:root[data-theme="light"] .lp-seo-tag::before { background: var(--accent-ink-text); }
:root[data-theme="light"] .lp-seo mark {
  background: linear-gradient(180deg, transparent 42%, rgba(114, 148, 0, 0.20) 42%);
}
:root[data-theme="light"] .lp-seo-cta-note { color: var(--lp-faint); }
:root[data-theme="light"] .lp-faq-item summary::after { color: var(--accent-ink-text); }
@media (hover: hover) {
  :root[data-theme="light"] .lp-faq-item summary:hover { color: var(--accent-ink-text); }
}
:root[data-theme="light"] .lp-flinks a.is-active { color: var(--accent-ink-text); }
:root[data-theme="light"] .lp-social a:hover,
:root[data-theme="light"] .lp-social a:focus-visible { color: var(--accent-ink-text); }

/* ── Testimonials: off-stars need a dark empty fill on white cards. ── */
:root[data-theme="light"] .gp-widget { --gp-empty: rgba(12, 13, 16, 0.14); }

/* ── Pricing: volt-as-text → olive; bright-volt frames/fills stay volt. ── */
:root[data-theme="light"] .lp-price.pro .lp-price-name,
:root[data-theme="light"] .lp-int-save,
:root[data-theme="light"] .lp-plan.free .lp-plan-amount .n,
:root[data-theme="light"] .lp-plan.feat .lp-plan-name,
:root[data-theme="light"] .lp-plan-offer .lp-off-pct,
:root[data-theme="light"] .lp-plan-feats svg,
:root[data-theme="light"] .lp-price-cta.ghost:hover,
:root[data-theme="light"] .lp-plans-more a:hover,
:root[data-theme="light"] .pz-card:not(.pz-pro) .pz-amount .n,
:root[data-theme="light"] .pz-cta.ghost:hover,
:root[data-theme="light"] .pr-table thead th.pro,
:root[data-theme="light"] .pr-table svg.ok { color: var(--accent-ink-text); }
:root[data-theme="light"] .lp-price-cta.ghost:hover,
:root[data-theme="light"] .pz-cta.ghost:hover { border-color: var(--accent-ink-text); }
/* Active interval tab is a black fill in light — its save % must use white ink
   (the group rule above out-orders the base .lp-int-tab.active .lp-int-save). */
:root[data-theme="light"] .lp-int-tab.active .lp-int-save { color: var(--ink); }

/* ── Language picker (light) ── */
:root[data-theme="light"] .lang-pick-btn {
  background: rgba(12, 13, 16, 0.04);
  color: #566072;
  border-color: rgba(12, 13, 16, 0.12);
}
:root[data-theme="light"] .lang-pick-btn:hover,
:root[data-theme="light"] .lang-pick-btn[aria-expanded="true"] {
  color: var(--text);
  border-color: rgba(12, 13, 16, 0.28);
}
:root[data-theme="light"] .lang-pick-menu {
  background: #ffffff;
  border-color: rgba(12, 13, 16, 0.12);
  box-shadow: 0 18px 50px -12px rgba(12, 13, 16, 0.22);
}
:root[data-theme="light"] .lang-pick-menu [data-code] { color: #566072; }
:root[data-theme="light"] .lang-pick-menu [data-code]:hover {
  color: var(--text);
  background: rgba(12, 13, 16, 0.05);
}
:root[data-theme="light"] .lang-pick-menu [data-code].active { color: var(--accent-ink-text); }

/* ── Theme toggle button (nav, beside the language picker) ── */
.lp-theme-toggle {
  display: flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; flex: none; padding: 0;
  background: rgba(255, 255, 255, 0.04);
  color: #8a8f98;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px; cursor: pointer;
  transition: color .15s ease, border-color .15s ease;
}
.lp-theme-toggle:hover { color: #f2f3f5; border-color: rgba(255, 255, 255, 0.22); }
.lp-theme-toggle svg { width: 18px; height: 18px; display: block; }
/* Show the sun in dark mode (click → light); the moon in light mode (click → dark). */
.lp-theme-toggle .i-moon { display: none; }
.lp-theme-toggle .i-sun { display: block; }
:root[data-theme="light"] .lp-theme-toggle {
  background: rgba(12, 13, 16, 0.04);
  color: #566072;
  border-color: rgba(12, 13, 16, 0.12);
}
:root[data-theme="light"] .lp-theme-toggle:hover { color: var(--text); border-color: rgba(12, 13, 16, 0.28); }
:root[data-theme="light"] .lp-theme-toggle .i-sun { display: none; }
:root[data-theme="light"] .lp-theme-toggle .i-moon { display: block; }

/* Mobile hamburger drawer panel: hardcoded dark → light (nav links use
   var(--text) so they flip automatically; only the panel surface is baked). */
@media (max-width: 1000px) {
  :root[data-theme="light"] .lp-menu {
    background: #ffffff;
    border-left-color: var(--line);
    box-shadow: -28px 0 60px -18px rgba(12, 13, 16, 0.22);
  }
}

/* ─── Link + button pointer motion ───────────────────────────────────────────
   1. Nav: ONE shared bar that slides between hovered links, so moving from
      "Features" to "AI Trainer" reads as travel, not a cross-fade. The element
      and its geometry come from public/js/landing-scroll.js (landing) and
      public/js/page-scroll.js (every other marketing page).
   2. Footer + prose links: CSS-only underline. It grows from the LEFT edge on
      enter and keeps travelling right on exit (rest origin = right, hover
      origin = left), so the line always sweeps one way.
   3. Buttons: a hover ripple that starts under the pointer, plus a short press
      shrink. Composed/button-like links only — never plain text links. */

/* ── 1. Nav sliding underline (desktop, fine pointers) ── */
.lp-nav-links { position: relative; }
.lp-nav-underline {
  position: absolute; left: 0; top: 0; width: 0; height: 2px;
  border-radius: 2px; background: var(--accent-ink-text);
  pointer-events: none;
  transform: translateX(0) scaleX(0);
  transform-origin: left center;
  transition: transform 0.2s cubic-bezier(0.2, 0.8, 0.3, 1),
              width 0.2s cubic-bezier(0.2, 0.8, 0.3, 1);
}
/* The drawer is a vertical list with no hover — the slider is JS-disabled
   there too, this just guarantees nothing stray can paint. */
@media (max-width: 1000px) { .lp-nav-underline { display: none; } }

/* ── 2. Grow-from-left underline for text links ── */
@media (hover: hover) and (pointer: fine) and (min-width: 901px) {
  .lp-flinks a, .lp-login-original { position: relative; }
  .lp-flinks a::after, .lp-login-original::after {
    content: ''; position: absolute; left: 0; right: 0; bottom: -4px;
    height: 1.5px; border-radius: 2px; background: currentColor;
    transform: scaleX(0); transform-origin: right center;
    transition: transform 0.22s ease;
  }
  /* Log in sits beside the other nav links, so its underline matches their
     volt sliding underline (.lp-nav-underline, var(--accent-ink-text))
     instead of the footer-link currentColor treatment above. */
  .lp-login-original::after { background: var(--accent-ink-text); }
  .lp-flinks a:hover::after,
  .lp-flinks a:focus-visible::after,
  .lp-login-original:hover::after,
  .lp-login-original:focus-visible::after { transform: scaleX(1); transform-origin: left center; }
}

/* ── 3. Button hover ripple + press shrink ── */
.lp-cta-sm, .lp-btn-primary, .lp-btn-ghost, .lp-band-btn, .lp-play-badge, .lp-app-store-badge, .pz-cta, .gp-write {
  position: relative; overflow: hidden; z-index: 0;
}
.lp-cta-sm, .lp-btn-primary, .lp-btn-ghost, .lp-band-btn, .lp-play-badge, .lp-app-store-badge {
  transition: transform 0.09s ease, border-color 0.15s ease, background 0.15s ease;
}
.pz-cta {
  transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease,
              transform 0.09s ease;
}
.gp-write { transition: background 0.2s ease, box-shadow 0.2s ease, transform 0.09s ease; }
.lp-cta-sm:active, .lp-btn-primary:active, .lp-btn-ghost:active,
.lp-band-btn:active, .lp-play-badge:active, .lp-app-store-badge:active,
.pz-cta:active, .gp-write:active { transform: scale(0.96); }

/* z-index -1 keeps the tint above the button's own fill but under its label
   (the button is a stacking context via z-index: 0 above). */
.lp-ripple {
  position: absolute; z-index: -1; border-radius: 50%; pointer-events: none;
  background: var(--lp-ripple, rgba(255, 255, 255, 0.10));
  transform: scale(0); opacity: 0;
  transition: transform 0.45s cubic-bezier(0.2, 0.8, 0.3, 1), opacity 0.25s ease;
}
.lp-ripple.is-in {
  transform: scale(1); opacity: 1;
  transition: transform 0.45s cubic-bezier(0.2, 0.8, 0.3, 1), opacity 0.12s ease;
}
.lp-ripple.is-in.is-out {
  opacity: 0;
  transition: transform 0.45s cubic-bezier(0.2, 0.8, 0.3, 1), opacity 0.25s ease;
}

/* Ripple ink flips with the surface: dark ink on bright fills, light ink on
   dark ones. The light theme swaps volt fills for black, so it flips again. */
.lp-cta-sm, .lp-btn-primary, .pz-cta.solid { --lp-ripple: rgba(12, 13, 16, 0.10); }
.lp-btn-ghost, .pz-cta.ghost { --lp-ripple: rgba(255, 255, 255, 0.10); }
.lp-band-btn, .lp-play-badge, .lp-app-store-badge { --lp-ripple: rgba(255, 255, 255, 0.14); }
.gp-write { --lp-ripple: rgba(255, 255, 255, 0.20); }
:root[data-theme="light"] .lp-cta-sm,
:root[data-theme="light"] .lp-btn-primary,
:root[data-theme="light"] .pz-cta.solid { --lp-ripple: rgba(255, 255, 255, 0.18); }
:root[data-theme="light"] .lp-btn-ghost,
:root[data-theme="light"] .pz-cta.ghost { --lp-ripple: rgba(12, 13, 16, 0.08); }
:root[data-theme="light"] .lp-band-btn { --lp-ripple: rgba(12, 13, 16, 0.10); }

@media (prefers-reduced-motion: reduce) {
  .lp-nav-underline { transition: none; }
  .lp-flinks a::after { transition: none; }
  .lp-ripple { display: none; }
  .lp-cta-sm, .lp-btn-primary, .lp-btn-ghost,
  .lp-band-btn, .lp-play-badge, .lp-app-store-badge, .pz-cta, .gp-write { transition: none; }
  /* The device mocks' idle float is decoration; the shot itself is the point,
     and it reads exactly the same standing still. */
  .lp-phone { animation: none; }
}

/* The trainer shot's slide-in is a desktop flourish: it arrives from off the
   LEFT EDGE of the viewport, which only exists in the two-column layout. In
   the stacked layout its trigger sits below the fold, so the shot would simply
   stay at opacity 0 — visible in the box model, invisible on screen. */
@media (prefers-reduced-motion: no-preference) and (max-width: 1000px) {
  #landing .lp-fscreen--flip .lp-fscreen-photo.reveal,
  #landing .lp-fscreen--flip .lp-fscreen-photo.reveal.in {
    opacity: 1; transform: none; transition: none;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   FEATURE SCREENS, SECOND WAVE
   Eight compositions that sit after the AI Trainer screen, plus the pair that
   now hangs under the Progress chart. Each one is a DIFFERENT skeleton — no
   two share a layout and none of them repeats the copy-beside-a-device split
   the hero and the trainer screen already own:

     #plan       two stacked full-width rows of different cardinality
                 (four answers in, seven days out)
     #library    a single full-bleed shelf, copy above it, nothing beside it
     #cardio     split header row (headline left / line right), then a band
     #bodyweight one short wide panel with the sentence INSIDE the data
     #share      poster: the artwork first, the sentence as its caption
     #offline    three moments on one hairline
     #languages  one very large word, changing language
     #promise    type only, no artwork at all
     Progress    unchanged chart, with a subordinate pair beneath it

   Every animation here is transform/opacity, under 600ms, and defined only
   inside `prefers-reduced-motion: no-preference`, so the reduced-motion and
   no-JS renders ARE the finished end states rather than a stripped-down
   version of them. The `.is-in` / `.is-live` classes come from index.html.
   ═══════════════════════════════════════════════════════════════════════════ */

#landing {
  /* One curve for this wave, the same decelerating ease the page's existing
     reveals already use. */
  --lp-ease: cubic-bezier(0.16, 1, 0.3, 1);
  /* Body-weight trend stroke. Neutral by rule (design.md): the chart never
     implies that up or down is good on its own. */
  --lp-wline: #c9ced6;
}
:root[data-theme="light"] #landing { --lp-wline: #7b828e; }

.lp-gen, .lp-shelf, .lp-cardio, .lp-weight,
.lp-share, .lp-offline, .lp-langs, .lp-promise {
  max-width: 1280px; margin: 0 auto; padding: 78px 56px;
}
/* Same display-size, light-weight headline the feature screens above use, so
   the second half of the page is set in one voice. */
#landing .lp-gen h2, #landing .lp-shelf h2, #landing .lp-cardio h2,
#landing .lp-weight h2, #landing .lp-share h2, #landing .lp-offline h2,
#landing .lp-langs h2 {
  margin: 0; font: 400 48px/1.08 var(--font-ui); letter-spacing: -1.7px;
  text-wrap: balance;
}
.lp-gen-head p, .lp-shelf-copy p, .lp-weight-copy p,
.lp-share-copy p, .lp-offline-copy p, .lp-langs-copy p {
  margin: 18px 0 0; color: var(--lp-muted); font: 400 17px/1.6 var(--font-ui);
  text-wrap: balance;
}

/* ── #plan — four answers in, a week out ─────────────────────────────────── */
.lp-gen-head { max-width: 720px; margin: 0 auto; text-align: center; }
.lp-gen-stage { margin-top: 48px; }
.lp-gen-answers {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px;
}
.lp-gen-q {
  display: flex; flex-direction: column; gap: 10px; min-width: 0;
  padding: 16px 18px; border-radius: 16px;
  background: var(--card); border: 1px solid var(--line); text-align: left;
}
.lp-gen-q-label {
  font: 600 9.5px var(--font-mono); letter-spacing: 1.4px; color: var(--lp-faint);
}
/* The value arrives from under its own label, so each question visibly
   answers itself instead of the whole chip fading in as one lump. */
.lp-gen-q-slot { display: block; overflow: hidden; }
.lp-gen-q-value {
  display: block; font: 600 19px/1.2 var(--font-ui); letter-spacing: -0.3px;
  color: var(--text);
}
.lp-gen-seam { position: relative; height: 46px; }
.lp-gen-seam::before {
  content: ''; position: absolute; left: 50%; top: 0; bottom: 8px; width: 1px;
  background: linear-gradient(var(--line), var(--line2));
}
.lp-gen-seam::after {
  content: ''; position: absolute; left: 50%; bottom: 0;
  width: 7px; height: 7px; margin-left: -3px; border-radius: 50%;
  background: var(--line2);
}
.lp-gen-week {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 10px; margin: 0; padding: 0; list-style: none;
}
.lp-gen-day {
  display: flex; flex-direction: column; gap: 6px; min-width: 0;
  min-height: 132px; padding: 16px 14px; border-radius: 18px;
  background: var(--card); border: 1px solid var(--line);
}
.lp-gen-day::before {
  content: ''; width: 22px; height: 2px; border-radius: 2px;
  background: var(--accent); margin-bottom: 4px;
}
.lp-gen-dow {
  font: 600 9.5px var(--font-mono); letter-spacing: 1.4px; color: var(--lp-faint);
}
.lp-gen-name {
  margin-top: auto; font: 600 17px/1.2 var(--font-ui); letter-spacing: -0.3px;
}
.lp-gen-n { font: 400 11px var(--font-ui); color: var(--lp-muted); min-height: 1em; }
.lp-gen-day--rest { background: transparent; border-style: dashed; }
.lp-gen-day--rest::before { background: var(--line2); }
.lp-gen-day--rest .lp-gen-name { font-weight: 400; color: var(--lp-faint); }
.lp-gen-note {
  margin: 26px 0 0; text-align: center;
  color: var(--lp-faint); font: 400 14px/1.6 var(--font-ui);
}

/* ── #library — the shelf ────────────────────────────────────────────────── */
.lp-shelf-copy { max-width: 660px; margin: 0 auto; text-align: center; }
.lp-shelf-chips {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: 8px; margin-top: 28px;
}
/* Chip geometry copied from the app's own picker filters
   (app/src/screens/plans/plans.css .picker-filter), so the row on this page is
   the row in the app. */
.lp-shelf-search {
  display: inline-flex; align-items: center; gap: 8px; padding: 7px 15px;
  border-radius: var(--radius-pill); background: var(--card);
  border: 1px solid var(--line); color: var(--lp-faint);
  font: 400 12.5px var(--font-ui);
}
.lp-shelf-search svg { width: 13px; height: 13px; flex: none; }
.lp-shelf-chip {
  padding: 7px 13px; border-radius: var(--radius-pill);
  background: var(--card-2); border: 1px solid var(--line);
  color: var(--lp-muted); font: 600 12px var(--font-ui);
}
.lp-shelf-chip.is-on {
  background: rgba(var(--accent-rgb), 0.12);
  border-color: rgba(var(--accent-rgb), 0.45);
  color: var(--accent-ink-text);
}
/* Full bleed: the rail is wider than the page and runs off both edges, which
   is what makes it read as a shelf that continues past the screen rather than
   a row of seven cards. #landing already clips overflow-x. */
.lp-shelf-rail {
  width: 100vw; margin-left: calc(50% - 50vw); margin-top: 46px;
  display: flex; justify-content: center; gap: 18px;
  -webkit-mask-image: linear-gradient(to right, transparent, #000 9%, #000 91%, transparent);
  mask-image: linear-gradient(to right, transparent, #000 9%, #000 91%, transparent);
}
.lp-shelf-tile { flex: none; width: clamp(126px, 13.6vw, 190px); margin: 0; }
/* The plate stays light in BOTH themes. The demo art is dark grey line work on
   a transparent ground: on the near-black page it all but disappears, and
   inverting it turns a photoreal render into a negative. A pale plate is the
   surface this artwork was drawn for. */
.lp-shelf-plate {
  position: relative; display: block; aspect-ratio: 1 / 1; overflow: hidden;
  border-radius: 20px;
  background: linear-gradient(168deg, #f7f8fa 0%, #dfe3e8 100%);
  box-shadow: 0 24px 46px -28px rgba(0, 0, 0, 0.8),
              inset 0 0 0 1px rgba(12, 13, 16, 0.07);
}
/* Same sprite geometry as app/src/components/ExerciseAnimation.svelte: one
   1024x512 two-frame atlas laid out at 200% width and moved by -50%. */
.lp-shelf-sprite {
  position: absolute; inset: 0 auto auto 0; display: block;
  width: 200%; height: 100%; max-width: none;
  transform: translate3d(0, 0, 0);
}
.lp-shelf-tile figcaption {
  display: flex; flex-direction: column; gap: 3px; margin-top: 13px;
  text-align: center; font: 600 14px/1.3 var(--font-ui); letter-spacing: -0.2px;
}
.lp-shelf-tile figcaption span {
  font: 400 10px var(--font-mono); letter-spacing: 1.3px;
  text-transform: uppercase; color: var(--lp-faint);
}
:root[data-theme="light"] .lp-shelf-plate {
  background: linear-gradient(168deg, #ffffff 0%, #e7eaee 100%);
  box-shadow: 0 18px 34px -24px rgba(12, 13, 16, 0.34),
              inset 0 0 0 1px rgba(12, 13, 16, 0.08);
}

/* ── #cardio — split header, then the route band ─────────────────────────── */
.lp-cardio-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 48px;
}
.lp-cardio-head h2 { flex: 1 1 auto; min-width: 0; }
.lp-cardio-head p {
  flex: 0 1 320px; margin: 0; text-align: right;
  color: var(--lp-muted); font: 400 16px/1.55 var(--font-ui);
}
.lp-cardio-band {
  position: relative; overflow: hidden; margin-top: 44px;
  padding: 26px 30px 24px; border-radius: 28px;
  background: var(--card); border: 1px solid var(--line);
  box-shadow: 0 44px 92px -46px rgba(0, 0, 0, 0.9);
}
/* The volt corner glow the real cardio share card paints behind its header. */
.lp-cardio-band::before {
  content: ''; position: absolute; top: -180px; right: -140px;
  width: 460px; height: 460px; border-radius: 50%; pointer-events: none;
  background: radial-gradient(circle, rgba(var(--accent-rgb), 0.085), transparent 72%);
}
.lp-cardio-type {
  position: relative; display: inline-flex; align-items: center; gap: 7px;
  padding: 6px 13px; border-radius: var(--radius-pill);
  border: 1px solid var(--line2); color: var(--lp-muted);
  font: 600 10px var(--font-mono); letter-spacing: 1.6px;
}
.lp-cardio-type b {
  width: 6px; height: 6px; border-radius: 50%; background: var(--accent);
}
.lp-cardio-route {
  position: relative; display: block; width: 100%;
  height: clamp(150px, 21vw, 290px); margin: 8px 0 0; overflow: visible;
}
.lp-cardio-start { fill: none; stroke: var(--lp-faint); stroke-width: 2.5; }
.lp-cardio-end {
  fill: var(--accent);
  filter: drop-shadow(0 0 12px rgba(var(--accent-rgb), 0.6));
}
.lp-cardio-stats {
  position: relative; display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 20px; margin: 22px 0 0; padding-top: 20px;
  border-top: 1px solid var(--line);
}
.lp-cardio-stats dt {
  font: 600 10px var(--font-mono); letter-spacing: 1.6px; color: var(--lp-muted);
}
.lp-cardio-stats dd {
  margin: 9px 0 0; font: 400 34px/1 var(--font-ui); letter-spacing: -1.2px;
  color: var(--text); font-variant-numeric: tabular-nums;
}
.lp-cardio-stats dd span {
  margin-left: 4px; font-size: 16px; letter-spacing: -0.3px; color: var(--lp-muted);
}
.lp-cardio-stats div:first-child dd { color: var(--accent); }

/* ── #bodyweight — the sentence inside the data ──────────────────────────── */
.lp-weight-panel {
  position: relative; overflow: hidden;
  display: grid; grid-template-columns: minmax(0, 1.1fr) auto;
  gap: 44px; align-items: start;
  padding: 36px 40px 0; border-radius: 26px;
  background: var(--card); border: 1px solid var(--line);
  box-shadow: 0 30px 70px -42px rgba(0, 0, 0, 0.6);
}
.lp-weight-copy { min-width: 0; max-width: 460px; }
.lp-weight-read {
  display: flex; flex-direction: column; align-items: flex-end; gap: 5px;
  text-align: right; white-space: nowrap;
}
.lp-weight-goal {
  padding: 5px 10px; border-radius: var(--radius-pill);
  background: var(--card-2); border: 1px solid var(--line);
  color: var(--lp-muted); font: 600 9.5px var(--font-mono); letter-spacing: 1.3px;
}
.lp-weight-label {
  margin-top: 4px; font: 600 9.5px var(--font-mono); letter-spacing: 1.4px;
  color: var(--lp-faint);
}
.lp-weight-value {
  font: 400 62px/1 var(--font-ui); letter-spacing: -2.2px;
  font-variant-numeric: tabular-nums;
}
.lp-weight-value em {
  font-style: normal; font-size: 23px; letter-spacing: -0.6px;
  margin-left: 4px; color: var(--lp-muted);
}
/* The arrow is the only coloured thing, and it is never the only signal: the
   direction glyph and the GOAL chip above both say it in text. */
.lp-weight-delta { font: 400 13px var(--font-ui); color: var(--lp-faint); }
.lp-weight-delta b { color: var(--good); font-weight: 600; }
.lp-weight-logged { font: 400 12px var(--font-ui); color: var(--lp-faint); }
.lp-weight-trend {
  grid-column: 1 / -1; display: block;
  width: calc(100% + 80px); margin: -14px -40px 0; height: 150px;
}

/* ── #share — the artwork first, the sentence as its caption ─────────────── */
.lp-share { text-align: center; }
.lp-share-fan {
  position: relative; display: flex; align-items: center; justify-content: center;
  height: clamp(292px, 32vw, 396px);
}
.lp-share-card {
  position: absolute; display: flex; flex-direction: column; overflow: hidden;
  padding: 2.2em; border-radius: 1.9em; text-align: left;
  background: var(--bg); border: 1px solid var(--line); color: var(--text);
  box-shadow: 0 44px 84px -36px rgba(0, 0, 0, 0.92);
  /* Every measurement inside a card is in `em`, so one font-size scales the
     whole 1080px canvas down to any width without a second set of rules. */
  font-size: clamp(3.5px, 0.465vw, 5.5px);
}
.lp-share-card--story {
  width: clamp(120px, 15.2vw, 182px); aspect-ratio: 9 / 16;
  transform: translateX(-70%) rotate(-8.5deg);
}
.lp-share-card--post {
  width: clamp(206px, 26vw, 306px); aspect-ratio: 1 / 1; z-index: 1;
  transform: translateX(20%) rotate(3.5deg);
}
.lp-share-head { display: flex; align-items: center; gap: 0.9em; }
.lp-share-logo {
  width: 3.4em; height: 3.4em; border-radius: 0.9em; display: block; flex: none;
}
.lp-share-card--story .lp-share-logo { width: 2.8em; height: 2.8em; border-radius: 0.75em; }
.lp-share-word { font: 600 2.6em/1.15 var(--font-ui); letter-spacing: -0.03em; }
.lp-share-card--story .lp-share-word { font-size: 2.1em; }
.lp-share-word i { font-style: normal; color: var(--accent); }
.lp-share-stamp {
  margin-left: auto; font: 400 1.4em var(--font-ui);
  letter-spacing: 0.14em; color: var(--dim);
}
.lp-share-daychip {
  margin-left: auto; display: inline-flex; align-items: center; gap: 0.6em;
  font: 400 1.6em var(--font-ui); letter-spacing: 0.02em; color: var(--dim);
}
.lp-share-daychip b { width: 0.5em; height: 0.5em; border-radius: 50%; background: var(--accent); }
.lp-share-day { margin-top: 0.8em; font: 700 8em/0.98 var(--font-ui); letter-spacing: -0.035em; }
.lp-share-meta { margin-top: 0.7em; font: 400 2em/1.3 var(--font-ui); color: var(--dim); }
.lp-share-panel {
  display: flex; flex-direction: column; gap: 0.5em;
  margin-top: 1.2em; padding: 1.4em; border-radius: 1.5em;
  background: linear-gradient(155deg, #1b1d23, #111216);
}
.lp-share-kicker {
  font: 400 1.5em/1.2 var(--font-ui); letter-spacing: 0.16em; color: var(--dim);
}
.lp-share-lift {
  font: 700 6.8em/1 var(--font-ui); letter-spacing: -0.04em; color: var(--accent);
}
.lp-share-lift em { font-style: normal; font-size: 0.38em; margin-left: 0.2em; }
.lp-share-liftname { font: 600 2.2em/1.2 var(--font-ui); letter-spacing: -0.02em; }
.lp-share-liftsub { font: 400 1.5em/1.2 var(--font-ui); letter-spacing: 0.05em; color: var(--dim); }
.lp-share-prs { display: flex; align-items: baseline; gap: 0.7em; margin-top: 1.1em; }
.lp-share-prs b { font: 700 4.2em/1 var(--font-ui); letter-spacing: -0.03em; color: var(--good); }
.lp-share-prs span { font: 400 1.7em var(--font-ui); letter-spacing: 0.14em; color: var(--dim); }
.lp-share-foot { margin-top: auto; padding-top: 1em; font: 400 1.8em/1.2 var(--font-ui); color: var(--text); }
.lp-share-streak {
  display: flex; flex-direction: column; align-items: center; gap: 0.3em;
  margin-top: 2.6em; text-align: center;
}
.lp-share-big {
  font: 700 14em/0.9 var(--font-ui); letter-spacing: -0.06em; color: var(--accent);
}
.lp-share-caption { font: 700 2.5em/1.2 var(--font-ui); letter-spacing: -0.02em; }
.lp-share-heat { margin-top: auto; }
.lp-share-heat-head {
  display: flex; justify-content: space-between; gap: 1em; margin-bottom: 0.9em;
  font: 400 1.15em var(--font-ui); letter-spacing: 0.1em; color: var(--text-faint);
}
/* 16 weeks across, Monday to Sunday down — the same grid the app's story card
   draws, and the same one under the Progress chart above. */
.lp-share-heat-grid {
  display: grid; grid-auto-flow: column;
  grid-template-rows: repeat(7, 1fr); grid-auto-columns: 1fr; gap: 0.42em;
}
.lp-share-heat-grid i { aspect-ratio: 1 / 1; border-radius: 0.28em; background: #20232a; }
.lp-share-heat-grid i.on { background: var(--accent); }
.lp-share-formats {
  display: flex; justify-content: center; gap: 8px; margin-top: 34px;
}
.lp-share-format {
  padding: 7px 14px; border-radius: var(--radius-pill);
  background: var(--card-2); border: 1px solid var(--line);
  color: var(--lp-muted); font: 600 12px var(--font-ui);
}
.lp-share-format.is-on {
  background: rgba(var(--accent-rgb), 0.12);
  border-color: rgba(var(--accent-rgb), 0.45);
  color: var(--accent-ink-text);
}
.lp-share-copy { max-width: 620px; margin: 30px auto 0; }

/* ── #offline — three moments on one hairline ────────────────────────────── */
.lp-offline-copy { max-width: 620px; margin: 0 auto; text-align: center; }
.lp-offline-rail {
  position: relative; display: flex; align-items: center;
  justify-content: space-between; gap: 20px; margin-top: 62px;
}
.lp-offline-line {
  position: absolute; left: 6%; right: 6%; top: 50%; height: 1px;
  background: var(--line); overflow: hidden;
}
.lp-offline-line-fill {
  display: block; width: 100%; height: 100%; transform-origin: 0 50%;
  background: linear-gradient(90deg, var(--line2), var(--accent));
}
.lp-offline-beat {
  position: relative; display: flex; flex-direction: column; align-items: center;
  gap: 11px; padding: 0 20px; background: var(--bg);
}
.lp-offline-beat--wide { max-width: 400px; }
.lp-offline-mark {
  display: flex; align-items: center; justify-content: center; flex: none;
  width: 46px; height: 46px; border-radius: 50%;
  background: var(--card); border: 1px solid var(--line2); color: var(--lp-muted);
}
.lp-offline-mark svg { width: 20px; height: 20px; }
.lp-offline-mark--done {
  background: var(--accent); border-color: transparent; color: var(--ink);
}
.lp-offline-label {
  font: 600 10px var(--font-mono); letter-spacing: 1.6px; color: var(--lp-faint);
}
.lp-offline-set {
  display: flex; align-items: center; gap: 11px;
  padding: 11px 15px; border-radius: 14px;
  background: var(--card); border: 1px solid var(--line);
}
.lp-offline-chk {
  display: flex; align-items: center; justify-content: center; flex: none;
  width: 19px; height: 19px; border-radius: 6px;
  background: var(--accent); color: var(--ink); font: 700 11px var(--font-ui);
}
.lp-offline-setn { font: 600 10px var(--font-mono); letter-spacing: 1.3px; color: var(--lp-muted); }
.lp-offline-setv { font: 400 15px var(--font-ui); letter-spacing: -0.2px; }
.lp-offline-note {
  text-align: center; font: 400 12.5px/1.45 var(--font-ui); color: var(--lp-muted);
}

/* ── #languages — one word, changing language ────────────────────────────── */
.lp-langs { text-align: center; }
.lp-langs-cycle {
  position: relative; height: 1.18em; margin: 0;
  font: 400 clamp(38px, 7.4vw, 104px)/1.18 var(--font-ui); letter-spacing: -0.035em;
}
/* Every translation is stacked in the same box and cross-faded, so the line
   never reflows as the language changes — and the static state is simply the
   English one, which is exactly what reduced motion and no-JS should see. */
.lp-langs-cycle span {
  position: absolute; inset: 0; display: flex;
  align-items: center; justify-content: center; white-space: nowrap;
  opacity: 0;
}
.lp-langs-cycle span:first-child { opacity: 1; }
.lp-langs-copy { max-width: 620px; margin: 26px auto 0; }
.lp-langs-list {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 8px 22px;
  margin: 30px 0 0; padding: 0; list-style: none;
  font: 400 13px var(--font-ui); color: var(--lp-faint);
}

/* ── #promise — type, and nothing else ───────────────────────────────────── */
.lp-promise { max-width: 800px; text-align: center; }
.lp-promise .lp-section-eyebrow { margin-bottom: 20px; }
.lp-promise-lines {
  display: flex; flex-direction: column; gap: 4px; margin: 0;
  font: 400 clamp(27px, 4.1vw, 46px)/1.2 var(--font-ui); letter-spacing: -1.4px;
  color: var(--lp-muted); text-wrap: balance;
}
.lp-promise-last { color: var(--text); }
.lp-promise-note {
  margin: 28px 0 0; color: var(--lp-faint); font: 400 15px/1.6 var(--font-ui);
  text-wrap: balance;
}

/* ── Progress: the subordinate pair under the chart ──────────────────────── */
/* The chart keeps the screen. These two are capped narrower than it, set a
   step quieter, and sit BELOW it, so the screen still has one focal point. */
.lp-fscreen--wide { min-height: 0; grid-template-rows: auto minmax(200px, 44vh) auto; }
.lp-progress-sub {
  display: grid; grid-template-columns: minmax(0, 0.86fr) minmax(0, 1.14fr);
  gap: 20px; width: 100%; max-width: 940px; margin: 46px auto 0; text-align: left;
}
.lp-progress-heat, .lp-progress-report {
  padding: 20px 22px; border-radius: 20px;
  background: var(--card); border: 1px solid var(--line);
}
.lp-progress-cardhead {
  display: flex; align-items: baseline; justify-content: space-between; gap: 14px;
}
.lp-progress-cardtitle { font: 600 15px var(--font-ui); letter-spacing: -0.2px; }
.lp-progress-cardmeta {
  font: 400 15px var(--font-ui); color: var(--text);
  font-variant-numeric: tabular-nums;
}
.lp-progress-cardmeta-q { color: var(--lp-faint); font-size: 12px; }
.lp-progress-heat-months {
  display: flex; gap: 0; max-width: 338px; margin: 16px auto 5px; padding-left: 34px;
  font: 400 10px var(--font-mono); letter-spacing: 0.6px; color: var(--lp-faint);
}
.lp-progress-heat-months span { flex: 1 1 0; }
.lp-progress-heat-body { display: flex; gap: 10px; max-width: 338px; margin: 0 auto; }
.lp-progress-heat-grid { max-width: 304px; }
.lp-progress-heat-days {
  display: flex; flex-direction: column; justify-content: space-between;
  flex: none; width: 24px; padding: 0;
  font: 400 9px var(--font-mono); color: var(--lp-faint);
}
/* Binary on purpose. app/src/screens/reports/heatmap.ts has no intensity ramp
   and ships no legend: a day was trained or it was not. */
.lp-progress-heat-grid {
  flex: 1 1 auto; display: grid; grid-auto-flow: column;
  grid-template-rows: repeat(7, 1fr); grid-auto-columns: 1fr; gap: 3px;
}
.lp-progress-heat-grid i { aspect-ratio: 1 / 1; border-radius: 3px; background: #1d2027; }
.lp-progress-heat-grid i.on {
  background: var(--accent); box-shadow: 0 0 5px rgba(var(--accent-rgb), 0.18);
}
/* The trained-day fill has to be restated for the light theme. The OFF rule
   below reads `[data-theme] .class i`, which outranks the plain
   `.lp-progress-heat-grid i.on` above it, so without repeating the fill here
   every cell went grey on the light page and the grid stopped saying
   anything at all. */
:root[data-theme="light"] .lp-progress-heat-grid i { background: #dce0e6; }
:root[data-theme="light"] .lp-progress-heat-grid i.on {
  background: var(--accent);
  box-shadow: 0 0 6px rgba(var(--accent-rgb), 0.25);
}

/* Cast shadows are theme-specific (design.md): the deep shadow tuned for the
   near-black page reads as a grey smudge on the near-white one. */
:root[data-theme="light"] .lp-cardio-band { box-shadow: 0 26px 50px -30px rgba(12, 13, 16, 0.4); }
:root[data-theme="light"] .lp-weight-panel { box-shadow: 0 16px 34px -22px rgba(12, 13, 16, 0.26); }
:root[data-theme="light"] .lp-share-card { box-shadow: 0 26px 52px -26px rgba(12, 13, 16, 0.42); }
.lp-progress-period {
  margin-top: 10px; font: 600 10px var(--font-mono); letter-spacing: 1.5px;
  color: var(--accent-ink-text);
}
.lp-progress-reviewlabel {
  margin-top: 16px; font: 600 9.5px var(--font-mono); letter-spacing: 1.4px;
  color: var(--lp-faint);
}
.lp-progress-review {
  margin: 8px 0 0; color: var(--lp-muted); font: 400 13.5px/1.6 var(--font-ui);
}
.lp-progress-kpis {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px; margin: 18px 0 0; padding-top: 16px; border-top: 1px solid var(--line);
}
.lp-progress-kpis dt {
  font: 600 9px var(--font-mono); letter-spacing: 1.3px; color: var(--lp-faint);
}
.lp-progress-kpis dd {
  margin: 7px 0 0; font: 400 26px/1 var(--font-ui); letter-spacing: -0.9px;
  font-variant-numeric: tabular-nums;
}
.lp-progress-kpi-sub {
  margin-top: 6px; font: 400 11px/1.35 var(--font-ui); color: var(--lp-muted);
  letter-spacing: 0;
}
#landing .lp-progress-kpis dd.lp-progress-kpi-sub { font-size: 11px; }

/* ── Motion for the second wave ──────────────────────────────────────────────
   Everything is inside `no-preference`, so a reader who asks for less motion
   (or has JS off) gets the finished composition with no hidden states to
   recover from. `.lp-staged` is added by index.html right before the observer
   starts, so nothing can be left invisible if the observer never runs. */
@media (prefers-reduced-motion: no-preference) {
  /* #plan — each question answers itself, then the week assembles. */
  .lp-staged .lp-gen-q { opacity: 0; }
  .lp-staged.is-in .lp-gen-q {
    animation: lp-rise-14 0.42s var(--lp-ease) both;
    animation-delay: calc(var(--i) * 80ms);
  }
  .lp-staged .lp-gen-q-value { transform: translateY(115%); }
  .lp-staged.is-in .lp-gen-q-value {
    animation: lp-slot 0.4s var(--lp-ease) both;
    animation-delay: calc(var(--i) * 80ms + 160ms);
  }
  .lp-staged .lp-gen-seam::before { transform: scaleY(0); transform-origin: 50% 0; }
  .lp-staged.is-in .lp-gen-seam::before { animation: lp-grow-y 0.34s var(--lp-ease) 440ms both; }
  .lp-staged .lp-gen-seam::after { opacity: 0; }
  .lp-staged.is-in .lp-gen-seam::after { animation: lp-fade 0.28s var(--lp-ease) 760ms both; }
  .lp-staged .lp-gen-day { opacity: 0; }
  .lp-staged.is-in .lp-gen-day {
    animation: lp-tile-in 0.44s var(--lp-ease) both;
    animation-delay: calc(820ms + var(--i) * 50ms);
  }

  /* #library — the shelf lands left to right, then each demo runs its own
     two-frame cycle at the app's 650ms, paused whenever it is off screen. */
  .lp-staged .lp-shelf-tile { opacity: 0; }
  .lp-staged.is-in .lp-shelf-tile {
    animation: lp-rise-20 0.5s var(--lp-ease) both;
    animation-delay: calc(var(--i) * 55ms);
  }
  .lp-shelf-sprite {
    animation: lp-shelf-flip 1.3s linear infinite;
    animation-play-state: paused;
    animation-delay: calc(var(--i) * -0.17s);
  }
  .lp-shelf-rail.is-live .lp-shelf-sprite { animation-play-state: running; }

  /* #cardio — the route draws itself, the finish pin lands on the last frame,
     the readouts follow it. */
  .lp-staged .lp-cardio-path { stroke-dasharray: 100; stroke-dashoffset: 100; }
  .lp-staged.is-in .lp-cardio-path {
    animation: lp-draw 0.6s cubic-bezier(0.22, 0.61, 0.36, 1) both;
  }
  .lp-staged .lp-cardio-start, .lp-staged .lp-cardio-end { opacity: 0; }
  .lp-staged.is-in .lp-cardio-start { animation: lp-fade 0.3s var(--lp-ease) 60ms both; }
  .lp-staged.is-in .lp-cardio-end { animation: lp-pin 0.36s var(--lp-ease) 560ms both; }
  .lp-staged .lp-cardio-stats div { opacity: 0; }
  .lp-staged.is-in .lp-cardio-stats div {
    animation: lp-rise-12 0.42s var(--lp-ease) both;
    animation-delay: calc(560ms + var(--i) * 70ms);
  }

  /* #bodyweight — the trend wipes in under the reading. */
  .lp-staged .lp-weight-trend { clip-path: inset(0 100% 0 0); }
  .lp-staged.is-in .lp-weight-trend {
    animation: lp-wipe 0.6s cubic-bezier(0.22, 0.61, 0.36, 1) 140ms both;
  }
  .lp-staged .lp-weight-read > * { opacity: 0; }
  .lp-staged.is-in .lp-weight-read > * { animation: lp-rise-10 0.4s var(--lp-ease) both; }
  .lp-staged.is-in .lp-weight-read > *:nth-child(2) { animation-delay: 60ms; }
  .lp-staged.is-in .lp-weight-read > *:nth-child(3) { animation-delay: 120ms; }
  .lp-staged.is-in .lp-weight-read > *:nth-child(4) { animation-delay: 180ms; }
  .lp-staged.is-in .lp-weight-read > *:nth-child(5) { animation-delay: 240ms; }

  /* #share — the two cards fan open from a closed stack. */
  .lp-staged .lp-share-card { opacity: 0; }
  .lp-staged.is-in .lp-share-card--story { animation: lp-fan-story 0.52s var(--lp-ease) both; }
  .lp-staged.is-in .lp-share-card--post { animation: lp-fan-post 0.52s var(--lp-ease) 90ms both; }

  /* #offline — the signal line runs across, the three moments arrive on it. */
  .lp-staged .lp-offline-line-fill { transform: scaleX(0); }
  .lp-staged.is-in .lp-offline-line-fill { animation: lp-grow-x 0.58s var(--lp-ease) 100ms both; }
  .lp-staged .lp-offline-beat { opacity: 0; }
  .lp-staged.is-in .lp-offline-beat {
    animation: lp-rise-12 0.44s var(--lp-ease) both;
    animation-delay: calc(var(--i) * 170ms);
  }

  /* #languages — the one deliberate loop on this half of the page. It is the
     content, not decoration: twelve real translations cannot be shown at once
     without turning into a list. It only runs while the section is on screen,
     and it holds still entirely under reduced motion. */
  .lp-langs-cycle.is-in span {
    animation: lp-lang-cycle 24s linear infinite backwards;
    animation-delay: calc(var(--i) * 2s);
    animation-play-state: paused;
  }
  .lp-langs-cycle.is-in.is-live span { animation-play-state: running; }
}

@keyframes lp-rise-10 { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@keyframes lp-rise-12 { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
@keyframes lp-rise-14 { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@keyframes lp-rise-20 { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: none; } }
@keyframes lp-tile-in { from { opacity: 0; transform: translateY(16px) scale(0.97); } to { opacity: 1; transform: none; } }
@keyframes lp-slot { from { transform: translateY(115%); } to { transform: none; } }
@keyframes lp-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes lp-pin { from { opacity: 0; transform: scale(0.4); } to { opacity: 1; transform: none; } }
@keyframes lp-grow-x { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes lp-grow-y { from { transform: scaleY(0); } to { transform: scaleY(1); } }
@keyframes lp-draw { from { stroke-dashoffset: 100; } to { stroke-dashoffset: 0; } }
@keyframes lp-wipe { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
/* The app cuts between the two demo frames; it does not cross-fade (see the
   component's own test). Two hard steps, 650ms each. */
@keyframes lp-shelf-flip {
  0%, 50% { transform: translate3d(0, 0, 0); }
  50.001%, 100% { transform: translate3d(-50%, 0, 0); }
}
@keyframes lp-fan-story {
  from { opacity: 0; transform: translateX(-50%) rotate(-15deg) scale(0.94); }
  to { opacity: 1; transform: translateX(-70%) rotate(-8.5deg); }
}
@keyframes lp-fan-post {
  from { opacity: 0; transform: translateX(11%) rotate(10deg) scale(0.95); }
  to { opacity: 1; transform: translateX(20%) rotate(3.5deg); }
}
/* Twelve two-second slots in one 24s turn; each word owns one of them. */
@keyframes lp-lang-cycle {
  0% { opacity: 0; transform: translateY(0.16em); }
  1.3% { opacity: 1; transform: translateY(0); }
  7% { opacity: 1; transform: translateY(0); }
  8.3%, 100% { opacity: 0; transform: translateY(-0.16em); }
}

/* ── Responsive: second wave ─────────────────────────────────────────────── */
@media (max-width: 1000px) {
  .lp-gen, .lp-shelf, .lp-cardio, .lp-weight,
  .lp-share, .lp-offline, .lp-langs, .lp-promise { padding: 60px 24px; }
  #landing .lp-gen h2, #landing .lp-shelf h2, #landing .lp-cardio h2,
  #landing .lp-weight h2, #landing .lp-share h2, #landing .lp-offline h2,
  #landing .lp-langs h2 { font-size: 38px; letter-spacing: -1.3px; }
  .lp-gen-answers { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* Headline over its supporting line, both left aligned: the split header row
     needs two real columns to mean anything. */
  .lp-cardio-head { flex-direction: column; align-items: flex-start; gap: 16px; }
  .lp-cardio-head p { flex: none; max-width: 520px; text-align: left; }
  .lp-cardio-band { padding: 20px 20px 18px; border-radius: 22px; }
  .lp-weight-panel { grid-template-columns: minmax(0, 1fr); gap: 26px; padding: 28px 24px 0; }
  .lp-weight-read { align-items: flex-start; text-align: left; }
  .lp-weight-trend { width: calc(100% + 48px); margin: 22px -24px 0; height: 100px; }
  .lp-progress-sub { grid-template-columns: minmax(0, 1fr); gap: 14px; margin-top: 34px; }
  /* One vertical rule instead of one horizontal rule. */
  .lp-offline-rail { flex-direction: column; align-items: center; gap: 24px; margin-top: 42px; }
  .lp-offline-line { left: 50%; right: auto; top: 4%; bottom: 4%; width: 1px; height: auto; }
  .lp-offline-line-fill { background: linear-gradient(180deg, var(--line2), var(--accent)); }
  .lp-offline-beat { padding: 12px 0; }
}
@media (prefers-reduced-motion: no-preference) and (max-width: 1000px) {
  .lp-staged .lp-offline-line-fill { transform: scaleY(0); transform-origin: 50% 0; }
  .lp-staged.is-in .lp-offline-line-fill { animation: lp-grow-y 0.58s var(--lp-ease) 100ms both; }
}
@media (max-width: 640px) {
  .lp-gen, .lp-shelf, .lp-cardio, .lp-weight,
  .lp-share, .lp-offline, .lp-langs, .lp-promise { padding: 48px 20px; }
  #landing .lp-gen h2, #landing .lp-shelf h2, #landing .lp-cardio h2,
  #landing .lp-weight h2, #landing .lp-share h2, #landing .lp-offline h2,
  #landing .lp-langs h2 { font-size: 32px; letter-spacing: -1.1px; }
  .lp-gen-head p, .lp-shelf-copy p, .lp-weight-copy p,
  .lp-share-copy p, .lp-offline-copy p, .lp-langs-copy p { font-size: 16px; }
  .lp-gen-stage { margin-top: 34px; }
  .lp-gen-seam { height: 34px; }
  /* Seven tiles cannot hold "Upper A" at 320px, so the week becomes the day
     list it is in the app instead of shrinking into unreadable columns. */
  .lp-gen-week { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  .lp-gen-day {
    flex-direction: row; align-items: center; gap: 12px;
    min-height: 0; padding: 13px 15px; border-radius: 15px;
  }
  .lp-gen-day::before { width: 3px; height: 18px; margin-bottom: 0; flex: none; }
  .lp-gen-dow { flex: none; width: 32px; }
  .lp-gen-name { margin-top: 0; font-size: 15px; }
  .lp-gen-n { margin-left: auto; text-align: right; }
  .lp-shelf-rail { gap: 12px; margin-top: 34px; }
  .lp-shelf-tile figcaption { margin-top: 10px; font-size: 12.5px; }
  .lp-shelf-tile figcaption span { font-size: 9px; }
  .lp-cardio-route { height: 96px; }
  .lp-cardio-stats { gap: 10px; margin-top: 16px; padding-top: 14px; }
  .lp-cardio-stats dt { font-size: 8.5px; letter-spacing: 1.2px; }
  .lp-cardio-stats dd { margin-top: 7px; font-size: 22px; letter-spacing: -0.7px; }
  .lp-cardio-stats dd span { font-size: 12px; }
  .lp-weight-value { font-size: 48px; letter-spacing: -1.6px; }
  .lp-weight-value em { font-size: 19px; }
  .lp-share-fan { height: 258px; }
  .lp-share-formats { margin-top: 26px; }
  .lp-share-copy { margin-top: 24px; }
  .lp-offline-set { padding: 10px 13px; }
  .lp-langs-list { gap: 6px 16px; margin-top: 24px; font-size: 12px; }
  .lp-progress-heat, .lp-progress-report { padding: 16px 16px; border-radius: 17px; }
  .lp-progress-kpis { gap: 8px; }
  .lp-progress-kpis dd { font-size: 21px; letter-spacing: -0.6px; }
  #landing .lp-progress-kpis dd.lp-progress-kpi-sub { font-size: 10px; }
}

.lp-phone-wrap:not(.is-playing) > .lp-phone { animation-play-state: paused; }
/* Homepage acquisition hierarchy. Shared pricing and public navigation keep their styles. */
#landing .lp-start-web,
#landing .lp-start-web:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-text);
}
.lp-demo-link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin-top: 8px;
  color: var(--text);
  font: 600 15px/1.4 var(--font-ui);
  text-decoration: underline;
  text-underline-offset: 4px;
}
.lp-hero p.lp-hero-proof { margin-top: 16px; }
#landing .lp-feature-tour {
  max-width: 1280px;
  margin: 24px auto;
  border-block: 1px solid var(--line2);
}
.lp-feature-tour > summary {
  position: relative;
  padding: 28px 56px;
  cursor: pointer;
  color: var(--text);
}
.lp-tour-title { font: 600 26px/1.3 var(--font-ui); }
.lp-tour-description {
  display: block;
  margin-top: 8px;
  color: var(--lp-muted);
  font: 400 16px/1.5 var(--font-ui);
}
.lp-feature-tour[open] > summary { border-bottom: 1px solid var(--line); }
.lp-feature-tour section { scroll-margin-top: 80px; }
.lp-cine-toggle {
  position: absolute;
  z-index: 2;
  bottom: 20px;
  right: 20px;
  min-height: 44px;
  padding: 10px 18px;
  border: 1px solid var(--line2);
  border-radius: 12px;
  background: var(--bg);
  color: var(--text);
  cursor: pointer;
  font: 600 14px/1.4 var(--font-ui);
}
.lp-cine-toggle[hidden] { display: none; }
.lp-feature-tour > summary:focus-visible,
.lp-demo-link:focus-visible,
.lp-cine-toggle:focus-visible,
#landing .lp-app-store-badge:focus-visible,
#landing .lp-play-badge:focus-visible,
#landing .lp-start-web:focus-visible {
  outline: 3px solid var(--text);
  outline-offset: 4px;
}
@media (max-width: 760px) {
  #landing #pricing .pz-pro { order: 0; }
}
@media (max-width: 640px) {
  #landing .lp-hero { padding-top: 18px; gap: 16px; }
  #landing .lp-hero h1 { margin-top: 0; font-size: clamp(32px, 9.75vw, 42px); }
  .lp-hero p { margin-top: 14px; }
  .lp-hero p.lp-hero-audience { font-size: 14px; margin-top: 8px; }
  .lp-hero .lp-store-row {
    display: flex;
    flex-direction: row;
    justify-content: center;
    gap: 10px;
    margin-top: 20px;
  }
  .lp-hero .lp-store-row > a { flex: 0 1 162px; width: 162px; max-width: 100%; }
  .lp-hero .lp-demo-link { display: flex; justify-content: center; }
  .lp-hero p.lp-hero-proof { margin-top: 8px; }
  /* Show the whole device so its frame and demo controls remain visible. */
  .lp-hero .lp-phone-wrap { width: 100%; max-width: 314px; margin-inline: auto; }
  .lp-hero .lp-phone { flex: none; height: 644px; animation: none; }
  .lp-feature-tour > summary { padding: 24px 20px; }
  .lp-tour-title { font-size: 23px; }
}

/* Center the single-column hero across phone and tablet widths. */
@media (min-width: 641px) and (max-width: 1000px) {
  .lp-hero-copy { width: 100%; max-width: 560px; margin-inline: auto; text-align: center; }
  .lp-hero p { margin-inline: auto; }
  .lp-hero .lp-store-row, .lp-hero p.lp-hero-proof { justify-content: center; }
}

/* Compact homepage feature story. Full comparison stays on the pricing page. */
.lp-feature-highlights { padding: 60px 56px; }
.lp-feature-highlights-inner { max-width: 1168px; margin: 0 auto; }
.lp-feature-highlights-head { text-align: center; }
#landing .lp-feature-highlights h2 { margin: 10px 0 0; font: 700 38px/1.12 var(--font-ui); letter-spacing: -1px; }
.lp-feature-grid { display: grid; grid-template-columns: repeat(4,minmax(0,1fr)); gap: 14px; margin-top: 32px; }
.lp-feature-language { margin: 24px 0 0; text-align: center; color: var(--lp-muted); font: 400 15px/1.5 var(--font-ui); }
.lp-feature-language a { margin-left: 8px; color: var(--text); text-decoration: underline; text-underline-offset: 3px; }
.lp-closing-trust { display: flex; flex-wrap: wrap; gap: 12px 24px; justify-content: center; padding: 0; margin: 24px 0 0; list-style: none; color: var(--lp-muted); font: 500 14px/1.4 var(--font-ui); }
.lp-closing-trust li::before { content: '✓'; color: var(--accent-ink-text); margin-right: 7px; }
@media (max-width: 900px) { .lp-feature-grid { grid-template-columns: repeat(2,minmax(0,1fr)); } }
@media (max-width: 640px) {
  .lp-feature-highlights { padding: 48px 20px; }
  #landing .lp-feature-highlights h2 { font-size: 30px; }
  .lp-feature-grid { gap: 10px; margin-top: 24px; }
  .lp-feature-language a { display: block; margin: 8px 0 0; }
  .lp-closing-trust { justify-content: flex-start; width: fit-content; max-width: 100%; margin: 24px auto 0; flex-direction: column; gap: 10px; }
}
@media (max-width: 350px) { .lp-feature-grid { grid-template-columns: 1fr; } }

/* Standalone two-set logger card, without phone chrome or a second preview frame. */
.lp-log-composition { display: block; }
.lp-log-preview { max-width: 540px; padding: 24px; color: #f2f3f5; background: #1e2024; border-color: #303238; border-radius: 24px; }
.lp-log-preview-done, .lp-log-preview-active { display: flex; align-items: center; gap: 12px; color: #f2f3f5; font: 600 18px var(--font-ui); }
.lp-log-preview-done { padding-bottom: 28px; }
.lp-log-preview-done strong { margin-left: auto; font-size: 18px; }
.lp-log-preview-check { display: grid; place-items: center; width: 26px; height: 26px; border-radius: 50%; background: #ccff00; color: #0c0d10; font-size: 16px; }
.lp-log-preview-ring { width: 25px; height: 25px; border: 2px solid #ccff00; border-radius: 50%; }
.lp-log-preview-menu { margin-left: auto; color: #8a8f98; font-size: 24px; }
.lp-log-preview-target { margin-top: 32px; text-align: center; color: #ccff00; font: 600 16px var(--font-ui); }
.lp-log-preview-wheels { display: grid; grid-template-columns: repeat(2,minmax(0,1fr)); gap: 24px; width: min(100%, 330px); margin: 24px auto 0; text-align: center; }
.lp-log-preview-wheels > div { display: flex; flex-direction: column; gap: 4px; }
.lp-log-preview-wheels span { color: #8a8f98; font: 700 10px var(--font-ui); letter-spacing: 2px; }
.lp-log-preview-wheels small { color: #737880; font: 600 22px var(--font-ui); }
.lp-log-preview-wheels strong { border-radius: 99px; background: #2b2e34; font: 700 30px/1.2 var(--font-ui); }
.lp-log-preview-add { margin-top: 28px; color: #8a8f98; font: 500 13px var(--font-ui); }
.lp-log-preview-actions { display: flex; gap: 10px; margin-top: 24px; }
.lp-log-preview-actions > span:first-child { flex: 1; display: grid; place-items: center; min-height: 52px; border-radius: 99px; background: #ccff00; color: #0c0d10; font: 700 18px var(--font-ui); }
.lp-log-preview-mic { display: grid; place-items: center; flex: none; width: 52px; height: 52px; border-radius: 50%; background: #282b31; }
.lp-log-preview-mic svg { width: 22px; height: 22px; }
@media (max-width: 640px) {
  .lp-log-preview { width: 100%; padding: 18px 16px; }
  .lp-log-preview-done, .lp-log-preview-active { font-size: 15px; }
  .lp-log-preview-done strong { font-size: 15px; }
  .lp-log-preview-wheels { gap: 12px; }
  .lp-log-preview-actions > span:first-child { font-size: 16px; }
}

/* Match the transition from other feature sections into the closing action. */
#landing .lp-closing { padding-top: 40px; }
@media (max-width: 640px) { #landing .lp-closing { padding-top: 24px; } }

.lp-features-detail .pg-hero { padding-bottom: 56px; }
.lp-features-detail .lp-fscreen--bleed { margin-top: 0; }
.lp-features-detail .lp-feature-detail-end { padding-bottom: 90px; }
.lp-features-detail .lp-demo-link { justify-content: center; margin: 24px auto 0; }


/* Keep the transition into AI review compact on phones; give trainer examples room on desktop. */
@media (max-width: 640px) { #landing .lp-fscreen--flip { margin-top: 0; } }

/* ── Hero film ──────────────────────────────────────────────────────────────
   The hero phone plays a scripted recording of the native tracker, driven by
   /js/hero-film.js through state classes on .hf. The device screen stays dark
   in both themes (design.md), so its colours are the app's dark values. */
.hf { --hf-bg: #111214; --hf-card: #1e2024; --hf-well: #2b2e34; --hf-round: #25272b;
  --hf-text: #f2f3f5; --hf-dim: #8a8f98; --hf-volt: #ccff00; --hf-ink: #0c0d10;
  background: var(--hf-bg); color: var(--hf-text); }
.hf-stage { position: relative; flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }
.hf-toolbar { display: flex; justify-content: space-between; padding: 2px 16px 0; }
.hf-round { display: grid; place-items: center; width: 32px; height: 32px; flex: none; border-radius: 50%; background: var(--hf-round); color: #c3c7ce; }
.hf-round svg { width: 16px; height: 16px; }
.hf-title { padding: 10px 18px 0; font: 700 21px/1.15 var(--font-ui); letter-spacing: -.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hf-pips { display: flex; gap: 4px; margin: 10px 18px 0; }
.hf-pips i { flex: 1; height: 4px; border-radius: 99px; background: #292c31; }
.hf-pips i.on { background: var(--hf-text); }
.hf-art { display: grid; place-items: center; height: 104px; margin-top: 4px; }
.hf-art img { width: 104px; height: 104px; object-fit: contain; }
.hf-last { display: flex; align-items: baseline; justify-content: center; gap: 8px; padding: 4px 0 8px; color: var(--hf-dim); }
.hf-last span { font: 700 9px var(--font-ui); letter-spacing: 2px; }
.hf-last strong { font: 700 15px var(--font-ui); }
.hf-card { flex: 1; min-height: 0; margin: 0 12px; padding: 12px 14px 0; border-radius: 20px 20px 0 0; background: var(--hf-card); }

/* Logged rows open in place above the active set. */
.hf-done { display: flex; align-items: center; gap: 9px; max-height: 0; overflow: hidden; opacity: 0;
  font: 600 13px var(--font-ui); transition: max-height .45s var(--hf-ease, cubic-bezier(.2,.8,.2,1)), opacity .3s ease, margin .45s cubic-bezier(.2,.8,.2,1); }
.hf-done strong { margin-left: auto; font: 700 13px var(--font-ui); font-variant-numeric: tabular-nums; }
.hf-check { display: grid; place-items: center; width: 20px; height: 20px; flex: none; border-radius: 50%; background: var(--hf-volt); color: var(--hf-ink); transform: scale(.4); transition: transform .5s cubic-bezier(.34,1.56,.64,1) .12s; }
.hf-check svg { width: 12px; height: 12px; }
.hf.is-done-1 .hf-done[data-set="1"], .hf.is-done-2 .hf-done[data-set="2"] { max-height: 28px; margin-bottom: 11px; opacity: 1; }
.hf.is-done-1 .hf-done[data-set="1"] .hf-check, .hf.is-done-2 .hf-done[data-set="2"] .hf-check { transform: scale(1); }
.hf-pr { padding: 2px 6px; border-radius: 99px; background: rgba(204,255,0,.14); color: var(--hf-volt); font: 800 9px/1.3 var(--font-ui); letter-spacing: .6px; opacity: 0; transform: scale(.6); transition: opacity .25s ease, transform .5s cubic-bezier(.34,1.56,.64,1); }
.hf.is-pr .hf-pr { opacity: 1; transform: scale(1); }

.hf-set { display: flex; align-items: center; gap: 9px; font: 700 16px var(--font-ui); }
.hf-ring { width: 19px; height: 19px; flex: none; box-sizing: border-box; border: 2px solid var(--hf-volt); border-radius: 50%; }
.hf-kebab { margin-left: auto; color: var(--hf-dim); display: inline-flex; }
.hf-kebab svg { width: 18px; height: 18px; }
.hf-set-name, .hf-log-label { display: inline-block; transition: opacity .3s ease, transform .45s cubic-bezier(.2,.8,.2,1); }
.hf.is-swapping :is(.hf-set-name, .hf-log-label) { opacity: 0; transform: translateY(8px); transition: none; }
.hf-target { margin-top: 12px; text-align: center; color: var(--hf-volt); font: 600 12px var(--font-ui); }
.hf-target b { font-weight: 700; }

/* Wheels: a dim list behind and a bright list seen only through the band,
   both translated by the same --i, which is how a native picker reads. */
.hf-wheels { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin: 8px 4px 0; text-align: center; transition: opacity .35s ease; }
.hf-field > span { color: var(--hf-dim); font: 700 9px/11px var(--font-ui); letter-spacing: 2px; }
.hf-wheel { --i: 2; position: relative; height: 102px; margin-top: 3px; overflow: hidden;
  -webkit-mask-image: linear-gradient(transparent, #000 34%, #000 66%, transparent);
          mask-image: linear-gradient(transparent, #000 34%, #000 66%, transparent); }
.hf-wheel::before { content: ''; position: absolute; top: 34px; left: 0; right: 0; height: 34px; border-radius: 99px; background: var(--hf-well); }
.hf-list { position: absolute; left: 0; right: 0; top: 0; transform: translateY(calc((1 - var(--i)) * 34px)); transition: transform .62s cubic-bezier(.2,.8,.2,1); }
.hf-list i { display: grid; place-items: center; height: 34px; font: 600 17px/1 var(--font-ui); font-style: normal; font-variant-numeric: tabular-nums; color: rgba(242,243,245,.42); }
/* Opaque, so the dim copy of the selected value never shows through. */
.hf-lit { position: absolute; top: 34px; left: 0; right: 0; height: 34px; overflow: hidden; border-radius: 99px; background: var(--hf-well); }
.hf-lit .hf-list { transform: translateY(calc(var(--i) * -34px)); }
.hf-lit .hf-list i { color: var(--hf-text); font-size: 24px; font-weight: 700; }

/* Rest card: the same card the phones draw, with the accent clock. */
.hf-rest { position: absolute; left: 12px; right: 12px; bottom: 78px; z-index: 2; display: flex; align-items: center; gap: 8px;
  padding: 10px 12px; border: 1px solid rgba(204,255,0,.28); border-radius: 18px; background: var(--hf-card);
  box-shadow: 0 -18px 30px -12px var(--hf-bg); opacity: 0; transform: translateY(24px);
  transition: opacity .35s ease, transform .55s cubic-bezier(.2,.8,.2,1); pointer-events: none; }
.hf-rest-copy { display: flex; flex-direction: column; margin-right: auto; }
.hf-rest-copy span { color: var(--hf-dim); font: 700 9px var(--font-ui); letter-spacing: 2px; }
.hf-rest-time { color: var(--hf-volt); font: 700 26px/1.1 var(--font-ui); font-variant-numeric: tabular-nums; }
.hf-rest-add { display: grid; place-items: center; height: 36px; padding: 0 11px; border-radius: 99px; background: var(--hf-well); font: 700 12px var(--font-ui); }
.hf-rest .hf-round { position: relative; width: 36px; height: 36px; background: var(--hf-well); color: var(--hf-text); }
.hf-rest .hf-round svg { width: 14px; height: 14px; }
.hf-rest .hf-round .hf-rest-ring { position: absolute; inset: 0; width: 100%; height: 100%; transform: rotate(-90deg); }
.hf-rest-ring circle { fill: none; stroke: var(--hf-volt); stroke-width: 3; stroke-linecap: round; stroke-dasharray: 100; stroke-dashoffset: 100; }
.hf.is-resting .hf-rest { opacity: 1; transform: none; }
.hf.is-resting .hf-wheels { opacity: .22; }
.hf.is-skipped .hf-rest { opacity: 0; transform: translateX(-110%) rotate(-4deg); transition: opacity .4s ease .1s, transform .5s cubic-bezier(.5,0,.75,0); }

.hf-actions { position: relative; z-index: 3; display: flex; gap: 8px; padding: 10px 12px 14px; background: var(--hf-bg); }
.hf-log { flex: 1; display: grid; place-items: center; min-height: 48px; border-radius: 99px; background: var(--hf-volt); color: var(--hf-ink); font: 700 16px var(--font-ui); }
.hf-mic { display: grid; place-items: center; width: 48px; height: 48px; flex: none; border-radius: 50%; background: #25282e; }
.hf-mic svg { width: 20px; height: 20px; }

/* Voice sheet: rises over the actions, listens, then shows what it heard. */
.hf-voice { position: absolute; left: 8px; right: 8px; bottom: 8px; z-index: 4; display: flex; flex-direction: column; align-items: center; gap: 12px;
  padding: 20px 16px 18px; border: 1px solid rgba(255,255,255,.08); border-radius: 26px; background: #181a1e;
  box-shadow: 0 -24px 48px -12px rgba(0,0,0,.8); transform: translateY(115%); transition: transform .6s cubic-bezier(.2,.8,.2,1); }
.hf.is-listening .hf-voice { transform: none; }
.hf-voice-orb { position: relative; display: grid; place-items: center; width: 56px; height: 56px; border-radius: 50%; background: var(--hf-volt); color: var(--hf-ink); }
.hf-voice-orb svg { width: 24px; height: 24px; }
.hf-voice-orb::before, .hf-voice-orb::after { content: ''; position: absolute; inset: 0; border-radius: 50%; border: 2px solid var(--hf-volt); opacity: 0; }
.hf.is-listening:not(.is-heard) .hf-voice-orb::before { animation: hf-ping 1.6s cubic-bezier(.2,.8,.2,1) infinite; }
.hf.is-listening:not(.is-heard) .hf-voice-orb::after { animation: hf-ping 1.6s cubic-bezier(.2,.8,.2,1) .8s infinite; }
@keyframes hf-ping { from { opacity: .55; transform: scale(1); } to { opacity: 0; transform: scale(1.9); } }
.hf-voice-label { color: var(--hf-dim); font: 600 12px var(--font-ui); }
.hf-wave { display: flex; align-items: center; justify-content: center; gap: 3px; height: 28px; transition: opacity .3s ease, height .4s ease; }
.hf-wave i { width: 3px; height: 6px; border-radius: 99px; background: var(--hf-volt); opacity: .9; }
.hf.is-listening:not(.is-heard) .hf-wave i { animation: hf-wave 0.9s ease-in-out infinite alternate; }
.hf-wave i:nth-child(4n+1) { animation-delay: -.2s !important; }
.hf-wave i:nth-child(4n+2) { animation-delay: -.55s !important; animation-duration: .7s !important; }
.hf-wave i:nth-child(4n+3) { animation-delay: -.35s !important; animation-duration: 1.1s !important; }
.hf-wave i:nth-child(5n) { animation-delay: -.75s !important; }
@keyframes hf-wave { from { height: 4px; } to { height: 26px; } }
.hf-voice-result { display: flex; align-items: baseline; justify-content: center; gap: 6px; max-height: 0; padding: 0 18px; border-radius: 99px; background: #0f1012; opacity: 0; overflow: hidden; transition: max-height .45s cubic-bezier(.2,.8,.2,1), opacity .35s ease; }
.hf-voice-result b { font: 700 24px/1.2 var(--font-ui); font-variant-numeric: tabular-nums; }
.hf-voice-result span { color: var(--hf-dim); font: 700 9px var(--font-ui); letter-spacing: 2px; }
.hf-voice-result span:not(:last-child) { margin-right: 8px; }
.hf.is-heard .hf-wave { opacity: 0; height: 0; }
.hf.is-heard .hf-voice-result { max-height: 44px; padding-block: 8px; opacity: 1; }

/* PR toast drops in from the top edge. */
.hf-toast { position: absolute; top: 104px; left: 12px; right: 12px; z-index: 5; display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; border: 1px solid rgba(204,255,0,.32); border-radius: 18px; background: #1e2024;
  box-shadow: 0 16px 36px -12px rgba(0,0,0,.8); opacity: 0; transform: translateY(-16px) scale(.96);
  transition: opacity .3s ease, transform .6s cubic-bezier(.34,1.3,.64,1); }
.hf.is-pr .hf-toast { opacity: 1; transform: none; }
.hf-toast-badge { flex: none; padding: 5px 9px; border-radius: 99px; background: var(--hf-volt); color: var(--hf-ink); font: 800 11px var(--font-ui); }
.hf-toast-copy { display: flex; flex-direction: column; min-width: 0; color: var(--hf-dim); font: 600 11px/1.3 var(--font-ui); }
.hf-toast-copy > span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hf-toast-copy strong { color: var(--hf-text); font: 700 15px/1.2 var(--font-ui); }

/* The finger, and the Volt sparks of the PR. */
.hf-touch { position: absolute; top: -17px; left: -17px; z-index: 6; width: 34px; height: 34px; box-sizing: border-box; border-radius: 50%;
  border: 1.5px solid rgba(255,255,255,.7); background: rgba(255,255,255,.22); box-shadow: 0 4px 14px rgba(0,0,0,.35);
  opacity: 0; pointer-events: none; }
.hf-spark { position: absolute; top: -3px; left: -3px; z-index: 6; width: 6px; height: 6px; border-radius: 2px; background: var(--hf-volt); pointer-events: none; }

/* Pause control: small and quiet, at the phone's lower corner. */
.hf-control { position: absolute; z-index: 5; right: calc(50% - 157px - 56px); bottom: 24px; display: grid; place-items: center;
  width: 44px; height: 44px; padding: 13px; border: 1px solid var(--line2); border-radius: 50%; background: var(--panel); color: var(--text); cursor: pointer;
  opacity: .72; transition: opacity .2s ease; }
.hf-control[hidden] { display: none; }
.hf-control:hover, .hf-control:focus-visible { opacity: 1; }
.hf-control:focus-visible { outline: 3px solid var(--text); outline-offset: 3px; }
.hf-control svg { display: block; width: 100%; height: 100%; }
.hf-control .lp-phone-play-icon, .is-user-paused > .hf-control .lp-phone-pause-icon { display: none; }
.is-user-paused > .hf-control .lp-phone-play-icon { display: block; }
/* Single column: no room beside the phone, so it rests on the frame's lower
   corner, clear of the screen's mic button. */
@media (max-width: 1000px) { .hf-control { right: calc(50% - 157px - 18px); bottom: -14px; } }

/* ── Voice logging ──────────────────────────────────────────────────────────
   The photo is shot for a text column on its dark left half, so it is shown
   whole and the copy sits there. A photograph, so it stays dark in both
   themes, with its own light text. */
.hp-voice { position: relative; width: min(100%, 1168px); margin: 72px auto 0; overflow: hidden; isolation: isolate;
  border: 1px solid rgba(255,255,255,.08); border-radius: 28px; background: #050505; color: #f2f3f5; text-align: left; }
.hp-voice-photo { display: block; width: 100%; height: auto; aspect-ratio: 1915 / 821; object-fit: cover; }
.hp-voice-copy { position: absolute; inset: 0 auto 0 0; z-index: 1; width: 46%; display: flex; flex-direction: column; justify-content: center; padding: 0 0 0 56px; }
#landing .hp-voice .lp-section-eyebrow { color: #a7adb7; }
#landing .hp-voice h3 { margin: 10px 0 0; font: 700 40px/1.08 var(--font-ui); letter-spacing: -1.3px; color: #f2f3f5; text-wrap: balance; }
.hp-voice p { margin: 14px 0 0; max-width: 40ch; color: #a7adb7; font: 400 17px/1.5 var(--font-ui); text-wrap: pretty; }
.hp-voice-demo { display: flex; align-items: center; gap: 14px; width: fit-content; min-width: 272px; height: 64px; margin-top: 32px; padding: 0 20px 0 10px;
  border: 1px solid rgba(255,255,255,.1); border-radius: 99px; background: rgba(24,26,30,.82);
  -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); box-shadow: 0 18px 40px -18px rgba(0,0,0,.9); }
.hp-voice-orb { position: relative; display: grid; place-items: center; width: 44px; height: 44px; flex: none; border-radius: 50%; background: #ccff00; color: #0c0d10; }
.hp-voice-orb svg { width: 20px; height: 20px; }
.hp-voice-orb::after { content: ''; position: absolute; inset: 0; border-radius: 50%; border: 2px solid #ccff00; opacity: 0; }
.hp-voice-wave { display: flex; align-items: center; gap: 3px; height: 30px; }
.hp-voice-wave i { width: 3px; height: 30%; border-radius: 99px; background: #ccff00; }
.hp-voice-heard { position: absolute; left: 68px; display: flex; align-items: baseline; gap: 6px; opacity: 0; }
.hp-voice-heard b { font: 700 22px/1 var(--font-ui); font-variant-numeric: tabular-nums; color: #f2f3f5; }
.hp-voice-heard span { margin-right: 10px; color: #8a8f98; font: 700 10px var(--font-ui); letter-spacing: 2px; }
.hp-voice-demo { position: relative; }
.hp-voice-heard { top: 50%; transform: translateY(-50%); }
@media (prefers-reduced-motion: no-preference) {
  .hp-voice-demo.is-live .hp-voice-wave i { animation: hp-wave 6s ease-in-out infinite; }
  .hp-voice-wave i:nth-child(3n+1) { --hp-h: 90%; animation-delay: -.1s !important; }
  .hp-voice-wave i:nth-child(3n+2) { --hp-h: 55%; animation-delay: -.25s !important; }
  .hp-voice-wave i:nth-child(3n) { --hp-h: 75%; animation-delay: -.4s !important; }
  .hp-voice-wave i:nth-child(4n) { --hp-h: 100%; }
  .hp-voice-demo.is-live .hp-voice-heard { animation: hp-heard 6s cubic-bezier(.2,.8,.2,1) infinite; }
  .hp-voice-demo.is-live .hp-voice-orb::after { animation: hp-orb 6s ease-out infinite; }
}
/* 0-55%: listening (bars dance), 55-60%: bars settle, 62-92%: what was heard. */
@keyframes hp-wave {
  0%, 60%, 100% { height: 18%; opacity: 1; }
  6%, 18%, 30%, 42% { height: var(--hp-h, 70%); }
  12%, 24%, 36%, 48% { height: 28%; }
  62%, 94% { height: 18%; opacity: 0; }
}
@keyframes hp-heard { 0%, 60% { opacity: 0; transform: translate(-6px, -50%); } 66%, 92% { opacity: 1; transform: translate(0, -50%); } 100% { opacity: 0; transform: translate(0, -50%); } }
@keyframes hp-orb { 0% { opacity: .6; transform: scale(1); } 20% { opacity: 0; transform: scale(1.7); } 21%, 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .hp-voice-wave { opacity: 0; }
  .hp-voice-heard { opacity: 1; }
}

/* ── Trainer chat and plans ─────────────────────────────────────────────── */
.hp-coach { width: min(100% - 112px, 1168px); margin: 0 auto; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; }
.hp-coach-card { position: relative; overflow: hidden; display: flex; flex-direction: column; gap: 28px; padding: 36px 36px 0;
  border: 1px solid var(--line2); border-radius: 28px;
  background: radial-gradient(120% 80% at 100% 0%, rgba(var(--accent-rgb), .08), transparent 55%), var(--panel); }
#landing .hp-coach-card h3 { margin: 0; font: 700 28px/1.15 var(--font-ui); letter-spacing: -.8px; }
.hp-coach-card p { margin: 10px 0 0; max-width: 38ch; color: var(--lp-muted); font: 400 16px/1.5 var(--font-ui); text-wrap: pretty; }
/* Both visuals sit on the same inset floor, flush with the card's bottom. */
.hp-chat, .hp-plan { flex: 1; display: flex; flex-direction: column; gap: 12px; min-height: 212px; padding: 24px 24px 28px;
  border: 1px solid var(--line); border-bottom: 0; border-radius: 20px 20px 0 0; background: var(--bg); }
.hp-chat { justify-content: flex-end; }
.hp-chat-q { align-self: flex-end; max-width: 80%; padding: 11px 16px; border-radius: 20px 20px 6px 20px; background: var(--accent); color: var(--accent-text, #0c0d10); font: 600 15px/1.35 var(--font-ui); }
.hp-chat-a { display: flex; align-items: flex-end; gap: 10px; }
.hp-chat-avatar { display: grid; place-items: center; width: 30px; height: 30px; flex: none; border-radius: 50%; background: var(--panel2); color: var(--accent-ink-text); }
.hp-chat-avatar svg { width: 16px; height: 16px; }
.hp-chat-bubble { position: relative; max-width: 86%; padding: 12px 16px; border-radius: 20px 20px 20px 6px; background: var(--panel2); color: var(--text); font: 500 15px/1.45 var(--font-ui); }
.hp-chat-typing { position: absolute; left: 16px; top: 50%; display: flex; gap: 4px; opacity: 0; transform: translateY(-50%); }
.hp-chat-typing i { width: 7px; height: 7px; border-radius: 50%; background: var(--lp-muted); }
@media (prefers-reduced-motion: no-preference) {
  .hp-chat.is-live .hp-chat-q { animation: hp-chat-q 8s cubic-bezier(.2,.8,.2,1) infinite; }
  .hp-chat.is-live .hp-chat-a { animation: hp-chat-a 8s cubic-bezier(.2,.8,.2,1) infinite; }
  .hp-chat.is-live .hp-chat-typing { animation: hp-typing-box 8s ease infinite; }
  .hp-chat.is-live .hp-chat-typing i { animation: hp-dot 1s ease-in-out infinite; }
  .hp-chat.is-live .hp-chat-typing i:nth-child(2) { animation-delay: .15s; }
  .hp-chat.is-live .hp-chat-typing i:nth-child(3) { animation-delay: .3s; }
  .hp-chat.is-live .hp-chat-text { animation: hp-chat-text 8s ease infinite; }
}
@keyframes hp-chat-q { 0% { opacity: 0; transform: translateY(12px) scale(.96); } 6%, 92% { opacity: 1; transform: none; } 100% { opacity: 0; } }
@keyframes hp-chat-a { 0%, 12% { opacity: 0; transform: translateY(12px); } 18%, 92% { opacity: 1; transform: none; } 100% { opacity: 0; } }
@keyframes hp-typing-box { 0%, 16% { opacity: 0; } 19%, 33% { opacity: 1; } 36%, 100% { opacity: 0; } }
@keyframes hp-chat-text { 0%, 34% { opacity: 0; } 40%, 100% { opacity: 1; } }
@keyframes hp-dot { 0%, 100% { opacity: .3; transform: translateY(0); } 50% { opacity: 1; transform: translateY(-3px); } }

.hp-plan { gap: 14px; }
.hp-plan-head { display: flex; align-items: center; gap: 8px; color: var(--text); font: 700 15px var(--font-ui); }
.hp-plan-mark { display: grid; place-items: center; width: 26px; height: 26px; border-radius: 8px; background: rgba(var(--accent-rgb), .14); color: var(--accent-ink-text); }
.hp-plan-mark svg { width: 14px; height: 14px; }
.hp-plan-week { margin-left: auto; color: var(--lp-muted); font: 600 12px var(--font-ui); }
.hp-plan-days { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 8px; margin: 0; padding: 0; list-style: none; }
.hp-plan-days li { display: flex; flex-direction: column; align-items: center; justify-content: space-between; gap: 10px; min-height: 132px; padding: 12px 4px;
  border: 1px solid var(--line); border-radius: 14px; background: var(--panel); }
.hp-plan-days span { color: var(--lp-muted); font: 700 11px var(--font-ui); letter-spacing: .6px; text-transform: uppercase; }
.hp-plan-days b { writing-mode: vertical-rl; transform: rotate(180deg); color: var(--text); font: 700 14px var(--font-ui); letter-spacing: .2px; }
.hp-plan-days li.is-rest b { color: var(--lp-muted); font-weight: 600; }
.hp-plan-days li:not(.is-rest)::before { content: ''; width: 8px; height: 8px; border-radius: 50%; background: var(--accent); order: 3; }
@media (prefers-reduced-motion: no-preference) {
  .hp-plan.is-live .hp-plan-days li { animation: hp-plan-in 8s cubic-bezier(.2,.8,.2,1) infinite; }
  .hp-plan.is-live .hp-plan-days li:nth-child(2) { animation-delay: .08s; }
  .hp-plan.is-live .hp-plan-days li:nth-child(3) { animation-delay: .16s; }
  .hp-plan.is-live .hp-plan-days li:nth-child(4) { animation-delay: .24s; }
  .hp-plan.is-live .hp-plan-days li:nth-child(5) { animation-delay: .32s; }
  .hp-plan.is-live .hp-plan-days li:nth-child(6) { animation-delay: .4s; }
  .hp-plan.is-live .hp-plan-days li:nth-child(7) { animation-delay: .48s; }
}
@keyframes hp-plan-in { 0% { opacity: 0; transform: translateY(14px); } 8%, 92% { opacity: 1; transform: none; } 100% { opacity: 0; } }

/* ── Keep the whole routine in one place ─────────────────────────────────── */
#landing .lp-feature-highlights h2 { font-size: 44px; letter-spacing: -1.4px; }
.hp-routine { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; margin-top: 48px; }
.hp-routine-card { display: flex; flex-direction: column; overflow: hidden; border: 1px solid var(--line2); border-radius: 24px; background: var(--panel); }
.hp-routine-art { position: relative; display: grid; place-items: center; height: 172px; overflow: hidden;
  border-bottom: 1px solid var(--line); background: radial-gradient(90% 90% at 50% 100%, rgba(var(--accent-rgb), .07), transparent 70%), var(--bg); }
.hp-routine-copy { padding: 22px 24px 26px; }
#landing .hp-routine-copy h3 { margin: 0; font: 700 20px/1.2 var(--font-ui); letter-spacing: -.4px; }
.hp-routine-copy p { margin: 8px 0 0; color: var(--lp-muted); font: 400 15px/1.5 var(--font-ui); }
.hp-art-stat { position: absolute; left: 16px; bottom: 12px; display: inline-flex; align-items: baseline; gap: 4px; color: var(--lp-muted); font: 600 12px var(--font-ui); }
.hp-art-stat b { color: var(--text); font: 700 20px/1 var(--font-ui); font-variant-numeric: tabular-nums; }
.hp-art-count { position: absolute; left: 16px; bottom: 12px; color: var(--text); font: 700 20px/1 var(--font-ui); }
/* Library: three demo figures fanned like cards. */
.hp-art-library img { position: absolute; top: 18px; width: 104px; height: 104px; object-fit: contain; border: 1px solid var(--line); border-radius: 18px; background: #16181d; }
.hp-art-library img:nth-child(1) { left: calc(50% - 116px); transform: rotate(-8deg); }
.hp-art-library img:nth-child(2) { left: calc(50% - 52px); z-index: 1; top: 12px; box-shadow: 0 14px 30px -12px rgba(0,0,0,.6); }
.hp-art-library img:nth-child(3) { left: calc(50% + 12px); transform: rotate(8deg); }
@media (prefers-reduced-motion: no-preference) {
  .hp-art-library img { transition: transform .5s cubic-bezier(.2,.8,.2,1); }
  .hp-routine-card:hover .hp-art-library img:nth-child(1) { transform: rotate(-12deg) translateX(-8px); }
  .hp-routine-card:hover .hp-art-library img:nth-child(3) { transform: rotate(12deg) translateX(8px); }
}
/* Cardio and weight: lines that draw themselves while in view. */
.hp-routine-art > svg:not(.hp-sync-cloud) { position: absolute; inset: 0; width: 100%; height: 100%; padding: 18px 16px 34px; box-sizing: border-box; overflow: visible; }
.hp-route-base { stroke: var(--line2); stroke-width: 3; stroke-linecap: round; stroke-dasharray: 2 7; }
.hp-route, .hp-trend { stroke: var(--accent); stroke-width: 3.5; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 100; stroke-dashoffset: 0; }
.hp-route-start { fill: var(--accent); }
.hp-trend-fill { fill: url(#hp-trend-grad); }
.hp-trend-grad-top { stop-color: var(--accent); stop-opacity: .18; }
.hp-trend-grad-end { stop-color: var(--accent); stop-opacity: 0; }
.hp-trend-dot { fill: var(--accent); stroke: var(--bg); stroke-width: 3; }
@media (prefers-reduced-motion: no-preference) {
  .is-live .hp-route, .is-live .hp-trend { animation: hp-draw 5s cubic-bezier(.45,0,.2,1) infinite; }
  .is-live .hp-trend-dot { animation: hp-dot-in 5s ease infinite; }
  .is-live .hp-trend-fill { animation: hp-fill 5s ease infinite; }
}
@keyframes hp-fill { 0%, 20% { opacity: 0; } 55%, 90% { opacity: 1; } 100% { opacity: 0; } }
@keyframes hp-draw { 0% { stroke-dashoffset: 100; } 55%, 90% { stroke-dashoffset: 0; } 100% { stroke-dashoffset: 0; opacity: 0; } }
@keyframes hp-dot-in { 0%, 50% { opacity: 0; transform: scale(.4); transform-origin: 210px 72px; } 58%, 90% { opacity: 1; transform: scale(1); transform-origin: 210px 72px; } 100% { opacity: 0; } }
/* Offline: three sets waiting, then syncing one by one. */
.hp-art-offline { place-items: stretch; align-content: center; gap: 8px; padding: 0 22px; }
.hp-sync-row { display: flex; align-items: center; gap: 10px; height: 30px; padding: 0 12px; border: 1px solid var(--line); border-radius: 10px; background: var(--panel); }
.hp-sync-row b { color: var(--text); font: 700 13px var(--font-ui); font-variant-numeric: tabular-nums; }
.hp-sync-dot { display: grid; place-items: center; width: 16px; height: 16px; flex: none; border-radius: 50%; background: var(--accent); color: var(--accent-text, #0c0d10); }
.hp-sync-dot svg { width: 10px; height: 10px; }
#landing .hp-sync-cloud { position: absolute; top: 14px; right: 16px; width: 22px; height: 22px; padding: 0; color: var(--lp-muted); }
@media (prefers-reduced-motion: no-preference) {
  .hp-art-offline.is-live .hp-sync-dot { animation: hp-sync 6s ease infinite; }
  .hp-art-offline.is-live .hp-sync-row:nth-child(2) .hp-sync-dot { animation-delay: .35s; }
  .hp-art-offline.is-live .hp-sync-row:nth-child(3) .hp-sync-dot { animation-delay: .7s; }
  .hp-art-offline.is-live .hp-sync-slash { animation: hp-slash 6s ease infinite; }
}
/* Pending = a hollow ring; synced = the filled check. */
@keyframes hp-sync {
  0%, 45% { background: transparent; color: transparent; box-shadow: inset 0 0 0 2px var(--lp-muted); }
  52%, 100% { background: var(--accent); color: var(--accent-text, #0c0d10); box-shadow: none; }
}
@keyframes hp-slash { 0%, 42% { opacity: 1; } 48%, 100% { opacity: 0; } }

/* ── FAQ: more questions ─────────────────────────────────────────────────── */
.lp-faq-more > summary { display: flex; align-items: center; justify-content: center; gap: 8px; width: fit-content; min-height: 48px; margin: 28px auto 8px; padding: 0 22px;
  border: 1px solid var(--line2); border-radius: 99px; color: var(--text); cursor: pointer; list-style: none; font: 600 15px var(--font-ui);
  transition: border-color .2s ease, background-color .2s ease; }
.lp-faq-more > summary::-webkit-details-marker { display: none; }
.lp-faq-more > summary:hover { border-color: var(--text); }
.lp-faq-more > summary svg { width: 18px; height: 18px; transition: transform .3s cubic-bezier(.2,.8,.2,1); }
.lp-faq-more[open] > summary svg { transform: rotate(180deg); }
.lp-faq-more > summary:focus-visible { outline: 3px solid var(--text); outline-offset: 3px; }
.lp-faq-more[open] > summary { margin-bottom: 20px; }
.lp-faq-more .lp-faq-item:last-of-type { border-bottom: 0; }

@media (max-width: 1100px) {
  .hp-routine { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 900px) {
  .hp-voice-copy { width: 54%; padding-left: 36px; }
  #landing .hp-voice h3 { font-size: 32px; }
  .hp-coach { grid-template-columns: 1fr; }
}
@media (max-width: 700px) {
  /* Phones: the subject side of the photo on top, the copy below it. */
  .hp-voice { border-radius: 24px; }
  .hp-voice-photo { aspect-ratio: 4 / 3; object-position: 82% 30%; }
  .hp-voice-copy { position: relative; inset: auto; width: auto; padding: 4px 22px 26px; margin-top: -40px; }
  #landing .hp-voice h3 { font-size: 28px; letter-spacing: -.8px; }
  .hp-voice p { font-size: 16px; }
  .hp-voice-demo { min-width: 0; width: 100%; box-sizing: border-box; margin-top: 22px; }
  .hp-voice-copy::before { content: ''; position: absolute; left: 0; right: 0; top: -96px; height: 136px; z-index: -1;
    background: linear-gradient(transparent, #050505); pointer-events: none; }
  .hp-coach { width: calc(100% - 40px); gap: 14px; }
  .hp-coach-card { gap: 22px; padding: 26px 22px 0; border-radius: 24px; }
  #landing .hp-coach-card h3 { font-size: 23px; }
  .hp-coach-card p { font-size: 15px; }
  .hp-chat, .hp-plan { min-height: 0; padding: 18px 16px 20px; }
  .hp-plan-days { gap: 5px; }
  .hp-plan-days li { min-height: 116px; padding: 10px 2px; border-radius: 12px; }
  .hp-plan-days b { font-size: 13px; }
  #landing .lp-feature-highlights h2 { font-size: 30px; letter-spacing: -.8px; }
  .hp-routine { grid-template-columns: 1fr; gap: 12px; margin-top: 28px; }
  /* A list on phones: visual on the left, words on the right. */
  .hp-routine-card { flex-direction: row; align-items: stretch; border-radius: 20px; }
  .hp-routine-art { flex: none; width: 112px; height: auto; min-height: 124px; border-bottom: 0; border-right: 1px solid var(--line); }
  .hp-routine-copy { padding: 18px 18px 18px 16px; align-self: center; }
  #landing .hp-routine-copy h3 { font-size: 17px; }
  .hp-routine-copy p { font-size: 14px; }
  .hp-art-library img { width: 64px; height: 64px; top: 22px; border-radius: 12px; }
  .hp-art-library img:nth-child(1) { left: 6px; }
  .hp-art-library img:nth-child(2) { left: 24px; top: 18px; }
  .hp-art-library img:nth-child(3) { left: 42px; }
  .hp-art-stat, .hp-art-count { left: 12px; bottom: 10px; }
  .hp-art-stat b, .hp-art-count { font-size: 16px; }
  .hp-routine-art > svg:not(.hp-sync-cloud) { padding: 14px 10px 30px; }
  .hp-art-offline { padding: 0 10px; gap: 6px; }
  .hp-sync-row { height: 24px; padding: 0 7px; gap: 6px; }
  .hp-sync-row b { font-size: 10px; }
  .hp-sync-cloud { display: none; }
}

/* ── Homepage section rhythm ─────────────────────────────────────────────────
   One space between every pair of homepage sections, owned here instead of by
   each section's own padding. Sections keep their side padding; only the
   vertical rhythm is replaced. The AI Trainer screen and its chat and plan
   cards are one topic, so they sit at half the space. */
#landing .hp-main { --hp-space: 128px; }
#landing .hp-main > .lp-hero { padding-bottom: 0; }
#landing .hp-main > section:not(.lp-hero),
#landing .hp-main > .hp-coach { margin-top: var(--hp-space); margin-bottom: 0; padding-top: 0; padding-bottom: 0; }
#landing .hp-main > .lp-fscreen:not(.lp-fscreen--flip) { min-height: 0; }
/* The trainer shot is positioned against this section's box, so its 40px
   padding stays and comes off the margin instead. */
#landing .hp-main > .lp-fscreen--flip { margin-top: calc(var(--hp-space) - 40px); padding-top: 40px; padding-bottom: 40px; }
#landing .hp-main > .hp-coach { margin-top: calc(var(--hp-space) / 2 - 40px); }
#landing .hp-main > section.lp-faq { padding-bottom: var(--hp-space); }
@media (max-width: 1000px) { #landing .hp-main { --hp-space: 104px; } }
@media (max-width: 640px) {
  #landing .hp-main { --hp-space: 80px; }
  #landing .hp-main > .lp-fscreen--flip { margin-top: var(--hp-space); padding-top: 0; padding-bottom: 0; }
  #landing .hp-main > .hp-coach { margin-top: 40px; }
}
