/* =====================================================================
   BLEXX ATMOSPHERE — the layer that makes it feel inhabited
   ---------------------------------------------------------------------
   Optional companion to blexx.css. Load it when a surface should feel
   like part of the BLEXX world rather than a tool: marketing pages,
   house surfaces, rituals, anything a member experiences.

   Every value here is lifted from the live house builds
   (chance_cinema.html and siblings). Don't retune them.

   Pair with js/blexx-atmosphere.js for the pieces that need a loop:
   dust, the cursor orb, the blessing reveal, and the ritual sigil.
   ===================================================================== */

/* ---------------------------------------------------------------------
   THE WORLD — the mystical ground BLEXX sits on.
   ---------------------------------------------------------------------
   BLEXX is not flat black. Every world in the brand is deep colour with
   light blooming through fog: the city's iridescent violet-and-teal
   haze, the interiors' amber chrome, each house's own light.

   Put ONE world layer behind everything, pick it with data-bx-world,
   and let it drift. Colours are sampled from the actual renders
   (STYLE_REF_CITY, STYLE_REF_INTERIOR, JOURNEY_*.mp4).

     data-bx-world="city"           violet fog, teal + magenta + acid blooms
     data-bx-world="interior"       blue-black with amber chrome pools
     data-bx-world="devotion"       rose chrome and candlelight
     data-bx-world="chance"         gold glass and green fungi light
     data-bx-world="manifestation"  cyan glass and cobalt depth
     data-bx-world="void"           near-black (tools and dashboards)

   Scope it to a section to change worlds mid-page.
   NOTE: this is .bx-world, not .bx-field — .bx-field is a form field.
   ------------------------------------------------------------------- */
