/* ═══════════════════════════════════════════════════════════════════════
   newdais.ai — Daybreak MOTION & GRAPHIC layer
   The site-wide "performed sunrise" system: a fixed warm page-wash whose
   colour climbs amber→gold with scroll, plus one recurring convergence
   graphic (the New DAIS "sun" loop) and its small relatives.

   Loaded from base.html AFTER tokens.css and style.css so it can lean on
   the semantic tokens. Colour comes ONLY from tokens (static/tokens.css);
   the single sanctioned literal is #1B1630 (dark ink on the bright sun,
   DESIGN.md §1.3). Kept out of style.css so the whole motion system is one
   revertable unit.

   Canon: static/hero-lab.html (the flagship home hero prototype). The
   .loop macro (templates/partials/_loop.html) reproduces this at its
   maximal 6-in/6-out; every interior graphic is an excerpt.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── registered custom properties ──────────────────────────────────────
   --p is scroll progress 0→1 (written once per frame by motion.js).
   Registering --sun/--sun2 as <color> lets the browser interpolate the
   color-mix chain below into a real colour we can both paint and read back. */
@property --p    { syntax: '<number>'; inherits: true; initial-value: 0; }
@property --sun  { syntax: '<color>';  inherits: true; initial-value: #FF6321; }
@property --sun2 { syntax: '<color>';  inherits: true; initial-value: #FFAE2E; }

/* ── the sunrise ramp ──────────────────────────────────────────────────
   AMBER at the core (ember-500) → GOLD as it spreads (solar-500/400).
   Coral and violet stay out of it entirely — they were "the pink". Scroll
   nudges the core amber→gold, so the page warms as you descend. Kept
   deliberately low-alpha in the wash so --ink keeps full contrast. */
:root {
  --sun:  color-mix(in oklab, var(--ember-500) calc((1 - var(--p)) * 100%), var(--solar-500));
  --sun2: color-mix(in oklab, var(--solar-500) calc((1 - var(--p)) * 100%), var(--solar-400));
}

/* ══ THE PAGE WASH ═════════════════════════════════════════════════════
   One fixed radial that sets the tone for every page: amber where the sun
   sits, spreading through gold, fading to bare ground at the edges. It
   lives at z-index:-1 behind all content; `body` is made transparent so
   the wash shows over html's --ground canvas. Opaque bands (.bg-elev-band,
   .bg-deep-band) naturally cover it — the warmth shows only on the plain
   ground sections, which is the "placed, not sprayed" intent (DESIGN.md §6). */
body { background: transparent; }   /* html still carries --ground beneath the wash */

.page-wash {
  position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(58vmax 52vmax at 72% 30%,
      color-mix(in srgb, var(--sun)  20%, transparent) 0%,
      color-mix(in srgb, var(--sun2) 15%, transparent) 30%,
      color-mix(in srgb, var(--solar-400) 8%, transparent) 54%,
      transparent 78%),
    radial-gradient(90vmax 70vmax at 82% 96%,
      color-mix(in srgb, var(--solar-400) 7%, transparent) 0%,
      transparent 62%);
}

/* ══ THE LOOP — convergence graphic ════════════════════════════════════
   "wherever you are → New DAIS AI → wherever you're going". Rendered by
   the loop() macro; the flagship is its 6-in/6-out instance. ViewBox is a
   fixed 680×620 with the sun at (360,305) r≈86 so every instance nests. */
.loop { width: 100%; height: auto; overflow: visible; display: block; }

/* headings + node labels */
.d-head  { font: 500 10px/1 var(--font-mono); letter-spacing: .18em; text-transform: uppercase; fill: var(--ink-3); }
.d-label { font: 500 9px/1  var(--font-mono); letter-spacing: .07em; text-transform: uppercase; }
.d-chip-box { fill: var(--surface); stroke: var(--line-strong); stroke-width: 1; }

/* the beds the work travels along */
.feed-bed { fill: none; stroke: var(--line-strong); stroke-width: 1; opacity: .8; }
/* a short dash chasing along each bed — plain CSS (not SMIL) so
   prefers-reduced-motion can switch it off. */
.feed-pulse {
  fill: none; stroke-width: 1.8; stroke-linecap: round; opacity: .8;
  stroke-dasharray: 30 300; animation: feed 4.4s linear infinite;
}
.feed-in  { stroke: var(--ember-500); }   /* inbound: ember */
.feed-out { stroke: var(--solar-500); }   /* outbound: gold  */
/* --line-strong is low-contrast on the dark ground, so the beds nearly
   vanish there; lift them to --ink-3 in dark (the ember/gold pulses carry
   the flow either way). Explicit [data-theme] wins over the media query
   in both directions, matching tokens.css. */
@media (prefers-color-scheme: dark) { .feed-bed, .flow-bed { stroke: var(--ink-3); } }
:root[data-theme="light"] .feed-bed, :root[data-theme="light"] .flow-bed { stroke: var(--line-strong); }
:root[data-theme="dark"]  .feed-bed, :root[data-theme="dark"]  .flow-bed { stroke: var(--ink-3); }
@keyframes feed { from { stroke-dashoffset: 330 } to { stroke-dashoffset: 0 } }
.f2 { animation-delay: -.66s } .f3 { animation-delay: -1.33s }
.f4 { animation-delay: -2s }   .f5 { animation-delay: -2.66s }
.f6 { animation-delay: -3.33s }

/* the rings orbiting the sun */
.loop-ring {
  fill: none; stroke: var(--solar-600); stroke-width: 1; opacity: .38;
  stroke-dasharray: 3 7; transform-origin: 360px 305px;
  animation: spin 26s linear infinite;
}
.loop-arc {
  fill: none; stroke: var(--solar-600); stroke-width: 1.6; stroke-linecap: round;
  stroke-dasharray: 250 454; opacity: .45;
  transform-origin: 360px 305px; animation: spin 11s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg) } }

