/* ─────────────────────────────────────────────────────────────────────
   Novyn — marketing site
   The palette and type are lifted straight from lib/theme.ts so the site
   and the app read as one product. Two identities: FREE (light, electric
   blue) and PRO (near-black, gold). The page walks from one to the other.
   ──────────────────────────────────────────────────────────────────── */

:root {
  /* FREE theme */
  --bg: #F8FAFC;
  --surface: #FFFFFF;
  --raised: #F1F5F9;
  --text: #0F172A;
  --dim: #64748B;
  --faint: #CBD5E1;
  --border: #E2E8F0;
  --accent: #2563EB;
  --accent-dark: #1D4ED8;
  --accent-bg: #EFF6FF;
  --success: #22C55E;
  --warn: #F59E0B;
  --danger: #EF4444;
  --cardio: #EA580C;

  /* PRO theme */
  --pro-bg: #09090B;
  --pro-surface: #18181B;
  --pro-text: #FAFAFA;
  --pro-dim: #A1A1AA;
  --pro-border: #27272A;
  --gold: #D4AF37;

  --display: 'Big Shoulders Display', 'Arial Narrow', sans-serif;
  --mono: 'IBM Plex Mono', ui-monospace, monospace;
  --body: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

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

html { scroll-behavior: smooth; }

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--body);
  -webkit-font-smoothing: antialiased;
  /* `clip`, not `hidden`. overflow-x:hidden turns the body into a scroll
     container, which breaks position:sticky and scroll measurement inside it.
     `clip` crops the same overflow without creating one. */
  overflow-x: clip;
}

/* Shared atoms ------------------------------------------------------- */

.kicker {
  font-family: var(--mono);
  font-weight: 600;
  font-size: 11px;
  letter-spacing: 0.16em;
  color: var(--dim);
  text-transform: uppercase;
}
.kicker.center { text-align: center; }
.kicker.gold { color: var(--gold); }

/* The app puts a coloured full stop after every title. It's the single
   most recognisable thing about Novyn's type, so it comes with us. */
.dot { color: var(--accent); }
.dot.gold { color: var(--gold); }

.line { display: block; overflow: hidden; }
.line > span { display: block; }

.btn {
  display: inline-block;
  background: var(--accent);
  color: #fff;
  font-family: var(--mono);
  font-weight: 600;
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  padding: 15px 26px;
  border-radius: 12px;
  transition: transform .25s ease, background .25s ease;
}
.btn:hover { background: var(--accent-dark); transform: translateY(-2px); }
.btn.ghost {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border);
}
.btn.ghost:hover { background: var(--surface); border-color: var(--faint); }

/* Nav ---------------------------------------------------------------- */

