/* TANK spells: small responses that make the world feel present. Every rule here is additive and
   scoped so that removing this file, or setting <html data-spells="off"> (spells.js does that for
   ?spells=off or a saved preference), restores the page exactly. Tunables are the custom properties
   on :root. Motion spells switch off under prefers-reduced-motion. Research: docs/plans/2026-09-18-spells-research.md */

:root{
  --spell-dive-ms:720ms;            /* 01 dive between places */
  --spell-ripple-ms:1000ms;         /* 05 ring life */
  --spell-ripple-size:96px;         /* 05 ring diameter at full spread */
  --spell-ripple-alpha:.45;         /* 05 ring strength at birth, 0 to 1 */
  --spell-glass-deg:1.6;            /* 07 max tilt of the aquarium glass, degrees */
  --spell-count-ms:620;             /* 09 counter tween, read by spells.js */
  --spell-print-ms:60;              /* 10 stagger between receipt lines */
}

/* ── 01 · swim there, don't load there ─────────────────────────────────────
   Cross-document view transition: the page you leave pushes in and softens, the next opens through it
   from the point you clicked (spells.js stores that point). Browsers without support simply navigate.
   The opt-in itself, @view-transition{navigation:auto}, is an inline <style> in each page's head: Chrome
   checks for it before external CSS has necessarily loaded, which skipped the dive on the live host. */
::view-transition-old(root){
  animation:spell-leave var(--spell-dive-ms) cubic-bezier(.65,0,.2,1) both;
}
::view-transition-new(root){
  animation:spell-arrive var(--spell-dive-ms) cubic-bezier(.65,0,.2,1) both;
  clip-path:circle(0% at var(--dive-x,50%) var(--dive-y,58%));
}
@keyframes spell-leave{to{transform:scale(1.12);filter:blur(3px) brightness(.55)}}
@keyframes spell-arrive{to{clip-path:circle(160% at var(--dive-x,50%) var(--dive-y,58%))}}
html[data-spells=off]::view-transition-old(root),
html[data-spells=off]::view-transition-new(root){animation:none;clip-path:none}

/* Keep scene copy and particles above decorative layers. */
.hub-scene>.hub-copy{position:relative;z-index:2}
#marine-snow{z-index:3}

/* ── 05 · the water moves where you point (home hero, aquarium) ─────────────
   A fixed-size ring scaled by transform: compositor-only, so it keeps up with the pointer. */
.spell-ripple{position:absolute;pointer-events:none;z-index:2;width:var(--spell-ripple-size);height:var(--spell-ripple-size);
  border:1px solid #cdeff5;border-radius:50%;opacity:var(--spell-ripple-alpha);transform:translate(-50%,-50%) scale(.05);
  animation:spell-spread var(--spell-ripple-ms) cubic-bezier(.15,.7,.3,1) forwards;will-change:transform,opacity}
.spell-ripple.fixed{position:fixed}
.spell-ripple.strong{border-width:2px;opacity:calc(var(--spell-ripple-alpha)*1.5)}
@keyframes spell-spread{to{transform:translate(-50%,-50%) scale(1);opacity:0}}

/* ── 07 · the glass has a viewing angle (aquarium) ────────────────────────── */
html[data-spell-glass] #gl{transform-origin:50% 55%;transition:transform 160ms ease-out;will-change:transform}
.spell-sheen{position:fixed;inset:0;z-index:2;pointer-events:none;opacity:.7;
  background:linear-gradient(112deg,transparent 40%,#ffffff12 50%,transparent 60%);transition:transform 160ms ease-out}

/* ── 09 · values arrive: a tabular column so the tween does not jitter ─────── */
[data-spell-tween]{font-variant-numeric:tabular-nums}

/* ── 10 · the receipt prints (business loop) ───────────────────────────────── */
#receipts[open] .breakdown>div,#receipts[open] .transactions>a,#receipts[open] .model-calls>article{
  animation:spell-print 340ms ease-out both;animation-delay:calc(var(--i,0)*var(--spell-print-ms))}
@keyframes spell-print{from{opacity:0;transform:translateY(-6px);clip-path:inset(0 0 100% 0)}to{opacity:1;transform:none;clip-path:inset(0)}}

/* ── 11 · seal the blueprint (business loop) ───────────────────────────────── */
.hash-label{position:relative}
.spell-seal{position:absolute;right:0;top:-26px;width:92px;height:92px;border-radius:50%;display:grid;place-items:center;
  text-align:center;font:8px/1.5 'Geist Mono',ui-monospace,monospace;letter-spacing:.11em;text-transform:uppercase;color:#ffe3d5;
  background:radial-gradient(circle at 36% 30%,#c4543f,#8e2f22 62%,#6d2118);
  box-shadow:inset 0 2px 6px #ffffff2e,inset 0 -4px 10px #00000055,0 8px 18px #00000038;pointer-events:none;
  transform:rotate(-9deg);animation:spell-stamp 420ms cubic-bezier(.2,1.5,.4,1) both}
@keyframes spell-stamp{from{opacity:0;transform:scale(2.2) rotate(-22deg)}30%{opacity:1}to{transform:scale(1) rotate(-9deg)}}
@media(max-width:700px){.spell-seal{width:72px;height:72px;top:-18px;font-size:7px}}

/* ── off switches ──────────────────────────────────────────────────────────── */
html[data-spells=off] .spell-ripple,html[data-spells=off] .spell-sheen,html[data-spells=off] .spell-seal{display:none}
html[data-spells=off] #gl{transform:none!important}
html[data-spells=off] #receipts[open] .breakdown>div,html[data-spells=off] #receipts[open] .transactions>a,
html[data-spells=off] #receipts[open] .model-calls>article{animation:none}

@media(prefers-reduced-motion:reduce){
  ::view-transition-old(root),::view-transition-new(root){animation:none;clip-path:none}
  .spell-ripple,.spell-seal{animation:none}
  #receipts[open] .breakdown>div,#receipts[open] .transactions>a,#receipts[open] .model-calls>article{animation:none}
  html[data-spell-glass] #gl{transition:none;transform:none!important}
  .spell-sheen{display:none}
}
