
/* ============================================================
   Atmosphere + hero composition.
   Background: fixed filament canvas + a radial lift so the page
   is not a flat void. Hero: two columns so the primary action
   sits above the fold next to the organism, not below it.
   ============================================================ */

#bg-field {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  pointer-events: none;
  opacity: .78;
}

/* Depth wash behind content: a soft green rise from the lower left,
   so the canvas reads as a volume instead of #0a0c0a nothing. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(120% 80% at 18% 108%, rgba(31,120,79,.28), transparent 62%),
    radial-gradient(90% 70% at 88% -10%, rgba(24,86,120,.16), transparent 58%);
}

/* Fine grain so large dark areas are never dead flat.
   Measured: 0.035 was invisible in a screenshot readback, 0.09 reads as
   texture without muddying type. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: .09;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* Everything real sits above the atmosphere. */
.site-head, main, .site-foot { position: relative; z-index: 1; }

/* ---------- hero: two columns, action above the fold ---------- */
.hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
  gap: 46px;
  align-items: center;
}
.hero-copy { min-width: 0; }
.hero-visual { min-width: 0; position: relative; }

/* The canvas is a framed specimen plate, not a floating box. */
.hero-stage {
  margin: 0;
  position: relative;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background:
    radial-gradient(80% 80% at 50% 45%, rgba(20,70,48,.34), transparent 70%),
    #05100b;
  overflow: hidden;
}
.hero-stage::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    linear-gradient(rgba(79,230,154,.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(79,230,154,.05) 1px, transparent 1px);
  background-size: 34px 34px;
}
.hero-stage canvas {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1;
  position: relative;
  z-index: 1;
}
.hero-stage figcaption {
  position: relative;
  z-index: 1;
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--muted);
  padding: 10px 12px;
  border-top: 1px solid var(--rule);
  background: rgba(3,9,6,.72);
}

/* Corner ticks: the specimen-frame cue from the reference. */
.hero-visual::before,
.hero-visual::after {
  content: "";
  position: absolute;
  width: 14px; height: 14px;
  border: 1px solid var(--accent);
  opacity: .5;
  pointer-events: none;
}
.hero-visual::before { top: -6px; left: -6px; border-right: 0; border-bottom: 0; }
.hero-visual::after { bottom: -6px; right: -6px; border-left: 0; border-top: 0; }

/* Tighter hero so the form clears the fold. */
.hero { padding: 40px 0 34px; }
.hero h1 { font-size: clamp(40px, 5.6vw, 78px); max-width: 15ch; }

/* Search field: make it the obvious primary action. */
.search {
  margin: 0;
  display: flex;
  gap: 10px;
  max-width: 100%;
}
.search input {
  flex: 1 1 auto;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: 13px;
}

@media (max-width: 900px) {
  .hero-grid { grid-template-columns: 1fr; gap: 28px; }
  .hero-visual { order: 2; }
  .hero-copy { order: 1; }
  #bg-field { opacity: .4; }
}

/* ============================================================
   Pass 2 fixes, each from a measured defect:
   - card looked "pasted on"      -> glow spills onto the page
   - button was a flat rectangle  -> it emits light
   - ragged right edges in hero   -> one shared measure
   - two hairlines collided       -> collapse the duplicate
   - corner ticks half-committed  -> all four
   ============================================================ */

/* Card lights the page around it. */
.hero-visual::after,
.hero-visual::before { z-index: 2; }
.hero-stage {
  box-shadow:
    0 0 0 1px rgba(79,230,154,.08),
    0 30px 90px -30px rgba(31,140,90,.55),
    0 0 140px -40px rgba(31,140,90,.35);
}

/* Four corner ticks, not two. */
.hero-visual { --tick: 15px; }
.hero-visual::before,
.hero-visual::after { width: var(--tick); height: var(--tick); opacity: .55; }
.hero-stage::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 3;
  background:
    linear-gradient(var(--accent), var(--accent)) 0 0 / var(--tick) 1px no-repeat,
    linear-gradient(var(--accent), var(--accent)) 0 0 / 1px var(--tick) no-repeat,
    linear-gradient(var(--accent), var(--accent)) 100% 100% / var(--tick) 1px no-repeat,
    linear-gradient(var(--accent), var(--accent)) 100% 100% / 1px var(--tick) no-repeat;
  opacity: .38;
}

/* The primary action should look alive. */
.search button.primary,
button.primary {
  box-shadow: 0 0 0 1px rgba(79,230,154,.5), 0 8px 30px -8px rgba(79,230,154,.55);
  transition: box-shadow var(--dur-mid) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.search button.primary:hover,
button.primary:hover {
  box-shadow: 0 0 0 1px rgba(79,230,154,.8), 0 12px 40px -8px rgba(79,230,154,.75);
  transform: translateY(-1px);
}
.search input:focus-visible,
input:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(79,230,154,.16);
}
@media (prefers-reduced-motion: reduce) {
  button.primary { transition: none; }
  button.primary:hover { transform: none; }
}

/* One measure for the whole hero column: kills four different right edges. */
.hero-copy > * { max-width: 46ch; }
.hero-copy h1 { max-width: 15ch; }
.hero-copy .hud { max-width: none; }

/* The hero already ends with a border; the section rule doubled it. */
.hero + .section { border-top: 0; }

/* Caption reads as a stat line, not a wrapped sentence. */
.hero-stage figcaption {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  line-height: 1.5;
}

/* ============================================================
   Pass 3. Each fix from a defect seen in a screenshot readback.
   ============================================================ */

/* Eyebrow orphaned the word "live" onto its own line, and the caption broke
   mid-phrase. Both are container-width problems, not copy problems. */
.hero-copy .eyebrow { max-width: none; white-space: nowrap; }
.hero-stage figcaption { white-space: normal; }

/* The 42-char placeholder ran edge to edge with no right padding. */
.search input::placeholder { opacity: .55; }
.search input { text-overflow: ellipsis; }

/* The stats rule stopped at the text measure while every other rule ran the
   full column. Let the HUD span its own grid cell. */
.hero-copy .hud { max-width: none; }

/* Card top third was dead space: crop the plate rather than leave a void.
   No object-fit here — the renderer reads getBoundingClientRect, so it
   redraws to the new ratio instead of being stretched. */
.hero-stage canvas { aspect-ratio: 1 / .82; }

/* Corner ticks were two systems at once: two L marks outside the card plus
   four inside it. Keep only the four inside so the frame reads as deliberate. */
.hero-visual::before,
.hero-visual::after { display: none; }
.hero-stage::after { opacity: .5; }

@media (max-width: 900px) {
  .hero-copy .eyebrow { white-space: normal; }
}
