/* site-ix.css — interaction layer.
   Kept separate from site.css so the static page still stands up if this never
   loads: everything here is enhancement over a working layout. */

/* ─── SCROLL PROGRESS ──────────────────────────────────── */
.prog{position:fixed;top:0;left:0;height:2px;width:100%;transform:scaleX(0);transform-origin:0 50%;
  background:var(--volt);z-index:60;will-change:transform}

/* ─── REVEAL, STAGGERED ────────────────────────────────── */
/* Children of a .rvs stagger in behind their parent. 60ms apart, capped at 8 —
   past that it stops reading as rhythm and starts reading as lag. */
.rvs>*{opacity:0;transform:translateY(12px);
  transition:opacity .55s cubic-bezier(.2,.8,.2,1),transform .55s cubic-bezier(.2,.8,.2,1)}
.rvs.in>*{opacity:1;transform:none}
.rvs.in>*:nth-child(1){transition-delay:0ms}
.rvs.in>*:nth-child(2){transition-delay:60ms}
.rvs.in>*:nth-child(3){transition-delay:120ms}
.rvs.in>*:nth-child(4){transition-delay:180ms}
.rvs.in>*:nth-child(5){transition-delay:240ms}
.rvs.in>*:nth-child(6){transition-delay:300ms}
.rvs.in>*:nth-child(7){transition-delay:360ms}
.rvs.in>*:nth-child(8){transition-delay:420ms}

/* ─── BUTTONS ──────────────────────────────────────────── */
/* A volt wash sweeps the ghost button on hover. The solid button only lifts —
   it is already the loudest thing on the page. */
.btn{position:relative;overflow:hidden}
.btn:hover{transform:translateY(-2px)}
.btn:active{transform:translateY(0)}
.btn.ghost::before{content:"";position:absolute;inset:0;background:var(--volt);
  transform:scaleX(0);transform-origin:0 50%;transition:transform .34s cubic-bezier(.4,0,.2,1);z-index:-1}
.btn.ghost:hover::before{transform:scaleX(1)}

/* ─── PLAYABLE MOCKS ───────────────────────────────────── */
/* Every mock on this page is operable. The point of a page selling a scan is to
   let people do a small version of the scan before they commit to one. */
.mock{position:relative}
.mock .hint{position:absolute;top:12px;right:14px;font-family:var(--mono);font-size:8px;
  font-weight:600;letter-spacing:.16em;color:var(--rule);pointer-events:none;
  transition:opacity .3s;text-transform:uppercase}
.mock.touched .hint{opacity:0}

/* 01 · the dial is a real range input, restyled. */
.dial input{position:absolute;inset:-11px 0;width:100%;height:28px;margin:0;opacity:0;
  cursor:grab;-webkit-appearance:none;appearance:none;z-index:3}
.dial input:active{cursor:grabbing}
.dial input:focus-visible~.thumb{box-shadow:0 0 0 3px rgba(200,240,60,.2),0 0 0 6px rgba(200,240,60,.34)}
.dial .fill,.dial .thumb{transition:width .12s linear,left .12s linear}
.dial-foot .r{transition:color .2s}
.mock .big{font-variant-numeric:tabular-nums;transition:color .2s}

/* 02 · the three slots fill on click, then the scan runs. */
.slots div{cursor:pointer;transition:border-color .25s,transform .25s}
.slots div:hover{transform:translateY(-2px)}
.slots .empty:hover{border-color:rgba(200,240,60,.5)}
.slots .empty span{transition:color .25s}
.slots .empty:hover span{color:var(--volt)}
.slots .filled{cursor:default}
/* the sweep. One pass per photo added, volt line + the band it has crossed. */
.slots div.scanning::after{content:"";position:absolute;left:0;right:0;top:0;height:2px;
  background:var(--volt);box-shadow:0 0 14px 2px rgba(200,240,60,.6);z-index:3;
  animation:sweep .85s cubic-bezier(.4,0,.2,1)}
@keyframes sweep{0%{top:0;opacity:0}12%{opacity:1}88%{opacity:1}100%{top:100%;opacity:0}}
.readout b{font-variant-numeric:tabular-nums}
.ladder i{transition:background .4s cubic-bezier(.2,.8,.2,1)}
.ladder-l span,.ladder-l b{transition:color .4s}

/* 03 · a wipe handle drags the projection over today. */
/* The week-16 crop is RE-DERIVED for this landscape box — site.css's values were
   measured against the old 3/4 portrait frame and produce a head-and-shoulders
   portrait here, which loses the body the comparison exists to show.
   Source andras-stageready.jpg is 1089x1753 (0.6213). Box measures 333.2x228.1
   (1.456). Keeping the same horizontal guard as the portrait crop — visible
   columns 26%-100%, which holds the restroom pictograms outside the frame —
   gives image width 135.1% and height 317.8%; top:-83.3% centres the visible
   band on source rows 26%-58%, i.e. mid-torso. Re-derive all four together if
   the aspect-ratio below ever changes. */
