/* ─── SCROLL PROGRESS ─── */
#scroll-progress {
  position: fixed;
  top: 0; left: 0;
  height: 3px;
  width: 0%;
  background: linear-gradient(90deg, var(--accent), var(--accent2));
  z-index: 200;
  transition: width 0.1s linear;
}

/* ─── RESET & BASE ─── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  --bg: #0d0d14;
  --bg2: #12121f;
  --bg3: #1a1a2e;
  /* Was lavender-purple + mint-green — the exact accent pairing every
     AI-startup/SaaS landing page reaches for by default. Replaced with a
     clinical teal (instrument, scrub-adjacent) and warm bone/ivory, tied
     to the site's actual subject instead of borrowed off-the-shelf. */
  --accent: #6fa39a;
  --accent2: #c9a06c;
  --text: #f0eef8;
  --text-muted: #9994b8;
  --footer-muted: #b7b2d6;
  --bone: #c9a06c;
  --red: #ff4466;
  --radius: 16px;
  /* "Expo out" curve — fast start, long soft settle. Same shape used by most
     premium product sites (Linear, Stripe, Apple) for anything that should
     feel considered rather than mechanical. Used everywhere below instead of
     plain "ease" so the whole page moves with one consistent personality. */
  --ease-premium: cubic-bezier(0.16, 1, 0.3, 1);
  --transition: 0.35s var(--ease-premium);

  /* Three typefaces doing three different jobs, instead of one system font
     doing everything: a serif for headlines (warmth, editorial weight), a
     clean grotesk for reading, and a mono for anything that's a number,
     label, or timestamp (ties back to the "documented, precise" premise
     of the whole site). */
  --font-display: 'Fraunces', Georgia, 'Times New Roman', serif;
  --font-body: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-mono: 'IBM Plex Mono', 'SFMono-Regular', Menlo, Consolas, monospace;

  /* Layered gray scale instead of a single --text-muted doing every job of
     secondary text — gives real hierarchy between "important body copy" and
     "quiet metadata" rather than everything reading at the same weight. */
  --ink-1: #f8f7fb;  /* headlines, primary emphasis */
  --ink-2: #d7d3e6;  /* readable body copy */
  --ink-3: #9994b8;  /* secondary / muted (was --text-muted) */
  --ink-4: #726d8f;  /* tertiary / quiet metadata */
}

html { scroll-behavior: smooth; }

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-feature-settings: 'ss01' 1, 'ss02' 1;
  -webkit-font-smoothing: antialiased;
  line-height: 1.6;
  overflow-x: hidden;
  position: relative;
}

h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -0.01em;
}

/* Faint film-grain over the whole page. Fixed + pointer-events:none so it
   never interferes with scrolling or taps, just adds texture instead of
   flat digital-looking color fields. */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 250;
  pointer-events: none;
  opacity: 0.035;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
}

/* Scroll-triggered heading reveal — a soft upward wipe instead of a plain
   fade, used on every section h2 (and the consult page h1). is-revealed is
   toggled by IntersectionObserver in script.js. */
.reveal-heading {
  clip-path: inset(0 0 100% 0);
  transition: clip-path 0.9s var(--ease-premium);
}

.reveal-heading.is-revealed { clip-path: inset(0 0 0% 0); }

/* ─── NAV ─── */
.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 100;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 20px;
  /* Blur cut from 12px to 6px and the background made more opaque to
     compensate. A blurred backdrop on a fixed element that's constantly
     animating transform on scroll is one of the more expensive things a
     mobile GPU can be asked to do every frame, this keeps most of the
     glass look at roughly half the recalculation cost. */
  background: rgba(13, 13, 20, 0.92);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  border-bottom: 1px solid rgba(111, 163, 154, 0.1);
  will-change: transform;
}

.nav-left {
  display: flex;
  align-items: center;
  gap: 10px;
}

.nav-logo {
  font-family: var(--font-mono);
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  color: var(--accent);
  text-decoration: none;
}

.nav-countdown {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 600;
  color: var(--text-muted);
  border: 1px solid rgba(111, 163, 154, 0.25);
  padding: 3px 9px;
  border-radius: 100px;
  white-space: nowrap;
}

/* Compact circular icon button instead of a "Follow on Instagram" text
   pill — the text version was the actual cause of the nav overflowing on
   phone widths. A fixed-size icon can't overflow regardless of screen
   size, so the countdown badge no longer needs to be hidden on mobile
   either (removed that compromise, there's room for everything now). */
.nav-ig {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  flex-shrink: 0;
  color: var(--text-muted);
  border: 1px solid rgba(111, 163, 154, 0.3);
  border-radius: 50%;
  transition: var(--transition);
}

.nav-ig:hover {
  background: var(--accent);
  color: var(--bg);
  border-color: var(--accent);
}

.nav-ig img {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  display: block;
}

/* Text-link variant, used on story/simulator/consult for the "back to
   the journey" link. .nav-ig on its own is a fixed 38px circle built for
   an icon — forcing "Back to the journey" into that circle is what was
   wrapping it into 3 lines and spilling out of the nav on narrow phones,
   pre-existing even before the consult button was added alongside it.
   This resets it to an auto-width pill and swaps to a shorter label
   under 420px instead of wrapping. */
.nav-ig--text {
  width: auto;
  height: auto;
  padding: 9px 14px;
  border-radius: 100px;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  white-space: nowrap;
}

.nav-ig--text .nav-ig__short { display: none; }

@media (max-width: 420px) {
  .nav-ig--text .nav-ig__long { display: none; }
  .nav-ig--text .nav-ig__short { display: inline; }
}

/* ─── NAV RIGHT / CONSULT BUTTON ───
   Wraps the consult button + Instagram icon so both sit fixed in the nav
   on every scroll position, instead of the consult CTA only existing
   further down the page. This is the "there's no easy way to get to the
   consult page" fix — it's now reachable from anywhere, on every page. */
.nav-right {
  display: flex;
  align-items: center;
  gap: 10px;
}

.nav-consult-btn {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--bg);
  background: var(--accent);
  border: none;
  border-radius: 100px;
  padding: 9px 15px;
  cursor: pointer;
  white-space: nowrap;
  transition: var(--transition);
}

.nav-consult-btn:hover { opacity: 0.85; }

.nav-consult-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Smallest phones (iPhone SE and similar, ~320-375px): logo + countdown
   badge on the left and the new consult button + IG icon on the right can
   get tight together. Same overflow risk the IG icon swap already solved
   once — drop the countdown badge here specifically (it's duplicated by
   the hero countdown a scroll away) rather than let anything wrap or clip. */
@media (max-width: 420px) {
  .nav-countdown { display: none; }
  .nav-consult-btn { padding: 8px 12px; font-size: 0.68rem; }
}

/* ─── JUMP NAV ─── */
.jump-nav {
  position: sticky;
  top: 64px; /* corrected by script.js to the real nav height, then held constant */
  z-index: 90;
  display: flex;
  gap: 8px;
  padding: 10px 20px;
  margin-top: 64px; /* corrected by script.js to the real nav height */
  background: linear-gradient(180deg, var(--bg) 75%, transparent);
  overflow-x: auto;
  scrollbar-width: none;
  /* Hide/show on scroll animates via transform (set inline by script.js),
     not top, so it never forces a layout recalculation mid-scroll. */
  transition: transform 0.3s var(--ease-premium);
  will-change: transform;
}

.jump-nav::-webkit-scrollbar { display: none; }