[data-blexx-theme] .bx-world {
  position: absolute; inset: 0; z-index: 0; pointer-events: none; overflow: hidden;
  background-color: var(--bxf-base, #14101c);
}
[data-blexx-theme] .bx-world-fixed { position: fixed; z-index: 0; }

/* ---- the world stack: the performant way to change worlds -----------
   Two fixed layers that crossfade. One world paints at a time instead of
   one per section, and there are no masks involved — on a long page this
   is several times cheaper than giving every section its own world.
   Drive it with BLEXX.worlds(); see js/blexx-atmosphere.js.            */
[data-blexx-theme] .bx-world-stack > .bx-world {
  transition: opacity var(--bxw-fade, 1.1s) ease;
}
[data-blexx-theme] .bx-world-stack > .bx-world[data-bxw-off] { opacity: 0; }
/* once it has finished fading it stops painting altogether — an
   opacity:0 layer still composites every frame otherwise */
[data-blexx-theme] .bx-world-stack > .bx-world[data-bxw-idle] { visibility: hidden; }

/* A section-scoped world feathers into whatever is behind it. Correct,
   but it means every section paints its own full-viewport gradient AND a
   mask — fine for a short page, expensive on a long one. Prefer the
   stack above unless you specifically need per-section layering. */
[data-blexx-theme] .bx-world-blend {
  -webkit-mask-image: linear-gradient(to bottom, transparent 0,
    #000 var(--bxf-feather, 200px), #000 calc(100% - var(--bxf-feather, 200px)), transparent 100%);
          mask-image: linear-gradient(to bottom, transparent 0,
    #000 var(--bxf-feather, 200px), #000 calc(100% - var(--bxf-feather, 200px)), transparent 100%);
}

[data-blexx-theme] .bx-world::before,
[data-blexx-theme] .bx-world::after {
  content: ""; position: absolute; inset: -22%;
  background-repeat: no-repeat;
  transform: translateZ(0);
}
/* the blooms — light through fog */
[data-blexx-theme] .bx-world::before {
  background-image:
    radial-gradient(38% 46% at var(--bxf-p1, 14% 12%), var(--bxf-c1, rgba(124,58,190,.62)), transparent 68%),
    radial-gradient(42% 48% at var(--bxf-p2, 86% 20%), var(--bxf-c2, rgba(46,230,214,.40)), transparent 68%),
    radial-gradient(46% 52% at var(--bxf-p3, 72% 88%), var(--bxf-c3, rgba(201,87,201,.44)), transparent 70%),
    radial-gradient(40% 44% at var(--bxf-p4, 18% 84%), var(--bxf-c4, rgba(125,255,90,.20)), transparent 70%);
  animation: bx-world-drift 34s ease-in-out infinite alternate;
}
/* the prismatic beam — the city's rainbow shaft, off by default */
[data-blexx-theme] .bx-world::after {
  background-image: var(--bxf-beam, none);
  mix-blend-mode: screen;
  opacity: var(--bxf-beam-a, 0);
  animation: bx-world-sweep 48s ease-in-out infinite alternate;
}
@keyframes bx-world-drift {
  0%   { transform: translate3d(0,0,0) scale(1); }
  50%  { transform: translate3d(2.5%,-2%,0) scale(1.08); }
  100% { transform: translate3d(-2%,2.5%,0) scale(1.04); }
}
@keyframes bx-world-sweep {
  0%   { transform: translate3d(-4%,0,0) rotate(-2deg); }
  100% { transform: translate3d(4%,0,0) rotate(2deg); }
}

/* -- the worlds ------------------------------------------------------ */
[data-bx-world="city"] {
  --bxf-base: #171128;
  --bxf-c1: rgba(124,58,190,.66);   --bxf-p1: 12% 10%;
  --bxf-c2: rgba(46,230,214,.42);   --bxf-p2: 88% 18%;
  --bxf-c3: rgba(201,87,201,.48);   --bxf-p3: 74% 90%;
  --bxf-c4: rgba(125,255,90,.20);   --bxf-p4: 16% 86%;
  --bxf-beam-a: .30;
  --bxf-beam: conic-gradient(from 205deg at 78% -14%,
    transparent 0deg,
    rgba(255,60,90,.34) 5deg,
    rgba(255,190,60,.30) 9deg,
    rgba(120,255,140,.26) 13deg,
    rgba(60,200,255,.30) 17deg,
    rgba(150,90,255,.32) 21deg,
    transparent 27deg);
}
[data-bx-world="interior"] {
  --bxf-base: #0d1020;
  --bxf-c1: rgba(255,150,45,.46);   --bxf-p1: 50% 6%;
  --bxf-c2: rgba(255,196,110,.34);  --bxf-p2: 14% 62%;
  --bxf-c3: rgba(42,107,255,.34);   --bxf-p3: 88% 78%;
  --bxf-c4: rgba(255,120,40,.20);   --bxf-p4: 78% 22%;
  --bxf-beam-a: 0;
}
[data-bx-world="devotion"] {
  --bxf-base: #1b0f1c;
  --bxf-c1: rgba(246,129,133,.50);  --bxf-p1: 50% 14%;
  --bxf-c2: rgba(198,83,102,.52);   --bxf-p2: 16% 70%;
  --bxf-c3: rgba(122,74,143,.56);   --bxf-p3: 86% 66%;
  --bxf-c4: rgba(255,168,90,.26);   --bxf-p4: 50% 96%;
  --bxf-beam-a: 0;
}
[data-bx-world="chance"] {
  --bxf-base: #171208;
  --bxf-c1: rgba(255,245,162,.44);  --bxf-p1: 50% 10%;
  --bxf-c2: rgba(215,137,50,.50);   --bxf-p2: 14% 62%;
  --bxf-c3: rgba(180,140,30,.44);   --bxf-p3: 88% 70%;
  --bxf-c4: rgba(113,255,140,.22);  --bxf-p4: 52% 94%;
  --bxf-beam-a: 0;
}
[data-bx-world="manifestation"] {
  --bxf-base: #071427;
  --bxf-c1: rgba(149,245,249,.40);  --bxf-p1: 50% 12%;
  --bxf-c2: rgba(100,159,218,.50);  --bxf-p2: 16% 68%;
  --bxf-c3: rgba(18,79,179,.62);    --bxf-p3: 86% 68%;
  --bxf-c4: rgba(120,200,255,.24);  --bxf-p4: 50% 96%;
  --bxf-beam-a: 0;
}
[data-bx-world="void"] {
  --bxf-base: #131112;
  --bxf-c1: rgba(0,76,255,.14);     --bxf-c2: rgba(255,0,60,.10);
  --bxf-c3: rgba(239,240,0,.07);    --bxf-c4: transparent;
  --bxf-beam-a: 0;
}

/* a scrim for text that sits directly on a bright part of the field */
[data-blexx-theme] .bx-scrim-soft {
  position: relative;
}
[data-blexx-theme] .bx-scrim-soft::before {
  content: ""; position: absolute; inset: -6% -4%; z-index: -1; pointer-events: none;
  background: radial-gradient(70% 70% at 30% 50%, rgba(9,8,10,.78), rgba(9,8,10,.42) 60%, transparent 82%);
}

/* ---------------------------------------------------------------------
   THE GRADE — vignette + grain, always in this order, always on top
   ------------------------------------------------------------------- */
[data-blexx-theme] .bx-vignette {
  position: fixed; inset: 0; z-index: 4; pointer-events: none;
  background: radial-gradient(ellipse at 50% 45%,
    transparent 48%, rgba(9,8,8,.55) 88%, rgba(9,8,8,.8) 100%);
}
[data-blexx-theme] .bx-grain {
  position: fixed; inset: -64px; z-index: 4; pointer-events: none;
  opacity: .05; mix-blend-mode: overlay; background-repeat: repeat;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: bx-grain-shift .6s steps(3) infinite;
}
@keyframes bx-grain-shift {
  0%   { transform: translate(0,0); }
  33%  { transform: translate(18px,-26px); }
  66%  { transform: translate(-22px,12px); }
  100% { transform: translate(0,0); }
}

/* the accent breathing over the scene — "the impossible flickering
   strobe of outcomes". Opacity is driven per-frame by the JS. */
[data-blexx-theme] .bx-flicker {
  position: fixed; inset: 0; z-index: 3; pointer-events: none;
  background: radial-gradient(ellipse at 50% 30%,
    rgba(var(--bx-accent),.55) 0%, rgba(var(--bx-accent),.12) 40%, transparent 72%);
  opacity: 0; mix-blend-mode: screen; will-change: opacity;
}

/* drifting motes — canvas, drawn by the JS */
[data-blexx-theme] .bx-dust {
  position: fixed; inset: 0; width: 100vw; height: 100vh;
  z-index: 2; pointer-events: none;
}

/* ---------------------------------------------------------------------
   THE CURSOR ORB — BLEXX's own pointer. Hide the system cursor on any
   surface that uses it.
   ------------------------------------------------------------------- */
[data-blexx-theme].bx-orb-cursor,
[data-blexx-theme].bx-orb-cursor * { cursor: none !important; }
[data-blexx-theme] .bx-cursor {
  position: fixed; top: 0; left: 0; width: 36px; height: 36px;
  border-radius: 50%; pointer-events: none !important; z-index: 10001;
  /* its own compositor layer, so moving it never repaints the page */
  will-change: transform; contain: strict; backface-visibility: hidden;
  transform: translate3d(-50%,-50%,0); mix-blend-mode: screen;
  background: radial-gradient(circle,
    rgba(233,238,238,1) 0%, rgba(233,238,238,.7) 40%, rgba(233,238,238,0) 80%);
  box-shadow: 0 0 20px rgba(233,238,238,.9), 0 0 40px rgba(233,238,238,.5);
}

/* ---------------------------------------------------------------------
   GLYPHS — the BLEXX alphabet. A solid accent-coloured div shaped by the
   glyph's alpha via CSS mask, so swapping the accent tints every glyph
   for free.

   Build one with BLEXX.glyph(n, el) where n is 1–43. That injects an
   inline <svg> whose path uses currentColor, so it recolours with the
   accent, scales crisply, and works over http AND file:// — a CSS mask
   pointing at an image file is blocked as cross-origin on file:// and
   renders nothing at all.
   ------------------------------------------------------------------- */
[data-blexx-theme] .bx-glyph {
  width: clamp(46px, 6.6vh, 64px); aspect-ratio: 1;
  display: inline-block; line-height: 0;
  color: rgb(var(--bx-accent));
  filter: drop-shadow(0 0 14px rgba(var(--bx-accent),.85))
          drop-shadow(0 0 42px rgba(var(--bx-accent),.4));
  animation: bx-glyph-float 5.5s ease-in-out infinite;
  transition: transform .25s ease, opacity .55s ease;
  user-select: none; -webkit-user-select: none;
}
[data-blexx-theme] .bx-glyph > svg { width: 100%; height: 100%; display: block; }
[data-blexx-theme] .bx-glyph > svg path { fill: currentColor; }
/* legacy: a glyph pointed at an image file still works over http, but
   masks are blocked on file:// — prefer BLEXX.glyph(n, el). */
[data-blexx-theme] .bx-glyph[style*="mask"] { background: rgb(var(--bx-accent)); }
[data-blexx-theme] .bx-glyph:hover { transform: scale(1.18); }
[data-blexx-theme] .bx-glyph.is-popped { animation: bx-glyph-pop .7s ease both; pointer-events: none; }
[data-blexx-theme] .bx-glyph-ink { color: var(--bx-ink); filter: drop-shadow(0 0 14px rgba(233,238,238,.5)); }
@keyframes bx-glyph-float {
  0%,100% { margin-top: 0;      rotate: -4deg; }
  50%     { margin-top: -16px;  rotate:  4deg; }
}
@keyframes bx-glyph-pop {
  0%   { opacity: 1; transform: scale(1); }
  30%  { opacity: 1; transform: scale(1.75); color: #ffffff; }
  100% { opacity: 0; transform: scale(.12) rotate(40deg); }
}

/* a word set in the BLEXX alphabet */
[data-blexx-theme] .bx-word { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 10px; }
[data-blexx-theme] .bx-word .bx-glyph { width: clamp(30px, 4.4vh, 44px); }
[data-blexx-theme] .bx-word-gap { width: clamp(14px, 2vh, 22px); }

/* a drifting glyph placed loose in a scene */
[data-blexx-theme] .bx-glyph-loose { position: absolute; z-index: 7; opacity: .92; }

/* ---------------------------------------------------------------------
   BEINGS — name tag + emote bubbles. The houses' characters aren't
   mascots sitting in a frame; they notice you.
   ------------------------------------------------------------------- */
[data-blexx-theme] .bx-nametag {
  display: inline-block; font-family: var(--bx-display);
  font-size: 13px; letter-spacing: .28em; text-indent: .28em;
  color: var(--bx-accent-ink); background: rgb(var(--bx-accent));
  border-radius: var(--bx-r-pill); padding: 5px 14px; white-space: nowrap;
  box-shadow: 0 0 18px rgba(var(--bx-accent),.5);
}
[data-blexx-theme] .bx-emote {
  font-family: var(--bx-display); font-size: clamp(26px,4vh,40px);
  color: rgb(var(--bx-accent)); line-height: 1;
  text-shadow: 0 0 18px rgba(var(--bx-accent),.8), 0 2px 12px rgba(0,0,0,.8);
  opacity: 0; pointer-events: none;
}
[data-blexx-theme] .bx-emote.is-popped { animation: bx-emote-pop 1.25s ease both; }
@keyframes bx-emote-pop {
  0%   { opacity: 0; transform: translateY(12px) scale(.4) rotate(-8deg); }
  18%  { opacity: 1; transform: translateY(0) scale(1.2) rotate(3deg); }
  32%  { transform: translateY(-2px) scale(1) rotate(0deg); }
  78%  { opacity: 1; }
  100% { opacity: 0; transform: translateY(-18px) scale(.9); }
}

/* idle breathing for a being */
[data-blexx-theme] .bx-idle { animation: bx-char-idle 7s ease-in-out infinite; }
@keyframes bx-char-idle {
  0%,100% { transform: translateY(0)    rotate(0deg)    scale(1); }
  30%     { transform: translateY(-9px) rotate(-.7deg)  scale(1.006); }
  55%     { transform: translateY(-2px) rotate(.5deg)   scale(.998); }
  78%     { transform: translateY(-12px) rotate(.2deg)  scale(1.01); }
}
/* the breathing light behind a being */
[data-blexx-theme] .bx-char-glow {
  position: absolute; left: 50%; top: 50%; width: 130%; height: 130%;
  transform: translate(-50%,-50%); pointer-events: none; z-index: -2;
  background: radial-gradient(circle,
    rgba(var(--bx-accent),.30) 0%, rgba(var(--bx-accent),.10) 40%, transparent 70%);
}

/* ---------------------------------------------------------------------
   WHISPERS — text that only appears when you go near it
   ------------------------------------------------------------------- */
[data-blexx-theme] .bx-hotspot { position: relative; display: inline-block; }
[data-blexx-theme] .bx-whisper {
  position: absolute; left: 26px; top: -6px; width: max-content; max-width: 30ch;
  font-family: var(--bx-coded); font-weight: 500; font-size: 12px;
  letter-spacing: .26em; line-height: 2; color: rgb(var(--bx-accent));
  text-shadow: 0 0 18px rgba(var(--bx-accent),.4), 0 2px 20px rgba(0,0,0,.95);
  opacity: 0; transform: translateX(-6px); pointer-events: none;
  transition: opacity .45s ease, transform .45s ease;
}
[data-blexx-theme] .bx-hotspot:hover .bx-whisper,
[data-blexx-theme] .bx-hotspot.is-touched .bx-whisper { opacity: 1; transform: none; }

/* ---------------------------------------------------------------------
   BLESSING — the house voice. Never a typewriter: every word sharpens
   out of a blur on a 95ms stagger, key words land in the accent, and
   finished lines relax so the live line carries the eye.
   ------------------------------------------------------------------- */
[data-blexx-theme] .bx-blessing {
  font-family: var(--bx-body); font-weight: 500;
  font-size: clamp(15px,2vh,18px); line-height: 1.9; letter-spacing: .02em;
  color: var(--bx-ink); text-shadow: 0 2px 18px rgba(0,0,0,.9);
}
[data-blexx-theme] .bx-blessing .bx-w {
  display: inline-block; opacity: 0; filter: blur(8px); transform: translateY(7px);
  transition: opacity .55s ease, filter .55s ease, transform .55s ease;
  will-change: opacity, filter, transform;
}
[data-blexx-theme] .bx-blessing .bx-w.is-on { opacity: 1; filter: blur(0); transform: none; }
[data-blexx-theme] .bx-blessing .bx-s.is-settled .bx-w { opacity: .62; transition: opacity 1.2s ease; }
[data-blexx-theme] .bx-blessing .bx-w.is-key { color: rgb(var(--bx-accent)); font-weight: 800; }
[data-blexx-theme] .bx-blessing .bx-w.is-key.is-on { text-shadow: 0 0 18px rgba(var(--bx-accent),.65); }

/* ---------------------------------------------------------------------
   RITUAL — press and hold. Never a button that says "submit".
   ------------------------------------------------------------------- */
[data-blexx-theme] .bx-ritual {
  display: flex; flex-direction: column; align-items: center; gap: 10px;
}
[data-blexx-theme] .bx-ritual-label {
  font-family: var(--bx-coded); font-weight: 500; font-size: 12px;
  letter-spacing: .45em; text-indent: .45em; color: rgb(var(--bx-accent)); opacity: .85;
}
[data-blexx-theme] .bx-ritual-hint {
  font-family: var(--bx-coded); font-size: 11px;
  letter-spacing: .4em; text-indent: .4em; color: var(--bx-ink); opacity: .5;
}
[data-blexx-theme] .bx-sigil {
  position: relative; width: 96px; height: 96px; padding: 0;
  background: transparent; border: none; cursor: pointer;
  touch-action: none; -webkit-tap-highlight-color: transparent;
  transition: transform .3s ease;
}
[data-blexx-theme] .bx-sigil:hover    { transform: scale(1.06); }
[data-blexx-theme] .bx-sigil.is-holding { transform: scale(1.1); }
[data-blexx-theme] .bx-sigil svg { width: 100%; height: 100%; overflow: visible; display: block; }
[data-blexx-theme] .bx-sigil-track { fill: none; stroke: rgba(233,238,238,.18); stroke-width: 2; }
[data-blexx-theme] .bx-sigil-fill {
  fill: none; stroke: rgb(var(--bx-accent)); stroke-width: 3; stroke-linecap: round;
  stroke-dasharray: 339.3; stroke-dashoffset: 339.3;
  transform: rotate(-90deg); transform-origin: 50% 50%;
  filter: drop-shadow(0 0 8px rgba(var(--bx-accent),.8));
}
[data-blexx-theme] .bx-sigil-tri {
  fill: none; stroke: rgba(var(--bx-accent),.85); stroke-width: 2.5; stroke-linejoin: round;
  filter: drop-shadow(0 0 10px rgba(var(--bx-accent),.5));
  animation: bx-tri-breathe 3.2s ease-in-out infinite; transform-origin: 50% 58%;
}
[data-blexx-theme] .bx-sigil.is-holding .bx-sigil-tri { animation: bx-tri-spin 1.6s linear infinite; }
@keyframes bx-tri-breathe { 0%,100% { transform: scale(1); opacity: .85; } 50% { transform: scale(1.08); opacity: 1; } }
@keyframes bx-tri-spin { to { transform: rotate(360deg); } }

[data-blexx-theme] .bx-seal {
  font-family: var(--bx-display); font-size: 15px;
  letter-spacing: .35em; text-indent: .35em; color: rgb(var(--bx-accent));
  text-shadow: 0 0 22px rgba(var(--bx-accent),.6);
}
/* the flash when a ritual completes */
[data-blexx-theme] .bx-flash {
  position: fixed; inset: 0; z-index: 9000; pointer-events: none; opacity: 0;
  background: radial-gradient(ellipse at 50% 55%,
    rgba(var(--bx-accent),.85) 0%, rgba(var(--bx-accent),.3) 45%, transparent 75%);
}

/* ---------------------------------------------------------------------
   CHAPTER CARD — announces where you've arrived, then leaves
   ------------------------------------------------------------------- */
[data-blexx-theme] .bx-chapter {
  font-family: var(--bx-coded); font-size: 12px;
  letter-spacing: .5em; text-indent: .5em; color: var(--bx-ink); opacity: .6;
}
[data-blexx-theme] .bx-chapter.is-shown { animation: bx-chapter-pop 2.4s ease both; }
@keyframes bx-chapter-pop {
  0%   { opacity: 0; transform: translateY(16px); }
  14%  { opacity: 1; transform: translateY(0); }
  78%  { opacity: 1; }
  100% { opacity: 0; transform: translateY(-12px); }
}

@media (prefers-reduced-motion: reduce) {
  [data-blexx-theme] .bx-grain,
  [data-blexx-theme] .bx-glyph,
  [data-blexx-theme] .bx-idle,
  [data-blexx-theme] .bx-sigil-tri { animation: none !important; }
  [data-blexx-theme] .bx-blessing .bx-w { transition-duration: .1s; }
}
