/* action ai · FX layer v3 (2026-10-05). = v2 (Refero-referenced) + the v1 effects reinstated by Alex ("reuse the effects"),
   all slowed to the calm capture pace. Motion + light only: adds no copy, no colours outside the Spectral palette,
   moves nothing at rest (layout diff = 0). Every effect carries an ID (E01–E17) that matches HANDOVER/EFFECTS.md.
   Everything switches off under prefers-reduced-motion.
   APP ADAPTATION (REDESIGN-R1-KIT-FX-2026-10-06), copied from BUILD HANDOVER src/kit/fx3.css with only these changes:
   (1) KIT-1 renames: the kit background token is read as --kx-bg (kit-tokens.css).
   (2) Inert until a screen opts in. The app already uses three contract class names with its own meaning
       (.sheet, .toast, .star: run-kit-class-collisions.mjs lists them), and E02 grain would cover every screen.
       Those rules apply only inside an element carrying the opt-in class .kx (body.kx turns on the grain),
       so today's screens are untouched; the area steps add .kx as they restyle each screen.
   (3) P1 (EFFECTS.md perf rules): the orb sheen turns with rotate on the GPU instead of repainting the conic --a every frame. */
@property --sx{syntax:'<length-percentage>';initial-value:-40%;inherits:false}
:root{--spring:cubic-bezier(.34,1.56,.64,1);--sheet:cubic-bezier(.32,.72,0,1);--out:cubic-bezier(.23,1,.32,1);
--fx-fast:120ms;--fx-state:320ms;--fx-stagger:50ms}

/* E01 · Sky: sparse twinkling stars, two four-point glints (canvas from fx3.js)
   [Refero: Luma 2f3c1e1f · Sora d8725ae4 · Napper 4b262860 · Remy 65af0f3c] */
canvas.fxsky{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:0}
.full>canvas.fxsky{z-index:-1}