.jump-nav__pill {
  flex-shrink: 0;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--text-muted);
  background: var(--bg3);
  border: 1px solid rgba(111, 163, 154, 0.2);
  border-radius: 100px;
  padding: 9px 14px;
  text-decoration: none;
  white-space: nowrap;
  transition: border-color 0.3s var(--ease-premium), color 0.3s var(--ease-premium), background 0.3s var(--ease-premium);
}

.jump-nav__pill:hover { border-color: rgba(111, 163, 154, 0.5); color: var(--text); }

.jump-nav__pill.is-active {
  color: var(--bg);
  background: var(--accent);
  border-color: var(--accent);
}

.jump-nav__pill:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ─── HERO ─── */
.hero {
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  padding: 40px 24px 60px;
  text-align: center;
  position: relative;
  overflow: hidden;
  /* Was two colored radial "blob" glows — the exact soft-gradient-behind-hero
     move every SaaS landing page uses. Replaced with a faint blueprint grid:
     ties to the "documented, precise" premise instead of borrowing a generic
     product-launch atmosphere. Barely visible on purpose, texture not decor. */
  background-image:
    repeating-linear-gradient(0deg, rgba(255, 255, 255, 0.025) 0px, rgba(255, 255, 255, 0.025) 1px, transparent 1px, transparent 34px),
    repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.025) 0px, rgba(255, 255, 255, 0.025) 1px, transparent 1px, transparent 34px);
  background-color: var(--bg);
  mask-image: radial-gradient(ellipse at 50% 40%, black 0%, transparent 78%);
  -webkit-mask-image: radial-gradient(ellipse at 50% 40%, black 0%, transparent 78%);
}

/* Giant ghost numeral behind the hero copy — the target height, quietly
   present before you've even read why it matters. A common premium-editorial
   trick: one oversized, barely-there typographic element instead of a stock
   photo or gradient blob. */
.hero-watermark {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 500;
  font-size: min(52vw, 400px);
  line-height: 1;
  color: transparent;
  -webkit-text-stroke: 1px rgba(111, 163, 154, 0.1);
  z-index: 0;
  pointer-events: none;
  user-select: none;
}

.hero-content { position: relative; z-index: 1; }

/* Real face before anything else — the fix for the site reading as "the
   surgery page" instead of a person's page. Falls back to an initial in
   an accent-colored circle if images/milo.jpg hasn't been added yet, same
   onerror pattern as the before/after comparison shot further down. */
.hero-portrait {
  width: 88px;
  height: 88px;
  margin: 0 auto 20px;
  border-radius: 50%;
  border: 2px solid rgba(111, 163, 154, 0.4);
  background: var(--bg3);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  animation: fadeUp 0.7s 0.05s forwards;
}

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

.hero-portrait__fallback {
  display: none;
  font-family: var(--font-display);
  font-size: 2rem;
  font-weight: 600;
  color: var(--accent);
}

.hero-portrait.img-missing img { display: none; }
.hero-portrait.img-missing .hero-portrait__fallback { display: block; }

.hero-facts {
  display: flex;
  gap: 8px;
  justify-content: center;
  flex-wrap: wrap;
  margin-bottom: 24px;
  opacity: 0;
  animation: fadeUp 0.75s 0.3s forwards;
}

.hero-facts__chip {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--text-muted);
  border: 1px solid rgba(111, 163, 154, 0.25);
  background: var(--bg3);
  padding: 5px 12px;
  border-radius: 100px;
  white-space: nowrap;
}

.hero-eyebrow {
  font-size: 0.85rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 20px;
  opacity: 0;
  transform: translateY(10px);
  animation: fadeUp 0.7s 0.2s forwards;
}

.hero-title {
  font-size: clamp(2rem, 8vw, 3.5rem);
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: -0.02em;
  margin-bottom: 24px;
  opacity: 0;
  transform: translateY(20px);
  animation: fadeUp 0.8s 0.4s forwards;
}

.accent { color: var(--accent); }

.hero-sub {
  font-size: 0.95rem;
  color: var(--text-muted);
  margin-bottom: 36px;
  opacity: 0;
  animation: fadeUp 0.8s 0.6s forwards;
}

/* ─── COUNTDOWN ───
   Was a live days/hours/mins/secs readout in separate boxes, then briefly a
   static once-a-day line. Landed on a running decimal ticker instead — the
   number itself moves, so it still reads as "counting down," but it's
   styled like a trading terminal, not a product-launch clock. He's a stock
   trader; a ticking decimal count is his own visual language, not a
   borrowed one. Tabular figures so the digits don't jitter the line width
   as they roll over. */
.countdown-line {
  font-family: var(--font-mono);
  font-style: italic;
  font-size: 0.95rem;
  color: var(--text-muted);
  margin-bottom: 36px;
  opacity: 0;
  animation: fadeUp 0.8s 0.8s forwards;
}

.countdown-line strong {
  display: inline-block;
  min-width: 9ch;
  font-variant-numeric: tabular-nums;
  font-style: normal;
  font-weight: 700;
  color: var(--accent2);
  letter-spacing: -0.01em;
}

.countdown-done {
  font-family: var(--font-mono);
  font-style: italic;
  font-size: 0.95rem;
  color: var(--accent2);
  margin-bottom: 36px;
}

/* ─── CTA BUTTON ─── */
.cta-btn {
  display: inline-block;
  background: var(--accent);
  color: var(--bg);
  font-weight: 700;
  font-size: 0.95rem;
  padding: 14px 32px;
  border-radius: 100px;
  text-decoration: none;
  border: none;
  cursor: pointer;
  transition: var(--transition);
  opacity: 0;
  animation: fadeUp 0.8s 1s forwards;
}

.cta-btn:hover {
  background: #8fc0b7;
  transform: translateY(-2px);
  box-shadow: 0 8px 30px rgba(111, 163, 154, 0.35);
}

/* Quick, snappy press feedback — separate from the slower hover lift so a
   tap/click reads as an immediate physical response, not a delayed one. */
.cta-btn:active {
  transform: translateY(0) scale(0.97);
  transition: transform 0.15s cubic-bezier(0.4, 0, 1, 1);
}

.cta-big {
  font-size: 1.05rem;
  padding: 18px 40px;
  opacity: 1;
  animation: none;
}

/* ─── CTA WEIGHT TIERS ───
   Every button on the site used to be the same solid pill regardless of
   what it was asking for — "Read My Story" looked exactly as committal as
   "Book a Call, $50/hr". Two modifiers now carry that distinction visually
   instead of relying on copy alone. */

/* Low-commitment: outline only, no fill. For exploratory asks — reading
   more, trying a tool — nothing that costs money or a calendar slot. */
.cta-btn--soft {
  background: transparent;
  color: var(--accent);
  border: 1.5px solid rgba(111, 163, 154, 0.5);
}

.cta-btn--soft:hover {
  background: rgba(111, 163, 154, 0.1);
  color: var(--accent);
  border-color: var(--accent);
  box-shadow: none;
}

/* High-commitment: the paid, calendar-blocking ask. Warm bone/ivory fill
   instead of the default teal, so "Book a Call, $50/hr" reads as a
   deliberately heavier, rarer action, not another identical pill in a
   row of five. */
.cta-btn--commit {
  background: var(--accent2);
  color: #1a1208;
  font-size: 1rem;
  padding: 16px 34px;
}

