/* ============================================================
   Outstellarr — depth layer
   A shared CSS-only 3D system: real perspective, cursor-tracked
   tilt, layered elevation, specular highlight and depth-staged
   scroll reveals. No dependencies, no libraries.

   Three modes, because the site mixes two card idioms:
     .d-card  — standalone cards in a gapped grid: full tilt.
     .d-lift  — seamless clipped panels (svc-grid, audit-grid…):
                the panel rises as one unit, no rotation, so the
                flush 1px dividers between cells never break.
     .d-sheen — the flush cells inside those panels, and ruled
                list rows: cursor highlight and inner-content Z
                only, the box itself never moves.

   Every transform on a .d-3d element is composed from custom
   properties so the tilt engine (pointer) and the reveal engine
   (scroll) drive one `transform` without fighting each other.
   ============================================================ */

:root{
  --d-persp:900px;          /* vanishing point distance      */
  --d-tilt:6deg;            /* max rotation, kept restrained */

  /* Layered elevation — several small shadows read as real
     depth far better than one large blurred drop shadow.     */
  --d-e0:0 1px 2px rgba(16,24,40,.04);
  --d-e1:0 1px 2px rgba(16,24,40,.05), 0 3px 8px rgba(16,24,40,.05);
  --d-e2:0 1px 2px rgba(16,24,40,.05), 0 6px 14px rgba(16,24,40,.06), 0 16px 34px rgba(16,24,40,.06);
  --d-e3:0 1px 2px rgba(16,24,40,.06), 0 10px 22px rgba(37,99,235,.10), 0 26px 56px rgba(37,99,235,.10);
}

/* ---------- 1. The composed transform ---------- */

.d-3d{
  --d-rx:0deg; --d-ry:0deg;              /* pointer tilt      */
  --d-tz:0px;  --d-ty:0px;               /* pointer lift      */
  --d-vx:0deg; --d-vy:0px; --d-vz:0px;   /* reveal offsets    */

  transform:
    perspective(var(--d-persp))
    translate3d(0, calc(var(--d-ty) + var(--d-vy)), calc(var(--d-tz) + var(--d-vz)))
    rotateX(calc(var(--d-rx) + var(--d-vx)))
    rotateY(var(--d-ry));
  transform-style:preserve-3d;
  transition:
    transform .7s cubic-bezier(.22,1,.36,1),
    box-shadow .45s cubic-bezier(.22,1,.36,1),
    border-color .3s ease,
    opacity .7s cubic-bezier(.22,1,.36,1);
}

/* While the pointer is inside a card the tilt must track it
   nearly 1:1; on exit we fall back to the slow settle above. */
.d-3d.d-live{ transition:transform .12s linear, box-shadow .3s ease, border-color .3s ease; }

/* ---------- 2. Depth-staged scroll reveal ---------- */
/* Cards rise *out of* the screen rather than just sliding up.
   `.visible` is set by each page's existing observer, `.d-in`
   by the depth engine for elements it tags itself. */

.d-3d.fade-up:not(.visible),
.d-3d.d-rise:not(.d-in){
  --d-vy:26px; --d-vz:-70px; --d-vx:7deg;
  opacity:0;
}
.d-3d.d-rise{ opacity:1; }
.d-3d.fade-up.visible,
.d-3d.d-rise.d-in{ --d-vy:0px; --d-vz:0px; --d-vx:0deg; opacity:1; }

/* ---------- 3. Surfaces ---------- */

.d-card,.d-lift,.d-sheen{ position:relative; }
.d-card{ box-shadow:var(--d-e1); }
.d-card.d-live{ box-shadow:var(--d-e3); z-index:2; }
.d-lift.d-live{ box-shadow:var(--d-e2); z-index:2; }

/* Cells that never move still get a perspective of their own, so
   their icon/number can lift off the surface on hover. */
.d-sheen{ perspective:700px; }

/* Specular highlight tracking the cursor across the surface: a
   soft white radial at the pointer reads as light catching a
   physical panel. */
.d-card::after,
.d-sheen::after{
  content:'';
  position:absolute; inset:0;
  border-radius:inherit;
  pointer-events:none;
  background:
    radial-gradient(420px circle at var(--d-mx,50%) var(--d-my,50%),
      rgba(255,255,255,.85), rgba(255,255,255,.18) 38%, rgba(255,255,255,0) 62%);
  opacity:0;
  transition:opacity .4s ease;
  z-index:1;
}
.d-card.d-live::after,
.d-sheen.d-live::after{ opacity:.55; }

/* Keep real content above the highlight film. */
.d-card > *,
.d-sheen > *{ position:relative; z-index:2; }

/* Dark surfaces need the opposite treatment — a cool sheen,
   not a white wash. */
