/* anim.css: motion proposal for the shop (Oct 13 2026, built on the s65 store). Only motion: no colours, fonts, sizes or layout change.
   Three strengths, picked by <html data-anim="a|b|c"> (anim.js sets it from ?anim=). No data-anim = the shop exactly as today.
   Rules: translate / rotate / scale + opacity only (nothing reflows, smooth on cheap phones); all of it sits inside
   prefers-reduced-motion: no-preference, so people who ask for less motion get none (anim.js also stops for them).
   The hero mug photo is never touched: only its wrapper link (.pd-mug) moves; the <img>, its file, filter and size stay as they are.
   Swing keyframes are generated by tools/gen_curves.py (damped pendulum / slow sine). */
@media (prefers-reduced-motion:no-preference){
html[data-anim]{
  --ease-out:cubic-bezier(.23,1,.32,1);
  --spring-b:linear(0, 0.029, 0.102, 0.202, 0.316, 0.434, 0.548, 0.654, 0.747, 0.827, 0.893, 0.945, 0.985, 1.015, 1.034, 1.047, 1.053, 1.054, 1.052, 1.048, 1.043, 1.036, 1.03, 1.024, 1.018, 1.013, 1.009, 1.005, 1.003, 1.001, 0.999, 0.998, 0.997, 0.997, 0.997, 0.997, 1);
  --spring-c:linear(0, 0.053, 0.185, 0.359, 0.547, 0.725, 0.879, 1, 1.085, 1.137, 1.16, 1.161, 1.145, 1.119, 1.089, 1.059, 1.032, 1.009, 0.992, 0.981, 0.975, 0.973, 0.975, 0.978, 0.983, 0.988, 0.993, 0.997, 1, 1.002, 1.004, 1.004, 1.004, 1.004, 1.003, 1.002, 1);
}
/* ---------- shared ---------- */
/* the hero stage: anim.js adds .pd-arm (items wait, invisible) when it is drawn, then .pd-go once the photos are decoded AND the stage
   is at least partly on screen (max 1.2 s wait for photos), and .pd-done a second later (medal taps then use shorter delays) */
html[data-anim] .pdo{transition:none}
html[data-anim] .pdstage.swap .pdo{transform:none;opacity:1}          /* today's fade-swap is replaced by each option's own exit */
html[data-anim] .pdstage.pd-arm:not(.pd-go) .pdo{opacity:0}
html[data-anim] .pd-orn{transform-origin:30% 2%}                     /* = the ornament's hook, so it swings from its string */
html[data-anim] .pd-tee{transform-origin:50% 4%}                     /* = the tee's collar, as if on a hanger */
html[data-anim] .pd-btn{transform-origin:50% -18%}                   /* a point just above the button: it hangs from there */
html[data-anim] .pdstage.pd-go .pdo{animation-fill-mode:both}
/* product cards / tiles: those below the screen wait on their first frame until they scroll in; anim.js then staggers each batch */
html[data-anim] .reveal{animation-delay:var(--rd,0ms)!important}
html[data-anim] .reveal.rv-wait,html[data-anim] .rv-wait .ph img.a,html[data-anim] .rv-wait .gph img{animation-play-state:paused}
/* press feedback on product cards + the add button (phones have no hover, so this is the only "I heard you") */
html[data-anim] .card a .ph,html[data-anim] .gtile .gph{transition:transform .24s var(--ease-out),box-shadow .24s var(--ease-out),scale .16s var(--ease-out)}
html[data-anim] .card a:active .ph,html[data-anim] .gtile:active .gph{scale:.97}
html[data-anim] #add,html[data-anim] #sadd{transition:scale .14s var(--ease-out)}
html[data-anim] #add:active,html[data-anim] #sadd:active{scale:.97}

/* ---------- A · subtle: things settle in, nothing bounces ---------- */
html[data-anim=a] .pd-tee{--d:0ms}html[data-anim=a] .pd-mug{--d:70ms}html[data-anim=a] .pd-orn{--d:140ms}html[data-anim=a] .pd-stk{--d:200ms}html[data-anim=a] .pd-btn{--d:250ms}
html[data-anim=a] .pdstage.pd-done .pdo{--d:0ms}
html[data-anim=a] .pdstage.pd-go .pdo{animation:aIn .46s var(--ease-out) var(--d) both}
html[data-anim=a] .pdstage.pd-go .pd-orn{animation:aIn .46s var(--ease-out) var(--d) both,aSwing 1.6s linear var(--d) both}
html[data-anim=a] .pdstage.pd-go .pd-btn{animation:aIn .46s var(--ease-out) var(--d) both,aSwingBtn 1.6s linear var(--d) both}
html[data-anim=a] .pdstage.pd-go.swap .pdo{animation:aOut .14s var(--ease-out) both}
@keyframes aIn{from{opacity:0;translate:0 14px}}
@keyframes aOut{to{opacity:0;translate:0 6px}}
html[data-anim=a] .reveal{animation:aCard .42s var(--ease-out) both}
@keyframes aCard{from{opacity:0;translate:0 10px}}
html[data-anim=a] .pdseal:active img{scale:.92;transition:scale .1s var(--ease-out)}

/* ---------- B · playful: things are hung / set down with a soft spring; ornament + button swing, then keep swaying very slowly ---------- */
html[data-anim=b] .pd-tee{--d:0ms}html[data-anim=b] .pd-mug{--d:90ms}html[data-anim=b] .pd-orn{--d:170ms}html[data-anim=b] .pd-stk{--d:300ms}html[data-anim=b] .pd-btn{--d:240ms}
html[data-anim=b] .pdstage.pd-done .pd-tee{--d:0ms}html[data-anim=b] .pdstage.pd-done .pd-mug{--d:40ms}html[data-anim=b] .pdstage.pd-done .pd-orn{--d:80ms}
html[data-anim=b] .pdstage.pd-done .pd-stk{--d:130ms}html[data-anim=b] .pdstage.pd-done .pd-btn{--d:110ms}
html[data-anim=b] .pdstage.pd-go .pd-tee{animation:bTee .7s var(--spring-b) var(--d) both}
html[data-anim=b] .pdstage.pd-go .pd-mug{animation:bDrop .62s var(--spring-b) var(--d) both}
html[data-anim=b] .pdstage.pd-go .pd-orn{animation:bHangIn .5s var(--ease-out) var(--d) both,bSwing 2.6s linear var(--d) both,bSwayO 5.6s linear calc(var(--d) + 2.6s) infinite}
html[data-anim=b] .pdstage.pd-go .pd-btn{animation:bHangIn .5s var(--ease-out) var(--d) both,bSwingBtn 2.8s linear var(--d) both,bSwayB 6.8s linear calc(var(--d) + 2.8s) infinite}
html[data-anim=b] .pdstage.pd-go .pd-stk{animation:bSlap .42s var(--spring-b) var(--d) both}
html[data-anim=b] .pdstage.pd-go.swap .pdo{animation:bOut .15s var(--ease-out) both}
@keyframes bTee{from{opacity:0;translate:0 -18px;rotate:-2.5deg}40%{opacity:1}}
@keyframes bDrop{from{opacity:0;translate:0 -30px}35%{opacity:1}}
@keyframes bHangIn{from{opacity:0;translate:0 -26px}}
@keyframes bSlap{from{opacity:0;scale:1.16;rotate:5deg}50%{opacity:1}}
@keyframes bOut{to{opacity:0;translate:0 10px;scale:.97}}
/* cards: rise with a soft spring, the photo settles inside its frame */
html[data-anim=b] .reveal{animation:bCard .66s var(--spring-b) both}
html[data-anim=b] .reveal .ph img.a,html[data-anim=b] .reveal .gph img{animation:phSettle .8s var(--ease-out) backwards;animation-delay:var(--rd,0ms)}
@keyframes bCard{from{opacity:0;translate:0 18px;scale:.965}30%{opacity:1}}
@keyframes phSettle{from{scale:1.07}}
/* the medal you tap gets "stamped" */
html[data-anim=b] .pdseal img.tap{animation:stamp .42s var(--spring-b)}
@keyframes stamp{from{scale:.84}}
html[data-anim=b] .pdseal:active img,html[data-anim=c] .pdseal:active img{scale:.9;transition:scale .1s var(--ease-out)}
/* Christmas strip: the arrow gives two small nudges, once, a second after the page opens */
html[data-anim=b] a.strip span[aria-hidden],html[data-anim=c] a.strip span[aria-hidden]{display:inline-block;animation:nudge 1.1s var(--ease-out) 1.2s both}
@keyframes nudge{0%,100%{translate:0}18%{translate:5px}38%{translate:0}56%{translate:4px}76%{translate:0}}
/* cart: the count jumps with a spring when something is added; the cart's rows slide in when it opens */
html[data-anim=b] .badge.bump,html[data-anim=c] .badge.bump{animation:bumpS .5s var(--spring-c)}
@keyframes bumpS{from{scale:1.5}}
html[data-anim=b] .drawer.d-in .line,html[data-anim=c] .drawer.d-in .line{animation:lineIn .42s var(--ease-out) calc(.18s + var(--li,0) * 50ms) both}
@keyframes lineIn{from{opacity:0;translate:24px 0}}

/* ---------- C · bold: everything lands like a real object; ornament + button are real pendulums (anim.js) that react to taps and scrolling ---------- */
/* the medals pop in one after another on the first page load (whole row done in ~0.55 s) */
html[data-anim=c] .pdseals.pop .pdseal img{animation:medalPop .42s var(--spring-c) calc(var(--mi,0) * 22ms) both}
@keyframes medalPop{from{opacity:0;scale:.55}45%{opacity:1}}
html[data-anim=c] .pd-tee{--d:0ms}html[data-anim=c] .pd-mug{--d:120ms}html[data-anim=c] .pd-orn{--d:220ms}html[data-anim=c] .pd-stk{--d:380ms}html[data-anim=c] .pd-btn{--d:300ms}
html[data-anim=c] .pdstage.pd-done .pd-tee{--d:0ms}html[data-anim=c] .pdstage.pd-done .pd-mug{--d:50ms}html[data-anim=c] .pdstage.pd-done .pd-orn{--d:90ms}
html[data-anim=c] .pdstage.pd-done .pd-stk{--d:150ms}html[data-anim=c] .pdstage.pd-done .pd-btn{--d:120ms}
html[data-anim=c] .pdstage.pd-go .pd-tee{animation:cTee .95s var(--spring-c) var(--d) both}
html[data-anim=c] .pdstage.pd-go .pd-mug{animation:cDrop .75s var(--spring-c) var(--d) both}
html[data-anim=c] .pdstage.pd-go .pd-orn{animation:cHangIn .55s var(--ease-out) var(--d) both}
html[data-anim=c] .pdstage.pd-go .pd-btn{animation:cHangIn .55s var(--ease-out) var(--d) both}
html[data-anim=c] .pdstage.pd-go .pd-stk{animation:cSlap .5s var(--spring-c) var(--d) both}
html[data-anim=c] .pdstage.pd-go.swap .pdo{animation:cOut .15s var(--ease-out) both}
@keyframes cTee{from{opacity:0;translate:0 -40px;rotate:-7deg}30%{opacity:1}}
@keyframes cDrop{from{opacity:0;translate:0 -56px}25%{opacity:1}}
@keyframes cHangIn{from{opacity:0;translate:0 -44px}}
@keyframes cSlap{from{opacity:0;scale:1.3;rotate:12deg}40%{opacity:1}}
@keyframes cOut{to{opacity:0;translate:0 22px;rotate:-3deg}}
/* cards are "dealt" onto the table: a slight tilt that straightens as they land */
html[data-anim=c] .reveal{animation:cCard .8s var(--spring-c) both}
html[data-anim=c] .reveal .ph img.a,html[data-anim=c] .reveal .gph img{animation:phSettle .9s var(--ease-out) backwards;animation-delay:var(--rd,0ms)}
@keyframes cCard{from{opacity:0;translate:0 30px;rotate:var(--tilt,-2deg)}25%{opacity:1}}
/* the medal you tap flips like a coin */
html[data-anim=c] .pdseal{perspective:240px}
html[data-anim=c] .pdseal img.tap{animation:flip .6s var(--spring-b)}
@keyframes flip{from{rotate:y 180deg}}
/* cart: the cart word gives a little shake with the count */
html[data-anim=c] .cartbtn:has(.badge.bump){animation:wig .42s var(--ease-out)}
@keyframes wig{25%{rotate:-5deg}50%{rotate:4deg}75%{rotate:-2deg}}
@keyframes aSwing{0%{rotate:5.00deg}2.5%{rotate:4.40deg}5%{rotate:3.55deg}7.5%{rotate:2.56deg}10%{rotate:1.54deg}12.5%{rotate:0.56deg}15%{rotate:-0.31deg}17.5%{rotate:-1.01deg}20%{rotate:-1.51deg}22.5%{rotate:-1.82deg}25%{rotate:-1.93deg}27.5%{rotate:-1.88deg}30%{rotate:-1.68deg}32.5%{rotate:-1.39deg}35%{rotate:-1.04deg}37.5%{rotate:-0.66deg}40%{rotate:-0.29deg}42.5%{rotate:0.04deg}45%{rotate:0.31deg}47.5%{rotate:0.52deg}50%{rotate:0.65deg}52.5%{rotate:0.71deg}55%{rotate:0.70deg}57.5%{rotate:0.64deg}60%{rotate:0.54deg}62.5%{rotate:0.42deg}65%{rotate:0.28deg}67.5%{rotate:0.14deg}70%{rotate:0.01deg}72.5%{rotate:-0.09deg}75%{rotate:-0.17deg}77.5%{rotate:-0.23deg}80%{rotate:-0.26deg}82.5%{rotate:-0.26deg}85%{rotate:-0.24deg}87.5%{rotate:-0.21deg}90%{rotate:-0.16deg}92.5%{rotate:-0.11deg}95%{rotate:-0.06deg}97.5%{rotate:-0.02deg}100%{rotate:0deg}}
@keyframes bSwing{0%{rotate:16.00deg}2.5%{rotate:13.25deg}5%{rotate:8.67deg}7.5%{rotate:3.36deg}10%{rotate:-1.64deg}12.5%{rotate:-5.50deg}15%{rotate:-7.75deg}17.5%{rotate:-8.28deg}20%{rotate:-7.28deg}22.5%{rotate:-5.18deg}25%{rotate:-2.54deg}27.5%{rotate:0.10deg}30%{rotate:2.27deg}32.5%{rotate:3.68deg}35%{rotate:4.21deg}37.5%{rotate:3.92deg}40%{rotate:3.00deg}42.5%{rotate:1.71deg}45%{rotate:0.35deg}47.5%{rotate:-0.85deg}50%{rotate:-1.69deg}52.5%{rotate:-2.10deg}55%{rotate:-2.07deg}57.5%{rotate:-1.69deg}60%{rotate:-1.08deg}62.5%{rotate:-0.39deg}65%{rotate:0.26deg}67.5%{rotate:0.75deg}70%{rotate:1.03deg}72.5%{rotate:1.08deg}75%{rotate:0.93deg}77.5%{rotate:0.65deg}80%{rotate:0.30deg}82.5%{rotate:-0.04deg}85%{rotate:-0.31deg}87.5%{rotate:-0.49deg}90%{rotate:-0.55deg}92.5%{rotate:-0.51deg}95%{rotate:-0.38deg}97.5%{rotate:-0.21deg}100%{rotate:0deg}}
@keyframes aSwingBtn{0%{rotate:3.00deg}2.5%{rotate:2.66deg}5%{rotate:2.20deg}7.5%{rotate:1.68deg}10%{rotate:1.13deg}12.5%{rotate:0.59deg}15%{rotate:0.11deg}17.5%{rotate:-0.30deg}20%{rotate:-0.63deg}22.5%{rotate:-0.86deg}25%{rotate:-1.00deg}27.5%{rotate:-1.05deg}30%{rotate:-1.02deg}32.5%{rotate:-0.94deg}35%{rotate:-0.80deg}37.5%{rotate:-0.64deg}40%{rotate:-0.46deg}42.5%{rotate:-0.28deg}45%{rotate:-0.11deg}47.5%{rotate:0.03deg}50%{rotate:0.16deg}52.5%{rotate:0.25deg}55%{rotate:0.31deg}57.5%{rotate:0.34deg}60%{rotate:0.34deg}62.5%{rotate:0.33deg}65%{rotate:0.29deg}67.5%{rotate:0.24deg}70%{rotate:0.18deg}72.5%{rotate:0.12deg}75%{rotate:0.06deg}77.5%{rotate:0.01deg}80%{rotate:-0.03deg}82.5%{rotate:-0.07deg}85%{rotate:-0.09deg}87.5%{rotate:-0.11deg}90%{rotate:-0.11deg}92.5%{rotate:-0.11deg}95%{rotate:-0.10deg}97.5%{rotate:-0.09deg}100%{rotate:0deg}}
@keyframes bSwingBtn{0%{rotate:11.00deg}2.5%{rotate:9.17deg}5%{rotate:6.28deg}7.5%{rotate:2.96deg}10%{rotate:-0.21deg}12.5%{rotate:-2.77deg}15%{rotate:-4.45deg}17.5%{rotate:-5.14deg}20%{rotate:-4.93deg}22.5%{rotate:-4.01deg}25%{rotate:-2.65deg}27.5%{rotate:-1.13deg}30%{rotate:0.28deg}32.5%{rotate:1.40deg}35%{rotate:2.10deg}37.5%{rotate:2.36deg}40%{rotate:2.21deg}42.5%{rotate:1.75deg}45%{rotate:1.11deg}47.5%{rotate:0.42deg}50%{rotate:-0.21deg}52.5%{rotate:-0.70deg}55%{rotate:-0.99deg}57.5%{rotate:-1.07deg}60%{rotate:-0.98deg}62.5%{rotate:-0.76deg}65%{rotate:-0.46deg}67.5%{rotate:-0.15deg}70%{rotate:0.13deg}72.5%{rotate:0.34deg}75%{rotate:0.46deg}77.5%{rotate:0.49deg}80%{rotate:0.44deg}82.5%{rotate:0.33deg}85%{rotate:0.19deg}87.5%{rotate:0.05deg}90%{rotate:-0.08deg}92.5%{rotate:-0.17deg}95%{rotate:-0.21deg}97.5%{rotate:-0.22deg}100%{rotate:0deg}}
@keyframes bSwayO{0%{rotate:0.00deg}5%{rotate:0.56deg}10%{rotate:1.06deg}15%{rotate:1.46deg}20%{rotate:1.71deg}25%{rotate:1.80deg}30%{rotate:1.71deg}35%{rotate:1.46deg}40%{rotate:1.06deg}45%{rotate:0.56deg}50%{rotate:0.00deg}55%{rotate:-0.56deg}60%{rotate:-1.06deg}65%{rotate:-1.46deg}70%{rotate:-1.71deg}75%{rotate:-1.80deg}80%{rotate:-1.71deg}85%{rotate:-1.46deg}90%{rotate:-1.06deg}95%{rotate:-0.56deg}100%{rotate:0deg}}
@keyframes bSwayB{0%{rotate:0.00deg}5%{rotate:0.40deg}10%{rotate:0.76deg}15%{rotate:1.05deg}20%{rotate:1.24deg}25%{rotate:1.30deg}30%{rotate:1.24deg}35%{rotate:1.05deg}40%{rotate:0.76deg}45%{rotate:0.40deg}50%{rotate:0.00deg}55%{rotate:-0.40deg}60%{rotate:-0.76deg}65%{rotate:-1.05deg}70%{rotate:-1.24deg}75%{rotate:-1.30deg}80%{rotate:-1.24deg}85%{rotate:-1.05deg}90%{rotate:-0.76deg}95%{rotate:-0.40deg}100%{rotate:0deg}}
}
/* ---------- the proposal's own switch (only when ?anim= is in the address and &rec is not; never in the real shop) ---------- */
.anim-sw{position:fixed;left:8px;top:50%;translate:0 -50%;z-index:60;display:grid;gap:4px;padding:6px;border-radius:12px;background:rgba(23,32,74,.9);font:12px/1 Plex,ui-monospace,monospace}
.anim-sw a{color:#F4F1EA;padding:7px 9px;border-radius:8px;text-align:center}
.anim-sw a.on{background:#F0509A;color:#fff}
