/* il-aura.css — per-family ambient lighting: an edge-light sweep on every
   panel, a cursor spotlight, and a per-family selected-nav marker.
   ===========================================================================
   Ported from the "Investor Leveling v2" design canvas (:381-441). This is the
   one part of that canvas that is genuinely NEW rather than a re-port — the
   earlier V3 pass brought over per-family SVG background *motifs*
   (index.html's .atmosphere-motifs), which are a different concept: those
   paint the page behind everything, this lights the chrome itself.

   Each of the six families gets its own gesture, and they are meant to read as
   the same idea in six accents rather than six effects:
     cs Vanguard  a warm band drifting across the plate
     rs Stacia    a diagonal rose-gold wash, corner to corner
     sv Aegis     a crest of light held at the top edge, breathing
     gt Sovereign a violet scanline falling down the plate
     ng Aether    a slow current running left to right, never stopping
     kr Eclipse   both vertical edges lit, alternating

   TOKEN NAMES: the canvas writes --accent/--accentHi/--warn/--neg/--pos.
   This app's theme.js sets --brand/--brand-deep/--warning/--critical/--good
   instead, so every reference below is translated. That translation is the
   whole point of this comment: CLAUDE.md records that the V2 motif port
   shipped with var(--accentHi) — a variable theme.js never sets — and every
   motif silently rendered with an undefined colour for weeks. Deliberately NO
   literal-hex fallbacks here: a missing var should make the rule drop out
   loudly, not paint a plausible wrong colour. Same reason there are no literal
   colours at all, per CLAUDE.md's rule.

   MOTION: gated on --envPlay (theme.js's Still/Calm/Surge setting, Still by
   default and paused whenever the tab is hidden), not on the canvas's own
   [data-motion="off"] — --envPlay is this app's existing convention and
   already handles the document.hidden case the canvas never had to.

   Load order: after il-panels.css (it styles the same panels), before
   il-aura.js runs.
   =========================================================================== */

/* ── the plate itself ──────────────────────────────────────────────────── */
/* :not(.hero) matters: .card.hero::before is already taken by style.css:585's
   gold foil sweep. A hero panel keeps that and simply opts out of the aura,
   rather than the two fighting over one pseudo-element. */
[data-il-panel]:not(.hero) { position: relative; isolation: isolate; }
[data-il-panel]:not(.hero) > * { position: relative; z-index: 1; }

/* **Still is the default, so the frame it freezes on is the one people see.**
   Each family's light used to pause on its first keyframe, and for two of the
   six that frame is empty: Vanguard's band starts past the right edge
   (-40% of a 220% image puts its centre at 1.58x the panel width) and
   Sovereign's scanline starts below the bottom (-70% of a 240% image). So at
   the default setting the default mood's panels carried no family light at
   all -- the flat plates behind the handoff's "the family barely shows once
   you're inside". Measured by sampling each cycle in steps of 5%.

   --auraDelay parks every family on its most characteristic frame instead:
   the band a third of the way in from the right, the scanline across the
   upper third, the breath and the blade edges most of the way up. It applies
   at every level, so moving from Still to Calm carries on from the frame that
   was on screen rather than jumping to another. --auraRestPos/--auraRestOp are
   the same frame written out, for the one case with no animation at all to
   park (the OS reduced-motion default, below). */
[data-il-panel]:not(.hero)::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  border-radius: inherit; opacity: var(--auraRestOp, var(--auraOp, .5));
  background: var(--aura, none); background-size: var(--auraSize, 220% 100%);
  background-repeat: var(--auraRepeat, no-repeat);
  background-position: var(--auraRestPos, 0 0);
  animation: var(--auraAnim, none) var(--auraDur, 20s) var(--auraEase, ease-in-out) infinite;
  animation-delay: var(--auraDelay, 0s);
  animation-play-state: var(--envPlay, paused);
  transition: opacity .45s ease;
}

/* The cursor spotlight. --mx/--my are written by il-aura.js on whichever
   plate the pointer is over; with no pointer they stay unset and the
   gradient sits centred and invisible at opacity 0. */
[data-il-panel]:not(.hero)::after {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  border-radius: inherit; opacity: 0; transition: opacity .4s ease;
  background: radial-gradient(var(--spotR, 280px) circle at var(--mx, 50%) var(--my, 50%),
                              var(--spotC, transparent), transparent 70%);
}
[data-il-panel]:not(.hero):hover::before { opacity: var(--auraHov, .9); }
[data-il-panel]:not(.hero):hover::after  { opacity: var(--spotOp, .9); }

