/* ============================================================================
   SetAside AI — hero match-network graphic (SA-02 · MATCH NET)
   ----------------------------------------------------------------------------
   The blueprint panel that sits beside the homepage headline: a dim field of
   indexed opportunities, a teal anchor diamond for the visitor's profile, and
   gold lines that reach out one at a time to the five that matched.

   Loaded by index.html only:

     <link rel="stylesheet" href="/assets/hero-net.css">
     <script src="/assets/hero-net.js" defer></script>

   The page supplies one empty host element and nothing else:

     <div class="sa-net" data-sa-net aria-hidden="true"></div>

   assets/hero-net.js fills it. If the script never runs the host collapses to
   an empty box and the hero is still a correct hero — same failure posture as
   the ambient backdrop.

   ── Why a fixed 520x560 stage that is then scaled ──────────────────────────
   Every mark in this graphic is placed by absolute pixel coordinate on a
   520x560 field (node positions, the crosshair through the anchor, the label
   collision nudge). Making those coordinates fluid would mean recomputing the
   whole layout per breakpoint and would drift from the source design.

   Instead the stage keeps its native coordinate system at every size and the
   whole panel is scaled with a transform. --sa-net-s is the only thing that
   changes between breakpoints; the outer box is sized from the same variable
   so the scaled panel still occupies real layout space (a transform alone does
   not affect flow, which would leave the hero grid reserving 520px forever).

   Colours are the backdrop palette (§1 of backdrop.css) restated as literals:
   this panel is decoration, and it must render identically whether or not the
   token layer happens to have loaded first.
   ========================================================================== */

/* ── 1. Host box ────────────────────────────────────────────────────────────
   Width/height track the scale so the hero grid reserves the right space.    */
.sa-net{
  --sa-net-s: 1;
  width:  calc(520px * var(--sa-net-s));
  height: calc(560px * var(--sa-net-s));
  flex: none;
  pointer-events: none;   /* decorative: never intercept a click near the CTA */
  user-select: none;
}

/* ── 2. Stage ───────────────────────────────────────────────────────────────
   Native coordinate space. The fine grid, the plate gradient and the hairline
   border are all here so they scale with everything else.                    */