/* ░░ THE SUN ░░ — the core of the loop and the brand mark */
.sun-core { animation: sunBreathe 7s var(--ease) infinite; transform-origin: 360px 305px; }
@keyframes sunBreathe {
  0%, 100% { filter: brightness(1) saturate(1); }
  50%      { filter: brightness(1.06) saturate(1.05); }
}
/* Text ON the bright sun takes DARK ink — DESIGN.md §1.3 (bright decorates,
   deep interacts; anything you READ on a bright ramp step is dark, never white). */
.sun-word { font: 700 25px/1 var(--font-sans); letter-spacing: -.02em; fill: #1B1630; }
.sun-sub  { font: 600 12px/1 var(--font-mono); letter-spacing: .16em; fill: #1B1630; opacity: .72; }

/* nodes: quiet breathing so the diagram feels alive without distracting */
.node { animation: nodeBlink 7s var(--ease) infinite; }
.node.f2 { animation-delay: -1.1s } .node.f3 { animation-delay: -2.3s }
.node.f4 { animation-delay: -3.5s } .node.f5 { animation-delay: -4.6s }
.node.f6 { animation-delay: -5.8s }
@keyframes nodeBlink { 0%, 72%, 100% { opacity: .82 } 82%, 90% { opacity: 1 } }

/* ── variant tweaks (node styling / geometry only; the sun is invariant) ──
   converge: inbound beds read "unresolved" (dashed) → outbound clean.
   databricks: the lone destination node reads as the lakehouse target. */
.loop--converge .bed-in { stroke-dasharray: 3 6; opacity: .55; }
.loop--databricks .dest-solo .d-chip-box { stroke: var(--solar-600); stroke-width: 1.4; }

/* ══ DRAW-IN — diagrams assemble as they enter ═════════════════════════
   Reuses base.html's existing .reveal IntersectionObserver: it adds .in,
   and these rules do the "drawing". Beds carrying .draw (with pathLength=1)
   are hidden (dash fully offset) until .in, then stroke on, staggered by
   --i. Everything else stays visible so the static composition reads with
   motion off. */
.draw { stroke-dasharray: 1; }
.reveal .draw { stroke-dashoffset: 1; }
.reveal.in .draw {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset .9s var(--ease);
  transition-delay: calc(var(--i, 0) * 70ms);
}

/* ══ PRIMITIVES ════════════════════════════════════════════════════════ */

/* horizon_sweep — the sunrise hairline that draws in left→right on reveal */
.horizon-sweep { height: 1px; width: 100%; background: var(--horizon-line); opacity: .85;
  transform: scaleX(0); transform-origin: left center; }
.reveal.in .horizon-sweep,
.horizon-sweep.reveal.in { transform: scaleX(1); transition: transform 1s var(--ease-dawn); }

/* sun_mark — a small breathing sun for eyebrows / band anchors / timelines */
.sun-mark { display: inline-block; vertical-align: middle; animation: sunBreathe 7s var(--ease) infinite; }
.sun-mark circle.disc { fill: var(--sun2); }
.sun-mark circle.halo { fill: var(--sun); opacity: .18; }

/* flow_rail — horizontal sequence bed with a travelling pulse (Agents, Approach) */
.flow-rail { width: 100%; height: auto; overflow: visible; display: block; }
.flow-bed  { fill: none; stroke: var(--line-strong); stroke-width: 1.5; }
.flow-pulse{ fill: none; stroke: var(--ember-500); stroke-width: 2.4; stroke-linecap: round;
  stroke-dasharray: 26 260; animation: feed 3.6s linear infinite; }
.flow-return { fill: none; stroke: var(--solar-500); stroke-width: 1.6; stroke-dasharray: 4 5; opacity: .7; }
.flow-stop   { fill: var(--surface); stroke: var(--line-strong); stroke-width: 1.4; }
.flow-num    { font: 700 13px/1 var(--font-mono); fill: var(--accent); }
.flow-gate   { stroke: var(--solar-600); stroke-width: 1.4; opacity: .8; }

/* mini_loop — a subordinate convergence for down-page bands (unlabeled sun) */
.mini-loop { width: 100%; max-width: 340px; height: auto; overflow: visible; display: block; margin-inline: auto; }

/* ══ NARROW SCREENS — the loop scales with its container; nudge label sizes
   up (they are SVG user-units, so they shrink with the viewBox) so the
   excerpt stays legible when stacked below the copy. The convergence shape
   still reads even where labels go quiet. ══ */
@media (max-width: 700px) {
  .loop .d-label { font-size: 12px; }
  .loop .d-head  { font-size: 11px; }
  .sun-word { font-size: 27px; }
}

/* ══ REDUCED MOTION — kill all motion; static composition must still read ══ */
@media (prefers-reduced-motion: reduce) {
  .feed-pulse, .flow-pulse, .loop-ring, .loop-arc, .sun-core, .sun-mark, .node { animation: none !important; }
  .draw, .horizon-sweep { transition: none !important; }   /* snap in, don't animate */
  .feed-pulse, .flow-pulse { opacity: .5; }                /* show the pulse dash statically */
  .node { opacity: .9; }
}