.d-on-dark.d-card::after,
.d-on-dark.d-sheen::after{
  background:
    radial-gradient(420px circle at var(--d-mx,50%) var(--d-my,50%),
      rgba(120,170,255,.32), rgba(120,170,255,.07) 40%, rgba(120,170,255,0) 65%);
}
.d-on-dark.d-card.d-live{ box-shadow:0 10px 30px rgba(0,0,0,.32), 0 26px 60px rgba(0,0,0,.26); }

/* ---------- 4. Content parallax inside a card ---------- */
/* Pushing the heading/icon forward on Z is what sells the tilt:
   the layers visibly separate as the card turns. */
.d-card .d-pop{ transform:translateZ(26px); transition:transform .5s cubic-bezier(.22,1,.36,1); }
.d-card.d-live .d-pop{ transform:translateZ(42px); }

.svc-card .svc-icon,
.audit-card .audit-num,
.trend-item .trend-num,
.pstep .pnum,
.process-step .step-num,
.about-principle .principle-icon,
.res-card .res-icon,
.wwd-item .wwd-check,
.stat-item .stat-val,
.strip-item .strip-n,
.result-card .result-val,
.ai-feat .ai-feat-icon,
.leader-card .leader-avatar,
.tcard .tmark{
  transform:translateZ(16px);
  transition:transform .5s cubic-bezier(.22,1,.36,1);
}
.d-live.svc-card .svc-icon,
.d-live.audit-card .audit-num,
.d-live.trend-item .trend-num,
.d-live.pstep .pnum,
.d-live.process-step .step-num,
.d-live.about-principle .principle-icon,
.d-live.res-card .res-icon,
.d-live.wwd-item .wwd-check,
.d-live.stat-item .stat-val,
.d-live.strip-item .strip-n,
.d-live.result-card .result-val,
.d-live.ai-feat .ai-feat-icon,
.d-live.leader-card .leader-avatar,
.d-live.tcard .tmark{ transform:translateZ(34px); }

/* ---------- 5. Atmosphere: receding perspective floor ---------- */
/* A ground plane laid into the hero and dark CTA bands. It gives
   an otherwise flat page an actual horizon to sit on. */