.sa-net__stage{
  position: relative;
  width: 520px; height: 560px;
  box-sizing: border-box;
  transform: scale(var(--sa-net-s));
  transform-origin: top left;
  overflow: hidden;
  border: 1px solid rgba(96,165,250,.28);
  background-image:
    linear-gradient(rgba(96,165,250,.055) 1px, transparent 1px),
    linear-gradient(90deg, rgba(96,165,250,.055) 1px, transparent 1px),
    linear-gradient(160deg, #0c1a36 0%, #0a132b 100%);
  background-size: 28px 28px, 28px 28px, 100% 100%;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}

/* ── 3. Chrome — ticks, rules, blueprint marks ──────────────────────────────*/
.sa-net__tick{ position:absolute; width:14px; height:14px; border:0 solid #4fd1c5; opacity:.8; }
.sa-net__tick--tl{ top:8px; left:8px;  border-top-width:1px; border-left-width:1px; }
.sa-net__tick--tr{ top:8px; right:8px; border-top-width:1px; border-right-width:1px; }
.sa-net__tick--bl{ bottom:8px; left:8px;  border-bottom-width:1px; border-left-width:1px; }
.sa-net__tick--br{ bottom:8px; right:8px; border-bottom-width:1px; border-right-width:1px; }

/* header / footer blueprint labels */
.sa-net__hdr,
.sa-net__ftr{
  position:absolute; left:32px; right:32px;
  display:flex; justify-content:space-between; align-items:center;
  font-size:10px; letter-spacing:.14em;
}
.sa-net__hdr{ top:16px;    color: rgba(125,211,252,.75); }
.sa-net__ftr{ bottom:16px; color: rgba(125,211,252,.6); }
.sa-net__live{ display:flex; align-items:center; gap:6px; color: rgba(79,209,197,.85); }
.sa-net__led{ width:5px; height:5px; border-radius:50%; background:#4fd1c5; }
.sa-net__fit{ color:#d9ae47; }

/* crosshair through the anchor at (185,295) */
.sa-net__cross-v{ position:absolute; left:185px; top:90px;  width:1px; height:420px; background: rgba(96,165,250,.12); }
.sa-net__cross-h{ position:absolute; left:40px;  top:295px; width:440px; height:1px;  background: rgba(96,165,250,.12); }

.sa-net__ring{
  position:absolute; left:157px; top:267px; width:56px; height:56px;
  box-sizing:border-box; border:1px dashed rgba(79,209,197,.45); border-radius:50%;
}

/* ── 4. Anchor — teal diamond echoing the hex logo mark ─────────────────────*/
.sa-net__anchor{
  position:absolute; left:180px; top:290px; width:10px; height:10px;
  background:#4fd1c5; transform: rotate(45deg);
  box-shadow: 0 0 12px rgba(79,209,197,.7);
}
.sa-net__anchor-label{
  position:absolute; left:185px; top:336px; transform: translateX(-50%);
  font-size:9px; letter-spacing:.16em; color: rgba(79,209,197,.85); white-space:nowrap;
}

/* ── 5. Opportunity field — the 16 dim, static candidates ───────────────────*/
.sa-net__node{ position:absolute; width:4px; height:4px; border-radius:50%; }

/* ── 6. Match overlay — lines, travelling dots, lit matches ─────────────────
   Faded as one layer at the end of a cycle, which is why it is a single box
   rather than styling each mark's opacity.                                   */
.sa-net__overlay{
  position:absolute; inset:0;
  opacity:1; transition: opacity 1s ease;
}
.sa-net__overlay[data-out="1"]{ opacity:0; }
.sa-net__svg{ position:absolute; inset:0; display:block; }

/* the drawn line: dasharray/offset over pathLength=1, so one transition covers
   any length at the same speed */
.sa-net__line{
  stroke:#d9ae47; stroke-opacity:.55; stroke-width:1;
  stroke-dasharray:1; stroke-dashoffset:1;
  transition: stroke-dashoffset .85s linear;
}
.sa-net__line[data-arrived="1"]{ stroke-dashoffset:0; }

/* the gold dot travelling anchor -> node, timed with the line */
.sa-net__dot{
  position:absolute; left:-3px; top:-3px; width:6px; height:6px; border-radius:50%;
  background:#d9ae47; box-shadow:0 0 8px #d9ae47; opacity:.9;
  transition: transform .85s linear;
}

/* the landed match + its label */
.sa-net__lit{
  position:absolute; left:-4px; top:-4px; width:8px; height:8px; border-radius:50%;
  background:#d9ae47; box-shadow:0 0 9px 2px rgba(217,174,71,.4);
}
.sa-net__label{
  position:absolute; left:0; top:0;
  font-size:9px; letter-spacing:.12em; color:#d9ae47; opacity:.9; white-space:nowrap;
  text-shadow:0 0 6px rgba(10,19,43,.9);
}

/* ── 7. Motion ──────────────────────────────────────────────────────────────
   Animations are attached by class, and the reduced-motion frame simply never
   gets them: hero-net.js renders a settled five-match state instead of
   starting the loop, so there is nothing to switch off. The media query below
   is the belt to that braces — it also covers a preference flipped mid-visit
   on marks that are already on screen.                                       */
.sa-net__led{      animation: sa-net-live 2s ease-in-out infinite; }
.sa-net__lit--in{  animation: sa-net-bloom .6s ease-out; }
.sa-net__label--in{ animation: sa-net-label-in .5s ease-out; }

@keyframes sa-net-live{ 0%,100%{opacity:1} 50%{opacity:.25} }
@keyframes sa-net-label-in{ from{opacity:0} to{opacity:.9} }
@keyframes sa-net-bloom{
  0%  { box-shadow:0 0 2px rgba(217,174,71,.2);    transform: scale(1.5); }
  40% { box-shadow:0 0 20px 8px rgba(217,174,71,.55); }
  100%{ box-shadow:0 0 9px 2px rgba(217,174,71,.4); transform: scale(1); }
}

@media (prefers-reduced-motion: reduce){
  .sa-net__led,
  .sa-net__lit--in,
  .sa-net__label--in{ animation: none !important; }
  .sa-net__overlay,
  .sa-net__line,
  .sa-net__dot{ transition: none !important; }
}

/* ── 8. Responsive ──────────────────────────────────────────────────────────
   Only --sa-net-s changes. See §9 of index.html for the hero grid that places
   this panel beside (or beneath) the headline.

   Below 768px the panel is removed outright rather than shrunk. Same call the
   backdrop's motion layer makes, for the same two reasons: on a phone this is
   where the animation costs the most and shows the least, and 560px of
   decoration between the headline and the founding-access CTA would push the
   one thing the page is asking for below the fold. hero-net.js checks the same
   breakpoint and never builds the panel at all, so the cost is not merely
   hidden — it is not paid.                                                   */
@media (max-width: 1179px){ .sa-net{ --sa-net-s: .85; } }
@media (max-width:  999px){ .sa-net{ --sa-net-s: .78; } }
@media (max-width:  767px){ .sa-net{ display:none; } }