.cta-btn--commit:hover {
  background: #dcb583;
  box-shadow: 0 8px 30px rgba(201, 160, 108, 0.35);
}

.cta-btn--commit.is-disabled {
  opacity: 0.35;
  pointer-events: none;
}

.hero-trust {
  max-width: 340px;
  margin: 18px auto 0;
  font-size: 0.75rem;
  line-height: 1.6;
  color: var(--ink-4);
  opacity: 0;
  animation: fadeUp 0.8s 1.15s forwards;
}

.hero-scroll-hint {
  position: absolute;
  bottom: 28px;
  left: 50%;
  transform: translateX(-50%);
  color: var(--text-muted);
  font-size: 1.5rem;
  animation: bounce 2s infinite;
}

/* ─── SECTIONS ─── */
.section {
  padding: 80px 0;
  position: relative;
}

/* Thin gradient hairline at the top of every section instead of a flat
   color-block boundary — a quiet, considered seam rather than a hard edge. */
.section::before {
  content: '';
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: min(90%, 680px);
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(111, 163, 154, 0.22), transparent);
}

.container {
  max-width: 680px;
  margin: 0 auto;
  padding: 0 24px;
}

.section-tag {
  font-family: var(--font-mono);
  display: inline-block;
  font-size: 0.75rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--accent);
  background: rgba(111, 163, 154, 0.1);
  border: 1px solid rgba(111, 163, 154, 0.2);
  padding: 4px 12px;
  border-radius: 100px;
  margin-bottom: 20px;
}

h2, .story-page h1, .consult-hero h1 {
  font-size: clamp(1.7rem, 5vw, 2.4rem);
  font-weight: 800;
  line-height: 1.2;
  letter-spacing: -0.02em;
  margin-bottom: 24px;
}

.section-sub {
  color: var(--text-muted);
  font-size: 0.95rem;
  margin-top: -12px;
  margin-bottom: 36px;
}

/* ─── STORY ─── */
.story { background: var(--bg2); }

.story-body p {
  /* Brighter than the site's usual muted body copy — this is the emotional
     core of the page and reads better with real contrast, not secondary
     treatment. */
  color: var(--ink-2);
  margin-bottom: 18px;
  font-size: 1.05rem;
  line-height: 1.75;
  font-family: var(--font-body);
}

.story-body p:last-child { margin-bottom: 0; }

.story-highlight {
  color: var(--text) !important;
  font-size: 1.15rem !important;
  border-left: 3px solid var(--accent);
  padding-left: 20px;
  margin: 28px 0 !important;
}

.story-body strong { color: var(--text); }

.story-readmore {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 8px;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--accent);
  text-decoration: none;
  transition: gap 0.3s var(--ease-premium);
}

.story-readmore:hover { gap: 10px; }

/* ─── STORY PAGE (story.html) ─── */
.story-page { background: var(--bg2); padding-top: 130px; }
.story-page .story-body { margin-bottom: 40px; }
.story-page__cta { display: inline-block; }

/* ─── BEFORE / AFTER ─── */
.before-after { background: var(--bg); }

.compare-shot {
  position: relative;
  width: 100%;
  max-width: 480px;
  margin: 0 auto;
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: 0 24px 60px rgba(0,0,0,0.5);
  background: var(--bg3);
}

.compare-shot img {
  width: 100%;
  display: block;
  /* Matches the actual uploaded photo's real dimensions, so the browser
     reserves the right amount of space before it finishes loading instead
     of the page jumping once it appears. object-fit keeps a future photo
     of different proportions cropping cleanly instead of distorting. */
  aspect-ratio: 1290 / 1455;
  object-fit: cover;
}

.compare-shot.img-missing img { display: none; }

/* On-image label, not just a caption someone can scroll past without
   reading. This is the single most important honesty fix on the page:
   the image is a pre-surgery projection, not a real outcome. */
.compare-shot__badge {
  position: absolute;
  top: 14px;
  left: 14px;
  z-index: 2;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: #1a1208;
  background: var(--amber, #f5c242);
  padding: 5px 11px;
  border-radius: 100px;
  box-shadow: 0 4px 14px rgba(0,0,0,0.35);
}

.compare-shot.img-missing .compare-shot__badge { display: none; }

.compare-shot__note {
  max-width: 480px;
  margin: 14px auto 0;
  font-size: 0.8rem;
  color: var(--ink-4);
  line-height: 1.6;
}

/* Featured callout, not a buried text link, this is a real growth feature. */
.simulator-promo {
  max-width: 460px;
  margin: 32px auto 0;
  padding: 28px 24px;
  text-align: center;
  border: 1px dashed rgba(111, 163, 154, 0.4);
  border-radius: var(--radius);
  background: linear-gradient(160deg, rgba(111, 163, 154, 0.08), rgba(111, 163, 154, 0.02));
}

.simulator-promo__title {
  font-family: var(--font-display);
  font-size: 1.3rem;
  font-weight: 600;
  color: var(--ink-1);
  margin-bottom: 8px;
}

.simulator-promo__sub {
  font-size: 0.88rem;
  color: var(--ink-3);
  line-height: 1.6;
  margin-bottom: 20px;
}

.simulator-promo .cta-btn { opacity: 1; animation: none; }

/* ─── HOW IT WORKS (scrollytelling) ─── */
.how { background: var(--bg2); padding-bottom: 40px; }

.scrolly {
  position: relative;
  max-width: 680px;
  margin: 0 auto;
  padding: 10px 24px 0;
}

.scrolly-visual {
  position: sticky;
  top: var(--sticky-top, 150px);
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  max-width: 360px;
  margin: 0 auto 10px;
}

/* ─── BONE FRAMES (real generated reference photos, one per stage) ─── */
.bone-frame-wrap {
  position: relative;
  width: 100%;
  aspect-ratio: 9 / 16;
  border-radius: var(--radius);
  overflow: hidden;
  background:
    radial-gradient(ellipse at 50% 25%, rgba(111, 163, 154, 0.09), transparent 60%),
    repeating-linear-gradient(0deg, rgba(255, 255, 255, 0.02) 0px, rgba(255, 255, 255, 0.02) 1px, transparent 1px, transparent 27px),
    linear-gradient(160deg, #1a1a2e, #12121f);
  border: 1px solid rgba(111, 163, 154, 0.15);
  box-shadow: 0 8px 32px rgba(0,0,0,0.4), inset 0 1px 0 rgba(255,255,255,0.05);
  animation: boneSway 8s ease-in-out infinite alternate;
  transform-origin: 50% 15%;
}

.bone-frame-wrap__badge {
  position: absolute;
  top: 14px;
  left: 14px;
  z-index: 3;
  font-family: var(--font-mono);
  font-size: 0.64rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  color: var(--ink-3);
  background: rgba(13, 13, 20, 0.65);
  backdrop-filter: blur(4px);
  padding: 4px 9px;
  border-radius: 100px;
  border: 1px solid rgba(255, 255, 255, 0.1);
}

/* Barely-there idle motion so the visual reads as alive even before you
   scroll, instead of sitting there like a flat, static photo. Scale drift
   layered onto the existing sway, both cheap GPU-composited transforms,
   so the active bone never fully sits still while it's on screen. */
@keyframes boneSway {
  0%   { transform: rotate(-0.6deg) scale(1); }
  100% { transform: rotate(0.6deg) scale(1.018); }
}

.bone-frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  padding: 22px 26px;
  opacity: 0;
  transform: scale(0.94);
  filter: blur(7px);
  transition: opacity 0.75s var(--ease-premium),
              transform 0.75s var(--ease-premium),
              filter 0.75s var(--ease-premium);
}

.bone-frame.is-active {
  opacity: 1;
  transform: scale(1);
  filter: blur(0px);
}

/* ─── VIDEO EMBED (real PRECICE animation, click-to-load) ─── */
.video-embed {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--bg3);
  border: 1px solid rgba(111, 163, 154, 0.18);
  box-shadow: 0 8px 32px rgba(0,0,0,0.4);
  cursor: pointer;
}

