/* ================================================================
   ISG — First-visit intro overlay (shared across pages).

   Loaded by /intro.js on every public surface. The animation plays
   once per cooldown window (default 7 days) keyed off
   localStorage['isg.introLastPlayed'] — so a visitor who lands on
   /slides first won't see it again on /main/ for the rest of the
   window. Hidden entirely under prefers-reduced-motion.

   Theme integration: prefers --bg / --ink / --ink-2 from the host
   page's design tokens, with hard-coded fallbacks for surfaces that
   don't load them. Glow alphas auto-flip for dark host themes.
   ================================================================ */

:root {
  /* Glow alphas are intentionally low — the goal is a soft halo,
     not a flash. Dark glow on light bg has higher perceived contrast
     than the inverse, so the dark-theme alphas are scaled down to
     match perceived weight. */
  --intro-glow-near: rgba(17, 18, 20, 0.18);
  --intro-glow-far:  rgba(17, 18, 20, 0.09);
  --intro-rule:      rgba(17, 18, 20, 0.35);
}
:root[data-theme='dark'] {
  --intro-glow-near: rgba(244, 243, 238, 0.30);
  --intro-glow-far:  rgba(244, 243, 238, 0.16);
  --intro-rule:      rgba(244, 243, 238, 0.35);
}
@media (prefers-color-scheme: dark) {
  /* Pages without an explicit data-theme follow the OS preference. */
  :root:not([data-theme]) {
    --intro-glow-near: rgba(244, 243, 238, 0.30);
    --intro-glow-far:  rgba(244, 243, 238, 0.16);
    --intro-rule:      rgba(244, 243, 238, 0.35);
  }
}

.intro {
  position: fixed;
  inset: 0;
  z-index: 200;
  /* var(--bg) wins on token-aware pages; fallbacks cover the rest. */
  background: var(--bg, #fbfbfb);
  display: grid;
  place-items: center;
  /* Default transition is for the click-skip path (.is-done) — fast. */
  transition: opacity 280ms cubic-bezier(0.16, 1, 0.3, 1);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) .intro { background: var(--bg, #0a0b0d); }
}
.intro[hidden] { display: none; }
.intro.is-done {
  opacity: 0;
  pointer-events: none;
}
/* Natural completion: overlay fades during the second half of the
   720ms fly-out so the logo stays opaque while it's heading toward
   the corner, then "burns out" as it leaves the frame. The 360ms
   delay holds the fade until the logo is well on its way. */
.intro.is-fly {
  opacity: 0;
  pointer-events: none;
  transition: opacity 360ms cubic-bezier(0.55, 0, 0.85, 0.4) 360ms;
}
.intro__stage {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 22px;
  will-change: transform;
}
.intro__svg-wrap {
  position: relative;
  width: min(560px, 82vw);
  aspect-ratio: 1852 / 1141;
  overflow: visible;
}

.intro__svg {
  width: 100%;
  height: 100%;
  color: var(--ink, #111214);
  display: block;
  overflow: visible;
  opacity: 0;
  transform: scale(1.06);
  /* Lower starting blur (32px vs 48px) so the focus exit doesn't
     traverse such a wide contrast range. The eased timing curve is
     evened out (more linear at the end) so the final 200 ms doesn't
     feel like a flash when sharpness lands. */
  filter: blur(32px);
  transition: opacity 1600ms cubic-bezier(0.33, 0.05, 0.4, 1),
              transform 1600ms cubic-bezier(0.33, 0.05, 0.4, 1),
              filter 1600ms cubic-bezier(0.33, 0.05, 0.4, 1);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) .intro__svg { color: var(--ink, #f3f4f6); }
}
.intro.is-playing .intro__svg {
  /* Hold short of full opacity during the focus exit; the glow
     keyframe nudges to 1 once the harsh contrast jump is past. */
  opacity: 0.92;
  transform: scale(1);
  filter: blur(0);
}
/* Soft halo, not a flash. Peak moved off-centre (40%) and the curve
   smoothed so it eases up rather than spiking. */
.intro.is-glow .intro__svg {
  animation: intro-glow 900ms cubic-bezier(0.4, 0, 0.4, 1) forwards;
}
@keyframes intro-glow {
  0%   { opacity: 0.92;
         filter: blur(0)
                 drop-shadow(0 0 0 transparent); }
  40%  { opacity: 1;
         filter: blur(0)
                 drop-shadow(0 0 22px var(--intro-glow-near))
                 drop-shadow(0 0 44px var(--intro-glow-far)); }
  100% { opacity: 1;
         filter: blur(0)
                 drop-shadow(0 0 0 transparent); }
}

.intro__rule {
  width: 0;
  height: 1px;
  background: var(--intro-rule);
  margin: 8px 0 0;
  opacity: 0;
  transition: width 800ms cubic-bezier(0.16, 1, 0.3, 1) 200ms,
              opacity 600ms cubic-bezier(0.16, 1, 0.3, 1) 200ms;
}
.intro.is-tagline .intro__rule {
  width: 88px;
  opacity: 1;
}
.intro.is-fly .intro__rule {
  opacity: 0;
  transition: opacity 180ms;
}

.intro__tagline {
  font-family: var(--font-mono, 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: clamp(13px, 1.4vw, 16px);
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--ink-2, #3a3c42);
  text-align: center;
  line-height: 1.5;
  opacity: 0;
  transform: translateY(10px);
  filter: blur(6px);
  transition: opacity 600ms cubic-bezier(0.16, 1, 0.3, 1),
              transform 600ms cubic-bezier(0.16, 1, 0.3, 1),
              filter 600ms cubic-bezier(0.16, 1, 0.3, 1),
              letter-spacing 600ms cubic-bezier(0.16, 1, 0.3, 1);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) .intro__tagline { color: var(--ink-2, #b9bdc4); }
}
.intro.is-tagline .intro__tagline {
  opacity: 1;
  transform: translateY(0);
  filter: blur(0);
  letter-spacing: 0.22em;
}
.intro.is-fly .intro__tagline {
  opacity: 0;
  filter: blur(0);
  transform: translateY(0);
  transition: opacity 240ms cubic-bezier(0.16, 1, 0.3, 1);
}

/* Fly-out trajectory: stage shrinks and slides diagonally past the
   top-left corner, exiting the viewport. Combined with the overlay's
   delayed opacity fade above, the logo stays opaque while it's
   moving, then fades as it nears / leaves the frame — and the
   landing's nav logo (already mounted at top-left) is what the user
   sees once the overlay clears. */
.intro.is-fly .intro__stage {
  animation: intro-flyout 720ms cubic-bezier(0.55, 0, 0.25, 1) forwards;
}
@keyframes intro-flyout {
  to { transform: translate(calc(-50vw - 80px), calc(-50vh - 80px)) scale(0.05); }
}

@media (prefers-reduced-motion: reduce) {
  .intro { display: none !important; }
}