.proj.compare .then i{width:135.1%;height:317.8%;left:-35.3%;top:-83.3%}
/* SIMULATED must survive every wipe position — it is the label the copy leans on
   ("labelled as generated, every time"), so it cannot live inside the clipped
   .then or it halves at rest and vanishes on drag. It sits on the container,
   pinned to the projected side. */
.proj.compare .simd{left:auto;right:10px;top:9px;transform:none;z-index:6}
.proj.compare{position:relative;display:block;aspect-ratio:3/2.06;border-radius:12px;overflow:hidden;
  border:1px solid var(--line);cursor:ew-resize;touch-action:none}
.proj.compare figure{position:absolute;inset:0;margin:0;aspect-ratio:auto;border:none;border-radius:0}
.proj.compare .then{clip-path:inset(0 0 0 50%)}
.proj.compare figcaption{width:50%}
.proj.compare .now figcaption{left:0;right:auto}
.proj.compare .then figcaption{right:0;left:auto;text-align:right}
.wipe{position:absolute;top:0;bottom:0;left:50%;width:2px;background:var(--volt);z-index:5;
  box-shadow:0 0 12px 1px rgba(200,240,60,.5);pointer-events:none}
.wipe::after{content:"";position:absolute;top:50%;left:50%;width:34px;height:34px;
  margin:-17px 0 0 -17px;border-radius:99px;background:var(--volt);
  box-shadow:0 3px 16px rgba(0,0,0,.5)}
.wipe i{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:6;
  width:16px;height:10px;color:var(--voltInk);display:block}
.deltas b{font-variant-numeric:tabular-nums}

/* 04 · the bolts close on click and the day banks. */
.bolt{cursor:pointer;transition:background .3s,border-color .3s,transform .2s}
.bolt:hover{transform:translateY(-2px)}
.bolt .b i{transition:width .5s cubic-bezier(.2,.8,.2,1)}
.gems i{transition:background .35s}
.gems i.mint{animation:gemMint .62s cubic-bezier(.3,.85,.25,1)}
@keyframes gemMint{0%{transform:scale(1)}18%{transform:scale(.82)}42%{transform:scale(1.06)}100%{transform:scale(1)}}
.secured{margin-top:2px;padding:11px 13px;border-radius:12px;background:rgba(200,240,60,.1);
  border:1px solid rgba(200,240,60,.34);font-family:var(--dsp);font-weight:800;
  text-transform:uppercase;font-size:17px;color:var(--volt);text-align:center;
  opacity:0;transform:translateY(6px);transition:opacity .4s,transform .4s}
.secured.on{opacity:1;transform:none}

/* ─── FEEDS ────────────────────────────────────────────── */
.feed{transition:transform .35s cubic-bezier(.2,.8,.2,1),border-color .35s}
.feed:hover{transform:translateY(-5px);border-color:rgba(200,240,60,.42)}
.feed .fi{transition:background .3s,transform .3s}
.feed:hover .fi{background:var(--volt);color:var(--voltInk);transform:scale(1.06)}
/* the connectors draw themselves once the band scrolls in */
.converge path{stroke-dasharray:var(--len,180);stroke-dashoffset:var(--len,180);
  transition:stroke-dashoffset 1.1s cubic-bezier(.4,0,.2,1)}
.converge.in path{stroke-dashoffset:0}
.converge circle{opacity:0;transition:opacity .4s .9s}
.converge.in circle{opacity:1}
.coach{transition:border-color .35s}

/* ─── PROOF COUNTERS ───────────────────────────────────── */
.proof-v{font-variant-numeric:tabular-nums}

/* ─── DOWNLOAD BAND ────────────────────────────────────── */
/* The page's one destination. Everything above it is the argument for doing
   this, and there is no price on the page because the scan is the ask. */
.dl{background:var(--graphite);border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  position:relative;overflow:hidden}
.dl::before{content:"";position:absolute;top:-30%;left:50%;width:min(760px,92%);height:150%;
  transform:translateX(-50%);background:radial-gradient(ellipse at 50% 0%,rgba(200,240,60,.09),transparent 62%);
  pointer-events:none}
.dl .wrap{position:relative}
.dl-grid{display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(30px,5vw,68px);align-items:center}
.dl h2{font-size:clamp(32px,5vw,60px)}
.dl-steps{margin-top:clamp(24px,3vw,32px);display:flex;flex-direction:column;gap:1px}
.dl-steps div{display:flex;gap:14px;align-items:baseline;padding:14px 0;border-top:1px solid var(--line)}
.dl-steps b{font-family:var(--mono);font-size:10px;font-weight:700;letter-spacing:.16em;color:var(--volt);flex-shrink:0}
.dl-steps span{font-size:14.5px;color:var(--ash);line-height:1.5}
.dl-steps strong{color:var(--bone);font-weight:600}
.dl-cta{margin-top:clamp(26px,3.4vw,34px);display:flex;flex-wrap:wrap;gap:12px;align-items:center}
.store{display:inline-flex;align-items:center;gap:11px;padding:14px 20px;border-radius:12px;
  background:var(--steel);border:1px solid var(--lineHi);color:var(--bone);text-decoration:none;
  transition:border-color .3s,transform .25s,background .3s}