.video-embed:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.video-embed__thumb {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  filter: saturate(0.85) brightness(0.72);
  transition: filter 0.4s var(--ease-premium), transform 6s linear;
}

.video-embed:hover .video-embed__thumb {
  filter: saturate(1) brightness(0.82);
  transform: scale(1.03);
}

/* Scanner-style sweep over the thumbnail only, a small nod to "this is
   being measured" — disappears once the real video is playing. */
.video-embed::after {
  content: '';
  position: absolute;
  left: 0; right: 0;
  height: 45%;
  top: -45%;
  background: linear-gradient(180deg, transparent, rgba(111, 163, 154, 0.22), transparent);
  mix-blend-mode: screen;
  pointer-events: none;
  animation: scanSweep 5.5s var(--ease-premium) infinite;
}

@keyframes scanSweep {
  0%   { top: -45%; }
  60%  { top: 100%; }
  100% { top: 100%; }
}

.video-embed__play {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 60px;
  height: 60px;
  border-radius: 50%;
  background: rgba(13, 13, 20, 0.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  border: 1px solid rgba(255, 255, 255, 0.28);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  padding-left: 3px; /* optically center the play triangle */
  pointer-events: none;
  transition: transform 0.3s var(--ease-premium), background 0.3s var(--ease-premium);
}

.video-embed:hover .video-embed__play { transform: scale(1.08); background: rgba(111, 163, 154, 0.55); }

.video-embed.is-playing::after,
.video-embed.is-playing .video-embed__thumb,
.video-embed.is-playing .video-embed__play {
  display: none;
}

.video-embed.is-playing { cursor: default; }

.video-embed iframe {
  width: 100%;
  height: 100%;
  display: block;
  border: 0;
}

/* Secondary video placement, below the scroll-driven bone sequence. */
.how-video-cta {
  max-width: 420px;
  margin: 48px auto 0;
  text-align: center;
}

.how-video-cta__label {
  margin-top: 14px;
  font-size: 0.85rem;
  color: var(--ink-3);
}

.scrolly-visual__caption {
  font-family: var(--font-mono);
  margin-top: 12px;
  text-align: center;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
}

/* Small stepper under the caption — reads as "you're on stage 3 of 6",
   a deliberate sequence, rather than just a photo that happens to
   change. Dots only, no connecting line: at this size a line reads as
   visual noise more than structure. */
.scrolly-progress {
  display: flex;
  justify-content: center;
  gap: 7px;
  margin-top: 10px;
}

.scrolly-progress__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: rgba(111, 163, 154, 0.25);
  transition: background 0.4s var(--ease-premium), transform 0.4s var(--ease-premium);
}

.scrolly-progress__dot.is-active {
  background: var(--accent);
  transform: scale(1.5);
}

.scrolly-steps { padding-top: 4px; }

.scrolly-step {
  min-height: 58vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 30px 0;
  opacity: 0.3;
  transition: opacity 0.5s var(--ease-premium);
}

.scrolly-step:last-child { min-height: 40vh; }

.scrolly-step.is-active { opacity: 1; }

.scrolly-step .step-num {
  font-family: var(--font-mono);
  display: inline-block;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--accent);
  margin-bottom: 8px;
}

.scrolly-step h3 {
  font-size: 1.3rem;
  font-weight: 700;
  margin-bottom: 12px;
}

.scrolly-step p {
  color: var(--text-muted);
  font-size: 0.95rem;
  line-height: 1.7;
  margin-bottom: 10px;
}

.scrolly-step p:last-child { margin-bottom: 0; }

/* Below 700px the shared sticky visual is dropped entirely. Sticky
   elements depend on a stable viewport height, and mobile browser chrome
   (the address bar collapsing/expanding on scroll) changes that height
   mid-scroll, which is what was causing the pinned image and the step
   text to drift on top of each other. Each step now carries its own
   small static image instead — nothing pinned, nothing that can
   desync, no JS-computed offset required. */
@media (max-width: 699px) {
  .scrolly-visual { display: none; }
}

/* Per-step inline visual, mobile only (hidden on desktop below). Split
   into two layers on purpose, mirroring the desktop bone-frame /
   bone-frame-wrap split: .scrolly-step__frame carries the same idle
   sway+scale drift as the desktop sticky visual (pure transform,
   continuous, harmless), while .scrolly-step__img independently handles
   the one-time scroll-triggered reveal (opacity/blur/scale transition,
   toggled by IntersectionObserver in script.js — the same safe pattern
   already used for .tl-item and .qa-pair on this page, deliberately not
   position:sticky, since that's what caused the mobile scroll jank this
   whole structure replaced). */
.scrolly-step__frame {
  display: none;
  width: 100%;
  max-width: 220px;
  margin: 0 auto 16px;
  animation: boneSway 8s ease-in-out infinite alternate;
}

@media (max-width: 699px) {
  .scrolly-step__frame { display: block; }
}

.scrolly-step__img {
  display: block;
  width: 100%;
  aspect-ratio: 9 / 16;
  object-fit: contain;
  border-radius: var(--radius);
  background:
    radial-gradient(ellipse at 50% 25%, rgba(111, 163, 154, 0.09), transparent 60%),
    linear-gradient(160deg, #1a1a2e, #12121f);
  border: 1px solid rgba(111, 163, 154, 0.15);
  box-shadow: 0 8px 32px rgba(0,0,0,0.4);
  padding: 16px 18px;
  opacity: 0;
  transform: scale(0.94);
  filter: blur(7px);
  transition: opacity 0.75s var(--ease-premium),
              transform 0.75s var(--ease-premium),
              filter 0.75s var(--ease-premium);
}

.scrolly-step__img.is-visible {
  opacity: 1;
  transform: scale(1);
  filter: blur(0px);
}

/* ─── MYTHS / REAL QUESTIONS ─── */
.myths { background: var(--bg); }

.qa-thread {
  display: flex;
  flex-direction: column;
  gap: 34px;
  margin-top: 8px;
}

/* Was a rebuilt iMessage-style bubble UI — a borrowed interface metaphor,
   not an original one, and it's become its own cliché for "authentic"
   personal-brand sites specifically because it looks real without any
   actual design work. Restyled as a captured artifact instead: a slightly
   tilted, cropped screenshot card with a platform/timestamp label, so it
   reads as evidence dropped onto the page rather than site chrome. */
.qa-pair {
  display: flex;
  flex-direction: column;
  gap: 0;
  max-width: 420px;
  padding: 16px 18px 18px;
  border-radius: 10px;
  background: var(--bg3);
  border: 1px solid rgba(255, 255, 255, 0.08);
  box-shadow: 0 14px 34px rgba(0,0,0,0.35);
  opacity: 0;
  transform: translateY(16px) rotate(var(--qa-tilt, -0.6deg));
  transition: opacity 0.6s var(--ease-premium), transform 0.6s var(--ease-premium);
}

.qa-pair:nth-child(even) { --qa-tilt: 0.5deg; align-self: flex-end; }
.qa-pair:nth-child(odd) { --qa-tilt: -0.6deg; align-self: flex-start; }

.qa-pair.visible { opacity: 1; transform: translateY(0) rotate(var(--qa-tilt, -0.6deg)); }

.qa-source {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-4);
  margin-bottom: 10px;
  padding-bottom: 10px;
  border-bottom: 1px dashed rgba(255, 255, 255, 0.1);
}