/* E02 · Grain: faint fractal noise so flat black reads as night sky [craft: anti-ai-slop "no flat void"; no Refero ref] */
body.kx::after{content:"";position:fixed;inset:0;z-index:200;pointer-events:none;opacity:.04;mix-blend-mode:overlay;
background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")}

/* E03 · Entrance cascade: cards, stats, panels and fields rise in one after another when a screen opens
   [craft: motion.md Level 2 "movement instead of teleportation", page 240–360ms, ease-out for enter] */
.fxin:not(.rise){animation:fxin var(--fx-state) var(--out) both;animation-delay:calc(var(--i,0) * var(--fx-stagger))}
@keyframes fxin{from{opacity:0;translate:0 8px;filter:blur(4px)}}

/* E05 · Progress bars draw in from zero (rings are swept in fx3.js) [craft: motion.md Level 3 continuity] */
.bar:not(.rise) i:not(.rise){transform-origin:left;animation:fxbar .9s .12s var(--out) both}
@keyframes fxbar{from{scale:0 1}}

/* E06 · Press: soft scale while held [craft: motion.md "Press scale .98, 90–120ms"] */
.pc,.sec,.go,.ln,.qb,.seg button,.cta,.tile{transition:scale var(--fx-fast) var(--out)}
.pc:active,.sec:active,.go:active,.ln:active,.qb:active,.seg button:active,.cta:active,.tile:active{scale:.98}
.cta:active{box-shadow:0 0 0 2px var(--kx-bg),0 18px 54px -10px rgba(162,155,254,.9)}

/* E07 · Touch light: a faint spotlight follows the finger across cards and the main button (no ripple) [no Refero ref; v1 #3 minus ripple] */
.fxw{position:absolute;inset:0;border-radius:inherit;overflow:hidden;pointer-events:none;z-index:-1}
.fxw::before{content:"";position:absolute;inset:0;opacity:0;transition:opacity .35s var(--out);
background:radial-gradient(240px circle at var(--mx,50%) var(--my,50%),rgba(199,192,255,.24),transparent 65%)}
.fxlit>.fxw::before{opacity:1}
.cta>.fxw::before{background:radial-gradient(240px circle at var(--mx,50%) var(--my,50%),rgba(162,155,254,.38),transparent 65%)}
.pc,.cta,.sec,.go,.ln,.qb,.seg button,.dock button,.tile{isolation:isolate}

/* E08 · Bottom sheets slide up on the iOS sheet curve; grabber drags to dismiss [Refero: Revolut 700fc345 · Cashcaded 46876924 · Copilot 0e17ef62] */
.kx .sheet,.kx .sheet.rise{opacity:1;filter:none;animation:fxsheet .55s var(--sheet) both}
@keyframes fxsheet{from{translate:0 105%}to{translate:0 0}}
.scrim:not(.rise){animation:fxfade .35s var(--out) both}
@keyframes fxfade{from{opacity:0}}
.kx .sheet.fxdrag{animation:none;transition:none}
.kx .sheet.fxback{transition:transform .5s var(--sheet)}
.grab{cursor:grab;touch-action:none;position:relative}
.grab::after{content:"";position:absolute;inset:-14px -60px}

/* E09 · Centred confirm scales in from 94% [Refero: Ten Percent Happier 92ff967f · Revolut 700fc345] */
.dialog:not(.rise){animation:fxdlg .55s var(--spring) both}
@keyframes fxdlg{from{opacity:0;transform:translateY(-50%) scale(.86)}}

/* E10 · Toast: dark glass, lifts in, one soft spectral sheen passes once [Refero: Apple Invites fbb06480 (glass); sheen = v1 #6, no Refero ref] */
.kx .toast{background:rgba(27,27,32,.78);backdrop-filter:blur(20px) saturate(1.4);-webkit-backdrop-filter:blur(20px) saturate(1.4);overflow:hidden}
.kx .toast:not(.rise){animation:fxtoast .5s var(--spring) both}
@keyframes fxtoast{from{opacity:0;transform:translate(-50%,20px) scale(.96)}}
.kx .toast::after{content:"";position:absolute;inset:0;pointer-events:none;border-radius:inherit;
background:linear-gradient(105deg,transparent calc(var(--sx) - 12%),rgba(199,192,255,.18) var(--sx),transparent calc(var(--sx) + 12%));
animation:fxsheen 1.6s .35s var(--out) both}
@keyframes fxsheen{to{--sx:140%}}

/* E11 · Tick: circle pops, mint halo rings out, Spectral sparks scatter (sparks in fx3.js) [Refero: Ten Percent Happier 92ff967f · Duolingo 95c04a1f] */
.check i{transition:background .25s var(--out),box-shadow .25s var(--out)}
.check.fxpop i{animation:fxpop .5s var(--spring)}
@keyframes fxpop{0%{scale:.6}60%{scale:1.18}100%{scale:1}}
.fxspark{position:fixed;width:6px;height:6px;border-radius:2px;pointer-events:none;z-index:210;background:var(--c);box-shadow:0 0 8px var(--c);animation:fxspark .7s var(--out) forwards}
@keyframes fxspark{to{transform:translate(var(--dx),var(--dy)) rotate(160deg) scale(.2);opacity:0}}
.fxhalo{position:fixed;width:24px;height:24px;margin:-12px 0 0 -12px;border-radius:50%;pointer-events:none;z-index:209;box-shadow:0 0 0 2px #55EFC4;animation:fxhalo .6s var(--out) forwards}
@keyframes fxhalo{to{transform:scale(2.6);opacity:0}}

/* E12 · Toggle knob springs across; focused fields glow softly (no spinning ring) [craft: motion.md Level 1 toggles/focus 120ms] */
.toggle::after{transition:transform .35s var(--spring)!important}
.toggle{transition:background .3s var(--out)}
.field{transition:box-shadow .2s var(--out)}
.field:focus-within{box-shadow:inset 0 0 0 1px rgba(162,155,254,.55),0 0 24px -8px rgba(162,155,254,.55)}

/* E13 · Listening orb: rings travel outward, a soft fluid sheen turns inside, the orb breathes [Refero: Shazam aa7a0ff1 · Google Maps d98452e5 · ElevenReader e54316fc] */
.orb:not(.rise){animation:fxbreath 3.2s ease-in-out infinite}
@keyframes fxbreath{50%{scale:1.035}}
.orb .fxring{position:absolute;inset:0;border-radius:50%;pointer-events:none;box-shadow:0 0 0 1.5px rgba(199,192,255,.5);animation:fxring 2.8s var(--out) infinite;opacity:0}
.orb .fxring+.fxring{animation-delay:1.4s}
@keyframes fxring{0%{opacity:.7;scale:1}100%{opacity:0;scale:1.75}}
.orb .fxsheen{position:absolute;inset:14%;border-radius:50%;pointer-events:none;filter:blur(16px);opacity:.38;mix-blend-mode:screen;
background:conic-gradient(from var(--a),#FF7676,#FDCB6E,#55EFC4,#74B9FF,#A29BFE,#FF7676);animation:perfrot 7s linear infinite}
@keyframes perfrot{to{rotate:360deg}}

/* E14 · Lit stars bloom; lit avatars shimmer slowly [Refero: Luma 2f3c1e1f (stars); avatars = v1 #12, no Refero ref] */
.kx .star:not(.rise){animation:fxtw 3.6s ease-in-out infinite}
@keyframes fxtw{50%{box-shadow:0 0 0 3px var(--c),0 0 20px 6px var(--c)}}
.PA.on::after{animation:fxtw2 4.8s ease-in-out infinite}
@keyframes fxtw2{50%{box-shadow:0 0 0 2px var(--c),0 0 18px var(--c)}}

/* E15 · Dock: the active marker grows in on arrival [no Refero ref; v1 #13] */
.dock .on::after{animation:fxdock .45s var(--spring) both}
@keyframes fxdock{from{scale:0 1;opacity:0}}

/* E16 · State change cross-fade with a slight blur (View Transitions, where supported) [craft: motion.md Level 2 route transition 240–360ms] */
::view-transition-old(root){animation:fxvto .24s var(--out) both}
::view-transition-new(root){animation:fxvtn .32s var(--out) both}
@keyframes fxvto{to{opacity:0;filter:blur(4px)}}
@keyframes fxvtn{from{opacity:0;filter:blur(4px)}}

/* E17 · Loading placeholders shimmer instead of sitting still [craft: motion.md "Loading: clear state indicator, not just spinner"] */
.skel,.skelbar,.skel i{position:relative;overflow:hidden}
.skel::after,.skelbar::after{content:"";position:absolute;inset:0;pointer-events:none;
background:linear-gradient(100deg,transparent 30%,rgba(255,255,255,.16) 50%,transparent 70%);background-size:220% 100%;animation:fxshim 1.6s linear infinite}
@keyframes fxshim{from{background-position:120% 0}to{background-position:-120% 0}}

@media (prefers-reduced-motion:reduce){canvas.fxsky,.fxspark,.fxhalo,.orb .fxring,.orb .fxsheen,.skel::after,.skelbar::after{display:none}
.kx .sheet,.kx .toast,.dialog,.fxin,.bar i{animation:none!important;opacity:1;filter:none}}
