/* yewho-web-effects bundle for SPT Maju v5 — stylesheet
   modules: wordfx.css, frames.css, gridglow.css, gridbeams.css, hover.css, modern.css, reveal.css, flipcard.css, cinema.css, loops.css, type.css, typewriter.css, tilt.css, fx-brand.css
   Each JS module is wrapped in try/catch so one failure cannot stop the rest.
   Rebuild via the scratchpad bundler; do not hand-edit. */

/* ===== wordfx.css ===== */
/* premium-motion : typography motion pack  (yewho-web-effects 2.3, Phase 9)
   Pairs with wordfx.js (splits text, adds .in on view). PLAIN TEXT only inside
   these elements — the splitter reads textContent.

     .md-words      — word-by-word cascade: each word rises out of a soft blur
                      (the keynote reveal). Tune: --wf-step (def 70ms)
     .md-chars      — per-character rise (tighter, for short accent lines)
     .md-outline    — headline starts as a hollow outline, fills with ink
                      left→right on view. Tune: --wf-fill (ink), --wf-line
     .md-letterwave — perpetual GENTLE letter bob on a short accent word
                      (armed only after the entrance settles; full tier only)

   All hidden states live under html.js — no-JS users always see text.
   ============================================================ */

/* ---- shared: split spans ---- */
.md-words .w, .md-chars .c, .md-letterwave .c{ display:inline-block; will-change:auto; }
.md-words .w{ margin-right:.28em; }
.md-words .w:last-child{ margin-right:0; }

/* ---- word cascade ---- */
html.js .md-words .w{
  opacity:0; transform:translateY(14px); filter:blur(6px);
  transition: opacity .55s var(--md-ease,cubic-bezier(.22,.61,.2,1)),
              transform .55s var(--md-ease,cubic-bezier(.22,.61,.2,1)),
              filter .55s var(--md-ease,cubic-bezier(.22,.61,.2,1));
  transition-delay: calc(var(--i,0) * var(--wf-step,70ms));
}
html.js .md-words.in .w{ opacity:1; transform:none; filter:blur(0); }
:root[data-motion="lite"] .md-words .w{ filter:none; }  /* skip blur cost on lite */

/* ---- char rise ---- */
html.js .md-chars .c{
  opacity:0; transform:translateY(.55em);
  transition: opacity .45s var(--md-ease,cubic-bezier(.22,.61,.2,1)),
              transform .45s var(--md-ease,cubic-bezier(.22,.61,.2,1));
  transition-delay: calc(var(--i,0) * 28ms);
}
html.js .md-chars.in .c{ opacity:1; transform:none; }

