/* ============================================================
   Kitsune AI — Ambient Motion System (Phase 1)
   Shared, sitewide. Two always-on layers driven by one scroll loop:
     · .mo-solar   — scroll-driven solar/eclipse ambient lighting (#5)
     · .mo-thread  — the Nine-Tails connective thread (#1)
   Both are fixed, pointer-events:none, and sit ABOVE section
   backgrounds but BELOW the nav. Restraint by design: low opacity,
   blended, concentrated in margins/empty space.
   ============================================================ */

.mo-solar,
.mo-thread {
  position: fixed;
  pointer-events: none;
  will-change: transform, opacity;
}

/* ---- #5 Solar / eclipse ambient light ---- */
.mo-solar {
  inset: 0;
  z-index: 60;                 /* above content, below nav (100) */
  /* driven by JS: */
  --mo-sun-x: 80%;
  --mo-sun-y: 14%;
  --mo-sun-r: 44%;
  --mo-hue: 18;               /* 18 warm-orange → 262 violet → 224 blue */
  --mo-sat: 92%;
  --mo-op: 0.16;
  background:
    radial-gradient(var(--mo-sun-r) calc(var(--mo-sun-r) * 1.05) at var(--mo-sun-x) var(--mo-sun-y),
      hsla(var(--mo-hue), var(--mo-sat), 56%, 0.95),
      hsla(var(--mo-hue), var(--mo-sat), 52%, 0.0) 70%);
  mix-blend-mode: screen;
  opacity: var(--mo-op);
}

/* a faint second pass on light pages so the glow doesn't vanish on white
   (screen does little on near-white; soft-light adds gentle tint) */
.mo-solar::after {
  content: "";
  position: absolute; inset: 0;
  background: inherit;
  mix-blend-mode: soft-light;
  opacity: 0.5;
}