/* Deliberately system-font, not the site's own Inter body copy — the
   visual break signals "quoted from somewhere else" the same way a
   different typeface does in print when reproducing a letter or a text
   message, rather than restyling it to match the surrounding page. */
.qa-bubble p {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  font-size: 0.9rem;
  line-height: 1.5;
}

.qa-bubble--in { margin-bottom: 10px; }
.qa-bubble--in p { color: var(--ink-3); }

.qa-bubble--out p { color: var(--ink-1); font-weight: 500; }

/* ─── CONSULT ─── */
.consult {
  background: var(--bg2);
  text-align: center;
}

.consult-body {
  color: var(--text-muted);
  font-size: 0.95rem;
  line-height: 1.7;
  max-width: 460px;
  margin: 0 auto 28px;
}

.consult-status {
  margin-top: 14px;
  font-size: 0.85rem;
  color: var(--text-muted);
  min-height: 1.2em;
}

.consult-status.is-error { color: #f0a5ae; }

.consult-plain-link {
  display: inline-block;
  margin-top: 16px;
  font-size: 0.88rem;
  color: var(--text-muted);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.consult-plain-link:hover { color: var(--text); }

/* ─── CONSULT PAGE (consult.html) ─── */
.consult-hero {
  background: var(--bg2);
  text-align: center;
  padding-top: 130px;
}

.consult-hero .section-sub { max-width: 460px; margin-left: auto; margin-right: auto; }

.consult-disclosure {
  max-width: 460px;
  margin: 0 auto 28px;
  padding: 12px 16px;
  border: 1px solid rgba(240, 198, 116, 0.3);
  background: rgba(240, 198, 116, 0.08);
  border-radius: 12px;
  font-size: 0.82rem;
  line-height: 1.6;
  color: var(--ink-2);
}

.price-tag {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 6px;
  margin: 4px 0 28px;
}

.price-tag__amount {
  font-family: var(--font-mono);
  font-size: 3.2rem;
  font-weight: 800;
  color: var(--accent);
  line-height: 1;
}

.price-tag__unit {
  font-family: var(--font-mono);
  font-size: 1rem;
  color: var(--text-muted);
}

/* Short value list under the price, left-aligned inside an otherwise
   centered hero on purpose — makes it read as a quick scan of "what
   you get" rather than more centered marketing prose. Arrow marks
   instead of numbering since these three items aren't a sequence. */
.consult-value {
  max-width: 440px;
  margin: 0 auto 28px;
  text-align: left;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.consult-value__item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
}

.consult-value__item p {
  color: var(--ink-2);
  font-size: 0.92rem;
  line-height: 1.55;
}

.consult-value__mark {
  flex-shrink: 0;
  font-family: var(--font-mono);
  color: var(--accent);
  line-height: 1.55;
}

.consult-details {
  background: var(--bg);
  text-align: left;
}

.consult-details h2 {
  font-size: 1.4rem;
  margin-bottom: 16px;
}

.consult-details p {
  color: var(--text-muted);
  font-size: 0.95rem;
  line-height: 1.7;
  margin-bottom: 14px;
  max-width: 560px;
}

.consult-details p:last-child { margin-bottom: 0; }

/* ─── TIMELINE ─── */
.timeline { background: var(--bg2); }

.latest-update {
  background: linear-gradient(135deg, rgba(201,160,108,0.12), rgba(201,160,108,0.03));
  border: 1px solid rgba(201,160,108,0.3);
  border-radius: var(--radius);
  padding: 20px;
  margin-top: 8px;
  margin-bottom: 32px;
}

.latest-update__badge {
  font-family: var(--font-mono);
  display: inline-block;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent2);
  background: rgba(201,160,108,0.15);
  padding: 4px 10px;
  border-radius: 100px;
  margin-bottom: 10px;
}

.latest-update__date {
  font-family: var(--font-mono);
  font-size: 0.95rem;
  margin-bottom: 6px;
}

.latest-update p {
  color: var(--text-muted);
  font-size: 0.9rem;
  line-height: 1.6;
}

.timeline-wrap {
  position: relative;
  margin-top: 40px;
  padding-left: 28px;
}

.timeline-wrap::before {
  content: '';
  position: absolute;
  left: 7px; top: 0; bottom: 0;
  width: 2px;
  background: linear-gradient(to bottom, var(--accent), transparent);
}

.tl-item {
  position: relative;
  margin-bottom: 40px;
  opacity: 0;
  transform: translateX(-20px);
  transition: opacity 0.7s var(--ease-premium), transform 0.7s var(--ease-premium);
}

.tl-item.visible { opacity: 1; transform: translateX(0); }
.tl-item:last-child { margin-bottom: 0; }

.tl-dot {
  position: absolute;
  left: -28px;
  top: 4px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--bg2);
  border: 2px solid var(--text-muted);
  transition: border-color 0.3s, background 0.3s;
}

.tl-item.active .tl-dot {
  border-color: var(--accent);
  background: var(--accent);
  box-shadow: 0 0 12px rgba(111, 163, 154, 0.5);
}

.tl-content h3 {
  font-family: var(--font-mono);
  font-size: 1rem;
  font-weight: 700;
  margin-bottom: 6px;
}

.tl-content p {
  color: var(--text-muted);
  font-size: 0.9rem;
  line-height: 1.6;
}

.tl-status {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 3px 9px;
  border-radius: 100px;
  margin-bottom: 8px;
}

