/* ============================================================
   SYSMarshal homepage — 3D & depth effects
   Loaded ONLY on the homepage (registered from Views/Home/Index.cshtml,
   paired with Content/js/sysmarshal-effects.js).

   Rules:
   - Every selector is scoped under .sm-fx so nothing bleeds site-wide.
   - Colors come from the .sm-fx custom properties (--sm-accent,
     --sm-accent-2, --sm-line, ...) via var()/color-mix() — no new palette.
   - Animations use transform/opacity only (GPU-friendly); everything
     is disabled under prefers-reduced-motion at the bottom of this file.
   To revert the whole effect layer: remove the two asset registrations
   in Index.cshtml — this file and the JS are self-contained.
   ============================================================ */

/* ------------------------------------------------------------
   1. HERO — FX layer (globe canvas + scanlines), entrance, glass console
   ------------------------------------------------------------ */
.sm-fx .sm-hero{position:relative;overflow:hidden}
.sm-fx .sm-hero-fx{
    position:absolute;inset:0;z-index:0;pointer-events:none;
    will-change:transform; /* parallax target */
}
.sm-fx .sm-hero-fx canvas{position:absolute;inset:0;width:100%;height:100%}
/* soft halo behind the globe (canvas centre is 72% / 54%) */
.sm-fx .sm-hero-fx::before{
    content:"";position:absolute;inset:0;
    background:radial-gradient(640px circle at 72% 54%,
        color-mix(in srgb, var(--sm-accent) 11%, transparent), transparent 62%);
}
/* Aurora light blobs — slow-morphing blurred colour fields behind the hero.
   filter creates one composited layer; only transform animates. */
.sm-fx .sm-aurora{
    position:absolute;width:58vw;height:58vw;max-width:880px;max-height:880px;
    border-radius:50%;filter:blur(90px);opacity:.38;
    will-change:transform;pointer-events:none;
}
.sm-fx .sm-aurora-a{
    left:-18%;top:-38%;
    background:radial-gradient(circle at 32% 32%, color-mix(in srgb, var(--sm-accent) 24%, transparent), transparent 62%);
    animation:sm-aur-a 22s ease-in-out infinite alternate;
}
.sm-fx .sm-aurora-b{
    right:-22%;bottom:-48%;
    background:radial-gradient(circle at 62% 62%, color-mix(in srgb, var(--sm-accent-2) 20%, transparent), transparent 62%);
    animation:sm-aur-b 28s ease-in-out infinite alternate;
}
@keyframes sm-aur-a{to{transform:translate3d(9vw,6vh,0) scale(1.22) rotate(18deg)}}
@keyframes sm-aur-b{to{transform:translate3d(-8vw,-5vh,0) scale(.92) rotate(-14deg)}}
/* Scanline + noise overlay — "SOC monitor" feel, plus one slow sweep band */
.sm-fx .sm-scanlines{
    position:absolute;inset:0;opacity:.55;mix-blend-mode:overlay;overflow:hidden;
    background:
      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)' opacity='.05'/%3E%3C/svg%3E"),
      repeating-linear-gradient(0deg, rgba(255,255,255,.02) 0 1px, transparent 1px 3px);
}
.sm-fx .sm-scanlines::after{
    content:"";position:absolute;left:0;right:0;top:-25%;height:20%;
    background:linear-gradient(180deg, transparent, rgba(255,255,255,.06), transparent);
    animation:sm-scan 9s linear infinite;
}
@keyframes sm-scan{to{transform:translateY(650%)}}

/* Headline entrance — staggered fade-up. Pure CSS (`backwards` fill so the
   pre-delay state is hidden, and NO lingering animation styles afterwards —
   fill:both would override the tilt module's inline transforms). */
@keyframes sm-up{from{opacity:0;transform:translateY(18px)}to{opacity:1;transform:none}}
@keyframes sm-ops-in{from{opacity:0;transform:translateY(28px) scale(.975)}to{opacity:1;transform:none}}
.sm-fx .sm-hero .sm-eyebrow{animation:sm-up .55s .05s cubic-bezier(.22,1,.36,1) backwards}
.sm-fx .sm-hero .sm-title  {animation:sm-up .65s .16s cubic-bezier(.22,1,.36,1) backwards}
.sm-fx .sm-hero .sm-lede   {animation:sm-up .65s .28s cubic-bezier(.22,1,.36,1) backwards}
.sm-fx .sm-hero .sm-cta    {animation:sm-up .65s .40s cubic-bezier(.22,1,.36,1) backwards}
.sm-fx .sm-hero .sm-trust  {animation:sm-up .65s .52s cubic-bezier(.22,1,.36,1) backwards}
.sm-fx .sm-hero .sm-ops    {animation:sm-ops-in .8s .35s cubic-bezier(.22,1,.36,1) backwards}
/* Glow sweep across the gradient words (one-shot). background-size lives
   inside the keyframes so the resting gradient keeps its original 100% stops. */