@keyframes fam-sweep { 0%, 100% { background-position: -40% 0; } 50% { background-position: 140% 0; } }
@keyframes fam-sheen { 0%, 100% { background-position: 0% 0%; opacity: .3; } 50% { background-position: 100% 100%; opacity: .74; } }
@keyframes fam-breath { 0%, 100% { opacity: .26; } 50% { opacity: .72; } }
@keyframes fam-scan { 0% { background-position: 0 -70%; opacity: .2; } 40% { opacity: .66; } 100% { background-position: 0 170%; opacity: .2; } }
/* 200% of travel on a 200%-wide image is exactly one image width, so with
   Aether's --auraRepeat (repeat-x) the last frame is the first and the current
   runs without a seam. With no-repeat, as ported, both bands slid off the left
   edge for the last third of every cycle and popped back in at the loop. */
@keyframes fam-flow { 0% { background-position: 0 0; } 100% { background-position: 200% 0; } }
@keyframes fam-edge { 0%, 100% { opacity: .3; } 26% { opacity: .88; } 58% { opacity: .44; } }
@keyframes fam-mark { 0%, 100% { opacity: .7; } 50% { opacity: 1; } }

/* ── the six families ──────────────────────────────────────────────────── */
/* Vanguard — high cloudsea light: one warm band drifting across the plate */
[data-family="cs"] {
  --aura: linear-gradient(100deg, transparent 26%, color-mix(in oklab, var(--warning) 30%, transparent) 50%, transparent 74%);
  --auraAnim: fam-sweep; --auraDur: 26s; --auraOp: .5; --auraHov: .95;
  --auraDelay: -5.72s; --auraRestPos: 32% 0;                 /* the band a third in from the right, where the landing's sun stands */
  --spotC: color-mix(in oklab, var(--warning) 26%, transparent); --spotR: 320px; --spotOp: 1;
  --navMark: var(--brand); --navMarkW: 100%; --navMarkH: 2px; --navMarkX: 0; --navMarkY: auto; --navMarkB: 0; --navMarkR: 999px;
  --enterEase: cubic-bezier(.2, .84, .24, 1);
}
/* Stacia — cathedral sheen: a diagonal rose-gold wash that travels corner to corner */
[data-family="rs"] {
  --aura: linear-gradient(135deg, color-mix(in oklab, var(--brand) 16%, transparent) 0%, transparent 46%, color-mix(in oklab, var(--warning) 20%, transparent) 100%);
  --auraSize: 260% 260%; --auraAnim: fam-sheen; --auraDur: 22s; --auraOp: .42; --auraHov: .88;
  --auraDelay: -6.6s; --auraRestPos: 66.8% 66.8%; --auraRestOp: .59;   /* the wash on its way across */
  --spotC: color-mix(in oklab, var(--brand) 17%, transparent); --spotR: 300px; --spotOp: 1;
  --navMark: radial-gradient(circle, var(--brand) 46%, transparent 66%); --navMarkW: 6px; --navMarkH: 6px; --navMarkX: 0; --navMarkY: 50%; --navMarkR: 999px;
  --enterEase: cubic-bezier(.16, .9, .3, 1);
}
/* Aegis — heraldry: a crest of light held at the top edge, breathing */
[data-family="sv"] {
  --aura: radial-gradient(130% 62% at 50% 0%, color-mix(in oklab, var(--brand) 22%, transparent), transparent 62%);
  --auraSize: 100% 100%; --auraAnim: fam-breath; --auraDur: 15s; --auraOp: .4; --auraHov: .9;
  --auraDelay: -4.95s; --auraRestOp: .6;                     /* most of the way into the breath */
  --spotC: color-mix(in oklab, var(--brand) 22%, transparent); --spotR: 260px; --spotOp: 1;
  --navMark: linear-gradient(180deg, var(--brand), var(--critical)); --navMarkW: 3px; --navMarkH: 66%; --navMarkX: 0; --navMarkY: 50%; --navMarkR: 0;
  --enterEase: cubic-bezier(.3, .9, .2, 1);
}
/* Sovereign — the rift: a violet scanline falling down the plate */
[data-family="gt"] {
  --aura: linear-gradient(180deg, transparent 0%, color-mix(in oklab, var(--brand) 26%, transparent) 46%, color-mix(in oklab, var(--critical) 16%, transparent) 54%, transparent 100%);
  --auraSize: 100% 240%; --auraAnim: fam-scan; --auraDur: 13s; --auraOp: .46; --auraHov: 1;
  --auraDelay: -6.89s; --auraRestPos: 0 62%; --auraRestOp: .61;        /* the scanline across the upper third */
  --spotC: color-mix(in oklab, var(--brand) 24%, transparent); --spotR: 300px; --spotOp: 1;
  --navMark: var(--brand); --navMarkW: 3px; --navMarkH: 18px; --navMarkX: 0; --navMarkY: 50%; --navMarkR: 0;
  --enterEase: cubic-bezier(.12, .95, .2, 1);
}
/* Aether — flow: a slow current running left to right, never stopping */
[data-family="ng"] {
  --aura: linear-gradient(90deg, transparent 0%, color-mix(in oklab, var(--brand) 20%, transparent) 26%, transparent 48%, color-mix(in oklab, var(--good) 16%, transparent) 74%, transparent 100%);
  --auraSize: 200% 100%; --auraAnim: fam-flow; --auraDur: 30s; --auraOp: .44; --auraHov: .92;
  /* A current never slows at the turn, so it runs linear, and it tiles so the
     turn has no seam (see fam-flow). Its first frame already has a band in. */
  --auraRepeat: repeat-x; --auraEase: linear;
  --spotC: color-mix(in oklab, var(--brand) 22%, transparent); --spotR: 340px; --spotOp: 1;
  --navMark: linear-gradient(90deg, var(--brand), transparent); --navMarkW: 70%; --navMarkH: 2px; --navMarkX: 0; --navMarkB: 4px; --navMarkR: 999px;
  --enterEase: cubic-bezier(.35, .8, .2, 1);
}
/* Eclipse — two blades: both vertical edges lit, alternating */
[data-family="kr"] {
  --aura: linear-gradient(90deg, var(--brand-deep) 0 2px, transparent 2px calc(100% - 2px), var(--brand) calc(100% - 2px) 100%);
  --auraSize: 100% 100%; --auraAnim: fam-edge; --auraDur: 9s; --auraOp: .4; --auraHov: 1;
  --auraDelay: -3.78s; --auraRestOp: .66;                    /* both edges lit, just past the flash */
  --spotC: color-mix(in oklab, var(--brand-deep) 20%, transparent); --spotR: 240px; --spotOp: 1;
  --navMark: linear-gradient(180deg, var(--brand-deep) 50%, var(--brand) 50%); --navMarkW: 3px; --navMarkH: 100%; --navMarkX: 0; --navMarkY: 50%; --navMarkR: 0;
  --enterEase: cubic-bezier(.1, 1, .3, 1);
}

