/* ══════════════════════════════════════════════════════════════════════════
   Obolark · Ambient Underworld FX Layer
   Optional atmosphere to pair with [data-theme=night] (the default).
   Add class="fx-atmosphere" to <body> to activate the whole bundle, or opt
   into individual effects via the sub-classes below.

   Effects (composable):
     .fx-atmosphere       → enables all defaults (vignette + grain + flicker)
     .fx-embers           → drifting ember particles rising from bottom
     .fx-scanlines        → faint horizontal paper-grain / film rule lines
     .fx-vignette         → radial corner darkening
     .fx-flicker          → oil-lamp flicker on --signal & --ember glows
     .fx-smoke            → slow warm-black smoke drifting up edges

   ALL effects:
     • are pointer-events: none  (never block clicks)
     • degrade gracefully on prefers-reduced-motion (static / removed)
     • auto-disable under [data-theme="day"]
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Root wrapper --------------------------------------------------- */
.fx-atmosphere {
  position: relative;
  isolation: isolate;           /* keep our ::before/::after layers scoped */
}
.fx-atmosphere::before,
.fx-atmosphere::after {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;                    /* sit behind page content */
}
.fx-atmosphere > * { position: relative; z-index: 1; }

/* ── Vignette (corner darken) --------------------------------------- */
.fx-atmosphere::before,
.fx-vignette::before {
  content: "";
  position: fixed; inset: 0; pointer-events: none; z-index: 2;
  background:
    radial-gradient(ellipse 110% 80% at 50% 50%,
      transparent 40%,
      rgba(0,0,0, calc(var(--fx-vignette-alpha) * 0.6)) 75%,
      rgba(0,0,0, var(--fx-vignette-alpha)) 100%);
  mix-blend-mode: multiply;
}

/* ── Paper-grain scanlines (film rule) ------------------------------ */
.fx-atmosphere::after,
.fx-scanlines::after {
  content: "";
  position: fixed; inset: 0; pointer-events: none; z-index: 3;
  background-image:
    repeating-linear-gradient(
      0deg,
      rgba(255,220,150, var(--fx-scanline-alpha)) 0px,
      rgba(255,220,150, var(--fx-scanline-alpha)) 1px,
      transparent 1px,
      transparent 3px
    );
  mix-blend-mode: overlay;
  opacity: 0.5;
}

/* ── Ember particles ------------------------------------------------ */
/* Usage: place <div class="fx-ember-field" aria-hidden="true"></div> in body,
   or use the ember-field.js helper to inject a configurable field. */
.fx-ember-field {
  position: fixed; inset: 0; pointer-events: none; z-index: 4;
  overflow: hidden;
}
.fx-ember {
  position: absolute;
  bottom: -20px;
  width: 3px; height: 3px;
  border-radius: 50%;
  background: radial-gradient(circle, var(--ember) 0%, #F76B2B 45%, transparent 70%);
  box-shadow: 0 0 6px var(--ember), 0 0 14px #F76B2B88;
  opacity: 0;
  will-change: transform, opacity;
  animation: ember-rise var(--dur, 14s) linear infinite;
  animation-delay: var(--delay, 0s);
  left: var(--x, 50%);
}
.fx-ember.small { width: 2px; height: 2px; opacity: 0.7; }
.fx-ember.large { width: 4px; height: 4px; }

@keyframes ember-rise {
  0%   { transform: translate3d(0, 0, 0)            scale(0.6); opacity: 0; }
  8%   { opacity: 0.95; }
  40%  { transform: translate3d(8px, -35vh, 0)      scale(1);   opacity: 0.8; }
  70%  { transform: translate3d(-4px, -68vh, 0)     scale(0.9); opacity: 0.5; }
  100% { transform: translate3d(12px, -110vh, 0)    scale(0.3); opacity: 0; }
}

/* ── Oil-lamp flicker on signal glows ------------------------------- */
/* Apply .fx-flicker (or put it on the root) to make elements with
   box-shadow/text-shadow using var(--signal) subtly flicker. */
.fx-flicker .led,
.fx-flicker [data-flicker],
.fx-atmosphere .led {
  animation: lamp-flicker 3.1s ease-in-out infinite;
}
@keyframes lamp-flicker {
  0%,  100% { filter: brightness(1)    drop-shadow(0 0 6px var(--signal)); }
  17%       { filter: brightness(1.08) drop-shadow(0 0 9px var(--signal)); }
  34%       { filter: brightness(0.94) drop-shadow(0 0 5px var(--signal)); }
  51%       { filter: brightness(1.04) drop-shadow(0 0 8px var(--signal)); }
  68%       { filter: brightness(0.96) drop-shadow(0 0 6px var(--signal)); }
  85%       { filter: brightness(1.02) drop-shadow(0 0 7px var(--signal)); }
}

/* ── Smoke drift (edge plume) --------------------------------------- */
.fx-smoke::before {
  content: "";
  position: fixed; left: -10%; right: -10%; bottom: -20%;
  height: 60vh; pointer-events: none; z-index: 1;
  background:
    radial-gradient(ellipse 40% 60% at 20% 100%, #2A1E1644 0%, transparent 60%),
    radial-gradient(ellipse 30% 50% at 70% 100%, #3A1E0833 0%, transparent 65%),
    radial-gradient(ellipse 25% 40% at 40% 100%, #1A0D0433 0%, transparent 70%);
  mix-blend-mode: screen;
  animation: smoke-drift 24s ease-in-out infinite alternate;
}
@keyframes smoke-drift {
  0%   { transform: translate3d(0, 0, 0) scale(1); }
  100% { transform: translate3d(-30px, -10px, 0) scale(1.05); }
}

/* ── Day mode: disable EVERYTHING ---------------------------------- */
/* Per brand direction: day = zero VFX. Flat parchment, static LEDs. */
[data-theme="day"] .fx-atmosphere::before,
[data-theme="day"] .fx-atmosphere::after,
[data-theme="day"] .fx-ember-field,
[data-theme="day"] .fx-vignette::before,
[data-theme="day"] .fx-scanlines::after,
[data-theme="day"] .fx-smoke::before {
  display: none !important;
}
[data-theme="day"] .fx-flicker .led,
[data-theme="day"] .fx-flicker [data-flicker],
[data-theme="day"] .fx-atmosphere .led {
  animation: none !important;
  filter: none !important;
}

/* ── Reduced motion: freeze animations ------------------------------ */
@media (prefers-reduced-motion: reduce) {
  .fx-ember,
  .fx-smoke::before,
  .fx-flicker .led,
  .fx-flicker [data-flicker],
  .fx-atmosphere .led {
    animation: none !important;
  }
  .fx-ember { opacity: 0.6; }
}