@keyframes sm-sheen{
    from{background-size:220% 100%;background-position:130% 0;filter:brightness(1.5)}
    to{background-size:100% 100%;background-position:0 0;filter:none}
}
.sm-fx h1.sm-title .accent{animation:sm-sheen 1.5s .55s ease-out backwards}

/* Live Threat Console — glassmorphism (frosted blur, gradient border ring,
   soft cyan outer glow). The tilt itself comes from data-tilt="soft". */
.sm-fx .sm-ops{
    background:linear-gradient(180deg, rgba(20,28,39,.60), rgba(16,22,31,.68));
    -webkit-backdrop-filter:blur(14px) saturate(1.25);
    backdrop-filter:blur(14px) saturate(1.25);
    border-color:transparent;
    box-shadow:
        0 30px 80px rgba(0,0,0,.55),
        0 0 70px color-mix(in srgb, var(--sm-accent) 9%, transparent),
        inset 0 1px 0 rgba(255,255,255,.05);
}

/* ------------------------------------------------------------
   2. CARDS — reusable [data-tilt] 3D module
   (JS sets the perspective/rotate transform inline and injects
   a .sm-tilt-glare layer; CSS provides the rest of the depth.)
   ------------------------------------------------------------ */
.sm-fx [data-tilt]{
    /* spring-back when the pointer leaves */
    transition:transform .55s cubic-bezier(.22,1,.36,1), box-shadow .3s ease, border-color .25s ease;
    transform-style:preserve-3d;
}
.sm-fx [data-tilt].is-tilt{transition:transform .12s ease-out, box-shadow .3s ease}
/* icons float above the card plane — needs a visible overflow + 3D chain */
.sm-fx .sm-pillar[data-tilt],
.sm-fx .sm-cap[data-tilt]{overflow:visible}
.sm-fx .sm-pillar[data-tilt]::before,
.sm-fx .sm-cap[data-tilt]::before{border-radius:2px} /* top line no longer clipped by overflow:hidden */
.sm-fx [data-tilt] .sm-pillar-top,
.sm-fx [data-tilt] .sm-cap-top{transform-style:preserve-3d}
.sm-fx .sm-pillar[data-tilt].is-tilt .icon,
.sm-fx .sm-cap[data-tilt].is-tilt .icon{transform:translateZ(26px)}
/* layered shadows on hover: tight dark + wide cyan glow */
.sm-fx .sm-pillar[data-tilt].is-tilt,
.sm-fx .sm-cap[data-tilt].is-tilt{
    box-shadow:
        0 4px 14px rgba(0,0,0,.5),
        0 28px 60px rgba(0,0,0,.45),
        0 0 44px color-mix(in srgb, var(--sm-accent) 13%, transparent);
}
/* border animates to a gradient ring (mask trick keeps just the 1px ring).
   --ring (0..1) is set by the JS cursor-proximity module, so card borders
   light up as the pointer travels across the grid — full on direct hover. */
.sm-fx [data-tilt]::after{
    content:"";position:absolute;inset:0;border-radius:inherit;padding:1px;
    background:linear-gradient(150deg,
        color-mix(in srgb, var(--sm-accent) 80%, transparent),
        transparent 40%, transparent 60%,
        color-mix(in srgb, var(--sm-accent-2) 70%, transparent));
    -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite:xor;
            mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
            mask-composite:exclude;
    opacity:var(--ring, 0);transition:opacity .2s ease;pointer-events:none;
}
.sm-fx [data-tilt]:hover::after{opacity:1}
/* Live console: always-on ring, upgraded to a slowly ROTATING conic sweep.
   @property lets the angle interpolate; unsupported browsers fall back to
   a static ring (the animation just doesn't move). */
@property --sm-rot{syntax:'<angle>';inherits:false;initial-value:0deg}
@keyframes sm-ring-rot{to{--sm-rot:360deg}}
.sm-fx .sm-ops[data-tilt]::after,
.sm-fx .sm-card.is-popular[data-tilt]::after{
    opacity:1;
    background:conic-gradient(from var(--sm-rot) at 50% 50%,
        transparent 0%,
        color-mix(in srgb, var(--sm-accent) 85%, transparent) 8%,
        color-mix(in srgb, var(--sm-accent-2) 75%, transparent) 15%,
        transparent 26%,
        transparent 52%,
        color-mix(in srgb, var(--sm-accent) 40%, transparent) 62%,
        transparent 74%);
    animation:sm-ring-rot 7s linear infinite;
}
/* glare/sheen layer injected by JS, follows the cursor via background */
.sm-fx .sm-tilt-glare{
    position:absolute;inset:0;border-radius:inherit;
    pointer-events:none;z-index:3;
}