.tl-status--progress { color: var(--accent); background: rgba(111, 163, 154, 0.14); }
.tl-status--planned { color: #f0c674; background: rgba(240, 198, 116, 0.14); }
.tl-status--estimated { color: var(--ink-4); background: rgba(255, 255, 255, 0.06); }

.timeline-note {
  margin-top: 8px;
  font-size: 0.78rem;
  color: var(--ink-4);
  line-height: 1.6;
}

.sources-line {
  margin-top: 24px;
  font-size: 0.78rem;
  color: var(--ink-4);
  line-height: 1.6;
  text-align: center;
}

.sources-line a {
  color: var(--ink-3);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.sources-line a:hover { color: var(--accent); }

/* ─── NOTIFY ─── */
.notify { background: var(--bg); text-align: center; }

.notify-form {
  display: flex;
  gap: 10px;
  max-width: 420px;
  margin: 0 auto;
  flex-wrap: wrap;
  justify-content: center;
}

.notify-form input[type="email"] {
  flex: 1;
  min-width: 200px;
  background: var(--bg3);
  border: 1px solid rgba(111, 163, 154, 0.25);
  color: var(--text);
  padding: 14px 18px;
  border-radius: 100px;
  font-size: 0.95rem;
  font-family: inherit;
}

.notify-form input[type="email"]::placeholder { color: var(--text-muted); }

.notify-form input[type="email"]:focus {
  outline: none;
  border-color: var(--accent);
}

.notify-status {
  margin-top: 14px;
  font-size: 0.85rem;
  color: var(--text-muted);
  min-height: 1.2em;
}

.notify-status.is-error { color: #f0a5ae; }
.notify-status.is-success { color: var(--accent2); }

/* ─── CTA SECTION ─── */
.cta-section {
  background: var(--bg);
  text-align: center;
}

.cta-section h2 { margin-bottom: 16px; }
.cta-section p { color: var(--text-muted); margin-bottom: 32px; }

/* ─── FOOTER SOCIAL ───
   Separate visual tier from .footer-links on purpose: those are internal
   page links (Home, Story...), these are "come follow me elsewhere" —
   bigger, bordered, icon-led, so YouTube/Instagram don't get lost in a
   row of plain text links. */
.footer-social {
  display: flex;
  justify-content: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 22px;
}

.footer-social__link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 18px;
  border-radius: 100px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: var(--bg3);
  color: var(--text);
  font-family: var(--font-mono);
  font-size: 0.78rem;
  font-weight: 600;
  text-decoration: none;
  transition: var(--transition);
}

.footer-social__link svg { flex-shrink: 0; }

.footer-social__link:hover {
  border-color: var(--accent);
  color: var(--accent);
  transform: translateY(-1px);
}

.footer-social__link--youtube:hover {
  border-color: #ff4d4d;
  color: #ff4d4d;
}

/* Was a generic outline-icon-kit glyph (1.8px stroke rounded-rect/circle) —
   indistinguishable from any Feather/Lucide/Heroicons set, the kind of icon
   that could be swapped onto any startup's footer. Rebuilt from the site's
   own visual language instead: same 2px ring weight and fill-on-active
   behavior as the .tl-dot timeline markers, with the platform initial set
   in the site's own mono type rather than a redrawn brand logo. */
.social-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  border-radius: 50%;
  border: 2px solid currentColor;
  font-family: var(--font-mono);
  font-size: 0.58rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  transition: background 0.3s, color 0.3s;
}

.footer-social__link:hover .social-mark {
  background: var(--accent);
  color: var(--bg);
}

.footer-social__link--youtube:hover .social-mark {
  background: #ff4d4d;
  color: var(--bg);
}

.nav-ig .social-mark {
  width: 22px;
  height: 22px;
  font-size: 0.62rem;
}

/* ─── FOOTER ─── */
.footer {
  padding: 32px 24px;
  text-align: center;
  border-top: 1px solid rgba(255,255,255,0.06);
}

/* So exploring one sub-page doesn't dead-end back to only the homepage. */
.footer-links {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 20px;
  margin-bottom: 18px;
}

.footer-links a {
  font-size: 0.8rem;
  color: var(--ink-3);
  text-decoration: none;
}

.footer-links a:hover { color: var(--accent); }

.footer p { color: var(--text-muted); font-size: 0.8rem; }

/* Was text-muted + opacity:0.5 (~2.5:1 contrast, fails WCAG AA).
   This is the "not medical advice" line — it should actually be readable. */
.footer-note { margin-top: 8px; font-size: 0.72rem; color: var(--footer-muted); }

/* ─── IMAGE PLACEHOLDER (before/after) ─── */
.compare-shot__placeholder {
  display: none;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 60px 24px;
  min-height: 280px;
  color: var(--text-muted);
  font-size: 0.9rem;
  line-height: 1.6;
}

.compare-shot__placeholder strong { color: var(--accent); }

.compare-shot.img-missing .compare-shot__placeholder { display: flex; }

/* ─── ANIMATIONS ─── */
@keyframes fadeUp {
  to { opacity: 1; transform: translateY(0); }
}

@keyframes bounce {
  0%, 100% { transform: translateX(-50%) translateY(0); }
  50% { transform: translateX(-50%) translateY(8px); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ─── HEIGHT SIMULATOR (simulator.html) ─── */
.simulator-intro { background: var(--bg2); text-align: center; padding-bottom: 20px; }

.simulator-privacy {
  max-width: 420px;
  margin: 14px auto 0;
  font-size: 0.78rem;
  color: var(--accent2);
  line-height: 1.6;
}

.simulator-tool { background: var(--bg2); padding-top: 20px; }

.simulator {
  max-width: 480px;
  margin: 0 auto;
  text-align: center;
}

.simulator-step-label {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 18px;
}

.simulator-label {
  display: block;
  text-align: left;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--ink-2);
  margin: 18px 0 8px;
}

.simulator-input {
  width: 100%;
  background: var(--bg3);
  border: 1px solid rgba(111, 163, 154, 0.25);
  color: var(--text);
  padding: 14px 16px;
  border-radius: 12px;
  font-size: 1rem;
  font-family: var(--font-mono);
}

.simulator-input:focus { outline: none; border-color: var(--accent); }

.simulator-dropzone {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  background: var(--bg3);
  border: 1px dashed rgba(111, 163, 154, 0.35);
  border-radius: var(--radius);
  padding: 36px 20px;
  color: var(--ink-2);
  font-size: 0.9rem;
  cursor: pointer;
  transition: border-color 0.3s var(--ease-premium), background 0.3s var(--ease-premium);
}

.simulator-dropzone:hover { border-color: var(--accent); background: #1e1e30; }
.simulator-dropzone__icon { font-size: 1.8rem; }

.simulator-guidelines {
  text-align: left;
  list-style: none;
  margin-top: 18px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.simulator-guidelines li {
  font-size: 0.82rem;
  color: var(--ink-4);
  line-height: 1.5;
  padding-left: 18px;
  position: relative;
}

.simulator-guidelines li::before {
  content: '·';
  position: absolute;
  left: 4px;
  color: var(--accent);
  font-weight: 700;
}

.simulator-error {
  margin-top: 14px;
  font-size: 0.85rem;
  color: #f0a5ae;
}

.simulator-hint {
  font-size: 0.85rem;
  color: var(--ink-3);
  line-height: 1.6;
  margin-bottom: 20px;
}

/* Card frame shared by the mark / preview / result canvases. Reuses the
   same measured-lightbox visual language as the femur photo frame. */
.simulator-frame {
  position: relative;
  margin: 0 auto 20px;
  border-radius: var(--radius);
  overflow: hidden;
  background:
    radial-gradient(ellipse at 50% 25%, rgba(111, 163, 154, 0.09), transparent 60%),
    repeating-linear-gradient(0deg, rgba(255, 255, 255, 0.02) 0px, rgba(255, 255, 255, 0.02) 1px, transparent 1px, transparent 27px),
    linear-gradient(160deg, #1a1a2e, #12121f);
  border: 1px solid rgba(111, 163, 154, 0.15);
  box-shadow: 0 8px 32px rgba(0,0,0,0.4), inset 0 1px 0 rgba(255,255,255,0.05);
}

.simulator-frame canvas { display: block; margin: 0 auto; }

/* One shared frame for before/after, not two separate cards. Both canvases
   are bottom-aligned inside it (align-items: flex-end) so feet land on the
   same baseline and the height difference reads as a single comparison,
   like standing next to a measuring wall, instead of two unrelated photos
   that happen to be near each other. Always side by side, even on mobile,
   since that's the entire point of a before/after. */
/* Single-photo drag-reveal comparison. The frame is sized to the "after"
   canvas's native pixel dimensions (it's the taller of the two, since the
   legs grow), and everything inside is positioned in real pixels, not
   percentages, so the before layer's clip lines up exactly with the after
   layer underneath regardless of how tall either one is. */
/* ─── RESULT: VIEW TOGGLE ─── */
.simulator-view-toggle {
  display: inline-flex;
  gap: 4px;
  padding: 4px;
  background: var(--bg3);
  border: 1px solid rgba(111, 163, 154, 0.2);
  border-radius: 100px;
  margin: 0 auto 18px;
}

.simulator-view-toggle__btn {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 600;
  padding: 8px 16px;
  border-radius: 100px;
  border: none;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  transition: var(--transition);
}

.simulator-view-toggle__btn.is-active {
  background: var(--accent);
  color: var(--bg);
}

.simulator-view-toggle__btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ─── RESULT: STATIC SIDE BY SIDE (default view) ───
   Two independent canvases rather than one flattened image, specifically
   so each side can shrink with width:100% on narrow phones instead of
   being locked to a fixed pixel size the way the single composed
   download image is. */
.simulator-sbs {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 10px;
  margin: 0 auto 10px;
}

.simulator-sbs__col {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}

.simulator-sbs__col canvas {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 14px;
  border: 1px solid rgba(111, 163, 154, 0.18);
  background:
    radial-gradient(ellipse at 50% 25%, rgba(111, 163, 154, 0.09), transparent 60%),
    linear-gradient(160deg, #1a1a2e, #12121f);
  box-shadow: 0 8px 32px rgba(0,0,0,0.4), inset 0 1px 0 rgba(255,255,255,0.05);
}

.simulator-sbs__label {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  color: var(--text-muted);
}

.simulator-slider-frame {
  position: relative;
  margin: 0 auto 10px;
  border-radius: var(--radius);
  overflow: hidden;
  cursor: ew-resize;
  touch-action: pan-y;
  background:
    radial-gradient(ellipse at 50% 25%, rgba(111, 163, 154, 0.09), transparent 60%),
    linear-gradient(160deg, #1a1a2e, #12121f);
  border: 1px solid rgba(111, 163, 154, 0.15);
  box-shadow: 0 8px 32px rgba(0,0,0,0.4), inset 0 1px 0 rgba(255,255,255,0.05);
}

.simulator-slider-frame canvas {
  display: block;
}

.simulator-slider-overlay {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 50%;
  overflow: hidden;
}

/* The before canvas keeps its own natural size and stays bottom-anchored
   (feet on the same baseline as the after layer); the overlay wrapper
   above is what actually does the clipping as the handle moves. */
.simulator-slider-overlay canvas {
  position: absolute;
  left: 0;
  bottom: 0;
  width: auto;
  height: auto;
  max-width: none;
}

.simulator-slider-handle {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 2px;
  background: rgba(255, 255, 255, 0.85);
  transform: translateX(-1px);
  pointer-events: none;
  box-shadow: 0 0 8px rgba(0,0,0,0.5);
}

.simulator-slider-handle__grip {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--accent2);
  color: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1rem;
  font-weight: 700;
  box-shadow: 0 4px 14px rgba(0,0,0,0.4);
}

.simulator-hint--center { text-align: center; }

.simulator-compare-label {
  position: absolute;
  top: 14px;
  z-index: 2;
  font-family: var(--font-mono);
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 4px 10px;
  border-radius: 100px;
  white-space: nowrap;
}

.simulator-compare-label--before {
  left: 10px;
  color: var(--ink-2);
  background: rgba(0, 0, 0, 0.45);
}

.simulator-compare-label--after {
  right: 10px;
  color: var(--bg);
  background: var(--accent2);
}

/* Preview frame only: canvas is pinned to the bottom of a taller reserved
   box, so as the legs stretch taller the person visibly grows upward,
   feet staying put, instead of the frame jumping around. */
.simulator-frame--grow canvas {
  position: absolute;
  bottom: 0;
  left: 0;
}

.simulator-hipline {
  position: absolute;
  left: 0;
  right: 0;
  height: 40px;
  display: flex;
  align-items: center;
  cursor: ns-resize;
  touch-action: none;
  z-index: 5;
}

.simulator-hipline::before {
  content: '';
  flex: 1;
  height: 2px;
  background: var(--accent);
  box-shadow: 0 0 8px rgba(111, 163, 154, 0.6);
}

.simulator-hipline__label {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  background: var(--accent);
  color: var(--bg);
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 700;
  padding: 4px 10px;
  border-radius: 100px;
  white-space: nowrap;
  box-shadow: 0 4px 12px rgba(0,0,0,0.35);
  pointer-events: none;
}

.simulator-controls { margin-bottom: 16px; }

.simulator-slider-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 0.85rem;
  color: var(--ink-2);
  margin-bottom: 10px;
}

.simulator-slider-value {
  font-family: var(--font-mono);
  font-weight: 700;
  color: var(--accent);
  font-size: 1.1rem;
}

.simulator-range {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 4px;
  border-radius: 100px;
  background: var(--bg3);
  outline: none;
}

.simulator-range::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--accent);
  border: 3px solid var(--bg);
  box-shadow: 0 2px 10px rgba(111, 163, 154, 0.5);
  cursor: pointer;
}

.simulator-range::-moz-range-thumb {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--accent);
  border: 3px solid var(--bg);
  box-shadow: 0 2px 10px rgba(111, 163, 154, 0.5);
  cursor: pointer;
}

.simulator-link-btn {
  display: inline-block;
  background: none;
  border: none;
  color: var(--ink-3);
  font-size: 0.85rem;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
  margin: 4px 0 18px;
  font-family: inherit;
}

.simulator-link-btn:hover { color: var(--accent); }

.simulator-disclaimer {
  font-size: 0.78rem;
  color: var(--ink-4);
  line-height: 1.6;
  margin-bottom: 18px;
}

.simulator-gate-heading {
  font-size: 1.4rem;
  margin-bottom: 10px;
}

.simulator-gate-form {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  justify-content: center;
  margin-top: 20px;
}

.simulator-gate-form input[type="email"] {
  flex: 1;
  min-width: 200px;
  background: var(--bg3);
  border: 1px solid rgba(111, 163, 154, 0.25);
  color: var(--text);
  padding: 14px 18px;
  border-radius: 100px;
  font-size: 0.95rem;
  font-family: inherit;
}

.simulator-gate-form input[type="email"]:focus { outline: none; border-color: var(--accent); }

.simulator-status {
  margin-top: 14px;
  font-size: 0.85rem;
  color: var(--ink-3);
  min-height: 1.2em;
}

.simulator-status.is-error { color: #f0a5ae; }

/* ─── TABLET+ ─── */

/* Wide enough for the visual to sit beside the text instead of above it. */
@media (min-width: 700px) {
  .scrolly {
    display: grid;
    grid-template-columns: 320px 1fr;
    gap: 48px;
    align-items: start;
    max-width: 820px;
  }

  .scrolly-visual { margin-bottom: 0; max-width: none; }

  .qa-bubble { max-width: 65%; }

}

/* ─── CONSULT MODAL ───
   Triggered from the .nav-consult-btn on any page. Modeled on the
   "read before you book" pattern: the real booking link stays visually
   present but genuinely disabled until the disclosure checkbox is
   checked, so it reads as a deliberate step, not a formality. */
.consult-modal {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 20px;
}

.consult-modal.is-open { display: flex; }

.consult-modal__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(8, 8, 14, 0.72);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
}

.consult-modal__panel {
  position: relative;
  width: 100%;
  max-width: 460px;
  max-height: 92vh;
  overflow-y: auto;
  background: var(--bg2);
  border: 1px solid rgba(111, 163, 154, 0.25);
  border-radius: var(--radius);
  padding: 34px 26px 28px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.5);
  animation: consultModalIn 0.35s var(--ease-premium);
}

@keyframes consultModalIn {
  from { opacity: 0; transform: translateY(14px) scale(0.98); }
  to { opacity: 1; transform: none; }
}

.consult-modal__close {
  position: absolute;
  top: 14px;
  right: 14px;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1px solid rgba(111, 163, 154, 0.3);
  background: transparent;
  color: var(--text-muted);
  font-size: 1.3rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: var(--transition);
}

.consult-modal__close:hover {
  background: var(--accent);
  color: var(--bg);
  border-color: var(--accent);
}

.consult-modal__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.6rem;
  margin: 8px 0 8px;
  color: var(--ink-1);
}

