/* PhopWatch motion v2. Uses assets/tokens.css easing/duration tokens only.
   Kinetics effects are reimplemented from their descriptions (repo has no LICENSE file).
   React Bits effects are reimplemented from their behaviour (MIT + Commons Clause), no code copied.
   Exceptions to "transform/opacity only" are tiny and listed in DESIGN.md: background-position (gradient text),
   offset-distance (heartbeat dot), filter blur (word reveal), stroke-dashoffset (check draw). */
/* ---- React Bits: GradientText, recolored, 6s slow shimmer ---- */
.gt{background:linear-gradient(100deg,var(--accent) 0%,var(--accent-2) 40%,var(--accent) 80%);background-size:220% 100%;-webkit-background-clip:text;background-clip:text;color:transparent;animation:pw-gt 6s var(--ease-inout) infinite alternate}
@keyframes pw-gt{to{background-position:100% 0}}
/* ---- React Bits: RotatingText, whole phrases, vertical slide ---- */
.rot{display:inline-grid;vertical-align:bottom;overflow:hidden;line-height:var(--lh-head);height:1.35em}
.rot>span{grid-area:1/1;transform:translateY(110%);opacity:0;transition:transform var(--dur-slow) var(--ease-inout),opacity var(--dur-slow) linear;color:var(--accent);font-weight:600}
.rot>span.on{transform:none;opacity:1}
.rot>span.off{transform:translateY(-110%);opacity:0}
/* ---- React Bits: BlurText, word by word (Intl.Segmenter th) ---- */
.bt-w{display:inline-block;opacity:0;transform:translateY(24px);filter:blur(8px);transition:opacity var(--dur-reveal) var(--ease-glide),transform var(--dur-reveal) var(--ease-glide),filter var(--dur-reveal) var(--ease-glide);transition-delay:calc(var(--i)*60ms)}
.bt.in .bt-w{opacity:1;transform:none;filter:none}
/* ---- React Bits: SpotlightCard, accent-soft glow follows pointer ---- */
.spot{position:relative;overflow:hidden}
.spot::before{content:"";position:absolute;inset:0;pointer-events:none;opacity:0;background:radial-gradient(320px circle at var(--mx,50%) var(--my,50%),rgba(109,91,232,.16),transparent 70%);transition:opacity var(--dur-base) linear}
.spot:hover::before{opacity:1}
.spot>*{position:relative}
/* ---- React Bits: DotGrid (canvas 2D, hero only). CSS fallback when canvas is not used ---- */
.dotgrid{position:relative;border-radius:var(--r-lg);overflow:hidden;background-image:radial-gradient(rgba(95,86,78,.32) 1.4px,transparent 1.6px);background-size:28px 28px}
.dotgrid canvas{position:absolute;inset:0;width:100%;height:100%}
/* ---- Kinetics: Heartbeat Monitor ---- */
.hb{position:relative;width:min(100%,520px);height:64px}
.hb svg{width:100%;height:100%;display:block}
.hb path{fill:none;stroke:var(--border-input);stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.hb-dot{position:absolute;left:0;top:0;width:12px;height:12px;margin:-6px 0 0 -6px;border-radius:50%;background:var(--accent);box-shadow:0 0 0 4px var(--accent-soft),var(--glow-accent);offset-path:path('M0 32 H120 L136 32 L148 8 L164 56 L176 32 H300 L316 32 L328 8 L344 56 L356 32 H520');offset-rotate:0deg;animation:pw-hb 3.6s linear infinite}
@keyframes pw-hb{from{offset-distance:0%}to{offset-distance:100%}}
/* ---- Kinetics: Parallax Tilt (max 4deg, desktop pointer only) ---- */
.tilt{transform:perspective(900px) rotateX(var(--rx,0deg)) rotateY(var(--ry,0deg));transition:transform var(--dur-slow) var(--ease-glide);will-change:transform}
/* ---- Kinetics: Magnetic + Squish (translate is separate from transform) ---- */
.mag{transition:translate var(--dur-base) var(--ease-spring),transform var(--dur-fast) var(--ease-spring)}
/* ---- Kinetics: Bento Expand ---- */
.bento{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--sp-3)}
.bento>.card{transition:transform var(--dur-base) var(--ease-glide),opacity var(--dur-base) linear}
@media (hover:hover){.bento:has(.card:hover)>.card:not(:hover){opacity:.55;transform:scale(.985)}.bento>.card:hover{transform:scale(1.02)}}
@media(max-width:700px){.bento{grid-template-columns:1fr}}
/* ---- Kinetics: Accordion Spring ---- */
.acc{border-bottom:1px solid var(--border)}
.acc-q{all:unset;box-sizing:border-box;width:100%;display:flex;justify-content:space-between;align-items:center;gap:var(--sp-3);padding:var(--sp-4) 0;cursor:pointer;font-weight:600;font-size:var(--fs-lg);min-height:48px}
.acc-q:focus-visible{outline:3px solid var(--focus);outline-offset:2px;border-radius:6px}
.acc-q .ico{transition:transform var(--dur-base) var(--ease-spring)}
.acc-q[aria-expanded="true"] .ico{transform:rotate(180deg)}
.acc-p{display:grid;grid-template-rows:0fr;transition:grid-template-rows var(--dur-slow) var(--ease-glide)}
.acc-p>div{overflow:hidden;color:var(--text-muted)}
.acc-p.open{grid-template-rows:1fr}
.acc-p.open>div{padding-bottom:var(--sp-4)}
/* ---- Kinetics: Odometer (tabular) ---- */
.odo{font-variant-numeric:tabular-nums}
/* ---- Kinetics: Pulse Badge ring (UP only) ---- */
.pbadge{position:relative}
.pbadge.up::after{content:"";position:absolute;inset:0;border-radius:inherit;border:2px solid var(--up);opacity:0;animation:pw-ring 3s var(--ease-glide) infinite}
@keyframes pw-ring{0%{transform:scale(1);opacity:.5}70%,100%{transform:scale(1.35,1.6);opacity:0}}
/* ---- Kinetics: Status Pill idle / sending / sent ---- */
.spill{position:relative;display:inline-grid;grid-template-columns:auto;min-width:190px}
.spill .st{grid-area:1/1;display:inline-flex;align-items:center;justify-content:center;gap:var(--sp-2);opacity:0;transform:translateY(6px);transition:opacity var(--dur-base) linear,transform var(--dur-base) var(--ease-spring);pointer-events:none}
.spill[data-s="idle"] .st-idle,.spill[data-s="sending"] .st-sending,.spill[data-s="sent"] .st-sent{opacity:1;transform:none}
.spill[data-s="sent"]{background:var(--up);}
.spill[data-s="sent"]::after{opacity:0}
.spin{animation:pw-spin .8s linear infinite}
@keyframes pw-spin{to{transform:rotate(360deg)}}
/* ---- Kinetics: Snap Rail ---- */
.rail{position:relative;display:grid;grid-template-columns:repeat(4,1fr);width:min(100%,360px);background:var(--surface-2);border:1.5px solid var(--border-strong);border-radius:var(--r-sm);padding:3px}
.rail button{all:unset;box-sizing:border-box;position:relative;z-index:1;text-align:center;padding:8px 4px;min-height:36px;font-size:var(--fs-sm);font-weight:600;cursor:pointer;color:var(--text-muted);transition:color var(--dur-fast) linear}
.rail button[aria-selected="true"]{color:var(--on-accent)}
.rail button:focus-visible{outline:3px solid var(--focus);outline-offset:1px;border-radius:6px}
.rail i{position:absolute;z-index:0;top:3px;bottom:3px;left:3px;width:calc((100% - 6px)/4);background:var(--accent);border-radius:6px;transform:translateX(calc(var(--i,0)*100%));transition:transform var(--dur-base) var(--ease-inout)}
/* ---- Kinetics: Step progress, checkbox draw, success check ---- */
.ck-bar{height:8px;background:var(--surface-3);border-radius:var(--r-pill);overflow:hidden}
.ck-bar i{display:block;height:100%;background:var(--accent);border-radius:inherit;transform-origin:left;transform:scaleX(var(--p,0));transition:transform var(--dur-slow) var(--ease-glide)}
.ck{display:flex;align-items:center;gap:var(--sp-3);padding:var(--sp-3) 0;cursor:pointer;min-height:48px}
.ck input{position:absolute;opacity:0;width:24px;height:24px;margin:0}
.ck .bx{flex:none;width:24px;height:24px;border:1.5px solid var(--border-input);border-radius:7px;display:grid;place-items:center;background:var(--surface);transition:background-color var(--dur-fast) linear,transform var(--dur-fast) var(--ease-spring)}
.ck input:focus-visible+.bx{outline:3px solid var(--focus);outline-offset:2px}
.ck input:checked+.bx{background:var(--accent);border-color:var(--accent);transform:scale(1.08)}
.ck .bx path{stroke:var(--on-accent);stroke-width:3;fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:24;stroke-dashoffset:24;transition:stroke-dashoffset var(--dur-base) var(--ease-inout)}
.ck input:checked+.bx path{stroke-dashoffset:0}
.ck input:checked~span{color:var(--text-muted);text-decoration:line-through}
.done-mark{display:none;align-items:center;gap:var(--sp-3);color:var(--up);font-weight:600}
.done-mark.show{display:flex}
.done-mark circle,.done-mark path{fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:70;stroke-dashoffset:70}
.done-mark.show circle{animation:pw-draw .6s var(--ease-glide) forwards}
.done-mark.show path{stroke-dasharray:20;stroke-dashoffset:20;animation:pw-draw .4s var(--ease-inout) .35s forwards}
@keyframes pw-draw{to{stroke-dashoffset:0}}
/* ---- Kinetics: Undo Snackbar timer bar, Copy button, Skeleton to content ---- */
.toast{position:relative;overflow:hidden}
.toast .bar{position:absolute;left:0;right:0;bottom:0;height:3px;background:var(--ink-up);transform-origin:left;animation:pw-drain var(--bar,3s) linear forwards}
@keyframes pw-drain{to{transform:scaleX(0)}}
.copy .c-a,.copy .c-b{transition:opacity var(--dur-fast) linear,transform var(--dur-base) var(--ease-spring)}
.copy{position:relative}.copy .c-b{position:absolute;opacity:0;transform:scale(.6)}
.copy.done .c-a{opacity:0;transform:scale(.6)}.copy.done .c-b{opacity:1;transform:none}
.cont{position:relative}
.cont .real,.cont .skl{transition:opacity var(--dur-slow) linear}
.cont .skl{position:absolute;inset:0}
.cont[data-ready="true"] .skl{opacity:0;pointer-events:none}
.cont[data-ready="false"] .real{opacity:0}
/* ---- reduced motion: no loops, no tilt, no reveal blur ---- */
@media (prefers-reduced-motion:reduce){
  .gt{animation:none;background-position:0 0}
  .hb-dot{animation:none;offset-distance:100%}
  .pbadge.up::after,.spin{animation:none}
  .bt-w{opacity:1;transform:none;filter:none;transition:none}
  .rot>span{transition:none}
  .tilt{transform:none!important}
  .acc-p,.ck-bar i,.rail i{transition:none}
}