/* ------------------------------------------------------------
   3. SCROLL-DRIVEN DEPTH — reveals + response-engine pulse
   (JS adds .sm-rv + --rv-d stagger index, then .is-in on intersect.
   Without JS the class is never added, so content stays visible.)
   ------------------------------------------------------------ */
@keyframes sm-rise{
    from{opacity:0;transform:translateY(32px) scale(.97);filter:blur(6px)}
    to{opacity:1;transform:none;filter:none}
}
.sm-fx .sm-rv{opacity:0}
.sm-fx .sm-rv.is-in{
    opacity:1;
    animation:sm-rise .7s cubic-bezier(.22,1,.36,1) backwards;
    animation-delay:calc(var(--rv-d, 0) * 85ms);
}

/* Response Engine strip — traveling glow pulse + sequential node lighting
   while on screen (JS toggles .is-live via IntersectionObserver) */
.sm-fx .sm-engine{position:relative;overflow:hidden}
.sm-fx .sm-engine::after{
    content:"";position:absolute;top:0;bottom:0;left:0;width:16%;
    pointer-events:none;opacity:0;
    background:linear-gradient(90deg, transparent,
        color-mix(in srgb, var(--sm-accent) 11%, transparent), transparent);
}
@keyframes sm-eng-sweep{
    0%{transform:translateX(-110%);opacity:0}
    8%{opacity:1}
    72%,100%{transform:translateX(720%);opacity:0}
}
.sm-fx .sm-engine.is-live::after{animation:sm-eng-sweep 3.8s ease-in-out infinite}
@keyframes sm-node-glow{
    0%,16%,100%{border-color:var(--sm-line);box-shadow:none}
    6%{border-color:color-mix(in srgb, var(--sm-accent) 65%, transparent);
       box-shadow:0 0 16px color-mix(in srgb, var(--sm-accent) 22%, transparent)}
}
.sm-fx .sm-engine.is-live .node{animation:sm-node-glow 3.8s infinite}
.sm-fx .sm-engine.is-live .node:nth-of-type(1){animation-delay:.25s}
.sm-fx .sm-engine.is-live .node:nth-of-type(2){animation-delay:.85s}
.sm-fx .sm-engine.is-live .node:nth-of-type(3){animation-delay:1.45s}
.sm-fx .sm-engine.is-live .node:nth-of-type(4){animation-delay:2.05s}
.sm-fx .sm-engine.is-live .node:nth-of-type(5){animation-delay:2.65s}
@keyframes sm-arrow-glow{0%,16%,100%{opacity:1}6%{opacity:.45}}
.sm-fx .sm-engine.is-live .step{animation:sm-arrow-glow 3.8s infinite}
.sm-fx .sm-engine.is-live .step:nth-of-type(1){animation-delay:.55s}
.sm-fx .sm-engine.is-live .step:nth-of-type(2){animation-delay:1.15s}
.sm-fx .sm-engine.is-live .step:nth-of-type(3){animation-delay:1.75s}
.sm-fx .sm-engine.is-live .step:nth-of-type(4){animation-delay:2.35s}

/* ------------------------------------------------------------
   4. AMBIENT DETAILS — spotlights, console ticks, CTA buttons
   ------------------------------------------------------------ */
/* Slow-drifting radial spotlights behind the pillar / capability sections.
   z-index:0 keeps them under .sm-container (which is already z-index:1). */
.sm-fx .sm-pillars,
.sm-fx .sm-caps{position:relative}
@keyframes sm-drift-a{from{transform:translate3d(0,0,0) scale(1)}to{transform:translate3d(7vw,5vh,0) scale(1.18)}}
@keyframes sm-drift-b{from{transform:translate3d(0,0,0) scale(1.1)}to{transform:translate3d(-6vw,-4vh,0) scale(.95)}}
.sm-fx .sm-pillars::after{
    content:"";position:absolute;left:-12%;top:-18%;z-index:0;pointer-events:none;
    width:52vw;height:52vw;max-width:860px;max-height:860px;border-radius:50%;
    background:radial-gradient(circle, color-mix(in srgb, var(--sm-accent) 7%, transparent), transparent 65%);
    animation:sm-drift-a 26s ease-in-out infinite alternate;
}
.sm-fx .sm-caps::after{
    content:"";position:absolute;right:-14%;bottom:-22%;z-index:0;pointer-events:none;
    width:56vw;height:56vw;max-width:920px;max-height:920px;border-radius:50%;
    background:radial-gradient(circle, color-mix(in srgb, var(--sm-accent-2) 6%, transparent), transparent 65%);
    animation:sm-drift-b 32s ease-in-out infinite alternate;
}