.consult-modal__sub {
  color: var(--text-muted);
  font-size: 0.88rem;
  line-height: 1.6;
  margin-bottom: 18px;
}

.consult-value--modal { margin-bottom: 20px; }

.consult-modal__waiver {
  border: 1px solid rgba(240, 198, 116, 0.3);
  background: rgba(240, 198, 116, 0.08);
  border-radius: 12px;
  padding: 14px 16px;
  margin-bottom: 18px;
}

.consult-modal__waiver-title {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #f0c674;
  margin-bottom: 8px;
}

.consult-modal__waiver p {
  font-size: 0.82rem;
  line-height: 1.6;
  color: var(--ink-2);
  margin-bottom: 12px;
}

.consult-modal__checkbox {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-size: 0.82rem;
  color: var(--ink-2);
  cursor: pointer;
}

.consult-modal__checkbox input {
  margin-top: 3px;
  accent-color: var(--accent);
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}

.consult-modal__cta {
  display: block;
  width: 100%;
  text-align: center;
  transition: var(--transition), opacity 0.25s var(--ease-premium);
}

.consult-modal__cta.is-disabled {
  opacity: 0.4;
  pointer-events: none;
}

.consult-modal__full-link {
  display: block;
  text-align: center;
  margin-top: 14px;
  font-size: 0.8rem;
  color: var(--text-muted);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.consult-modal__waiver.is-shake { animation: consultShake 0.4s var(--ease-premium); }

@keyframes consultShake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-4px); }
  75% { transform: translateX(4px); }
}