/* ---- outline → ink fill ---- */
.md-outline{
  color:transparent;
  -webkit-text-stroke:1.5px var(--wf-line,#98A1AE);
  background:linear-gradient(90deg, var(--wf-fill,#111823) 50%, transparent 50%);
  background-size:200% 100%; background-position:100% 0;
  -webkit-background-clip:text; background-clip:text;
}
html.js .md-outline.in{
  transition: background-position 1.1s var(--md-ease,cubic-bezier(.22,.61,.2,1)) .15s;
  background-position:0 0;
}

/* ---- perpetual letter wave (accent word) ---- */
:root[data-motion="full"] .md-letterwave.in .c{
  animation: md-lw var(--lw-dur,3.2s) ease-in-out infinite;
  animation-delay: calc(var(--i,0) * .12s + .8s);
}
@keyframes md-lw{
  0%,72%,100%{ transform:translateY(0); }
  84%{ transform:translateY(calc(-1 * var(--lw-amp,.14em))); }
}

/* ---- reduced motion: everything lands instantly, no wave ---- */
@media (prefers-reduced-motion: reduce){
  html.js .md-words .w, html.js .md-chars .c{
    opacity:1; transform:none; filter:none; transition:none;
  }
  .md-outline{ color:var(--wf-fill,#111823); -webkit-text-stroke:0;
    background:none; -webkit-background-clip:border-box; background-clip:border-box; }
  .md-letterwave .c{ animation:none !important; }
}
:root[data-motion="off"] .md-words .w, :root[data-motion="off"] .md-chars .c{
  opacity:1; transform:none; filter:none; transition:none;
}

/* ===== frames.css ===== */
/* premium-motion : living frames  (yewho-web-effects 2.2, Phase 8)
   Pair with frames.js (only .md-corners needs it, for the on-view trigger).

     .md-border   — rotating conic-gradient border. The element MUST have its own
                    solid background (the gradient sits behind it, showing only at
                    the edge). Radius is inherited. Tune:
                      --mdb-c1 (bright stop, def brand red)
                      --mdb-c2 (dim stop),  --mdb-dur (spin, def 4.5s), --mdb-w (edge, def 1.6px)
                    Add .glow for a soft blurred halo of the same gradient.
     .md-corners  — corner brackets (top-left + bottom-right) that draw in on view.
                    Tune: --mdc-c (color), --mdc-s (size, def 26px).
     .md-underglow— soft brand glow beneath the element; breathes on full tier.
                    Tune: --mdg-c (color).

   All perpetual loops stop under data-motion lite/off and reduced motion.
   ============================================================ */

/* ---- rotating gradient border ----
   Double-background technique (robust, no z-index games): the surface color paints
   over padding-box, the conic gradient shows only through the transparent border ring.
   IMPORTANT: the element's own background comes from --mdb-bg (default white) —
   set --mdb-bg to match your card color (e.g. --mdb-bg:#16202E on navy cards). */
@property --mdb-a { syntax:'<angle>'; initial-value:0deg; inherits:false; }
.md-border{
  position:relative;
  border:var(--mdb-w,1.6px) solid transparent;
  background:
    linear-gradient(var(--mdb-bg,#fff), var(--mdb-bg,#fff)) padding-box,
    conic-gradient(from var(--mdb-a,0deg),
      var(--mdb-c1,#C8102E) 0%,  var(--mdb-c2,rgba(200,16,46,.12)) 22%,
      var(--mdb-c2,rgba(200,16,46,.12)) 46%, var(--mdb-c1,#C8102E) 50%,
      var(--mdb-c2,rgba(200,16,46,.12)) 72%, var(--mdb-c2,rgba(200,16,46,.12)) 96%,
      var(--mdb-c1,#C8102E) 100%) border-box;
  animation: md-border-spin var(--mdb-dur,4.5s) linear infinite;
}
/* optional soft halo. NOTE: sits at z-index:-1 — if an opaque section background
   swallows it, give that section position:relative;z-index:0 so the halo paints
   just behind the card instead. */
.md-border.glow::after{
  content:""; position:absolute; inset:-2px; z-index:-1;
  border-radius:inherit; pointer-events:none;
  background:conic-gradient(from var(--mdb-a,0deg),
    var(--mdb-c1,#C8102E), transparent 30%, transparent 70%, var(--mdb-c1,#C8102E));
  filter:blur(14px); opacity:.35;
  animation: md-border-spin var(--mdb-dur,4.5s) linear infinite;
}
@keyframes md-border-spin{ to{ --mdb-a:360deg; } }

/* ---- corner brackets, draw in on view (transform-only) ---- */
.md-corners{ position:relative; }
.md-corners::before,.md-corners::after{
  content:""; position:absolute; width:var(--mdc-s,26px); height:var(--mdc-s,26px);
  pointer-events:none; opacity:0; transform:scale(.4);
  transition: transform .55s cubic-bezier(.22,.61,.2,1), opacity .4s cubic-bezier(.22,.61,.2,1);
}
.md-corners::before{ top:-3px; left:-3px; transform-origin:top left;
  border-top:2.5px solid var(--mdc-c,#C8102E); border-left:2.5px solid var(--mdc-c,#C8102E);
  border-top-left-radius:8px; }
.md-corners::after{ bottom:-3px; right:-3px; transform-origin:bottom right;
  border-bottom:2.5px solid var(--mdc-c,#C8102E); border-right:2.5px solid var(--mdc-c,#C8102E);
  border-bottom-right-radius:8px; }
.md-corners.in::before,.md-corners.in::after{ opacity:1; transform:scale(1); }
.md-corners.in:hover::before{ transform:scale(1) translate(-3px,-3px); }
.md-corners.in:hover::after{ transform:scale(1) translate(3px,3px); }
[data-motion="off"] .md-corners::before,[data-motion="off"] .md-corners::after{ opacity:1; transform:none; transition:none; }

/* ---- underglow ---- */
.md-underglow{ box-shadow:0 14px 40px -12px var(--mdg-c,rgba(200,16,46,.35)); }
.md-underglow.breathe{ animation: md-underglow 5s ease-in-out infinite; }
@keyframes md-underglow{
  0%,100%{ box-shadow:0 14px 40px -12px var(--mdg-c,rgba(200,16,46,.28)); }
  50%    { box-shadow:0 18px 52px -10px var(--mdg-c,rgba(200,16,46,.5)); }
}

/* ---- governor / reduced-motion ---- */
:root[data-motion="lite"] .md-border, :root[data-motion="off"] .md-border,
:root[data-motion="lite"] .md-border.glow::after, :root[data-motion="off"] .md-border.glow::after,
:root[data-motion="lite"] .md-underglow.breathe, :root[data-motion="off"] .md-underglow.breathe{ animation:none; }
@media (prefers-reduced-motion: reduce){
  .md-border,.md-border.glow::after,.md-underglow.breathe{ animation:none; }
  .md-corners::before,.md-corners::after{ opacity:1; transform:none; transition:none; }
}

/* ===== gridglow.css ===== */
/* premium-motion : collective border glow  (yewho-web-effects 2.3, Phase 9)
   Pairs with gridglow.js. Move the cursor over a card GRID and a soft glow
   travels along the borders of every nearby card — one shared light source,
   not per-card hover (the "Linear grid" look).

   Markup: add .md-gridglow to the GRID, nothing to the cards:
     <div class="grid md-gridglow" style="--gg-c:rgba(200,16,46,.85)">
       <div class="card">…</div> …
     </div>
   Cards need a border-radius for the ring to follow (inherit handles it).
   Tune: --gg-c (glow colour), --gg-r (reach, def 240px).
   Fine pointers + full tier only; elsewhere it's simply inert.
   ============================================================ */
@media (hover:hover) and (pointer:fine){
  .md-gridglow > *{ position:relative; }
  .md-gridglow > *::after{
    content:""; position:absolute; inset:-1px; border-radius:inherit; padding:1px;
    background: radial-gradient(var(--gg-r,240px) circle at var(--gx,-999px) var(--gy,-999px),
                var(--gg-c,rgba(200,16,46,.85)), transparent 70%);
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor; mask-composite: exclude;
    pointer-events:none; opacity:0;
    transition: opacity .35s var(--md-ease,cubic-bezier(.22,.61,.2,1));
  }
  .md-gridglow.gg-on > *::after{ opacity:1; }
  /* optional soft interior wash on the card actually under the cursor */
  .md-gridglow.wash > *::before{
    content:""; position:absolute; inset:0; border-radius:inherit; pointer-events:none;
    background: radial-gradient(calc(var(--gg-r,240px) * .8) circle at var(--gx,-999px) var(--gy,-999px),
                color-mix(in srgb, var(--gg-c,rgba(200,16,46,.85)) 10%, transparent), transparent 72%);
    opacity:0; transition: opacity .35s var(--md-ease,cubic-bezier(.22,.61,.2,1));
  }
  .md-gridglow.wash.gg-on > *::before{ opacity:1; }
}
:root[data-motion="lite"] .md-gridglow > *::after,
:root[data-motion="off"]  .md-gridglow > *::after,
:root[data-motion="lite"] .md-gridglow > *::before,
:root[data-motion="off"]  .md-gridglow > *::before{ display:none; }

/* ===== gridbeams.css ===== */
/* premium-motion : grid beams backdrop  (yewho-web-effects 2.3, Phase 9)  CSS-ONLY
   A faint blueprint grid with light pulses that occasionally travel along its
   lines (the "infrastructure at work" backdrop). Works on light OR dark
   sections — set the vars.

   Markup (host must be position:relative + overflow:hidden — the class does it):
     <section class="md-gridbeams">
       <i class="gb h" style="--y:25%; --d:0s"></i>
       <i class="gb h" style="--y:75%; --d:3.4s"></i>
       <i class="gb v" style="--x:30%; --d:1.6s"></i>
       <i class="gb v" style="--x:70%; --d:5.1s"></i>
       …content (z-index:1 it yourself if needed)…
     </section>
   Tune: --gb-gap (cell size), --gb-line (grid colour), --gb-c (beam colour),
   --gb-dur (travel time, def 7s). Align --y/--x to multiples of --gb-gap for
   beams that ride exactly on a line. Full tier only; grid stays, beams stop.
   ============================================================ */
.md-gridbeams{ position:relative; overflow:hidden;
  background-image:
    linear-gradient(var(--gb-line,rgba(152,161,174,.16)) 1px, transparent 1px),
    linear-gradient(90deg, var(--gb-line,rgba(152,161,174,.16)) 1px, transparent 1px);
  background-size: var(--gb-gap,56px) var(--gb-gap,56px); }
.md-gridbeams > .gb{ position:absolute; pointer-events:none; display:block; }

.md-gridbeams > .gb.h{ top:var(--y,30%); left:-260px; width:240px; height:1px;
  background:linear-gradient(90deg, transparent, var(--gb-c,rgba(200,16,46,.75)) 55%, transparent); }
.md-gridbeams > .gb.v{ left:var(--x,30%); top:-260px; height:240px; width:1px;
  background:linear-gradient(180deg, transparent, var(--gb-c,rgba(200,16,46,.75)) 55%, transparent); }

@media (prefers-reduced-motion: no-preference){
  :root[data-motion="full"] .md-gridbeams > .gb.h{
    animation: md-gbx var(--gb-dur,7s) linear var(--d,0s) infinite; }
  :root[data-motion="full"] .md-gridbeams > .gb.v{
    animation: md-gby var(--gb-dur,7s) linear var(--d,0s) infinite; }
}
/* travel past any sane section width/height, then rest until the next lap */
@keyframes md-gbx{ 0%{ transform:translateX(0); } 62%,100%{ transform:translateX(calc(100vw + 520px)); } }
@keyframes md-gby{ 0%{ transform:translateY(0); } 62%,100%{ transform:translateY(120vh); } }

/* ===== hover.css ===== */
/* premium-motion : hover FX pack  (premium-motion 2.0, Phase 5)
   "Mouse-over" micro-delights. Most are pure CSS; .md-dir needs hover.js.
   All gated to @media(hover:hover) so touch devices are unaffected.
     .md-dir (+ .md-dir-fill child) — fill enters from the edge the cursor crosses
     .md-hzoom (+ .md-hcap child)   — image zooms, caption slides up on hover
     .md-link                       — animated underline sweep on a link
     .md-shine                      — glossy light sweep across a button/card
     .md-glow                       — soft brand glow on hover
     .md-swap (.a + .b children)    — old text slides up, new slides in
   ============================================================ */
@media (hover:hover){

  /* direction-aware fill */
  .md-dir{ position:relative; overflow:hidden; isolation:isolate; }
  .md-dir > *{ position:relative; z-index:1; }
  .md-dir-fill{ position:absolute; inset:0; z-index:0; background:var(--red,#C8102E);
    transform: translate(var(--dx,0), var(--dy,101%)); transition: transform .32s cubic-bezier(.22,.61,.2,1); }

  /* image hover-zoom + caption */
  .md-hzoom{ position:relative; overflow:hidden; }
  .md-hzoom img,.md-hzoom .bg{ transition: transform .55s cubic-bezier(.22,.61,.2,1); will-change:transform; }
  .md-hzoom:hover img,.md-hzoom:hover .bg{ transform: scale(1.08); }
  .md-hcap{ position:absolute; left:0; right:0; bottom:0; padding:16px; color:#fff;
    background:linear-gradient(transparent, rgba(17,24,35,.85)); transform: translateY(30%); opacity:0;
    transition: transform .4s cubic-bezier(.22,.61,.2,1), opacity .4s; }
  .md-hzoom:hover .md-hcap{ transform: translateY(0); opacity:1; }

  /* animated underline sweep */
  .md-link{ background-image: linear-gradient(currentColor, currentColor);
    background-repeat:no-repeat; background-position: left 100%; background-size: 0% 2px;
    transition: background-size .3s cubic-bezier(.22,.61,.2,1); text-decoration:none; padding-bottom:1px; }
  .md-link:hover{ background-size: 100% 2px; }

  /* glossy shine sweep */
  .md-shine{ position:relative; overflow:hidden; }
  .md-shine::after{ content:""; position:absolute; inset:0; pointer-events:none;
    background:linear-gradient(120deg, transparent 30%, rgba(255,255,255,.5) 50%, transparent 70%);
    transform: translateX(-130%); transition: transform .6s cubic-bezier(.22,.61,.2,1); }
  .md-shine:hover::after{ transform: translateX(130%); }

  /* brand glow */
  .md-glow{ transition: box-shadow .3s, transform .3s; }
  .md-glow:hover{ box-shadow: 0 0 0 4px var(--glow-ring,rgba(200,16,46,.14)), 0 12px 34px var(--glow-c,rgba(200,16,46,.22)); }

  /* text swap */
  .md-swap{ position:relative; display:inline-grid; overflow:hidden; line-height:1.15; }
  .md-swap .a,.md-swap .b{ grid-area:1/1; transition: transform .32s cubic-bezier(.22,.61,.2,1); }
  .md-swap .b{ transform: translateY(110%); }
  .md-swap:hover .a{ transform: translateY(-110%); }
  .md-swap:hover .b{ transform: translateY(0); }
}

/* ===== modern.css ===== */
/* premium-motion : modern CSS engine pack  (yewho-web-effects 2.3, Phase 9)
   Zero-JS effects unlocked by 2024+ CSS. EVERYTHING here is wrapped in
   @supports / @media guards — older browsers simply get the static state.

     .md-pop        — entry/exit animation for [popover] & <dialog> via
                      @starting-style (open: rises in; close: settles out)
     details.md-acc — accordion whose height:auto ANIMATES (interpolate-size);
                      no JS height measuring ever again
     .md-path       — a glowing dot that endlessly runs around the element's own
                      border (offset-path: border-box; follows border-radius!)
                      Tune: --path-c, --path-dur (def 7s), --path-size (def 8px)
     .md-hoverdim   — hover one child, the SIBLINGS dim + shrink slightly
                      (pure :has()) — the "focus what I point at" grid
     .md-focusdim   — same but keyboard/:focus-within driven (forms, menus)

   Easing tokens (linear() — gentle settle, ≤0.6% overshoot, still "no bounce"):
     --ease-settle  — for entrances that should land with weight
     --ease-glide   — long decelerating glide for large travels
   ============================================================ */

:root{
  --md-ease: cubic-bezier(.22,.61,.2,1);
}
@supports (transition-timing-function: linear(0, 1)){
  :root{
    --ease-settle: linear(0, .38 18%, .74 36%, .93 54%, 1.006 76%, 1);
    --ease-glide:  linear(0, .55 22%, .84 44%, .96 66%, .995 84%, 1);
  }
}

/* ---- popover / dialog entrance (@starting-style) ----------------------- */
@supports (transition-behavior: allow-discrete){
  .md-pop{
    opacity:1; transform:translateY(0) scale(1);
    transition: opacity .3s var(--md-ease), transform .3s var(--md-ease),
                display .3s allow-discrete, overlay .3s allow-discrete;
  }
  .md-pop:not(:popover-open):not([open]){ opacity:0; transform:translateY(10px) scale(.985); }
  @starting-style{
    .md-pop:popover-open, dialog.md-pop[open]{ opacity:0; transform:translateY(10px) scale(.985); }
  }
  dialog.md-pop::backdrop{
    background:rgba(17,24,35,.45); backdrop-filter:blur(3px);
    transition: opacity .3s var(--md-ease), display .3s allow-discrete, overlay .3s allow-discrete;
  }
  @starting-style{ dialog.md-pop[open]::backdrop{ opacity:0; } }
  @media (prefers-reduced-motion: reduce){
    .md-pop, dialog.md-pop::backdrop{ transition-duration:1ms; }
  }
}

/* ---- animating accordion (height: auto tween) --------------------------- */
@supports (interpolate-size: allow-keywords) {
  details.md-acc{ interpolate-size: allow-keywords; }
  details.md-acc::details-content{
    height:0; overflow:clip; opacity:0;
    transition: height .42s var(--md-ease), opacity .35s var(--md-ease),
                content-visibility .42s allow-discrete;
  }
  details.md-acc[open]::details-content{ height:auto; opacity:1; }
  @media (prefers-reduced-motion: reduce){
    details.md-acc::details-content{ transition-duration:1ms; }
  }
}
details.md-acc > summary{ cursor:pointer; list-style:none; }
details.md-acc > summary::-webkit-details-marker{ display:none; }
details.md-acc > summary .md-acc-chev{ display:inline-block; transition:transform .3s var(--md-ease); }
details.md-acc[open] > summary .md-acc-chev{ transform:rotate(180deg); }

/* ---- border runner (offset-path around the element's own edge) --------- */
@supports (offset-path: border-box){
  .md-path{ position:relative; }
  .md-path::after{
    content:""; position:absolute; z-index:1; pointer-events:none;
    width:var(--path-size,8px); height:var(--path-size,8px); border-radius:50%;
    background:var(--path-c,#C8102E);
    box-shadow:0 0 10px 2px color-mix(in srgb, var(--path-c,#C8102E) 55%, transparent);
    offset-path: border-box; offset-anchor: 50% 50%;
    animation: md-path var(--path-dur,7s) linear infinite;
  }
  /* a soft comet tail — second, dimmer dot slightly behind */
  .md-path.tail::before{
    content:""; position:absolute; z-index:1; pointer-events:none;
    width:calc(var(--path-size,8px) * .62); height:calc(var(--path-size,8px) * .62);
    border-radius:50%; background:var(--path-c,#C8102E); opacity:.35; filter:blur(1px);
    offset-path: border-box; offset-anchor: 50% 50%;
    animation: md-path var(--path-dur,7s) linear infinite;
    animation-delay: calc(var(--path-dur,7s) / -60);
  }
  @keyframes md-path{ from{ offset-distance:0%; } to{ offset-distance:100%; } }
  :root[data-motion="lite"] .md-path::after, :root[data-motion="lite"] .md-path.tail::before,
  :root[data-motion="off"]  .md-path::after, :root[data-motion="off"]  .md-path.tail::before{
    animation:none; display:none;
  }
  @media (prefers-reduced-motion: reduce){
    .md-path::after,.md-path.tail::before{ animation:none; display:none; }
  }
}

/* ---- hover-dim group (:has) --------------------------------------------- */
@media (hover:hover){
  .md-hoverdim > *{ transition: opacity .32s var(--md-ease), transform .32s var(--md-ease),
                    filter .32s var(--md-ease); }
  .md-hoverdim:has(> :hover) > :not(:hover){ opacity:.45; }
  @media (prefers-reduced-motion: no-preference){
    .md-hoverdim:has(> :hover) > :not(:hover){ transform:scale(.985); }
  }
}

/* ---- focus-dim group (keyboard equivalent) ------------------------------ */
.md-focusdim > *{ transition: opacity .32s var(--md-ease); }
.md-focusdim:has(> :focus-within) > :not(:focus-within){ opacity:.5; }

/* ===== reveal.css ===== */
/* premium-motion : reveal variants  (premium-motion 2.0, Phase 5)
   Entrance variants beyond the core fade-up. Pair with reveal.js (adds .in on view).
   Combine one base with one variant class:
     <div class="md-rv zoom">…</div>   scale-in
     <div class="md-rv blur">…</div>   blur-in
     <div class="md-rv flip">…</div>   3D flip-in
     <div class="md-rv rot">…</div>    tilt-in
     <div class="md-rv mask">…</div>   clip-path mask-up
     <div class="md-rv left|right|rise">…</div>  directional slide
   Respects data-stagger on the parent (reveal.js reads --d like the core engine).
   ============================================================ */
.md-rv{ opacity:0; transition: opacity .7s cubic-bezier(.22,.61,.2,1), transform .7s cubic-bezier(.22,.61,.2,1), filter .7s cubic-bezier(.22,.61,.2,1), clip-path .7s cubic-bezier(.22,.61,.2,1); transition-delay: var(--d,0ms); }
.md-rv.in{ opacity:1; transform:none; filter:none; }

.md-rv.zoom { transform: scale(.9); }
.md-rv.blur { filter: blur(14px); }
.md-rv.rise { transform: translateY(42px); }
.md-rv.left { transform: translateX(-42px); }
.md-rv.right{ transform: translateX(42px); }
.md-rv.rot  { transform: rotate(-4deg) translateY(30px); transform-origin: left bottom; }
.md-rv.flip { transform: perspective(900px) rotateX(-38deg); transform-origin: center bottom; }
.md-rv.mask { opacity:1; clip-path: inset(0 0 100% 0); }
.md-rv.mask.in{ clip-path: inset(0 0 0 0); }

[data-motion="off"] .md-rv{ opacity:1 !important; transform:none !important; filter:none !important; clip-path:none !important; }

/* ===== flipcard.css ===== */
/* premium-motion : flip cards  (premium-motion 2.0, Phase 5)
   3D card that flips to reveal a back face. Pair with flipcard.js for click mode.
     <div class="md-flip"><div class="md-flip-inner">
       <div class="md-flip-front">…</div><div class="md-flip-back">…</div>
     </div></div>
   Add data-click for click-to-flip instead of hover. Add .y for horizontal axis (default).
   ============================================================ */
.md-flip{ perspective:1200px; }
.md-flip-inner{ position:relative; transform-style:preserve-3d; transition: transform .7s cubic-bezier(.22,.61,.2,1); }
.md-flip:not([data-click]):hover .md-flip-inner,
.md-flip.flipped .md-flip-inner{ transform: rotateY(180deg); }
.md-flip.x:not([data-click]):hover .md-flip-inner,
.md-flip.x.flipped .md-flip-inner{ transform: rotateX(180deg); }
.md-flip-front,.md-flip-back{ backface-visibility:hidden; -webkit-backface-visibility:hidden; }
.md-flip-back{ position:absolute; inset:0; transform: rotateY(180deg); }
.md-flip.x .md-flip-back{ transform: rotateX(180deg); }
@media (prefers-reduced-motion: reduce){ .md-flip-inner{ transition:none; } }
[data-motion="off"] .md-flip:hover .md-flip-inner{ transform:none; }

/* ===== cinema.css ===== */
/* premium-motion : image cinema  (premium-motion 2.0, Phase 3)
   Pair with cinema.js (which adds .in on view for wipe/blur-up).
     .md-wipe      — clip-path reveal on view
     .md-blurup    — blurred → sharp on view (or on <img> load)
     .md-kenburns  — slow, subconscious zoom/drift (ambient; full tier)
     .md-duo       — duotone/greyscale → full colour on hover
   Works on <img>, background boxes, or any block.
   ============================================================ */
.md-wipe{ clip-path: inset(0 100% 0 0); }
.md-wipe.in{ transition: clip-path .9s cubic-bezier(.22,.61,.2,1); clip-path: inset(0 0 0 0); }

.md-blurup{ filter: blur(16px); transform: scale(1.03); }
.md-blurup.in{ transition: filter .8s ease, transform .8s ease; filter: blur(0); transform: none; }

.md-duo{ filter: grayscale(1) contrast(1.05); transition: filter .5s ease; }
@media (hover:hover){ .md-duo:hover{ filter: grayscale(0) contrast(1); } }

.md-kenburns{ overflow:hidden; }
.md-kenburns > *{ transform-origin:center; }
@media (prefers-reduced-motion: no-preference){
  :root[data-motion="full"] .md-kenburns > img,
  :root[data-motion="full"] .md-kenburns > .kb{ animation: md-kb 20s ease-in-out infinite alternate; }
  @keyframes md-kb{ from{ transform:scale(1) translate(0,0) } to{ transform:scale(1.12) translate(-2%,-2%) } }
}

[data-motion="off"] .md-wipe{ clip-path:none !important; }
[data-motion="off"] .md-blurup{ filter:none !important; transform:none !important; }

/* --- scroll-scrubbed image sequence (opt-in; needs frame images) --------
   <div class="md-sequence" data-frames="120" data-src="/frames/f-{n}.jpg"></div>
   cinema.js paints the frame matching scroll progress onto a <canvas>. -------- */
.md-sequence{ position:relative; }
.md-sequence canvas{ width:100%; height:auto; display:block; }

/* ===== loops.css ===== */
/* premium-motion : perpetual loop pack  (yewho-web-effects 2.2, Phase 8)
   CSS-only ambient loops — no JS needed. Complements .md-beat (scene.css) and
   .md-float (scene.js). Keep them SLOW and quiet: these are sub-conscious cues.

     .md-ring    — pulse rings emanating from the element's edge (CTA / live dot /
                   avatar). Radius is inherited, so it works on pills and circles.
                   Tune: --ring-c (color), --ring-dur (def 2.6s), --ring-s (spread, def 1.35)
     .md-breathe — soft glow that swells and settles (box-shadow; small area only).
                   Tune: --breathe-c, --breathe-dur (def 4.5s)
     .md-sway    — gentle pendulum rotate for icons / badges hanging from their top.
                   Tune: --sway-a (def 2.4deg), --sway-dur (def 5s)
     .md-blink   — status-dot blink (the classic REC dot). Tune: --blink-dur (def 1.5s)

   Stagger any of them across siblings with style="--d:.2s" like md-beat.
   All stop under data-motion lite/off and prefers-reduced-motion.
   ============================================================ */

/* ---- emanating pulse rings ---- */
.md-ring{ position:relative; }
.md-ring::before,.md-ring::after{
  content:""; position:absolute; inset:0; border-radius:inherit; pointer-events:none;
  border:2px solid var(--ring-c,rgba(200,16,46,.55)); opacity:0;
  animation: md-ring var(--ring-dur,2.6s) cubic-bezier(.22,.61,.2,1) var(--d,0s) infinite;
}
.md-ring::after{ animation-delay: calc(var(--d,0s) + var(--ring-dur,2.6s) / 2); }
@keyframes md-ring{
  0%{ transform:scale(1); opacity:.65; }
  100%{ transform:scale(var(--ring-s,1.35)); opacity:0; }
}

/* ---- glow breathe ---- */
.md-breathe{ animation: md-breathe var(--breathe-dur,4.5s) ease-in-out var(--d,0s) infinite; }
@keyframes md-breathe{
  0%,100%{ box-shadow:0 0 0 0 rgba(200,16,46,0); }
  50%    { box-shadow:0 0 26px 2px var(--breathe-c,rgba(200,16,46,.32)); }
}

/* ---- pendulum sway ---- */
.md-sway{ transform-origin:50% -4px; display:inline-block;
  animation: md-sway var(--sway-dur,5s) ease-in-out var(--d,0s) infinite; }
@keyframes md-sway{
  0%,100%{ transform:rotate(calc(-1 * var(--sway-a,2.4deg))); }
  50%    { transform:rotate(var(--sway-a,2.4deg)); }
}

/* ---- status blink ---- */
.md-blink{ animation: md-blink var(--blink-dur,1.5s) ease-in-out var(--d,0s) infinite; }
@keyframes md-blink{ 0%,100%{ opacity:1; } 50%{ opacity:.25; } }

/* ---- governor / reduced-motion ---- */
:root[data-motion="lite"] .md-ring::before, :root[data-motion="off"] .md-ring::before,
:root[data-motion="lite"] .md-ring::after,  :root[data-motion="off"] .md-ring::after,
:root[data-motion="lite"] .md-breathe,      :root[data-motion="off"] .md-breathe,
:root[data-motion="lite"] .md-sway,         :root[data-motion="off"] .md-sway,
:root[data-motion="lite"] .md-blink,        :root[data-motion="off"] .md-blink{ animation:none; }
@media (prefers-reduced-motion: reduce){
  .md-ring::before,.md-ring::after,.md-breathe,.md-sway,.md-blink{ animation:none; }
}

/* ===== type.css ===== */
/* premium-motion : kinetic typography  (premium-motion 2.0, Phase 2)
   Pair with type.js. All effects are opt-in via class and reduced-motion safe
   (type.js prints final text / final weight when motion is off).
   ============================================================ */

/* --- odometer digit roll (data-odometer) ------------------------------- */
.odm{ display:inline-flex; align-items:flex-start; font-variant-numeric:tabular-nums; line-height:1; }
.odm-d{ display:inline-block; height:1em; overflow:hidden; }
.odm-reel{ display:flex; flex-direction:column; transform:translateY(0);
           transition:transform 1.15s cubic-bezier(.22,.61,.2,1); will-change:transform; }
.odm-reel > span{ height:1em; display:block; }
.odm-sep{ display:inline-block; }

/* --- gradient shimmer sweep on a phrase (.md-shimmer) ------------------ */
/* readable at every tier; the clip/transparent treatment only under full + motion */
.md-shimmer{ color: var(--red,#C8102E); }
@media (prefers-reduced-motion: no-preference){
  :root[data-motion="full"] .md-shimmer{
    background:linear-gradient(100deg, var(--red-dark,#9c0c24) 0 42%, var(--shimmer-hi,#ff5470) 50%, var(--red-dark,#9c0c24) 58% 100%);
    background-size:250% 100%;
    -webkit-background-clip:text; background-clip:text; color:transparent;
    animation: pm-shimmer 5.5s ease-in-out 1.2s infinite;
  }
  @keyframes pm-shimmer{ 0%,100%{background-position:120% 0} 45%,55%{background-position:-20% 0} }
}

/* --- variable-font weight morph on view (.md-weight) ------------------- */
.md-weight{ font-variation-settings:'wght' 340; transition: font-variation-settings .9s cubic-bezier(.22,.61,.2,1); }
.md-weight.in{ font-variation-settings:'wght' 760; }
[data-motion="off"] .md-weight{ font-variation-settings:'wght' 700; transition:none; }

/* --- decode / scramble (.md-decode) ------------------------------------ */
.md-decode{ white-space:pre-wrap; }

/* ===== typewriter.css ===== */
/* yewho typewriter — styles for typewriter.js. Ship both together. */
.tw-a11y{ position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0; }
.tw-vis{ display:inline; }
.tw-vis::after{ content:""; display:inline-block; width:.06em; min-width:2px;
  height:1.05em; background:currentColor; margin-left:.06em; vertical-align:-.12em;
  animation:tw-caret 1s steps(1) infinite; }
@keyframes tw-caret{ 50%{ opacity:0; } }
@media (prefers-reduced-motion:reduce){ .tw-vis::after{ display:none; } }

/* ===== tilt.css ===== */
/* premium-motion : dimensional cards  (premium-motion 2.0, Phase 3)
   Pointer-driven 3D tilt with in-card parallax layers and a specular glare.
   Pair with tilt.js. Fine-pointer + full-tier only; degrades to a flat card.
     <article class="md-tilt" data-tilt="8">
       <div class="md-tilt-layer" style="--z:40px">…floats above…</div>
       …base content…
     </article>
   ============================================================ */
.md-tilt{
  transform: perspective(900px) rotateX(var(--rx,0deg)) rotateY(var(--ry,0deg));
  transform-style: preserve-3d;
  transition: transform .3s cubic-bezier(.22,.61,.2,1);
  position: relative; will-change: transform;
}
.md-tilt-layer{
  transform: translate3d(var(--px,0), var(--py,0), var(--z,30px));
  transition: transform .3s cubic-bezier(.22,.61,.2,1);
}
.md-tilt::after{
  content:""; position:absolute; inset:0; border-radius:inherit; pointer-events:none;
  background: radial-gradient(300px circle at var(--gx,50%) var(--gy,50%), rgba(255,255,255,.4), transparent 60%);
  opacity:0; transition: opacity .3s; mix-blend-mode: overlay; z-index:2;
}
.md-tilt:hover::after{ opacity:1; }
@media (prefers-reduced-motion: reduce){ .md-tilt,.md-tilt-layer{ transform:none !important; transition:none; } }
:root[data-motion="lite"] .md-tilt,:root[data-motion="off"] .md-tilt{ transform:none !important; }

/* ===== fx-brand.css ===== */
/* ==========================================================================
   yewho-web-effects — SPT Maju brand theme
   --------------------------------------------------------------------------
   The effects library ships themed for the SyncTech house red. SPT Maju is
   locked to the customer's four colours, so every effect token is remapped
   here to navy / light blue. Load AFTER the module CSS.

   Locked palette:  #4E6981 navy · #A0C9EE light blue · #FFFFFF · #313131
   ========================================================================== */
:root{
  /* --- frames.css --------------------------------------------------------- */
  --mdc-c:#A0C9EE;                      /* corner brackets */
  --mdg-c:rgba(160,201,238,.42);        /* underglow */
  --mdb-c1:#A0C9EE;                     /* rotating border — bright stop */
  --mdb-c2:rgba(78,105,129,.14);        /* rotating border — dim stop */
  --mdb-bg:#fff;                        /* rotating border — card bg behind it */

  /* --- loops.css ---------------------------------------------------------- */
  --breathe-c:rgba(160,201,238,.34);
  --ring-c:rgba(160,201,238,.5);

  /* --- gridglow.css ------------------------------------------------------- */
  --gg-c:rgba(160,201,238,.9);

  /* --- gridbeams.css (used on the dark navy band) ------------------------- */
  --gb-c:rgba(160,201,238,.85);
  --gb-line:rgba(255,255,255,.11);

  /* --- props.css ---------------------------------------------------------- */
  --mc-c1:#A0C9EE;
  --mc-c2:rgba(78,105,129,.12);

  /* --- wordfx.css --------------------------------------------------------- */
  --wf-fill:#4E6981;                    /* outline headline ink */
  --wf-line:#C3D0DD;                    /* outline headline stroke */

  /* --- svgfx.css ---------------------------------------------------------- */
  --mark-c:rgba(160,201,238,.30);       /* highlighter sweep */

  /* --- modern.css --------------------------------------------------------- */
  --path-c:#A0C9EE;                     /* border runner dot */

  /* --- hover.css (patched to accept tokens) ------------------------------- */
  --glow-ring:rgba(160,201,238,.22);
  --glow-c:rgba(51,72,92,.20);

  /* The library's generic accent token. It normally comes from motion.css,
     which we deliberately do NOT load (its :root would overwrite --body,
     --navy, --ink and break the site's fonts and palette). Define it here so
     nothing can fall back to the house red. */
  --red:#A0C9EE;

  /* --- type.css (.md-shimmer) ------------------------------------------- */
  --red-dark:#4E6981;
  --shimmer-hi:#A0C9EE;
}

/* --------------------------------------------------------------------------
   Per-context adjustments
   -------------------------------------------------------------------------- */

/* Corner brackets sit on light surfaces across the site; on the navy band they
   need the lighter stop to stay visible. */
.brands .md-corners,
.site-footer .md-corners{ --mdc-c:rgba(160,201,238,.85); }

/* Word cascade: keep the step tight so headlines still read as one unit. */
.md-words{ --wf-step:52ms; }

/* Grid glow is a border light — make sure it never fights the card's own
   1px line by keeping the radius small and the falloff short. */
.md-gridglow{ --gg-r:190px; }

/* Blueprint grid backdrop: the navy band already carries the brand colour, so
   keep the grid itself faint and let only the travelling beams read. */
.md-gridbeams{ --gb-gap:52px; --gb-dur:9s; }

/* The library's shine sweep is white by default — correct on navy, too strong
   on the light-blue guarantee panel, so soften it there. */
.guar--lblue.md-shine::after{ opacity:.55; }

/* --------------------------------------------------------------------------
   Host fixes
   -------------------------------------------------------------------------- */

/* gridbeams ships as a *wrapper* (position:relative). On the brands band we
   want it as a backdrop behind existing content, so fill the section instead. */
.brands .md-gridbeams{position:absolute;inset:0;z-index:0}
.brands .wrap{position:relative;z-index:1}

/* .pd-figure and .wwd-media clip their overflow, which would cut the corner
   brackets off. Inset them so they read inside the frame. */
.pd-figure.md-corners::before,.wwd-media.md-corners::before,
.pd-viewer.md-corners::before{top:12px;left:12px}
.pd-figure.md-corners::after,.wwd-media.md-corners::after,
.pd-viewer.md-corners::after{bottom:12px;right:12px}
.pd-figure.md-corners::before,.pd-figure.md-corners::after{--mdc-c:#fff}
/* the viewer sits on a light surface, so the brackets stay light blue */
.pd-viewer.md-corners::before,.pd-viewer.md-corners::after{--mdc-c:var(--lblue)}
.pd-figure.md-corners.in:hover::before{transform:scale(1) translate(-2px,-2px)}
.pd-figure.md-corners.in:hover::after{transform:scale(1) translate(2px,2px)}

/* Underline sweep on the address blocks (footer + contact page). Kept as its
   own rule rather than tagging every anchor with .md-link. */
.md-linkset a{position:relative;display:inline-block}
.md-linkset a::after{
  content:"";position:absolute;left:0;right:100%;bottom:-1px;height:1px;
  background:currentColor;opacity:.7;
  transition:right .34s cubic-bezier(.22,.61,.2,1);
}
.md-linkset a:hover::after{right:0}

/* Grid glow needs the card to own a border for the light to ride; the service
   and capability cards use shared edges, so lift them onto their own line. */
.svc-grid.md-gridglow .svc,.cap-grid.md-gridglow .cap{position:relative}

/* --------------------------------------------------------------------------
   Brand chip flip — front: logo · back: partnership role
   The brand NAME stays outside the flip so it is always readable, and where
   there is no hover to trigger the flip the role is shown inline instead, so
   touch users never lose the content.
   -------------------------------------------------------------------------- */
.brand-chip.md-flip{perspective:1000px;background:transparent;padding:0}
.brand-chip.md-flip .md-flip-inner{width:100%;height:100%}
.brand-chip .md-flip-front,.brand-chip .md-flip-back{
  position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  background:#fff;border-radius:var(--r-sm);padding:clamp(16px,1.8vw,26px);
}
.brand-chip .md-flip-back{background:var(--lblue)}
.brand-chip .md-flip-back span{
  font-family:var(--body);font-weight:600;font-size:.86rem;line-height:1.45;
  letter-spacing:.02em;color:var(--navy-deep);text-align:center;
}
/* the flip owns the transform here, so the cell must not also translate */
.brand-cell:hover{transform:none}
@media (hover:none){
  .brand-chip.md-flip .md-flip-inner{transform:none !important}
  .brand-chip .md-flip-back{display:none}
}

/* --------------------------------------------------------------------------
   Credential strip — slow pulse ring behind each icon (ambient "live" signal)
   -------------------------------------------------------------------------- */
.cred-live .cred-ico{position:relative}
.cred-live .cred-ico::after{
  content:"";position:absolute;inset:-6px;border-radius:50%;
  border:1px solid var(--lblue);opacity:0;
}
:root[data-motion="full"] .cred-live .cred-ico::after{
  animation:cred-pulse 4.2s var(--ease,ease-out) infinite;
}
.cred-live .cred:nth-child(2) .cred-ico::after{animation-delay:1.4s}
.cred-live .cred:nth-child(3) .cred-ico::after{animation-delay:2.8s}
@keyframes cred-pulse{
  0%{transform:scale(.7);opacity:0}
  35%{opacity:.55}
  100%{transform:scale(1.5);opacity:0}
}

/* odometer suffix inherits the stat unit styling */
.hero-stats .odm-sep{color:var(--lblue);font-size:.6em;vertical-align:top;margin-left:2px}

/* blur-up must not fight the hero photo's object-fit cover */
.hero-media .md-blurup{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}

/* --------------------------------------------------------------------------
   md-hzoom on the news thumbnails
   The old `.post:hover .thumb img{transform:scale(1.04)}` is switched off in
   v3.css — md-hzoom owns that transform now, so the two cannot fight.
   -------------------------------------------------------------------------- */
.post .thumb.md-hzoom{cursor:default}
.post .md-hcap{
  position:absolute;left:0;right:0;bottom:0;z-index:2;
  padding:14px 16px;background:linear-gradient(0deg,rgba(51,72,92,.92),transparent);
  font-family:var(--body);font-weight:600;font-size:.84rem;line-height:1.35;color:#fff;
  transform:translateY(100%);opacity:0;
  transition:transform .4s var(--ease),opacity .4s var(--ease);
}
.post .thumb.md-hzoom:hover .md-hcap{transform:translateY(0);opacity:1}

/* --------------------------------------------------------------------------
   md-tilt on the about panel — it carries no other transform, so the tilt is
   free to own it. Kept shallow; this is a corporate page, not a product shot.
   -------------------------------------------------------------------------- */
.about-panel.md-tilt{transform-style:preserve-3d}
.about-panel.md-tilt img{transform:translateZ(24px)}

/* --------------------------------------------------------------------------
   Constellation backdrop on the services CTA band
   -------------------------------------------------------------------------- */
.cta-band{position:relative;overflow:hidden}
.cta-band .md-constellation{position:absolute;inset:0;z-index:0;pointer-events:none}
.cta-band .wrap{position:relative;z-index:1}

/* md-swap sits inside a flex button — keep it from breaking the baseline */
.hero-cta .md-swap,.fc-cta .md-swap{align-items:center}
.md-swap .a,.md-swap .b{white-space:nowrap}

/* --------------------------------------------------------------------------
   Card sections below the hero
   -------------------------------------------------------------------------- */

/* Client logo cards sit on white, so the library's white gloss is invisible —
   sweep a light-blue tint instead. */
.client-card.md-shine::after{
  background:linear-gradient(105deg,transparent 35%,rgba(160,201,238,.42) 50%,transparent 65%);
}
/* Service cards already change background on hover; keep the sweep subtle so the
   two read as one gesture rather than competing. */
.svc.md-shine::after{
  background:linear-gradient(105deg,transparent 38%,rgba(160,201,238,.30) 50%,transparent 62%);
}

/* Underglow on the solid navy guarantee panel. Its own :hover box-shadow wins on
   hover by specificity, which is the intent: rest = bloom, hover = lift. */
.guar--navy.md-underglow{--mdg-c:rgba(160,201,238,.38)}

/* Hover-dim on the client rail cannot fight the marquee: the library dims
   siblings with opacity, the rail animates scrollLeft — different properties. */
.rail-track.md-hoverdim .client-card{transition:opacity .3s var(--ease),border-color .3s,box-shadow .3s,transform .3s var(--ease)}

/* --------------------------------------------------------------------------
   Collision guards
   Several v4 components already animate `transform` on hover. The effects
   library warns never to stack two transform effects on one element, so the
   classes applied in the markup are deliberately shadow/border/overlay-only
   (md-shine, md-gridglow, md-corners, md-underglow). These guards make that
   explicit so a future edit can't silently reintroduce a conflict.
   -------------------------------------------------------------------------- */
.proj.md-tilt,.pd-ix.md-tilt,.client-card.md-tilt,
.guar.md-tilt,.brand-cell.md-tilt,.pd-figure.md-tilt{ transform:none !important; }

/* ===== flow.css ===== */
/* premium-motion : flow diagram scenes  (yewho-web-effects 2.1, Phase 7)
   SVG "node & wire" diagrams that feel alive — flowing energy currents,
   travelling pulses, draw-on wires, and a cascade node-pop. Pairs with flow.js.
   Extracted from the SyncTech hosting pages (gateway, ecosystem, domain→brand).

   Skeleton:
     <div class="scene"><svg class="md-draw" viewBox="0 0 W H" style="max-width:900px">
        <path class="trace" d="M…"/>                            grey wires (draw on view)
        <path class="eflow" d="M…" style="animation-delay:.1s"/> red energy current
        <path class="gflow" d="M…"/>                            green ("clean/healthy") current
        <g class="nd" style="--d:.2s"><rect rx="9"/><text/></g>  a node (cascade pop, --d = delay)
        <circle r="4" fill="#C8102E"><animateMotion dur="2.4s"    a travelling pulse
          repeatCount="indefinite" path="M…"/></circle>
     </svg></div>

   Nodes are just <g class="nd"> — style the rect/text however you like (accent, glass, ghost…).
   Cascade the pop root→leaves by giving each node a bigger --d.
   Everything is governor- and reduced-motion-safe.
   ============================================================ */

.scene svg{ width:100%; height:auto; display:block; margin-inline:auto; }
.scene .nd rect{ transition:none; }

/* ---- flowing currents (a short dash that streams along a whole path) ---- */
.scene .eflow{ fill:none; stroke:#C8102E; stroke-width:3.4; stroke-linecap:round;
  stroke-dasharray:36 460; stroke-dashoffset:36; animation:md-flow 1.6s linear infinite; }
.scene .gflow{ fill:none; stroke:#1fa971; stroke-width:3.4; stroke-linecap:round;
  stroke-dasharray:36 460; stroke-dashoffset:36; animation:md-flow 1.6s linear infinite; }
@keyframes md-flow{ to{ stroke-dashoffset:-500; } }

/* ---- cascade node-pop: each box gently pulses + red glow, root→leaves ---- */
.scene .nd{ transform-box:fill-box; transform-origin:center;
  animation:md-ndpop 2.1s ease-in-out infinite; animation-delay:var(--d,0s); }
@keyframes md-ndpop{
  0%,56%,100%{ transform:scale(1); filter:none; }
  72%{ transform:scale(1.05); filter:drop-shadow(0 0 7px var(--pop, rgba(200,16,46,.5))); }
}
@media (hover:hover){ .scene .nd:hover{ animation-play-state:paused; } }

/* ---- governor / reduced-motion ---- */
:root[data-motion="lite"] .scene .eflow, :root[data-motion="off"] .scene .eflow,
:root[data-motion="lite"] .scene .gflow, :root[data-motion="off"] .scene .gflow{ animation:none; opacity:0; }
:root[data-motion="lite"] .scene .nd,   :root[data-motion="off"] .scene .nd{ animation:none; }
@media (prefers-reduced-motion: reduce){
  .scene .eflow, .scene .gflow{ animation:none; opacity:0; }
  .scene .nd{ animation:none; }
}