/* Console feed rows tick in (rows are prepended by the existing feed JS) */
@keyframes sm-row-in{from{opacity:0;transform:translateY(-9px)}to{opacity:1;transform:none}}
.sm-fx .sm-feed-row{animation:sm-row-in .4s cubic-bezier(.22,1,.36,1)}
/* severity badges pulse gently (opacity only — cheap) */
@keyframes sm-sev-pulse{0%,100%{opacity:1}50%{opacity:.6}}
.sm-fx .sm-feed-row .sev.crit{animation:sm-sev-pulse 2.1s ease-in-out infinite}
.sm-fx .sm-feed-row .sev.high{animation:sm-sev-pulse 3.2s ease-in-out infinite}

/* CTA buttons — gradient shift + glow bloom on hover, press-down on click */
.sm-fx .sm-btn{
    transition:transform .16s ease, box-shadow .3s ease,
               background-position .5s ease, border-color .2s ease,
               background-color .2s ease, color .2s ease;
}
.sm-fx .sm-btn:active{transform:translateY(1px) scale(.98)}
.sm-fx .sm-btn-primary{
    background-image:linear-gradient(115deg, var(--sm-accent) 0%, var(--sm-accent-2) 55%, var(--sm-accent) 100%);
    background-size:230% 100%;background-position:0% 0;
}
.sm-fx .sm-btn-primary:hover{
    background-image:linear-gradient(115deg, var(--sm-accent) 0%, var(--sm-accent-2) 55%, var(--sm-accent) 100%);
    background-size:230% 100%;background-position:98% 0;
    transform:translateY(-1px);
    box-shadow:0 6px 26px color-mix(in srgb, var(--sm-accent) 42%, transparent), 0 2px 8px rgba(0,0,0,.4);
}
.sm-fx .sm-btn-ghost:hover{
    box-shadow:0 0 22px color-mix(in srgb, var(--sm-accent) 16%, transparent);
    background:color-mix(in srgb, var(--sm-accent) 7%, transparent);
}

/* ------------------------------------------------------------
   Mobile — no globe, no spotlights (tilt/parallax already skipped in JS);
   reveals stay because they're a single cheap one-shot animation.
   ------------------------------------------------------------ */
@media (max-width:768px){
    .sm-fx .sm-hero-fx canvas{display:none}
    .sm-fx .sm-aurora{display:none}
    .sm-fx .sm-pillars::after,
    .sm-fx .sm-caps::after{display:none}
    .sm-fx .sm-scanlines{opacity:.35}
    .sm-fx .sm-ops[data-tilt]::after,
    .sm-fx .sm-card.is-popular[data-tilt]::after{animation:none}
}

/* ------------------------------------------------------------
   Reduced motion — everything this file animates goes still.
   (The JS also early-outs for globe/tilt/parallax/reveals.)
   :not(.sm-fx-force) — the ?fx=on preview override (JS adds the class)
   for machines where the OS forces reduce, e.g. Windows Server / RDP.
   ------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce){
    .sm-fx:not(.sm-fx-force) .sm-hero .sm-eyebrow, .sm-fx:not(.sm-fx-force) .sm-hero .sm-title,
    .sm-fx:not(.sm-fx-force) .sm-hero .sm-lede, .sm-fx:not(.sm-fx-force) .sm-hero .sm-cta,
    .sm-fx:not(.sm-fx-force) .sm-hero .sm-trust, .sm-fx:not(.sm-fx-force) .sm-hero .sm-ops,
    .sm-fx:not(.sm-fx-force) h1.sm-title .accent,
    .sm-fx:not(.sm-fx-force) .sm-rv.is-in,
    .sm-fx:not(.sm-fx-force) .sm-engine.is-live::after, .sm-fx:not(.sm-fx-force) .sm-engine.is-live .node,
    .sm-fx:not(.sm-fx-force) .sm-engine.is-live .step,
    .sm-fx:not(.sm-fx-force) .sm-pillars::after, .sm-fx:not(.sm-fx-force) .sm-caps::after,
    .sm-fx:not(.sm-fx-force) .sm-feed-row, .sm-fx:not(.sm-fx-force) .sm-feed-row .sev.crit,
    .sm-fx:not(.sm-fx-force) .sm-feed-row .sev.high{
        animation:none !important;
    }
    .sm-fx:not(.sm-fx-force) .sm-rv{opacity:1}
    .sm-fx:not(.sm-fx-force) [data-tilt]{transition:none}
    .sm-fx:not(.sm-fx-force) .sm-hero-fx canvas{display:none}
    .sm-fx:not(.sm-fx-force) .sm-aurora,
    .sm-fx:not(.sm-fx-force) .sm-scanlines::after,
    .sm-fx:not(.sm-fx-force) .sm-ops[data-tilt]::after,
    .sm-fx:not(.sm-fx-force) .sm-card.is-popular[data-tilt]::after{animation:none}
}