.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 50;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding: 20px 34px;
  /* No backdrop-filter. A blurred backdrop on a fixed bar forces the whole
     page into a composited layer, and after a viewport resize the browser
     could stop painting that layer entirely — the page looked blank until a
     manual refresh, while the DOM was intact the whole time. A solid bar
     costs nothing and cannot do that. */
  background: var(--bg);
  border-bottom: 1px solid transparent;
  transition: background .4s ease, border-color .4s ease, color .4s ease;
}
.nav.scrolled { border-bottom-color: var(--border); }
.nav a {
  font-family: var(--mono);
  font-weight: 600;
  font-size: 13px;
  letter-spacing: 0.11em;
  color: var(--text);
  text-decoration: none;
  transition: color .2s ease, opacity .2s ease;
}
.nav a:hover { color: var(--accent); }
.nav-left { display: flex; align-items: center; gap: 26px; }
.nav-right { display: flex; justify-content: flex-end; }
.nav-mark {
  font-family: var(--display) !important;
  font-weight: 800;
  font-size: 34px !important;
  letter-spacing: 0.02em !important;
  color: var(--text) !important;
  line-height: 1;
}
.nav-cta {
  border: 1.5px solid var(--text);
  padding: 11px 20px;
  border-radius: 999px;
  color: var(--text) !important;
  font-size: 12px;
  /* Never wrap. A two-line pill balloons its grid column's min width, which
     shoves the centred wordmark off-centre on narrow screens. */
  white-space: nowrap;
}
.nav-cta:hover { background: var(--accent); border-color: var(--accent); color: #fff !important; }

/* Marks a feature that needs the subscription. Anywhere a paid feature is
   described, this has to be next to it — a free app that turns out to be
   missing the thing you came for reads worse than an honest price. */
.plus-tag {
  display: inline-block;
  font-family: var(--mono);
  font-weight: 600;
  font-size: 0.72em;
  letter-spacing: 0.1em;
  color: #8A6D1F;
  background: rgba(212,175,55,.16);
  border: 1px solid rgba(212,175,55,.42);
  border-radius: 999px;
  padding: 2px 8px;
  margin-left: 8px;
  vertical-align: middle;
  text-transform: none;
}
.fs-copy h3 .plus-tag { font-size: 0.32em; vertical-align: 0.42em; }

/* Nav inverts while the Pro section owns the screen. */
.nav.on-dark { background: var(--pro-bg); }
.nav.on-dark a { color: var(--pro-dim); }
.nav.on-dark a:hover { color: var(--pro-text); }
/* The Features control is a <button>, not an <a>, so the rule above never
   reached it — over the near-black Novyn+ section it stayed near-black text
   on a near-black bar and vanished. */
.nav.on-dark .drop-btn { color: var(--pro-dim); }
.nav.on-dark .drop-btn:hover,
.nav.on-dark .drop.open .drop-btn { color: var(--pro-text); }
.nav.on-dark .nav-mark { color: var(--pro-text) !important; }
.nav.on-dark .nav-cta { color: var(--pro-text) !important; border-color: var(--pro-border); }
.nav.on-dark .nav-cta:hover { background: var(--gold); border-color: var(--gold); color: #000 !important; }

/* Hero --------------------------------------------------------------- */

.hero {
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  padding: 120px 24px 80px;
  position: relative;
}
.hero-inner { max-width: 900px; }

/* Capped against viewport height as well as width — three lines of a
   condensed 800 weight will happily eat a laptop screen otherwise. */
.hero-title {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(66px, min(13vw, 19svh), 186px);
  line-height: 0.83;
  letter-spacing: -0.015em;
  margin: 16px 0 24px;
  text-transform: none;
}

.hero-sub {
  max-width: 560px;
  margin: 0 auto;
  font-size: 17px;
  line-height: 1.6;
  color: var(--dim);
}

.hero-actions {
  display: flex;
  gap: 12px;
  justify-content: center;
  margin-top: 34px;
  flex-wrap: wrap;
}

.scroll-cue {
  position: absolute;
  bottom: 34px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.2em;
  color: var(--dim);
}
.scroll-cue i {
  width: 1px;
  height: 44px;
  background: linear-gradient(to bottom, var(--faint), transparent);
}

/* Pinned feature section --------------------------------------------- */

.pin-section { height: 560vh; position: relative; }

.pin-stage {
  position: sticky;
  top: 0;
  height: 100svh;
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: clamp(30px, 6vw, 90px);
  padding: 0 clamp(24px, 7vw, 110px);
  overflow: hidden;
}

/* Phone */
.phone {
  position: relative;
  justify-self: center;
  height: min(74svh, 660px);
  aspect-ratio: 715 / 1496;  /* physical iPhone 16 Pro body, not the screen */
}
/* Geometry taken from the physical iPhone 16 Pro rather than eyeballed:
   body 71.5 × 149.6 mm, screen 66.6 × 144.8 mm, so the bezel is ~2.45 mm and
   identical on all four sides. Percentage padding resolves against WIDTH on
   every side, which is exactly what gives an even bezel top and bottom — the
   previous frame was built to 1179×2556 while the screenshots are 1206×2622,
   and that mismatch is what thickened the bottom edge.
   The Dynamic Island, status bar and earpiece all live inside the screenshot;
   the frame never draws them. */
.phone-body {
  position: relative;
  height: 100%;
  width: 100%;
  border-radius: 11.75%/5.61%;   /* ≈ 8.4 mm corner */
  padding: 3.43%;                /* ≈ 2.45 mm bezel, all four sides */
  background:
    linear-gradient(115deg,
      #4a4a4f 0%, #96969c 5%, #3a3a3f 12%,
      #2b2b30 50%,
      #3a3a3f 88%, #96969c 95%, #4a4a4f 100%);
  box-shadow:
    0 1px 2px rgba(15,23,42,.10),
    0 34px 68px -14px rgba(15,23,42,.34),
    inset 0 0 0 0.6px rgba(255,255,255,.24);
  z-index: 2;
}
/* The black bezel between the metal rail and the glass. This used to sit at
   the same inset as the screen, so it was completely hidden underneath it —
   the phone had a rail and glass and nothing in between. */
.phone-body::before {
  content: '';
  position: absolute;
  inset: 0.85%;
  border-radius: 11%/5.25%;
  background: #08080a;
  z-index: 0;
}
.phone-screen {
  position: relative;
  height: 100%;
  width: 100%;
  border-radius: 8.93%/4.11%;    /* ≈ 5.95 mm, i.e. corner minus bezel */
  overflow: hidden;
  background: var(--bg);
  z-index: 1;
}

/* Side buttons. Left rail: silence switch, volume up, volume down.
   Right rail: power. Proportional so they hold at any phone size. */
.phone-btn {
  position: absolute;
  width: 1.6%;
  border-radius: 2px;
  background: linear-gradient(90deg, #2b2b30, #6e6e74 60%, #3a3a3f);
  z-index: 1;
}
.phone-btn.silence { left: -1.1%; top: 15.5%; height: 3.1%; }
.phone-btn.vol-up { left: -1.1%; top: 21.5%; height: 6.4%; }
.phone-btn.vol-down { left: -1.1%; top: 29.5%; height: 6.4%; }
.phone-btn.power { right: -1.1%; top: 24%; height: 9.4%; }
.phone-screen .screen {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
  opacity: 0;
}
.phone-screen .screen.is-active { opacity: 1; }

/* A soft wash of the active section's colour behind the device. */
/* A radial gradient is already soft — the blur() on top of it bought almost
   nothing visually and cost a full-size composited layer. Gone for the same
   reason as the nav's backdrop-filter. */
.phone-glow {
  position: absolute;
  inset: -18% -26%;
  border-radius: 50%;
  background: radial-gradient(closest-side, var(--glow, rgba(37,99,235,.20)), transparent 74%);
  z-index: 1;
  transition: background .5s ease;
}

/* Copy panels */
.panels { position: relative; min-height: 430px; max-width: 540px; }
.panel {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
}
.panel.is-active { pointer-events: auto; }
.panel-kicker {
  font-family: var(--mono);
  font-weight: 600;
  font-size: 11px;
  letter-spacing: 0.16em;
  color: var(--dim);
  margin-bottom: 12px;
}
.panel h2 {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(48px, 6.4vw, 92px);
  line-height: 0.88;
  letter-spacing: -0.01em;
  margin-bottom: 18px;
}
.panel-body {
  font-size: 16px;
  line-height: 1.65;
  color: var(--dim);
  max-width: 430px;
}

/* Stat tiles, same shape the app uses under every card title. */
.tiles { display: flex; gap: 8px; margin-top: 26px; flex-wrap: wrap; }
.tile {
  background: var(--raised);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 9px 14px;
  min-width: 76px;
}
.tile b {
  display: block;
  font-family: var(--display);
  font-weight: 800;
  font-size: 27px;
  line-height: 1;
  letter-spacing: -0.01em;
}
.tile span {
  display: block;
  font-family: var(--mono);
  font-weight: 500;
  font-size: 8.5px;
  letter-spacing: 0.13em;
  color: var(--dim);
  margin-top: 4px;
}

/* Progress rail */
.rail {
  position: absolute;
  right: clamp(16px, 3vw, 44px);
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  flex-direction: column;
  gap: 9px;
}
.rail i {
  width: 2px;
  height: 26px;
  border-radius: 2px;
  background: var(--faint);
  transition: background .35s ease, height .35s ease;
}
.rail i.on { background: var(--accent); height: 40px; }

/* Specs -------------------------------------------------------------- */

.specs {
  padding: clamp(110px, 16vh, 190px) 24px;
  text-align: center;
  border-top: 1px solid var(--border);
}
.specs-title {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(42px, 6.4vw, 96px);
  line-height: 0.9;
  letter-spacing: -0.01em;
  margin: 12px 0 68px;
}
.spec-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: 16px;
  overflow: hidden;
  max-width: 1080px;
  margin: 0 auto;
}
.spec { background: var(--surface); padding: 42px 20px; }
.spec b {
  display: block;
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(56px, 7vw, 88px);
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--accent);
}
.spec span {
  display: block;
  font-family: var(--mono);
  font-weight: 500;
  font-size: 9.5px;
  letter-spacing: 0.14em;
  color: var(--dim);
  margin-top: 12px;
}

/* Pro ---------------------------------------------------------------- */

.pro {
  background: var(--pro-bg);
  color: var(--pro-text);
  padding: clamp(120px, 18vh, 210px) 24px;
}
.pro-inner { max-width: 980px; margin: 0 auto; }
.pro-title {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(54px, 9vw, 140px);
  line-height: 0.86;
  letter-spacing: -0.015em;
  margin: 16px 0 26px;
}
.pro-sub {
  font-size: 17px;
  line-height: 1.65;
  color: var(--pro-dim);
  max-width: 560px;
}
.pro-list { margin-top: 62px; border-top: 1px solid var(--pro-border); }
.pro-row {
  display: grid;
  grid-template-columns: 210px 1fr;
  gap: 20px;
  padding: 24px 0;
  border-bottom: 1px solid var(--pro-border);
  align-items: baseline;
}
.pro-row b {
  font-family: var(--display);
  font-weight: 800;
  font-size: 32px;
  letter-spacing: -0.01em;
  color: var(--gold);
}
.pro-row span { color: var(--pro-dim); font-size: 15.5px; line-height: 1.55; }

/* CTA ---------------------------------------------------------------- */

.cta {
  padding: clamp(110px, 17vh, 200px) 24px;
  text-align: center;
}
.cta-title {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(52px, 8.4vw, 132px);
  line-height: 0.88;
  letter-spacing: -0.015em;
  margin: 12px 0 20px;
}
.cta-sub {
  max-width: 500px;
  margin: 0 auto;
  color: var(--dim);
  font-size: 16.5px;
  line-height: 1.65;
}
.cta-form {
  display: flex;
  gap: 8px;
  max-width: 440px;
  margin: 36px auto 14px;
}
.cta-form input {
  flex: 1;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 15px 16px;
  font-size: 15px;
  font-family: var(--body);
  color: var(--text);
}
.cta-form input:focus { outline: none; border-color: var(--accent); }
.cta-form button {
  background: var(--accent);
  color: #fff;
  border: 0;
  border-radius: 12px;
  padding: 0 26px;
  font-family: var(--mono);
  font-weight: 600;
  font-size: 12px;
  letter-spacing: 0.1em;
  cursor: pointer;
  transition: background .2s ease;
}
.cta-form button:hover { background: var(--accent-dark); }
.cta-note { font-family: var(--mono); font-size: 10px; letter-spacing: 0.1em; color: var(--faint); }

.footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
  padding: 26px 32px;
  border-top: 1px solid var(--border);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  color: var(--dim);
}
.footer-mark {
  font-family: var(--display);
  font-size: 21px;
  font-weight: 800;
  letter-spacing: 0.02em;
  color: var(--text);
  text-decoration: none;
}
.footer-links { display: flex; gap: 16px; flex-wrap: wrap; }
.footer-links a { color: var(--dim); text-decoration: none; transition: color .2s ease; }
.footer-links a:hover { color: var(--accent); }

/* Novyn+ page — the paid theme ---------------------------------------- */
/* Every component on the site reads its colours from these variables, so
   remapping them at body level flips the entire page in one block: nav,
   dropdown, tiles, phone, footer and all. Same trick the app uses when a
   subscriber signs in. */

body.is-plus {
  --bg: #09090B;
  --surface: #18181B;
  --raised: #1F1F23;
  --text: #FAFAFA;
  --dim: #A1A1AA;
  --faint: #3F3F46;
  --border: #27272A;
  --accent: #D4AF37;
  --accent-dark: #C09A2B;
  --accent-bg: rgba(212,175,55,.13);
}

/* Gold is a light colour — anything sitting on it needs dark ink, not white. */
body.is-plus .btn,
body.is-plus .cta-form button { color: #0A0A0A; }
body.is-plus .btn.ghost { color: var(--text); }
body.is-plus .panel-more:hover,
body.is-plus .nav-cta:hover { color: #0A0A0A; }

/* The hero wash and the glow behind the device go gold too. */
body.is-plus .fp-hero::before { --wash: rgba(212,175,55,.13); }
body.is-plus .phone-glow { --glow: rgba(212,175,55,.16); }

/* On black the tag reads as gold rather than the darker bronze. */
body.is-plus .plus-tag {
  color: var(--gold);
  background: rgba(212,175,55,.14);
  border-color: rgba(212,175,55,.45);
}
body.is-plus .drop-item.plus .drop-tab { color: var(--gold) !important; }

/* The phone's drop shadow was tuned for a light page; on black it just
   muddies the area around the device. */
body.is-plus .phone-body {
  box-shadow:
    0 1px 2px rgba(0,0,0,.5),
    0 34px 68px -14px rgba(0,0,0,.75),
    inset 0 0 0 0.6px rgba(255,255,255,.22);
}
body.is-plus .fs-shot img { box-shadow: 0 16px 34px -14px rgba(0,0,0,.7); }

/* Tones -------------------------------------------------------------- */
/* Each tab owns a colour in the app; the site borrows the same mapping. */

.tone-accent { color: var(--accent); }
.tone-cardio { color: var(--cardio); }
.tone-warn { color: var(--warn); }
.tone-success { color: var(--success); }

/* Features dropdown --------------------------------------------------- */

.drop { position: relative; }
.drop-btn {
  display: flex;
  align-items: center;
  gap: 7px;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  font-family: var(--mono);
  font-weight: 600;
  font-size: 13px;
  letter-spacing: 0.11em;
  color: var(--text);
  transition: color .2s ease;
}
.drop-btn:hover, .drop.open .drop-btn { color: var(--text); }
.drop-btn svg { transition: transform .28s ease; }
.drop.open .drop-btn svg { transform: rotate(180deg); }

.drop-menu {
  position: absolute;
  top: calc(100% + 14px);
  left: -14px;
  width: 288px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 7px;
  box-shadow: 0 18px 44px -12px rgba(15,23,42,.22);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-8px);
  transition: opacity .24s ease, transform .24s ease, visibility .24s;
}
.drop.open .drop-menu { opacity: 1; visibility: visible; transform: translateY(0); }

/* Frames the whole list as the app's tabs. Without it, "Home" reads as the
   website's home page rather than the app's Home screen. */
.drop-head {
  font-family: var(--mono);
  font-weight: 600;
  font-size: 9px;
  letter-spacing: 0.16em;
  color: var(--dim);
  padding: 6px 11px 8px;
  margin-bottom: 2px;
  border-bottom: 1px solid var(--border);
}

.drop-item {
  display: block;
  padding: 9px 11px;
  border-radius: 9px;
  text-decoration: none;
  transition: background .18s ease;
}
.drop-item:hover { background: var(--raised); }
.drop-item.on { background: var(--accent-bg); }
/* Novyn+ sits below the seven tabs and is visibly a different thing. */
.drop-item.plus {
  margin-top: 5px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
  border-radius: 0 0 9px 9px;
}
.drop-item.plus .drop-tab { color: #A98424 !important; }
.drop-tab {
  display: block;
  font-family: var(--display) !important;
  font-weight: 800;
  font-size: 21px !important;
  line-height: 1.05;
  letter-spacing: 0 !important;
  color: var(--text) !important;
}
.drop-line {
  display: block;
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.09em;
  color: var(--dim);
  margin-top: 2px;
  text-transform: uppercase;
}

.nav.on-dark .drop-menu { background: var(--pro-surface); border-color: var(--pro-border); }
.nav.on-dark .drop-item:hover { background: #232327; }
.nav.on-dark .drop-tab { color: var(--pro-text) !important; }

/* "Go deeper" link on each scroll stop */
.panel-more {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: 24px;
  padding: 12px 20px;
  border-radius: 999px;
  background: var(--accent-bg);
  font-family: var(--mono);
  font-weight: 600;
  font-size: 15px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--accent);
  text-decoration: none;
  align-self: flex-start;
  transition: background .22s ease, color .22s ease;
}
.panel-more:hover { background: var(--accent); color: #fff; }
.panel-more svg { transition: transform .25s ease; }
.panel-more:hover svg { transform: translateX(4px); }

/* Feature page -------------------------------------------------------- */

.fp-hero {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: clamp(32px, 6vw, 80px);
  padding: clamp(130px, 17vh, 190px) clamp(24px, 7vw, 110px) clamp(70px, 11vh, 120px);
  position: relative;
  overflow: hidden;
}
/* A wash of the tab's own colour, so each page has a different temperature. */
.fp-hero::before {
  content: '';
  position: absolute;
  top: -30%; right: -12%;
  width: 780px; height: 780px;
  border-radius: 50%;
  background: radial-gradient(closest-side, var(--wash, rgba(37,99,235,.14)), transparent 70%);
  pointer-events: none;
}
.tone-bg-accent { --wash: rgba(37,99,235,.14); }
.tone-bg-cardio { --wash: rgba(234,88,12,.13); }
.tone-bg-warn { --wash: rgba(245,158,11,.14); }
.tone-bg-success { --wash: rgba(34,197,94,.13); }

.fp-hero-copy { position: relative; z-index: 1; max-width: 640px; }
.fp-title {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(52px, 7.6vw, 116px);
  line-height: 0.9;
  letter-spacing: -0.015em;
  margin: 14px 0 22px;
}
/* Feature headlines are full sentences and wrap to two or three lines. The
   slide-up mask only works on a single line — on a wrapped one it cropped the
   descenders of the last line ("way." lost its tail). These reveal by fading
   instead, so nothing is ever clipped. */
.fp-title .line { overflow: visible; }
.fp-lede {
  font-size: 17px;
  line-height: 1.65;
  color: var(--dim);
  max-width: 540px;
}
.fp-hero .tiles { margin-top: 28px; }

.fp-phone {
  position: relative;
  z-index: 1;
  height: min(64svh, 580px);
  aspect-ratio: 715 / 1496;  /* physical iPhone 16 Pro body, not the screen */
}
.fp-phone .phone-body { height: 100%; width: 100%; }
.fp-phone .screen { opacity: 1; }

.fp-sections {
  max-width: 900px;
  margin: 0 auto;
  padding: clamp(40px, 8vh, 90px) 24px clamp(60px, 10vh, 120px);
}
.fs-row {
  display: grid;
  grid-template-columns: 58px 1fr;
  gap: 18px;
  padding: 38px 0;
  border-top: 1px solid var(--border);
}
.fs-row.has-shot { grid-template-columns: 58px 1fr 220px; }
.fs-num {
  font-family: var(--mono);
  font-weight: 600;
  font-size: 11px;
  letter-spacing: 0.1em;
  color: var(--faint);
  padding-top: 7px;
}
.fs-copy h3 {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(30px, 3.6vw, 44px);
  line-height: 1;
  letter-spacing: -0.01em;
  margin-bottom: 12px;
}
.fs-copy p { font-size: 16px; line-height: 1.7; color: var(--dim); max-width: 560px; }
.fs-shot img {
  width: 100%;
  border-radius: 16px;
  border: 1px solid var(--border);
  box-shadow: 0 16px 34px -14px rgba(15,23,42,.24);
}

.fp-jump {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  background: var(--border);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}
.fp-jump-link {
  background: var(--bg);
  padding: 34px clamp(24px, 5vw, 60px);
  text-decoration: none;
  transition: background .25s ease;
}
.fp-jump-link:hover { background: var(--surface); }
.fp-jump-link.next { text-align: right; }
.fp-jump-link span {
  display: block;
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.16em;
  color: var(--dim);
  margin-bottom: 6px;
}
.fp-jump-link b {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(30px, 4vw, 50px);
  letter-spacing: -0.01em;
  color: var(--text);
}

/* Responsive --------------------------------------------------------- */

@media (max-width: 900px) {
  /* On a phone the whole stage has to fit one screen or the argument falls
     off the bottom where nobody reads it. The device shrinks; the words do
     not. The copy is the point — the screenshot is the evidence. */
  /* Both rows size to their content and the pair is centred as a group. The
     copy row used to be `1fr` — it swallowed all the leftover height and left
     a canyon between the screenshot and the sentence it belongs to. */
  .pin-stage {
    grid-template-columns: 1fr;
    grid-template-rows: auto auto;
    justify-items: center;
    gap: 22px;
    padding: 74px 20px 22px;
    align-content: center;
  }
  .phone { height: min(31svh, 300px); order: 1; }
  /* Panels are absolutely stacked, so the box needs its own height. */
  .panels { order: 2; min-height: 300px; width: 100%; max-width: 560px; }
  .panel { justify-content: flex-start; text-align: center; align-items: center; }
  .panel-kicker { font-size: 10px; margin-bottom: 7px; }
  .panel h2 {
    font-size: clamp(34px, 9.4vw, 52px);
    line-height: 0.92;
    margin-bottom: 10px;
  }
  .panel-body { max-width: 100%; font-size: 14.5px; line-height: 1.5; }
  .tiles { justify-content: center; gap: 6px; margin-top: 14px; }
  .tile { padding: 7px 11px; min-width: 0; }
  .tile b { font-size: 21px; }
  .tile span { font-size: 7.5px; }
  .rail { right: 10px; }
  .panel-more { align-self: center; margin-top: 18px; font-size: 14px; padding: 11px 18px; }
  .pro-row { grid-template-columns: 1fr; gap: 4px; }

  .fp-hero {
    grid-template-columns: 1fr;
    justify-items: center;
    text-align: center;
    padding-top: 108px;
  }
  .fp-hero-copy { order: 1; }
  .fp-phone { order: 2; height: min(48svh, 440px); }
  .fp-hero .tiles { justify-content: center; }
  .fp-lede { margin: 0 auto; }
  .fs-row, .fs-row.has-shot { grid-template-columns: 1fr; gap: 10px; }
  .fs-num { padding-top: 0; }
  .fs-shot { max-width: 200px; margin-top: 8px; }
  .fp-jump-link { padding: 26px 20px; }
}

/* The nav holds its three-column shape far longer than the page layout —
   it only has three small things in it, and a centred wordmark is the
   whole look. Collapse it late. */
@media (max-width: 620px) {
  .nav { padding: 13px 16px; gap: 10px; grid-template-columns: auto 1fr auto; }
  /* Direct children only — the dropdown's items are <a>s too, and hiding
     them turned the whole Features menu into an empty white box. */
  .nav-left > a { display: none; }
  /* Logo left, actions right. A centred wordmark needs equal columns either
     side, and at phone width FEATURES and the CTA can't be equal — the grid
     was shoving NOVYN visibly off-centre. Left-aligned is honest instead. */
  .nav-mark { font-size: 21px !important; grid-column: 1; grid-row: 1; justify-self: start; }
  .nav-left { grid-column: 2; grid-row: 1; justify-self: end; margin-right: 14px; }
  .nav-right { grid-column: 3; grid-row: 1; }
  .nav-cta { font-size: 9px; padding: 8px 10px; letter-spacing: 0.08em; }
  .drop-btn { font-size: 10px; }
  .drop-menu { left: -8px; width: min(76vw, 288px); }
  .footer { justify-content: center; text-align: center; }
  .footer-links { justify-content: center; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { animation-duration: .001s !important; transition-duration: .001s !important; }
}

/* ── Legal pages ────────────────────────────────────────────────────────
   Long-form reading, which nothing else on this site is. Measure is capped
   near 70 characters and the type is a size up from the marketing body copy:
   a privacy policy that is unpleasant to read does not do its job, and this
   one is the page a store reviewer opens first. */
.legal {
  /* This site has no shared container class — each section sets its own
     padding and centres its inner column. Copied that rather than inventing
     a wrapper: without margin auto the 720px measure pinned itself to the
     left edge with no gutter at all. */
  max-width: 720px;
  margin: 0 auto;
  padding: 132px 24px 96px;
}
.legal .kicker { margin-bottom: 14px; }
.legal-title {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(44px, 8vw, 68px);
  line-height: 0.95;
  letter-spacing: -0.02em;
  margin-bottom: 18px;
}
.legal-meta {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  color: var(--dim);
  margin-bottom: 34px;
}
.legal-lead {
  font-size: 18px;
  line-height: 1.62;
  color: var(--text);
  border-left: 2px solid var(--accent);
  padding-left: 20px;
  margin-bottom: 44px;
}
.legal h2 {
  font-family: var(--display);
  font-weight: 800;
  font-size: 27px;
  letter-spacing: -0.01em;
  margin: 40px 0 12px;
}
.legal p,
.legal li {
  font-size: 16px;
  line-height: 1.68;
  color: var(--dim);
}
.legal p { margin-bottom: 14px; }
.legal ul { margin: 0 0 20px; padding-left: 20px; }
.legal li { margin-bottom: 9px; }
.legal b { color: var(--text); font-weight: 700; }
.legal a { color: var(--accent); }
.legal a:hover { text-decoration: underline; }

@media (max-width: 640px) {
  .legal { padding-top: 104px; }
  .legal-lead { font-size: 16px; padding-left: 16px; }
}
