/* Vyota scrollcraft — CSS scroll-driven only (0 JS). Base rules = final frame (fallback + reduced motion); scrubs apply only under @supports + motion OK.
   Three sticky tracks (skin scan, shelf scan, meal scan): track 220vh desktop / 160vh mobile, stage sticky 100vh, timeline = the track's own view progress (contain 0→100 = the sticky window). */
:root{--ease:cubic-bezier(.2,.8,.2,1);--navh:68px}
@property --wk{syntax:"<integer>";inherits:true;initial-value:12}
@property --score{syntax:"<integer>";inherits:true;initial-value:78}
/* ── shared scan language: beam, brackets, result card ── */
/* beam: 3px porcelain core @.95, gold halo 12px/32px, 40px soft trail above, everything below the line dimmed to ~brightness .82 */
.cam-beam{position:absolute;left:0;right:0;top:0;height:200%;z-index:2;pointer-events:none;opacity:0;background:linear-gradient(to bottom,transparent calc(50% - 40px),rgba(176,141,87,.12) calc(50% - 16px),rgba(176,141,87,.25) calc(50% - 12px),rgba(176,141,87,.6) calc(50% - 4px),rgba(246,239,230,.95) calc(50% - 1.5px),rgba(246,239,230,.95) calc(50% + 1.5px),rgba(176,141,87,.6) calc(50% + 4px),rgba(176,141,87,.25) calc(50% + 12px),rgba(38,32,26,.18) calc(50% + 16px),rgba(38,32,26,.18) 100%);transform:translateY(0)}
/* brackets pinned to the target via --bx (top right bottom left, % of the frame). ::before = 2.5px porcelain corners, 22% long, gold halo; ::after = dims everything outside the box */
.cam-scan{position:absolute;inset:var(--bx);z-index:2;pointer-events:none;opacity:1}
.cam-scan::before{content:"";position:absolute;inset:0;--c:linear-gradient(#F6EFE6,#F6EFE6);background:var(--c) top left/22% 2.5px no-repeat,var(--c) top left/2.5px 22% no-repeat,var(--c) top right/22% 2.5px no-repeat,var(--c) top right/2.5px 22% no-repeat,var(--c) bottom left/22% 2.5px no-repeat,var(--c) bottom left/2.5px 22% no-repeat,var(--c) bottom right/22% 2.5px no-repeat,var(--c) bottom right/2.5px 22% no-repeat;filter:drop-shadow(0 0 6px rgba(176,141,87,.7))}
.cam-scan::after{content:"";position:absolute;inset:0;box-shadow:0 0 0 200vmax rgba(38,32,26,.3)}
.pcard{position:absolute;left:0;right:0;bottom:0;z-index:3;background:var(--card);color:var(--espresso);border-radius:22px 22px 0 0;padding:18px 18px 20px;display:flex;flex-direction:column;gap:12px}
.pc-title{font-family:var(--mono);font-size:8px;letter-spacing:1.4px;color:var(--ink-faint);padding-bottom:12px;border-bottom:1px solid var(--hairline)}
.pc-row{font-size:10.5px;font-weight:300;line-height:1.4;color:var(--espresso)}
.pc-row+.pc-row,.meal-visual .pc-row:first-of-type{padding-left:10px;text-indent:-10px}
.pc-row+.pc-row::before,.meal-visual .pc-row:first-of-type::before{content:"· ";color:var(--gold)}
.pc-badge{margin-top:2px;font-family:var(--mono);font-size:8px;letter-spacing:1.4px;color:var(--gold-ink);display:block;line-height:1.6}
.pc-badge::before{content:"";display:inline-block;vertical-align:middle;width:14px;height:1px;background:var(--gold);margin-right:8px}
.pc-badge b{font-weight:500;color:var(--espresso)}
/* ── D1 skin scan ── */
.seq{position:relative}
.seq .phone{box-shadow:none}
.seq-sticky{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:56px;align-items:center;padding-top:88px;padding-bottom:88px}
.seq-lines{display:grid;margin-top:22px}
.seq-lines .ln{grid-area:1/1;margin:0;font-family:var(--serif);font-size:clamp(28px,3.2vw,40px);line-height:1.15;letter-spacing:-.4px;font-weight:500;max-width:18ch;text-wrap:pretty}
.seq-lines .ln em{font-style:italic;font-weight:400;color:var(--ink-soft)}
.seq-lines .ln:not(:last-child){opacity:0}
.seq-bar{margin-top:36px;height:1px;background:var(--hairline);max-width:320px;position:relative}
.seq-bar i{position:absolute;inset:0;background:var(--gold);transform-origin:left}
.seq-steps{display:flex;justify-content:space-between;max-width:320px;margin-top:12px;font-family:var(--mono);font-size:9px;letter-spacing:1.6px;color:var(--ink-faint);text-transform:uppercase}
.seq-phone{display:flex;justify-content:center}
.seq-phone .screen image-slot,.seq-phone .screen .selfie{position:absolute;inset:0;width:100%;height:100%;background:#3B332C;object-fit:cover;object-position:center top}
.scan.sq{background:linear-gradient(to bottom,rgba(20,17,16,.55),rgba(20,17,16,0) 32%);color:var(--porcelain);overflow:hidden;--bx:27% 20% 30% 20%}
.scan.sq .k{color:rgba(247,242,235,.6)}
.scan.sq .k,.scan.sq .t{position:relative;z-index:3}
.scan.sq .t{color:var(--porcelain)}
.scan.sq svg{position:relative;z-index:2}
.scan.sq .dot{fill:var(--gold);animation:none;opacity:1;transform-box:fill-box;transform-origin:center}
.scan.sq .ring{position:relative;z-index:3;color:#1A1A1A}
.scan.sq .ring .fill{animation:none;stroke-dashoffset:39}
.scan.sq .ring .n{animation:none;opacity:1;--score:78}
.scan.sq .ring .n::before{counter-reset:s var(--score);content:counter(s)}
@media(max-width:820px){.seq-sticky{grid-template-columns:1fr;gap:28px;padding-top:64px;padding-bottom:64px}.seq-lines .ln{font-size:26px}.seq-steps,.seq-bar{display:none}.seq .phone{width:200px}}
/* ── D2 shelf scan + meal scan (same stage) ── */
.shelf-visual{display:flex;justify-content:center}
.shelf-visual .phone{box-shadow:0 30px 80px rgba(0,0,0,.5),0 2px 0 rgba(255,255,255,.12) inset}
.meal .shelf-visual .phone{box-shadow:0 30px 80px rgba(38,32,26,.18),0 2px 0 rgba(255,255,255,.4) inset}
.shot-cam{position:absolute;inset:0;background:#141110;color:var(--porcelain);padding:54px 18px 0;display:flex;flex-direction:column;overflow:hidden}
.shot-cam .k{font-family:var(--mono);font-size:9px;letter-spacing:1.6px;color:rgba(247,242,235,.5)}
.cam-frame{flex:1;position:relative;margin:12px -18px 0;overflow:hidden;z-index:1;--bx:62% 30% 23% 31%}
.cam-frame image-slot,.cam-frame .cam-photo{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center 58%}
.cam-frame .cam-photo.plate{object-position:center 40%}
.cam-frame .cam-beam{transform:translateY(-15.5%)}
.meal-dots{position:absolute;inset:0;z-index:2;pointer-events:none}
.meal-dots i{position:absolute;width:10px;height:10px;margin:-5px;border-radius:50%;background:var(--gold);box-shadow:0 0 0 3px rgba(247,242,235,.85)}
.meal-visual .pcard .pc-title{color:var(--ink-soft)}
@media(max-width:900px){.shelf-sticky .fb-list,.shelf-sticky .retailers{display:none}.shelf-sticky h2.display{font-size:30px}.shelf-sticky .body-copy{font-size:14px;margin-top:14px}.shelf-sticky .phone.sm{width:200px}}
/* ── D4 twelve weeks ── */
.weeks{margin-top:56px;padding-top:56px;border-top:1px solid var(--hairline);display:grid;grid-template-columns:minmax(0,.8fr) minmax(0,1.2fr);gap:0 56px;align-items:end;--wk:12}
.weeks>div:first-child{grid-row:1/3;align-self:end}
.weeks .body-copy{margin-top:22px}
.wk{display:flex;align-items:baseline;gap:14px;margin-top:18px}
.wk-n::before{counter-reset:wk var(--wk);content:counter(wk);font-family:var(--serif);font-size:clamp(72px,9vw,120px);line-height:.9;font-weight:500;letter-spacing:-3px;font-variant-numeric:tabular-nums}
.wk-l,.wk-of{font-family:var(--mono);font-size:11px;letter-spacing:1.8px;color:var(--ink-faint)}
.glow{grid-column:2;width:100%;height:180px;display:block;overflow:visible}
.glow .grid line{stroke:var(--hairline);stroke-width:1;vector-effect:non-scaling-stroke}
.glow .curve{fill:none;stroke:var(--gold);stroke-width:1.5;stroke-dasharray:1;stroke-dashoffset:0}
.glow-axis{grid-column:2;display:flex;justify-content:space-between;margin-top:10px;font-family:var(--mono);font-size:9px;letter-spacing:1.4px;color:var(--ink-faint)}
.rites{grid-column:1/-1;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:24px;margin-top:44px}
.rite{position:relative;border-top:1px solid var(--hairline);padding-top:14px;font-size:13px;color:var(--espresso)}
.rite .kicker{margin-bottom:6px}
.rite::before{content:"";position:absolute;top:-1px;left:0;right:0;height:1px;background:var(--gold);transform-origin:left}
@media(max-width:820px){.weeks{grid-template-columns:1fr}.weeks>div:first-child{grid-row:auto}.glow,.glow-axis{grid-column:1}.glow{margin-top:32px;height:140px}.rites{grid-template-columns:repeat(2,minmax(0,1fr))}}

/* ── scrubs: only where supported and motion is welcome ── */
@supports (animation-timeline:view()){
@media (prefers-reduced-motion:no-preference){
  /* sticky tracks: skin has the most phases so it gets the longest run */
  .seq{height:calc(300vh - var(--navh))}.shelf.seq2{height:calc(220vh - var(--navh))}.meal.seq3{height:calc(200vh - var(--navh))}
  .shelf.seq2,.meal.seq3{padding:0}
  .seq-sticky,.shelf-sticky{position:sticky;top:var(--navh);height:calc(100vh - var(--navh))}
  .seq-sticky{padding-top:0;padding-bottom:0}
  .shelf-sticky{display:flex;align-items:center}
  .shelf-sticky>.container{width:100%}
  @media(max-width:820px){.seq{height:calc(220vh - var(--navh))}.shelf.seq2,.meal.seq3{height:calc(160vh - var(--navh))}}
  /* short viewports: stage would overflow — release sticky, show final frames */
  @media(max-height:680px){
    .seq,.shelf.seq2,.meal.seq3{height:auto}.shelf.seq2,.meal.seq3{padding:128px 0}
    .seq-sticky,.shelf-sticky{position:static;height:auto}.seq-sticky{padding-top:88px;padding-bottom:88px}
    .seq *,.shelf.seq2 *,.meal.seq3 *{animation:none!important}
    .cam-beam{opacity:0}
    .seq-lines .ln:not(:last-child){display:none}
  }
  /* D1 skin (300vh): 0-10 photo only · 10-20 brackets land · 20-40 beam · 40-70 five zone dots one by one · 70-88 ring fills, score counts up · 88-100 result settles */
  .seq{view-timeline-name:--seq}
  .scan.sq .cam-scan{animation:landFace linear both;animation-range:contain 10% contain 20%}
  .scan.sq .cam-beam{animation:beamPass linear both;animation-range:contain 20% contain 40%}
  .scan.sq .dot{animation:dotIn linear both}
  .scan.sq .dot:nth-of-type(1){animation-range:contain 40% contain 46%}
  .scan.sq .dot:nth-of-type(2){animation-range:contain 46% contain 52%}
  .scan.sq .dot:nth-of-type(3){animation-range:contain 52% contain 58%}
  .scan.sq .dot:nth-of-type(4){animation-range:contain 58% contain 64%}
  .scan.sq .dot:nth-of-type(5){animation-range:contain 64% contain 70%}
  .scan.sq .ring .fill{animation:sqRing linear both;animation-range:contain 70% contain 88%}
  .scan.sq .ring .n{animation:sqScore linear both;animation-range:contain 70% contain 88%}
  .scan.sq .ring{animation:sqCard linear both;animation-range:contain 88% contain 100%}
  .seq-bar i{animation:sqBar linear both;animation-range:contain}
  .seq-lines .ln{animation:sqLine linear both}
  .seq-lines .ln:nth-child(1){animation-name:sqLineFirst;animation-range:contain 0% contain 22%}
  .seq-lines .ln:nth-child(2){animation-range:contain 18% contain 42%}
  .seq-lines .ln:nth-child(3){animation-range:contain 38% contain 72%}
  .seq-lines .ln:nth-child(4){animation-range:contain 68% contain 90%}
  .seq-lines .ln:nth-child(5){animation-name:sqLineLast;animation-range:contain 88% contain 100%}
  .scan.sq .cam-scan,.scan.sq .cam-beam,.scan.sq .dot,.scan.sq .ring .fill,.scan.sq .ring .n,.scan.sq .ring,.seq-bar i,.seq-lines .ln{animation-timeline:--seq}
  @media(max-width:820px){.seq-lines .ln{animation-name:sqLineM}.seq-lines .ln:nth-child(1){animation-name:sqLineFirst}.seq-lines .ln:nth-child(5){animation-name:sqLineLast}}
  /* D2 shelf: 0-20 photo only · 20-55 beam descends · 55-70 slows onto the barcode, brackets land · 70-80 beam gone, brackets flash · 80-100 card rises, everything under it fades */
  .shelf.seq2{view-timeline-name:--shelf}
  .seq2 .cam-beam{animation:beamBarcode linear both;animation-range:contain 20% contain 80%}
  .seq2 .cam-scan{animation:landTarget linear both;animation-range:contain 55% contain 100%}
  .seq2 .pcard{animation:cardUp linear both;animation-range:contain 80% contain 96%}
  .seq2 .pc-badge{animation:badgeIn linear both;animation-range:contain 94% contain 100%}
  .seq2 .cam-beam,.seq2 .cam-scan,.seq2 .pcard,.seq2 .pc-badge{animation-timeline:--shelf}
  /* meal: same stage, no brackets — three dots mark the dishes */
  .meal.seq3{view-timeline-name:--meal}
  .seq3 .cam-beam{animation:beamPassFrame linear both;animation-range:contain 20% contain 55%}
  .seq3 .meal-dots i{animation:dotIn linear both}
  .seq3 .meal-dots i:nth-child(1){animation-range:contain 55% contain 61%}
  .seq3 .meal-dots i:nth-child(2){animation-range:contain 62% contain 68%}
  .seq3 .meal-dots i:nth-child(3){animation-range:contain 69% contain 75%}
  .seq3 .pcard{animation:cardUp linear both;animation-range:contain 80% contain 96%}
  .seq3 .pc-badge{animation:badgeIn linear both;animation-range:contain 94% contain 100%}
  .seq3 .cam-beam,.seq3 .meal-dots i,.seq3 .pcard,.seq3 .pc-badge{animation-timeline:--meal}
  /* D4 */
  .weeks{view-timeline-name:--wk;animation:wkCount linear both;animation-timeline:--wk;animation-range:cover 15% cover 70%}
  .glow .curve{animation:wkCurve linear both;animation-timeline:--wk;animation-range:cover 15% cover 70%}
  .rite::before{animation:lineX linear both;animation-timeline:--wk}
  .rite:nth-child(1)::before{animation-range:cover 15% cover 29%}
  .rite:nth-child(2)::before{animation-range:cover 29% cover 43%}
  .rite:nth-child(3)::before{animation-range:cover 43% cover 57%}
  .rite:nth-child(4)::before{animation-range:cover 57% cover 70%}
}}
/* brackets land: 130% → 100%, one flash .7 → 1, then hold (skin: stays on) */
@keyframes landFace{0%{opacity:0;transform:scale(1.3);animation-timing-function:var(--ease)}60%{opacity:.7;transform:none}80%{opacity:1}100%{opacity:1}}
/* brackets land then fade under the card: 55-70 land (0..33) · 70-80 flash (33..55) · 80-100 fade (55..100) */
@keyframes landTarget{0%{opacity:0;transform:scale(1.3);animation-timing-function:var(--ease)}33%{opacity:.7;transform:none}44%{opacity:1}55%{opacity:1}100%{opacity:0}}
/* beam, full pass top → bottom (element is 200% tall, the line sits at its middle) */
@keyframes beamPass{0%{opacity:0;transform:translateY(-50%)}6%{opacity:1}94%{opacity:1;transform:translateY(0)}100%{opacity:0;transform:translateY(0)}}
@keyframes beamPassFrame{0%{opacity:0;transform:translateY(-50%)}6%{opacity:1}94%{opacity:1;transform:translateY(-4%)}100%{opacity:0;transform:translateY(-4%)}}
/* beam onto the barcode: constant speed (0..58 of the 20-80 window), decelerates and rests on the barcode (58..83), fades (83..100) */
@keyframes beamBarcode{0%{opacity:0;transform:translateY(-50%)}4%{opacity:1}58%{opacity:1;transform:translateY(-18%);animation-timing-function:var(--ease)}83%{opacity:1;transform:translateY(-15.5%)}100%{opacity:0;transform:translateY(-15.5%)}}
@keyframes dotIn{from{opacity:0;transform:scale(.4);animation-timing-function:var(--ease)}to{opacity:1;transform:none}}
@keyframes cardUp{from{transform:translateY(100%);animation-timing-function:var(--ease)}to{transform:none}}
@keyframes badgeIn{from{opacity:0;transform:translateX(-6px);animation-timing-function:var(--ease)}to{opacity:1;transform:none}}
@keyframes sqRing{from{stroke-dashoffset:176}to{stroke-dashoffset:39}}
@keyframes sqScore{from{--score:0}to{--score:78}}
@keyframes sqFade{from{opacity:0}to{opacity:1}}
@keyframes sqCard{from{opacity:.6;transform:translateY(16px);animation-timing-function:var(--ease)}to{opacity:1;transform:none}}
@keyframes sqBar{from{transform:scaleX(0)}to{transform:scaleX(1)}}
@keyframes sqLine{0%{opacity:0;transform:translateY(10px);animation-timing-function:var(--ease)}18%{opacity:1;transform:none}82%{opacity:1;transform:none;animation-timing-function:var(--ease)}100%{opacity:0;transform:translateY(-10px)}}
@keyframes sqLineM{0%{opacity:0;transform:translateY(10px);animation-timing-function:var(--ease)}18%{opacity:1;transform:none}82%{opacity:1;transform:none;animation-timing-function:var(--ease)}100%{opacity:0;transform:translateY(-10px)}}
@keyframes sqLineFirst{0%{opacity:1;transform:none}80%{opacity:1;transform:none;animation-timing-function:var(--ease)}100%{opacity:0;transform:translateY(-10px)}}
@keyframes sqLineLast{from{opacity:0;transform:translateY(10px);animation-timing-function:var(--ease)}to{opacity:1;transform:none}}
@keyframes lineX{from{transform:scaleX(0)}to{transform:scaleX(1)}}
@keyframes wkCount{from{--wk:1}to{--wk:12}}
@keyframes wkCurve{from{stroke-dashoffset:1}to{stroke-dashoffset:0}}