.d-floor{
  position:absolute;
  left:-25%; right:-25%; bottom:-8%;
  height:62%;
  pointer-events:none;
  z-index:0;
  perspective:340px;
  perspective-origin:50% 0%;
  -webkit-mask-image:linear-gradient(to top, #000 0%, rgba(0,0,0,.5) 42%, transparent 88%);
          mask-image:linear-gradient(to top, #000 0%, rgba(0,0,0,.5) 42%, transparent 88%);
}
.d-floor i{
  position:absolute; inset:-60% 0 -10% 0;
  display:block;
  transform:rotateX(74deg);
  transform-origin:50% 100%;
  background-image:
    linear-gradient(to right,  var(--d-floor-line,rgba(37,99,235,.15)) 1px, transparent 1px),
    linear-gradient(to bottom, var(--d-floor-line,rgba(37,99,235,.15)) 1px, transparent 1px);
  background-size:74px 74px;
  animation:d-floor-drift 26s linear infinite;
}
@keyframes d-floor-drift{ from{background-position:0 0;} to{background-position:0 74px;} }
.d-floor.d-floor-dark i{ --d-floor-line:rgba(96,165,250,.20); }

/* Free-floating depth motes, parallaxed by the pointer. */
.d-motes{ position:absolute; inset:0; pointer-events:none; z-index:0; overflow:hidden; }
.d-motes b{
  position:absolute;
  width:var(--s,7px); height:var(--s,7px);
  border-radius:50%;
  background:radial-gradient(circle at 32% 30%, #fff, rgba(37,99,235,.5) 55%, rgba(37,99,235,.12));
  box-shadow:0 6px 18px rgba(37,99,235,.22);
  opacity:var(--o,.5);
  /* `translate` is a separate property, so the pointer parallax
     composes with the bob keyframes instead of overwriting them. */
  translate:var(--d-px,0px) var(--d-py,0px);
  animation:d-mote-bob var(--dur,9s) ease-in-out var(--del,0s) infinite;
}
@keyframes d-mote-bob{
  0%,100%{ transform:translate3d(0,0,0); }
  50%    { transform:translate3d(0,-22px,0); }
}

/* Content wrappers must out-paint the injected floor: a positioned
   z-index:0 layer would otherwise paint over in-flow siblings. */
#hero > *:not(.d-floor):not(.d-motes):not(.hero-glow):not(.hero-blob),
.page-hero > *:not(.d-floor):not(.d-motes):not(.page-hero-glow),
#contact > .cta-inner,
.cta-section > .section,
.ea-section > .ea-inner{ position:relative; z-index:1; }

/* ---------- 6. Nav gains real elevation once you scroll ---------- */
nav{ transition:box-shadow .35s ease, background .35s ease; }
nav.d-stuck{ box-shadow:0 1px 0 rgba(16,24,40,.04), 0 8px 24px rgba(16,24,40,.07); }

/* ---------- 7. Pointer parallax on the ambient hero layers ----------
   These already carry a centring translateX(-50%); the parallax
   offset layers on top via custom properties so the engine never
   has to reconstruct the base transform. */
.hero-glow,.hero-blob,.page-hero-glow{
  transition:transform .9s cubic-bezier(.22,1,.36,1);
}
.hero-glow,
.page-hero-glow{ transform:translateX(-50%) translate3d(var(--d-px,0px), var(--d-py,0px), 0); }
.hero-blob    { transform:translate3d(var(--d-px,0px), var(--d-py,0px), 0); }

/* ============================================================
   8. The GTM stack — brand logos on 3D tiles
   ============================================================ */

.stack-3d{
  display:grid;
  grid-template-columns:repeat(3,1fr);
  gap:14px;
  margin-top:48px;
  align-items:start;
}

.scat-head{ display:flex; align-items:baseline; justify-content:space-between; gap:12px; margin-bottom:16px; }
.scat-note{ font-size:10.5px; color:#a1a1a8; font-weight:400; white-space:nowrap; }

.tool-grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(78px,1fr)); gap:8px; }

.tool{
  --tool-c:#2563EB;
  --tool-tint:rgba(37,99,235,.14);
  position:relative;
  display:flex; flex-direction:column; align-items:center; gap:8px;
  padding:14px 6px 11px;
  border-radius:12px;
  background:linear-gradient(180deg,#fff 0%,#fbfbfd 100%);
  border:1px solid var(--border,#e5e5e7);
  box-shadow:var(--d-e0), inset 0 1px 0 #fff;
  transform-style:preserve-3d;
  transition:transform .45s cubic-bezier(.22,1,.36,1), box-shadow .45s ease, border-color .3s ease;
  cursor:default;
}
.tool:hover{
  transform:translateZ(30px) translateY(-4px);
  border-color:var(--tool-tint);
  box-shadow:0 8px 18px rgba(16,24,40,.09), 0 20px 40px var(--tool-tint);
  z-index:3;
}

/* The logo plate — a small raised chip carrying the brand mark. */
.tool-plate{
  position:relative;
  width:42px; height:42px;
  border-radius:11px;
  display:grid; place-items:center;
  background:#fff;
  border:1px solid rgba(16,24,40,.07);
  box-shadow:0 1px 2px rgba(16,24,40,.06), inset 0 1px 0 #fff;
  transform:translateZ(14px);
  transition:transform .45s cubic-bezier(.22,1,.36,1), box-shadow .45s ease;
  overflow:hidden;
}
.tool:hover .tool-plate{
  transform:translateZ(34px) scale(1.06);
  box-shadow:0 6px 14px rgba(16,24,40,.13);
}
.tool-plate img{ width:26px; height:26px; object-fit:contain; display:block; }

/* Lettermark, held in reserve and shown only if every logo
   request fails. The dark side of the gradient guarantees the
   white glyph stays legible whatever the brand hue is. */
.tool-mark{
  display:none;
  place-items:center;
  width:100%; height:100%;
  font-size:15px; font-weight:600; letter-spacing:-.02em; color:#fff;
  background:linear-gradient(150deg, var(--tool-c,#2563EB), rgba(0,0,0,.5));
}
.is-fallback .tool-plate img{ display:none; }
.is-fallback .tool-mark{ display:grid; }

.tool-name{
  font-size:10.5px; line-height:1.25; text-align:center;
  color:var(--gray,#6e6e73); font-weight:450;
  /* Labels like SPF/DKIM/DMARC are one unbreakable token and would
     otherwise spill past the tile edge. */
  max-width:100%; overflow-wrap:anywhere;
  transform:translateZ(6px);
  transition:color .3s ease;
}
.tool:hover .tool-name{ color:var(--black,#1d1d1f); }

/* Tint each tile's hover glow with its own brand colour. Falls
   back to the flat blue tint above where color-mix is missing. */
@supports (color:color-mix(in srgb, red, blue)){
  .tool,.lm-chip{ --tool-tint:color-mix(in srgb, var(--tool-c,#2563EB) 26%, transparent); }
}

/* Non-branded capabilities (SPF/DKIM, warm-up, audits) render as
   spec chips with a drawn glyph — honest, and visually distinct
   from the real product logos. */
.tool.is-spec .tool-plate{ background:linear-gradient(180deg,#f6f8ff,#eef2ff); border-color:rgba(37,99,235,.16); }
.tool.is-spec .tool-plate svg{ width:20px; height:20px; stroke:var(--blue,#2563EB); fill:none; stroke-width:1.6; stroke-linecap:round; stroke-linejoin:round; }

@media(max-width:980px){ .stack-3d{ grid-template-columns:repeat(2,1fr); } }
@media(max-width:600px){
  .stack-3d{ grid-template-columns:1fr; }
  .tool-grid{ grid-template-columns:repeat(auto-fill,minmax(72px,1fr)); }
}

/* ---------- 9. Homepage logo marquee ---------- */

.lm-wrap{
  position:relative;
  padding:38px 0 42px;
  background:var(--white,#fff);
  border-bottom:1px solid var(--border,#e5e5e7);
  overflow:hidden;
  perspective:800px;
}
.lm-head{
  text-align:center;
  font-size:11px; font-weight:600; letter-spacing:.1em; text-transform:uppercase;
  color:#a1a1a8;
  margin-bottom:26px;
}
.lm-stage{ transform:rotateX(9deg); transform-style:preserve-3d; }
.lm-track{
  display:flex; gap:12px; width:max-content;
  animation:lm-scroll 46s linear infinite;
}
.lm-wrap:hover .lm-track{ animation-play-state:paused; }
@keyframes lm-scroll{ from{transform:translate3d(0,0,0);} to{transform:translate3d(-50%,0,0);} }

.lm-chip{
  --tool-c:#2563EB;
  --tool-tint:rgba(37,99,235,.14);
  display:flex; align-items:center; gap:9px;
  padding:9px 15px 9px 11px;
  border-radius:100px;
  background:#fff;
  border:1px solid var(--border,#e5e5e7);
  box-shadow:0 1px 2px rgba(16,24,40,.05), 0 6px 14px rgba(16,24,40,.04);
  white-space:nowrap;
  transform-style:preserve-3d;
  transition:transform .4s cubic-bezier(.22,1,.36,1), box-shadow .4s ease, border-color .3s ease;
}
.lm-chip:hover{
  transform:translateZ(34px) translateY(-3px);
  border-color:var(--tool-tint);
  box-shadow:0 10px 22px rgba(16,24,40,.10), 0 24px 46px var(--tool-tint);
}
.lm-chip img{ width:20px; height:20px; object-fit:contain; display:block; }
.lm-chip .tool-plate{
  width:22px; height:22px; border-radius:7px;
  transform:none; box-shadow:none; border:none; background:none;
}
.lm-chip .tool-mark{ font-size:10px; border-radius:6px; }
.lm-chip span{ font-size:12.5px; font-weight:450; color:var(--black,#1d1d1f); letter-spacing:-.01em; }

/* Feather the marquee edges so chips fade rather than clip. */
.lm-fade{ position:absolute; top:0; bottom:0; width:120px; pointer-events:none; z-index:2; }
.lm-fade.l{ left:0;  background:linear-gradient(to right, #fff 8%, transparent); }
.lm-fade.r{ right:0; background:linear-gradient(to left,  #fff 8%, transparent); }

@media(max-width:600px){
  .lm-fade{ width:56px; }
  .lm-wrap{ padding:30px 0 34px; }
}

/* ============================================================
   10. Accessibility & capability guards
   ============================================================ */

/* Touch devices: no pointer to track, so keep the depth (shadows,
   reveals) but drop the tilt. */
@media(hover:none){
  .d-3d{ --d-rx:0deg; --d-ry:0deg; --d-tz:0px; --d-ty:0px; }
  .tool:hover,.lm-chip:hover{ transform:none; }
}

@media(prefers-reduced-motion:reduce){
  .d-3d{
    --d-rx:0deg!important; --d-ry:0deg!important; --d-tz:0px!important; --d-ty:0px!important;
    --d-vx:0deg!important; --d-vy:0px!important;  --d-vz:0px!important;
    opacity:1!important;
    transition:box-shadow .2s ease, border-color .2s ease;
  }
  .d-card::after,.d-sheen::after{ display:none; }
  .d-card .d-pop,.tool-plate,.tool-name{ transform:none!important; }
  .lm-track{ animation:none; }
  .lm-stage{ transform:none; }
  .d-floor i,.d-motes b{ animation:none; }
  /* Zero the parallax offset rather than the whole transform —
     .hero-glow needs to keep its centring translateX(-50%). */
  .hero-glow,.hero-blob,.page-hero-glow,.d-motes b{ --d-px:0px!important; --d-py:0px!important; }
  .tool:hover,.lm-chip:hover{ transform:none; }
}