body.modal-open { overflow: hidden; }

@media (max-width: 480px) {
  .consult-modal__panel { padding: 30px 20px 24px; }
}

/* ─── HUB (index.html landing hub — replaces the old full-scroll hero) ───
   Photo, one-line identity, then every platform link and the consult CTA
   above the fold. Reuses .hero-portrait/.hero-eyebrow/.hero-trust/.cta-btn
   patterns already established elsewhere on the site so it reads as the
   same design system, just a much shorter first screen. */
.hub {
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  padding: 100px 24px 60px;
  text-align: center;
  position: relative;
  overflow: hidden;
  background-image:
    repeating-linear-gradient(0deg, rgba(255, 255, 255, 0.025) 0px, rgba(255, 255, 255, 0.025) 1px, transparent 1px, transparent 34px),
    repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.025) 0px, rgba(255, 255, 255, 0.025) 1px, transparent 1px, transparent 34px);
  background-color: var(--bg);
  mask-image: radial-gradient(ellipse at 50% 35%, black 0%, transparent 78%);
  -webkit-mask-image: radial-gradient(ellipse at 50% 35%, black 0%, transparent 78%);
}

/* On narrow/tall viewports the ellipse mask above fades out much closer to
   the left/right edges than it does on desktop, so the fade ring itself
   becomes visible as a glow strip near the sides. Simplest fix: drop the
   grid + mask on mobile and just use a flat background there. */
@media (max-width: 640px) {
  .hub {
    background-image: none;
    mask-image: none;
    -webkit-mask-image: none;
  }
}

.hub-portrait {
  width: 104px;
  height: 104px;
  margin: 0 auto 20px;
  border-radius: 50%;
  border: 2px solid rgba(111, 163, 154, 0.4);
  background: var(--bg3);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  z-index: 1;
  opacity: 0;
  animation: fadeUp 0.7s 0.05s forwards;
}

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

.hub-portrait__fallback {
  display: none;
  font-family: var(--font-display);
  font-size: 2.3rem;
  font-weight: 600;
  color: var(--accent);
}

.hub-portrait.img-missing img { display: none; }
.hub-portrait.img-missing .hub-portrait__fallback { display: block; }

.hub-title {
  position: relative;
  z-index: 1;
  font-family: var(--font-mono);
  font-size: 1.4rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--text);
  margin-bottom: 10px;
  opacity: 0;
  transform: translateY(10px);
  animation: fadeUp 0.7s 0.15s forwards;
}

.hub-sub {
  position: relative;
  z-index: 1;
  max-width: 440px;
  margin: 0 auto 30px;
  font-size: 0.98rem;
  line-height: 1.6;
  color: var(--ink-2);
  opacity: 0;
  transform: translateY(15px);
  animation: fadeUp 0.75s 0.25s forwards;
}

.hub-links {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(128px, 1fr));
  gap: 10px;
  width: 100%;
  max-width: 460px;
  margin: 0 auto 30px;
  opacity: 0;
  transform: translateY(15px);
  animation: fadeUp 0.75s 0.35s forwards;
}

.hub-link {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  padding: 14px 16px;
  border-radius: 14px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: var(--bg3);
  color: var(--text);
  font-family: var(--font-mono);
  font-size: 0.82rem;
  font-weight: 600;
  text-decoration: none;
  transition: var(--transition);
}

.hub-link:hover { transform: translateY(-2px); border-color: var(--accent); }

.hub-link__mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  border-radius: 50%;
  border: 2px solid currentColor;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  transition: background 0.3s, color 0.3s;
}

.hub-link:hover .hub-link__mark { background: currentColor; }
.hub-link:hover .hub-link__mark { color: var(--bg); }

.hub-link--youtube:hover { border-color: #ff4d4d; color: #ff4d4d; }
.hub-link--tiktok:hover { border-color: #25f4ee; color: #25f4ee; }
.hub-link--instagram:hover { border-color: #e1306c; color: #e1306c; }
.hub-link--twitch:hover { border-color: #9146ff; color: #9146ff; }
.hub-link--discord:hover { border-color: #5865f2; color: #5865f2; }

/* Consult is the one paid, high-commitment ask on the page, so it gets
   its own row, full width up to a cap, visually heavier than the platform
   grid above it rather than just another tile in the same row. */
.hub-cta-row {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 400px;
  margin: 0 auto 8px;
  opacity: 0;
  transform: translateY(15px);
  animation: fadeUp 0.8s 0.45s forwards;
}

.hub-cta-row .cta-btn {
  display: block;
  width: 100%;
  opacity: 1;
  animation: none;
}

.hub-countdown {
  position: relative;
  z-index: 1;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: var(--ink-4);
  margin: 14px 0 4px;
  opacity: 0;
  animation: fadeUp 0.8s 0.6s forwards;
}

.hub-countdown strong {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  color: var(--accent2);
}

.hub .hero-trust {
  position: relative;
  z-index: 1;
  animation-delay: 0.7s;
}

/* ─── COMPRESSED STORY (index.html only — full version on story.html) ─── */
.story-compressed { background: var(--bg2); }
.story-compressed .story-body p { margin-bottom: 16px; }