/* ── the selected-nav marker ───────────────────────────────────────────── */
/* data-il-nav is set by app.js's buildNav on each rail button. Marking the
   active section is the rail's only per-family flourish -- each family marks
   it with its own gesture (a full underline, a dot, a vertical bar, a split
   two-tone edge) rather than everyone sharing one generic indicator. */
[data-il-nav] { position: relative; overflow: hidden; }
[data-il-nav][aria-selected="true"]::after {
  content: ""; position: absolute; pointer-events: none;
  left: var(--navMarkX, 0); bottom: var(--navMarkB, auto); top: var(--navMarkY, auto);
  width: var(--navMarkW, 3px); height: var(--navMarkH, 100%);
  transform: translateY(var(--navMarkT, 0));
  border-radius: var(--navMarkR, 0); background: var(--navMark, var(--brand));
  animation: fam-mark 4.5s ease-in-out infinite;
  animation-play-state: var(--envPlay, paused);
}
/* These four centre their mark on the button's midline, so it needs pulling
   back by half its own height; cs hangs its underline off the bottom instead. */
[data-family="rs"] [data-il-nav][aria-selected="true"]::after,
[data-family="sv"] [data-il-nav][aria-selected="true"]::after,
[data-family="gt"] [data-il-nav][aria-selected="true"]::after,
[data-family="kr"] [data-il-nav][aria-selected="true"]::after { --navMarkT: -50%; }
[data-family="cs"] [data-il-nav][aria-selected="true"]::after { top: auto; }

/* Same scoping as style.css: an explicit Still/Calm/Surge choice is the
   person telling us what they want, and it wins over the OS default. */
@media (prefers-reduced-motion: reduce) {
  :root:not([data-motion-choice="user"]) [data-il-panel]:not(.hero)::before,
  :root:not([data-motion-choice="user"]) [data-il-nav][aria-selected="true"]::after { animation: none !important; }
}
