/* ============================================================================
   SiteFX — composable visitor-site techniques (the "Lego" effects layer)
   ----------------------------------------------------------------------------
   Styles for the opt-in effects driven by public/techniques.js. Every effect is
   applied via a data-attribute (data-fx="parallax tilt", etc.) or per-section
   config (page_sections.settings.fx). All motion is an ENHANCEMENT: it degrades
   gracefully and is fully disabled under prefers-reduced-motion (see the bottom
   block + the JS guards). Generic / white-label — no industry assumptions.
   ============================================================================ */

/* Parallax — the element is translated a few px as it scrolls through the
   viewport (JS sets --fx-parallax). Kept GPU-friendly via translate3d. */
[data-fx~="parallax"], .fx-parallax { will-change: transform; }
[data-fx~="parallax"] > *, .fx-parallax > * { will-change: auto; }

/* 3D tilt — a card leans toward the cursor (JS sets --fx-rx/--fx-ry, and a soft
   glow position via --fx-mx/--fx-my). */
[data-fx~="tilt"], .fx-tilt {
  transform: perspective(900px) rotateX(var(--fx-rx, 0deg)) rotateY(var(--fx-ry, 0deg));
  transform-style: preserve-3d;
  transition: transform 0.25s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: transform;
}
.fx-tilt-glow { position: relative; }
.fx-tilt-glow::after {
  content: "";
  position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  opacity: 0; transition: opacity 0.3s ease;
  background: radial-gradient(220px circle at var(--fx-mx, 50%) var(--fx-my, 50%),
              color-mix(in srgb, var(--color-accent, #c9a96e) 22%, transparent), transparent 60%);
}
.fx-tilt-glow:hover::after { opacity: 1; }
/* glare sweep — a diagonal sheen that tracks the cursor x (hixlab "lab-tilt") */
.fx-tilt-glow::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; z-index: 3;
  opacity: 0; transition: opacity 0.25s ease;
  background: linear-gradient(105deg, transparent 35%, rgba(255,255,255,0.28) var(--fx-mx, 50%), transparent 66%);
}
.fx-tilt-glow:hover::before { opacity: 1; }

/* Magnetic — a button/link drifts toward the cursor when near (JS sets --fx-tx/--fx-ty). */
[data-fx~="magnetic"], .fx-magnetic {
  transform: translate(var(--fx-tx, 0px), var(--fx-ty, 0px));
  transition: transform 0.18s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: transform;
}

/* Marquee — an infinite, seamless horizontal scroller. The JS clones the track
   so the loop is seamless; CSS does the animation. Pauses on hover. */
.fx-marquee { overflow: hidden; width: 100%; -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); }
.fx-marquee-track { display: inline-flex; flex-wrap: nowrap; gap: var(--fx-marquee-gap, 2.5rem); align-items: center; will-change: transform; animation: fx-marquee-move var(--fx-marquee-dur, 38s) linear infinite; }
.fx-marquee:hover .fx-marquee-track { animation-play-state: paused; }
.fx-marquee[data-fx-reverse] .fx-marquee-track { animation-direction: reverse; }
@keyframes fx-marquee-move { from { transform: translate3d(0,0,0); } to { transform: translate3d(-50%,0,0); } }

/* Sticky-stack — cards that pin and stack as you scroll past them. */
.fx-stack { position: relative; }
.fx-stack > .fx-stack-item { position: sticky; top: var(--fx-stack-top, 12vh); }

/* Gradient-mesh — an animated, brand-tinted aurora behind a section. The JS adds
   .fx-mesh and (where supported) a canvas; this is the CSS fallback look. */
.fx-mesh { position: relative; isolation: isolate; }
.fx-mesh > .fx-mesh-bg {
  position: absolute; inset: -10% -10% -10% -10%; z-index: -1; pointer-events: none;
  filter: blur(60px) saturate(125%); opacity: 0.55;
  background:
    radial-gradient(40% 50% at 20% 25%, color-mix(in srgb, var(--color-accent,  #c9a96e) 60%, transparent), transparent 70%),
    radial-gradient(45% 55% at 80% 30%, color-mix(in srgb, var(--color-accent-2, #6366f1) 45%, transparent), transparent 70%),
    radial-gradient(50% 60% at 50% 85%, color-mix(in srgb, var(--color-accent,  #c9a96e) 35%, transparent), transparent 70%);
  background-size: 180% 180%;
  animation: fx-mesh-drift 22s ease-in-out infinite alternate;
}
@keyframes fx-mesh-drift {
  0%   { background-position:  0%   0%,  100% 0%,   50% 100%; }
  100% { background-position: 100% 100%, 0%  100%,  50% 0%;  }
}

/* Count-up — purely JS (replaces text content); no special CSS needed, but a
   tabular-nums feel keeps the digits from jittering. */
[data-fx~="countup"], .fx-countup { font-variant-numeric: tabular-nums; }

/* Scramble — the text decodes from random glyphs on reveal; JS swaps characters.
   A subtle accent tint while scrambling. */
.fx-scrambling { color: color-mix(in srgb, var(--color-accent, #c9a96e) 75%, currentColor); }

/* ============================================================================
   EXPANDED TECHNIQUE LIBRARY (hixlab-inspired) — visual / motion families.
   Each effect is keyed by a .fx-<name> class added by techniques.js. Uses the
   tenant brand vars (--color-accent / --color-accent-2) so it stays on-brand.
   ============================================================================ */

/* ── Visual & glamour ─────────────────────────────────────────────────────── */
/* glassmorphism */
.fx-glass{background:rgba(255,255,255,.06);backdrop-filter:blur(14px) saturate(140%);-webkit-backdrop-filter:blur(14px) saturate(140%);
  border:1px solid rgba(255,255,255,.16);border-radius:18px;box-shadow:0 8px 40px rgba(0,0,0,.25);}
/* neon sign */
.fx-neon{color:var(--color-accent,#22d3ee);text-shadow:0 0 4px currentColor,0 0 12px currentColor,0 0 28px currentColor;
  animation:fx-neon-flicker 3.6s infinite;}
@keyframes fx-neon-flicker{0%,18%,22%,25%,53%,57%,100%{opacity:1}20%,24%,55%{opacity:.55}}
/* aurora backdrop (element-scoped) */
.fx-aurora{position:relative;isolation:isolate;overflow:hidden;}
.fx-aurora::before{content:"";position:absolute;inset:-30%;z-index:-1;filter:blur(60px) saturate(140%);opacity:.7;
  background:radial-gradient(40% 50% at 20% 20%,color-mix(in srgb,var(--color-accent,#22d3ee) 70%,transparent),transparent 70%),
  radial-gradient(45% 55% at 80% 30%,color-mix(in srgb,var(--color-accent-2,#a855f7) 60%,transparent),transparent 70%),
  radial-gradient(50% 60% at 50% 90%,color-mix(in srgb,var(--color-accent,#22d3ee) 45%,transparent),transparent 70%);
  background-size:160% 160%;animation:fx-aurora-drift 18s ease-in-out infinite alternate;}
@keyframes fx-aurora-drift{0%{background-position:0% 0%,100% 0%,50% 100%}100%{background-position:100% 100%,0% 100%,50% 0%}}
/* conic glow border */
.fx-conic-border{position:relative;border-radius:16px;}
.fx-conic-border::before{content:"";position:absolute;inset:-2px;z-index:-1;border-radius:inherit;padding:2px;
  background:conic-gradient(from 0deg,var(--color-accent,#22d3ee),var(--color-accent-2,#a855f7),var(--color-accent,#22d3ee));
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;mask-composite:exclude;
  animation:fx-conic-spin 4s linear infinite;}
@keyframes fx-conic-spin{to{transform:rotate(1turn)}}
/* metallic shimmer text */
.fx-shimmer-text{background:linear-gradient(100deg,#888 20%,#fff 38%,#fff 42%,#888 58%);background-size:200% auto;
  -webkit-background-clip:text;background-clip:text;color:transparent;animation:fx-shimmer 3s linear infinite;}
@keyframes fx-shimmer{to{background-position:-200% center}}
/* animated gradient text */
.fx-gradient-text{background:linear-gradient(90deg,var(--color-accent,#22d3ee),var(--color-accent-2,#a855f7),var(--color-accent,#22d3ee));
  background-size:200% auto;-webkit-background-clip:text;background-clip:text;color:transparent;animation:fx-shimmer 4s linear infinite;}
/* morphing blob */
.fx-blob{border-radius:42% 58% 70% 30%/45% 45% 55% 55%;background:linear-gradient(135deg,var(--color-accent,#22d3ee),var(--color-accent-2,#a855f7));
  animation:fx-blob-morph 8s ease-in-out infinite;}
@keyframes fx-blob-morph{0%,100%{border-radius:42% 58% 70% 30%/45% 45% 55% 55%}33%{border-radius:62% 38% 38% 62%/58% 62% 38% 42%}66%{border-radius:38% 62% 56% 44%/48% 38% 62% 52%}}
/* hover shine sweep */
.fx-shine{position:relative;overflow:hidden;}
.fx-shine::after{content:"";position:absolute;top:0;left:-120%;width:60%;height:100%;transform:skewX(-20deg);pointer-events:none;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.35),transparent);transition:left .7s ease;}
.fx-shine:hover::after{left:140%;}
/* gentle float */
.fx-float{animation:fx-float 5s ease-in-out infinite;}
@keyframes fx-float{0%,100%{transform:translateY(0)}50%{transform:translateY(-10px)}}
/* holographic foil (cursor-reactive via --fx-hx/--fx-hy/--fx-hr from JS) */
.fx-holo{position:relative;overflow:hidden;border-radius:16px;transform:rotateY(var(--fx-hr,0deg));transition:transform .2s ease;}
.fx-holo::before{content:"";position:absolute;inset:0;pointer-events:none;mix-blend-mode:color-dodge;opacity:.55;
  background:radial-gradient(120% 120% at var(--fx-hx,50%) var(--fx-hy,50%),rgba(255,255,255,.7),transparent 45%),
  conic-gradient(from 0deg at var(--fx-hx,50%) var(--fx-hy,50%),#ff5f6d,#ffc371,#3cba92,#5b86e5,#9d50bb,#ff5f6d);}

/* ── Kinetic typography ───────────────────────────────────────────────────── */
.fx-glitch{position:relative;color:var(--color-text,#fff);}
.fx-glitch::before,.fx-glitch::after{content:attr(data-text);position:absolute;inset:0;background:transparent;clip-path:inset(0);}
.fx-glitch::before{left:2px;text-shadow:-2px 0 #ff00c1;animation:fx-glitch-a 2.4s infinite linear alternate-reverse;}
.fx-glitch::after{left:-2px;text-shadow:-2px 0 #00fff9;animation:fx-glitch-b 3s infinite linear alternate-reverse;}
@keyframes fx-glitch-a{0%{clip-path:inset(10% 0 85% 0)}25%{clip-path:inset(80% 0 5% 0)}50%{clip-path:inset(40% 0 40% 0)}75%{clip-path:inset(20% 0 65% 0)}100%{clip-path:inset(60% 0 20% 0)}}
@keyframes fx-glitch-b{0%{clip-path:inset(75% 0 8% 0)}25%{clip-path:inset(15% 0 70% 0)}50%{clip-path:inset(55% 0 30% 0)}75%{clip-path:inset(35% 0 50% 0)}100%{clip-path:inset(5% 0 88% 0)}}
.fx-typewriter::after{content:"";display:inline-block;width:.6ch;height:1.05em;vertical-align:-.12em;margin-left:2px;
  background:currentColor;animation:fx-caret 1s steps(1) infinite;}
@keyframes fx-caret{50%{opacity:0}}
.fx-reveal{clip-path:inset(0 100% 0 0);opacity:.0;transition:clip-path 1s cubic-bezier(.22,1,.36,1),opacity 1s;}
.fx-reveal.fx-revealed{clip-path:inset(0 0 0 0);opacity:1;}

/* ── Cursor & pointer ─────────────────────────────────────────────────────── */
.fx-glow{position:relative;overflow:hidden;}
.fx-glow::before{content:"";position:absolute;inset:0;pointer-events:none;opacity:0;transition:opacity .3s;
  background:radial-gradient(260px circle at var(--fx-gx,50%) var(--fx-gy,50%),color-mix(in srgb,var(--color-accent,#22d3ee) 30%,transparent),transparent 60%);}
.fx-glow:hover::before{opacity:1;}
/* glow: a cursor-tracking masked gradient border (hixlab "lab-spotcard::after") */
.fx-glow::after{content:"";position:absolute;inset:0;border-radius:inherit;padding:1px;pointer-events:none;opacity:0;transition:opacity .3s;
  background:radial-gradient(220px circle at var(--fx-gx,50%) var(--fx-gy,50%),color-mix(in srgb,var(--color-accent,#22d3ee) 90%,transparent),transparent 60%);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;mask-composite:exclude;}
.fx-glow:hover::after{opacity:1;}
.fx-spotlight{position:relative;}
.fx-spotlight::before{content:"";position:absolute;inset:0;pointer-events:none;border-radius:inherit;opacity:0;transition:opacity .25s;
  background:radial-gradient(220px circle at var(--fx-sx,50%) var(--fx-sy,50%),rgba(255,255,255,.16),transparent 60%);}
.fx-spotlight:hover::before{opacity:1;}
/* spotlight: matching cursor-tracking masked border so the panel edge lights up too */
.fx-spotlight::after{content:"";position:absolute;inset:0;border-radius:inherit;padding:1px;pointer-events:none;opacity:0;transition:opacity .3s;
  background:radial-gradient(240px circle at var(--fx-sx,50%) var(--fx-sy,50%),color-mix(in srgb,var(--color-accent,#22d3ee) 70%,transparent),transparent 60%);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;mask-composite:exclude;}
.fx-spotlight:hover::after{opacity:1;}
.fx-cursor-trail{position:relative;overflow:hidden;cursor:crosshair;}
.fx-trail-dot{position:absolute;width:14px;height:14px;margin:-7px 0 0 -7px;border-radius:50%;pointer-events:none;visibility:hidden;
  background:var(--color-accent,#22d3ee);}

/* ── Micro-interactions ───────────────────────────────────────────────────── */
.fx-ripple{position:relative;overflow:hidden;}
.fx-ripple-wave{position:absolute;border-radius:50%;background:rgba(255,255,255,.45);transform:scale(0);animation:fx-ripple .6s ease-out;pointer-events:none;}
@keyframes fx-ripple{to{transform:scale(2.4);opacity:0}}
.fx-like{position:relative;cursor:pointer;color:#9aa;transition:transform .15s,color .15s;}
.fx-like.is-liked{color:#ff4d6d;transform:scale(1.12);}
.fx-like-particle{position:absolute;left:50%;top:50%;width:6px;height:6px;border-radius:50%;background:#ff4d6d;pointer-events:none;
  animation:fx-like-pop .55s ease-out forwards;}
@keyframes fx-like-pop{to{transform:translate(var(--fx-dx),var(--fx-dy)) scale(0);opacity:0}}
.fx-confetti{position:relative;}
.fx-confetti-piece{position:absolute;top:30%;width:8px;height:14px;border-radius:2px;pointer-events:none;
  animation:fx-confetti-fall var(--fx-cd,1s) ease-in forwards;}
@keyframes fx-confetti-fall{to{transform:translate(var(--fx-cx,0),140px) rotate(var(--fx-cr,360deg));opacity:0}}
/* 3D card flip (hover) — wrap faces in .fx-flip-front/.fx-flip-back */
.fx-flip{perspective:1000px;}
.fx-flip-inner{position:relative;transform-style:preserve-3d;transition:transform .7s cubic-bezier(.22,1,.36,1);}
.fx-flip:hover .fx-flip-inner{transform:rotateY(180deg);}
.fx-flip-front,.fx-flip-back{position:absolute;inset:0;backface-visibility:hidden;border-radius:inherit;}
.fx-flip-back{transform:rotateY(180deg);}
/* before/after slider */
.fx-ba{position:relative;overflow:hidden;border-radius:14px;touch-action:none;user-select:none;}
.fx-ba-before,.fx-ba-after{position:absolute;inset:0;background-size:cover;background-position:center;}
.fx-ba-after{clip-path:inset(0 0 0 50%);}
.fx-ba-handle{position:absolute;top:0;bottom:0;left:50%;width:2px;background:#fff;transform:translateX(-50%);pointer-events:none;}
.fx-ba-handle::after{content:"⟺";position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:34px;height:34px;border-radius:50%;
  background:#fff;color:#111;display:flex;align-items:center;justify-content:center;font-size:14px;box-shadow:0 2px 10px rgba(0,0,0,.4);}

/* ----------------------------------------------------------------------------
   SHOWCASE COMPONENT FAMILIES — UI patterns (layout / controls / overlays /
   data-viz) shown in the Components showcase. These are pure-CSS, self-animating
   reference components (no SiteFX/JS needed); they read brand tokens so every demo
   is on-brand. Looping animations are frozen under prefers-reduced-motion below.
   ---------------------------------------------------------------------------- */
@property --fx-p { syntax: "<percentage>"; inherits: false; initial-value: 72%; }

/* ── Layout & structure ─────────────────────────────────────────────────── */
.fx-bento { display:grid; grid-template-columns:1.4fr 1fr 1fr; grid-template-rows:1fr 1fr; gap:6px; width:100%; height:100%; }
.fx-bento > i { border-radius:8px; border:1px solid rgba(255,255,255,.1);
  background:linear-gradient(135deg, color-mix(in srgb,var(--color-accent) 34%,transparent), color-mix(in srgb,var(--color-accent-secondary,#a855f7) 24%,transparent)); }
.fx-bento > i:nth-child(1) { grid-row:1/3; }
.fx-bento > i:nth-child(4) { grid-column:2/4; }

.fx-masonry { column-count:3; column-gap:6px; width:100%; }
.fx-masonry > i { display:block; margin:0 0 6px; border-radius:7px; border:1px solid rgba(255,255,255,.1); background:color-mix(in srgb,var(--color-accent) 26%,transparent); }
.fx-masonry > i:nth-child(3n)   { height:62px; }
.fx-masonry > i:nth-child(3n+1) { height:40px; }
.fx-masonry > i:nth-child(3n+2) { height:52px; }

.fx-stack-peek { position:relative; width:78%; height:78%; }
.fx-stack-peek > i { position:absolute; left:0; right:0; height:46px; border-radius:10px; border:1px solid rgba(255,255,255,.12);
  background:color-mix(in srgb,var(--color-bg,#0a0f1a) 64%, var(--color-accent)); box-shadow:0 -5px 14px rgba(0,0,0,.35); }
.fx-stack-peek > i:nth-child(1) { top:0; }
.fx-stack-peek > i:nth-child(2) { top:22px; }
.fx-stack-peek > i:nth-child(3) { top:44px; }

.fx-split { display:flex; width:100%; height:100%; border-radius:10px; overflow:hidden; border:1px solid rgba(255,255,255,.1); }
.fx-split > i { flex:1; display:flex; align-items:center; justify-content:center; font-size:.72rem; color:#fff; letter-spacing:.04em; }
.fx-split > i:nth-child(1) { background:linear-gradient(135deg, var(--color-accent), transparent); }
.fx-split > i:nth-child(2) { background:color-mix(in srgb,var(--color-accent-secondary,#a855f7) 55%, transparent); }

/* ── Controls & inputs ──────────────────────────────────────────────────── */
.fx-seg { display:inline-flex; background:rgba(255,255,255,.06); border:1px solid rgba(255,255,255,.12); border-radius:10px; padding:3px; gap:2px; }
.fx-seg > i { padding:6px 14px; border-radius:7px; font-size:.78rem; color:var(--color-text,#e4e4e7); opacity:.65; }
.fx-seg > i.on { background:var(--color-accent); color:#fff; opacity:1; }

.fx-switch { width:52px; height:30px; border-radius:999px; background:var(--color-accent); position:relative; box-shadow:inset 0 0 0 1px rgba(255,255,255,.18); }
.fx-switch::after { content:""; position:absolute; top:3px; left:25px; width:24px; height:24px; border-radius:50%; background:#fff; box-shadow:0 1px 3px rgba(0,0,0,.4); animation:fx-switch 2.6s ease-in-out infinite; }
@keyframes fx-switch { 0%,38% { left:25px; } 54%,88% { left:3px; } 100% { left:25px; } }

.fx-slider { width:80%; height:6px; border-radius:999px; background:rgba(255,255,255,.12); position:relative; }
.fx-slider > span { position:absolute; left:0; top:0; bottom:0; width:62%; border-radius:999px; background:linear-gradient(90deg, var(--color-accent), var(--color-accent-secondary,#a855f7)); }
.fx-slider > i { position:absolute; top:50%; left:62%; width:16px; height:16px; border-radius:50%; background:#fff; transform:translate(-50%,-50%); box-shadow:0 1px 5px rgba(0,0,0,.45); }

.fx-stepper { display:inline-flex; align-items:center; border:1px solid rgba(255,255,255,.14); border-radius:10px; overflow:hidden; }
.fx-stepper > i { width:34px; height:34px; display:flex; align-items:center; justify-content:center; font-size:1.05rem; color:var(--color-accent); }
.fx-stepper > b { width:44px; height:34px; line-height:34px; text-align:center; font-size:.9rem; border-left:1px solid rgba(255,255,255,.12); border-right:1px solid rgba(255,255,255,.12); }

/* ── Overlays & surfaces ────────────────────────────────────────────────── */
.fx-toast { display:flex; align-items:center; gap:10px; border-radius:10px; padding:10px 14px; max-width:90%;
  background:color-mix(in srgb,var(--color-bg,#0a0f1a) 55%, #000); border:1px solid rgba(255,255,255,.12); border-left:3px solid var(--color-accent);
  box-shadow:0 10px 26px rgba(0,0,0,.45); animation:fx-toast-in 3s ease-in-out infinite; }
.fx-toast .dot { width:18px; height:18px; border-radius:50%; background:var(--color-accent); flex:none; }
.fx-toast div { font-size:.78rem; line-height:1.25; }
.fx-toast small { display:block; font-size:.68rem; opacity:.6; }
@keyframes fx-toast-in { 0%,10% { transform:translateY(16px); opacity:0; } 24%,80% { transform:none; opacity:1; } 96%,100% { transform:translateY(-8px); opacity:0; } }

.fx-tip { position:relative; padding:8px 16px; border-radius:9px; background:rgba(255,255,255,.06); border:1px solid rgba(255,255,255,.12); font-size:.8rem; }
.fx-tip::before { content:attr(data-tip); position:absolute; bottom:calc(100% + 9px); left:50%; transform:translateX(-50%); white-space:nowrap; background:var(--color-accent); color:#fff; padding:5px 10px; border-radius:6px; font-size:.72rem; box-shadow:0 4px 12px rgba(0,0,0,.4); }
.fx-tip::after  { content:""; position:absolute; bottom:calc(100% + 4px); left:50%; transform:translateX(-50%); border:5px solid transparent; border-top-color:var(--color-accent); }

.fx-modal { width:88%; border-radius:12px; overflow:hidden; border:1px solid rgba(255,255,255,.12);
  background:color-mix(in srgb,var(--color-bg,#0a0f1a) 50%, #000); box-shadow:0 14px 32px rgba(0,0,0,.5); }
.fx-modal header { padding:9px 13px; font-size:.82rem; font-weight:600; border-bottom:1px solid rgba(255,255,255,.1); }
.fx-modal p { margin:0; padding:9px 13px; font-size:.72rem; opacity:.65; }
.fx-modal footer { display:flex; justify-content:flex-end; gap:6px; padding:8px 12px; }
.fx-modal footer i { font-size:.72rem; padding:5px 12px; border-radius:7px; }
.fx-modal footer i:nth-child(1) { border:1px solid rgba(255,255,255,.2); }
.fx-modal footer i:nth-child(2) { background:var(--color-accent); color:#fff; }

.fx-badges { display:flex; flex-wrap:wrap; gap:7px; align-items:center; justify-content:center; }
.fx-badges > i { display:inline-flex; align-items:center; gap:5px; font-size:.72rem; padding:4px 10px; border-radius:999px; border:1px solid currentColor; }
.fx-badges > i::before { content:""; width:7px; height:7px; border-radius:50%; background:currentColor; }
.fx-badges .ok   { color:#34d399; }
.fx-badges .warn { color:#fbbf24; }
.fx-badges .info { color:var(--color-accent); }
.fx-badges .live::before { animation:fx-pulse 1.4s ease-in-out infinite; }
@keyframes fx-pulse { 0%,100% { opacity:1; transform:scale(1); } 50% { opacity:.3; transform:scale(.7); } }

/* ── Data & viz ─────────────────────────────────────────────────────────── */
.fx-ring { position:relative; width:96px; height:96px; border-radius:50%; display:flex; align-items:center; justify-content:center;
  --fx-p:72%; background:conic-gradient(var(--color-accent) var(--fx-p), rgba(255,255,255,.1) 0); animation:fx-ring 3.2s ease-out infinite; }
.fx-ring::before { content:""; position:absolute; width:72px; height:72px; border-radius:50%; background:var(--color-bg,#0a0f1a); }
.fx-ring b { position:relative; font-size:1rem; font-weight:700; }
@keyframes fx-ring { 0% { --fx-p:0%; } 55%,100% { --fx-p:72%; } }

.fx-bars { display:flex; align-items:flex-end; gap:8px; height:78%; }
.fx-bars > i { width:16px; border-radius:5px 5px 0 0; transform-origin:bottom; animation:fx-bars-grow 3s ease-in-out infinite;
  background:linear-gradient(180deg, var(--color-accent), color-mix(in srgb,var(--color-accent-secondary,#a855f7) 60%, transparent)); }
.fx-bars > i:nth-child(1) { height:40%; animation-delay:0s; }
.fx-bars > i:nth-child(2) { height:70%; animation-delay:.08s; }
.fx-bars > i:nth-child(3) { height:52%; animation-delay:.16s; }
.fx-bars > i:nth-child(4) { height:88%; animation-delay:.24s; }
.fx-bars > i:nth-child(5) { height:62%; animation-delay:.32s; }
@keyframes fx-bars-grow { 0% { transform:scaleY(0); } 45%,82% { transform:scaleY(1); } 100% { transform:scaleY(1); } }

.fx-spark { width:90%; height:auto; }
.fx-spark .area { fill:color-mix(in srgb,var(--color-accent) 14%, transparent); }
.fx-spark .line { fill:none; stroke:var(--color-accent); stroke-width:2.5; stroke-linecap:round; stroke-linejoin:round;
  stroke-dasharray:260; stroke-dashoffset:260; animation:fx-spark-draw 3.2s ease-out infinite; }
@keyframes fx-spark-draw { 0% { stroke-dashoffset:260; } 55%,100% { stroke-dashoffset:0; } }

.fx-gauge { position:relative; width:120px; height:64px; overflow:hidden; }
.fx-gauge .arc { width:120px; height:120px; border-radius:50%;
  background:conic-gradient(from 270deg, var(--color-accent) 0deg, var(--color-accent-secondary,#a855f7) 120deg, rgba(255,255,255,.1) 122deg 360deg); }
.fx-gauge .hole { position:absolute; left:20px; top:20px; width:80px; height:80px; border-radius:50%; background:var(--color-bg,#0a0f1a); }
.fx-gauge b { position:absolute; left:0; right:0; bottom:2px; text-align:center; font-size:.92rem; font-weight:700; }

/* ----------------------------------------------------------------------------
   Accessibility — motion is an enhancement. Under reduced-motion, freeze every
   animated technique to its resting state (the JS also no-ops the motion ones).
   ---------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .fx-switch::after, .fx-toast, .fx-badges .live::before, .fx-ring, .fx-bars > i, .fx-spark .line { animation: none !important; }
  .fx-ring { --fx-p: 72%; }
  .fx-spark .line { stroke-dashoffset: 0; }
  [data-fx~="parallax"], .fx-parallax,
  [data-fx~="tilt"], .fx-tilt,
  [data-fx~="magnetic"], .fx-magnetic { transform: none !important; }
  .fx-marquee-track, .fx-mesh > .fx-mesh-bg { animation: none !important; }
  .fx-marquee { -webkit-mask-image: none; mask-image: none; }
  .fx-neon, .fx-aurora::before, .fx-conic-border::before, .fx-shimmer-text, .fx-gradient-text,
  .fx-blob, .fx-float, .fx-glitch::before, .fx-glitch::after, .fx-confetti-piece, .fx-like-particle,
  .fx-typewriter::after { animation: none !important; }
  .fx-reveal { clip-path: none !important; opacity: 1 !important; }
}