.store:hover{border-color:rgba(200,240,60,.5);transform:translateY(-2px);background:#23262d}
.store small{display:block;font-family:var(--mono);font-size:8px;letter-spacing:.16em;color:var(--dim)}
.store b{display:block;margin-top:3px;font-family:var(--ui);font-size:14.5px;font-weight:600}

/* the phone, doing the one thing the page is asking for */
.dl-phone{justify-self:center;width:min(280px,100%);aspect-ratio:9/18.4;border-radius:34px;
  background:var(--coal);border:1px solid var(--lineHi);padding:11px;position:relative;
  box-shadow:0 40px 80px -30px rgba(0,0,0,.9)}
.dl-screen{position:relative;height:100%;border-radius:24px;overflow:hidden;background:var(--coal);
  display:flex;flex-direction:column}
.dl-shot{position:relative;flex:1;background-image:url(/landing/img/physique.jpg);background-size:cover;
  background-position:50% 20%;filter:grayscale(1) contrast(1.25) brightness(.6)}
.dl-shot::after{content:"";position:absolute;left:0;right:0;top:0;height:2px;background:var(--volt);
  box-shadow:0 0 16px 2px rgba(200,240,60,.6);animation:sweepLoop 3.4s cubic-bezier(.45,0,.55,1) infinite}
@keyframes sweepLoop{0%{top:0;opacity:0}8%{opacity:1}80%{opacity:1}92%{top:100%;opacity:0}100%{top:100%;opacity:0}}
.dl-bracket{position:absolute;inset:16px;border-radius:14px;z-index:2;
  background:
    linear-gradient(var(--volt),var(--volt)) 0 0/16px 2px no-repeat,
    linear-gradient(var(--volt),var(--volt)) 0 0/2px 16px no-repeat,
    linear-gradient(var(--volt),var(--volt)) 100% 0/16px 2px no-repeat,
    linear-gradient(var(--volt),var(--volt)) 100% 0/2px 16px no-repeat,
    linear-gradient(var(--volt),var(--volt)) 0 100%/16px 2px no-repeat,
    linear-gradient(var(--volt),var(--volt)) 0 100%/2px 16px no-repeat,
    linear-gradient(var(--volt),var(--volt)) 100% 100%/16px 2px no-repeat,
    linear-gradient(var(--volt),var(--volt)) 100% 100%/2px 16px no-repeat;
  opacity:.8}
.dl-read{padding:14px;border-top:1px solid var(--line);background:var(--graphite)}
.dl-read .l{font-family:var(--mono);font-size:8px;letter-spacing:.18em;color:var(--volt)}
.dl-read .n{margin-top:7px;display:flex;align-items:baseline;gap:7px}
.dl-read .n b{font-family:var(--mono);font-weight:600;font-size:27px;color:var(--bone);font-variant-numeric:tabular-nums}
.dl-read .n span{font-family:var(--mono);font-size:11px;color:var(--rule)}
.dl-read .n em{margin-left:auto;font-style:normal;font-family:var(--dsp);font-weight:800;
  text-transform:uppercase;font-size:15px;color:var(--volt)}
@media(max-width:900px){
  .dl-grid{grid-template-columns:1fr}
  .dl-phone{grid-row:1;width:min(240px,80%)}
}

/* ─── STICKY MOBILE CTA ────────────────────────────────── */
/* Appears once the hero button is off screen. Mobile only — on desktop the nav
   button is always in view and a second one would just be noise. */
.sticky{position:fixed;left:0;right:0;bottom:0;z-index:55;padding:12px 16px calc(12px + env(safe-area-inset-bottom));
  background:rgba(12,12,14,.94);backdrop-filter:blur(14px);border-top:1px solid var(--line);
  transform:translateY(110%);transition:transform .38s cubic-bezier(.2,.8,.2,1);display:none}
.sticky.on{transform:none}
.sticky .btn{width:100%;justify-content:center}
@media(max-width:760px){.sticky{display:block}}

@media(prefers-reduced-motion:reduce){
  .prog{display:none}
  .rvs>*{opacity:1;transform:none;transition:none}
  .btn:hover,.feed:hover,.store:hover,.bolt:hover,.slots div:hover{transform:none}
  .converge path{stroke-dashoffset:0;transition:none}
  .converge circle{opacity:1;transition:none}
  .dl-shot::after,.slots div.scanning::after,.gems i.mint{animation:none}
  .sticky{transition:none}
}


/* ─── WAITLIST BANNER · interaction ───────────────────────────────────────
   Static appearance lives in site.css; the page reads correctly if this
   file never loads. */
.wl-mail,.wl-btn{transition:border-color .18s,background .18s,opacity .18s}
.wl-mail:focus{border-color:var(--volt)}
.wl-mail:focus-visible{outline:2px solid var(--volt);outline-offset:2px}
.wl-btn:hover{background:#d4f957}
.wl-btn:focus-visible{outline:2px solid var(--volt);outline-offset:3px}
.wl-btn[disabled]{opacity:.55;cursor:default}
.wl-mail[aria-invalid="true"]{border-color:var(--alarm)}
@media(prefers-reduced-motion:reduce){.wl-mail,.wl-btn{transition:none}}