/* ---- #1 Nine-Tails connective thread ---- */
.mo-thread {
  top: 0; left: 0;
  width: 70px; height: 100vh; height: 100svh;
  z-index: 62;
  overflow: visible;
}
.mo-thread__svg { display: block; width: 100%; height: 100%; overflow: visible; will-change: transform; }
.mo-thread__p {
  fill: none;
  stroke: url(#moThreadG);
  stroke-width: 2;
  stroke-linecap: round;
  filter: drop-shadow(0 0 5px rgba(238, 77, 31, 0.45));
}
/* faint full-path ghost so the gutter never looks empty before it draws */
.mo-thread__ghost {
  fill: none;
  stroke: rgba(140, 120, 200, 0.16);
  stroke-width: 1.25;
  stroke-linecap: round;
}

/* Mobile: the vertical gutter thread is desktop-tuned. For Phase 1 it
   collapses to a hairline top progress filament (full re-stage in Phase 4). */
@media (max-width: 760px) {
  .mo-thread {
    width: 100vw; height: 3px; top: 0;
  }
  .mo-thread__svg { display: none; }
  .mo-thread__bar {
    position: absolute; top: 0; left: 0; height: 100%;
    width: var(--mo-progress-pct, 0%);
    background: linear-gradient(90deg, #ee4d1f, #7a4ddb 55%, #2337f1);
    box-shadow: 0 0 8px rgba(238, 77, 31, 0.5);
  }
  .mo-solar { --mo-op: 0.12; }
}
@media (min-width: 761px) {
  .mo-thread__bar { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .mo-solar { transition: none; }
  .mo-thread__p { filter: none; }
}

/* ============================================================
   #3 FOUNDRY CAST — molten-to-solid headline reveal
   Opt-in via .mo-cast (auto-applied by motion.js to key titles).
   Decoupled from site.js reveal: uses its own .mo-in toggle.
   A soft "cooling front" wipes across; a heat-glow cools to crisp.
   ============================================================ */
.mo-cast {
  opacity: 1 !important;
  transform: none !important;
  /* descenders (g, p, y) sat below the line-box; the mask is sized to the box
     (mask-size height 100%), so they were being clipped. Extend the box
     downward and cancel it in flow so layout is unchanged. */
  padding-bottom: 0.2em;
  margin-bottom: -0.2em;
  -webkit-mask-image: linear-gradient(100deg, #000 0 36%, rgba(0,0,0,.35) 50%, transparent 64%);
          mask-image: linear-gradient(100deg, #000 0 36%, rgba(0,0,0,.35) 50%, transparent 64%);
  -webkit-mask-size: 300% 100%; mask-size: 300% 100%;
  -webkit-mask-position: 100% 0; mask-position: 100% 0;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
}
.mo-cast.mo-in {
  -webkit-mask-position: 0 0; mask-position: 0 0;
  transition: -webkit-mask-position 1.05s cubic-bezier(.22,.9,.25,1),
                      mask-position 1.05s cubic-bezier(.22,.9,.25,1);
  animation: moCastGlow 1.1s ease-out both;
}
@keyframes moCastGlow {
  0%   { text-shadow: 0 0 26px rgba(238,77,31,.5), 0 0 9px rgba(255,120,60,.42); }
  60%  { text-shadow: 0 0 14px rgba(238,77,31,.28); }
  100% { text-shadow: 0 0 0 rgba(238,77,31,0); }
}

/* ============================================================
   #2 FRICTION → FLOW — canvas seam (chaos resolving to laminar)
   Drop <div class="mo-flow" aria-hidden="true"></div> at a
   problem→solution seam. motion.js fills it with a canvas.
   ============================================================ */
.mo-flow {
  position: relative; width: 100%;
  height: clamp(180px, 30vh, 320px);
  overflow: hidden; pointer-events: none;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
}
.mo-flow canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }

/* ============================================================
   #4 GOVERNED FLOW — pulses travel lanes, pause at gates
   <div class="mo-gov"><span class="mo-gov__lane">…gates…</span></div>
   Pure CSS. Amber gate = awaiting judgment; green = approved.
   ============================================================ */
.mo-gov { display: flex; flex-direction: column; gap: 16px; width: 100%; max-width: 880px; margin: 0 auto; padding: 8px 0; }
.mo-gov__lane { position: relative; height: 2px; background: linear-gradient(90deg, rgba(140,120,200,.18), rgba(140,120,200,.28)); border-radius: 2px; }
.mo-gov__pulse { position: absolute; top: 50%; left: 0; width: 7px; height: 7px; margin-top: -3.5px; border-radius: 50%; background: #ee4d1f; box-shadow: 0 0 12px 2px rgba(238,77,31,.65); offset-rotate: 0deg; animation: moGovRun var(--gov-dur, 7s) linear infinite; animation-delay: var(--gov-delay, 0s); }
@keyframes moGovRun {
  0%   { left: 0%;  opacity: 0; }
  6%   { opacity: 1; }
  44%  { left: 48%; opacity: 1; }      /* arrive at gate */
  56%  { left: 48%; opacity: 1; }      /* pause — human judgment */
  94%  { left: 100%; opacity: 1; }
  100% { left: 100%; opacity: 0; }
}
.mo-gov__gate { position: absolute; top: 50%; left: 48%; width: 11px; height: 11px; margin: -5.5px 0 0 -5.5px; transform: rotate(45deg); border: 1.5px solid var(--kit-fox-500, #ee4d1f); background: rgba(238,77,31,.12); border-radius: 2px; animation: moGovGate var(--gov-dur, 7s) linear infinite; animation-delay: var(--gov-delay, 0s); }
@keyframes moGovGate {
  0%, 44%   { border-color: rgba(140,120,200,.5); background: rgba(140,120,200,.1); box-shadow: none; }
  46%, 54%  { border-color: #ee4d1f; background: rgba(238,77,31,.18); box-shadow: 0 0 12px 1px rgba(238,77,31,.5); }   /* amber: awaiting */
  60%, 100% { border-color: #2f8f5d; background: rgba(47,143,93,.16); box-shadow: 0 0 10px 1px rgba(47,143,93,.45); }   /* green: approved */
}

@media (prefers-reduced-motion: reduce) {
  .mo-cast { -webkit-mask-image: none; mask-image: none; }
  .mo-cast.mo-in { animation: none; transition: none; }
  .mo-gov__pulse { display: none; }
  .mo-gov__gate { animation: none; border-color: #2f8f5d; background: rgba(47,143,93,.16); }
}
