/* Avenix Agency — v2 styles ("radial core" design language)
   Mobile-first, no framework, no build step.

   Contrast notes (WCAG AA, computed against the ACTUAL rendered hex,
   relative-luminance method):
   - Body text #EDEDF5 on ground #06060F  -> ~17.3:1
   - Body text #EDEDF5 on ground #0A0A18  -> ~16.9:1
   - Body text #EDEDF5 on --bg-elevated #10101C -> ~16.2:1
   - Muted text #9B9BB0 on ground #06060F -> ~7.4:1
   - Muted text #9B9BB0 on --bg-card #2C2C47 -> ~4.96:1
   - Button text #EDEDF5 on button gradient (#7C3AED -> #6D28D9)
     -> worst stop ~4.9:1 (against the lighter #7C3AED stop)
   - Link text #818CF8 on --bg-1 #06060F -> ~6.76:1
   - Link text #818CF8 on --bg-2 #0A0A18 -> ~6.58:1
   - Link text #818CF8 on --bg-card #2C2C47 -> ~4.52:1
     (the original #6366F1 link color only cleared AA against the single
     best-case gradient stop --bg-1, which `background: … fixed` only
     ever renders across the very top of the viewport — every link
     below ~12% of viewport height was actually rendering against
     --bg-2/--bg-card and failing AA. #818CF8 is bumped brighter, and
     clears AA against every background this token renders against, but
     the margin against --bg-card specifically is thin (0.02), not the
     "real margin" this note previously claimed — flagged so a future
     editor doesn't darken --bg-card without re-checking this pair.)
   - a:hover text #A881F7 on --bg-card #2C2C47 -> ~4.59:1
     (raised from #A855F7, which computed to ~3.41:1 against the raised
     --bg-card value below and failed AA — reachable on the no-JS
     success page's "Back to Avenix" link. This token's other use,
     .btn-secondary:hover, sits on --bg-1/--bg-2 and only improves.)
   - --bg-card #2C2C47 vs ground #0A0A18 -> ~1.46:1 (raised from the
     previous #13131F, which computed to ~1.07:1 against the same
     ground — effectively invisible as a card boundary on a
     non-calibrated display). Kept just under a flat 1.5:1 so the link
     contrast above stays >=4.5:1 rather than overshooting the card
     separation target at the cost of breaking that AA floor.
   - --border rgba(139,92,246,0.4) vs --bg-card #2C2C47 -> ~1.58:1
   - --border rgba(139,92,246,0.4) vs ground #0A0A18 -> ~1.67:1
     (both raised from the previous 0.22-alpha border, which computed to
     ~1.26-1.58:1 against these same surfaces; the ground-comparison figure
     is corrected here from an earlier miscalculated ~2.30:1 — recomputed
     by hand with the standard sRGB alpha-composite-then-luminance method,
     matching how a browser actually renders a translucent border over a
     solid background. Purely decorative border, not a WCAG 1.4.11
     component boundary, so this figure is informational only and does
     not gate anything.)
   All pairs computed by hand with the standard relative-luminance
   formula. */

:root {
  /* Ground — near-black gradient, never flat #000 */
  --bg-1: #06060F;
  --bg-2: #0A0A18;
  --bg-elevated: #10101C;
  /* Raised from #13131F — the original computed to only ~1.07:1 against
     --bg-2, effectively invisible as a card boundary on a non-calibrated
     (non-OLED) display. See the contrast notes above for the full
     before/after math. */
  --bg-card: #2C2C47;

  /* Borders — violet-tinted, low-opacity so they read as "structure
     in the dark" rather than hard UI chrome. Alpha raised from 0.22 —
     see the contrast notes above for the before/after math. */
  --border: rgba(139, 92, 246, 0.4);
  --border-strong: rgba(139, 92, 246, 0.42);
  --border-interactive: #6b6485;

  /* Text */
  --text: #EDEDF5;
  --text-dim: #9B9BB0;

  /* Core / primary — electric violet + hot core (glows, rings, brand) */
  --violet: #8B5CF6;
  --violet-hot: #A881F7;
  /* Deeper violet stops used specifically for SOLID FILLS that carry
     text (buttons, step badges) — the bright --violet/--violet-hot
     pair reads beautifully as glow/ring/gradient-accent but is too
     light to hold 4.5:1 with on-brand near-white text at UI font
     sizes, so filled controls use this darker pair instead and the
     bright pair is reserved for glow/shadow/border treatment. */
  --violet-fill-1: #7C3AED;
  --violet-fill-2: #6D28D9;

  /* Filament secondary — links / hover / secondary glow.
     Bumped from an earlier #6366F1 (which only passed AA against the
     single best-case background stop) to #818CF8, which clears AA
     against every background this token actually renders on — see the
     contrast notes above. */
  --indigo: #818CF8;

  /* Accent A / Accent B — one per section, violet always leads */
  --amber: #F59E0B;
  --cyan: #22D3EE;

  --success: #4ADE80;
  --danger: #F87171;

  --radius: 12px;
  --max-width: 1080px;
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  color-scheme: dark;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  margin: 0;
  font-family: var(--font);
  background: linear-gradient(180deg, var(--bg-1) 0%, var(--bg-2) 100%) fixed;
  color: var(--text);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

.wrap {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 20px;
  position: relative;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

h1, h2, h3 {
  line-height: 1.15;
  margin: 0 0 0.5em;
  /* Text never glows — no text-shadow anywhere in this file. Headings
     get color/weight for hierarchy, never a light-emitting treatment. */
}

h1 { font-size: clamp(2rem, 5vw, 3rem); font-weight: 700; }
h2 { font-size: clamp(1.5rem, 3.5vw, 2.1rem); font-weight: 700; }
h3 { font-size: 1.15rem; font-weight: 600; }

p { color: var(--text-dim); margin: 0 0 1em; }

a {
  color: var(--indigo);
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}

a:hover { color: var(--violet-hot); text-decoration-thickness: 2px; }

/* ---------- Decorative background layer (constellation) ----------
   One lightweight, inline SVG layer. Fixed, behind everything (z-index
   -1 in the root stacking context; every real UI element is a normal
   static-flow box, which always paints above a negative-z-index
   sibling — no other element needs its own z-index for this to work).
   Nodes are clustered in the four corners only, and the whole layer is
   masked to fade toward zero opacity across the center column, so it
   never sits under a body-text measure at any viewport width. Decorative
   only: aria-hidden, pointer-events: none, no semantic content. */
.bg-field {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: 0.55;
  -webkit-mask-image: radial-gradient(ellipse 70% 60% at 50% 45%, transparent 0%, transparent 30%, black 68%);
  mask-image: radial-gradient(ellipse 70% 60% at 50% 45%, transparent 0%, transparent 30%, black 68%);
}

.bg-field svg {
  width: 100%;
  height: 100%;
  display: block;
}

.constellation-dot {
  animation: dot-pulse 6s ease-in-out infinite;
}

.constellation-line {
  animation: line-flow 8s ease-in-out infinite;
}

@keyframes dot-pulse {
  0%, 100% { opacity: 0.35; }
  50% { opacity: 0.9; }
}

@keyframes line-flow {
  0%, 100% { opacity: 0.15; }
  50% { opacity: 0.5; }
}

/* prefers-reduced-motion: cleanly disable all drift/pulse. Nodes/lines
   stay visible (static) at their mid-value opacity — only the motion
   stops. */
@media (prefers-reduced-motion: reduce) {
  .constellation-dot,
  .constellation-line {
    animation: none;
    opacity: 0.5;
  }
}

/* Its corner clusters live at the extreme edges of a 1600x900 viewBox
   rendered with `xMidYMid slice`. On a narrow/tall viewport (phones,
   most tablets in portrait) the slice crops in from the sides so
   aggressively that every cluster falls outside the visible box — the
   layer was painting and animating 24 SVG elements every frame for zero
   visible effect on the exact device class this mobile-first build
   leads with. Below the width this stops being true (empirically,
   clusters start re-entering the visible crop above roughly a 1.35:1
   viewport aspect ratio), hide the whole decorative layer entirely
   rather than pay its paint/animation cost for nothing. This does NOT
   remove the motif from the design — it's still the first thing a
   desktop/wide-tablet visitor sees — it only stops shipping invisible
   animation weight to the majority of first visits, which are phones. */
@media (max-width: 900px), (max-aspect-ratio: 4/3), (min-aspect-ratio: 3/1) {
  .bg-field {
    display: none;
  }
}

/* ---------- Header ---------- */

.site-header {
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  background: rgba(6, 6, 15, 0.82);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  z-index: 10;
}

.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-top: 14px;
  padding-bottom: 14px;
}

.logo {
  font-weight: 800;
  font-size: 1.25rem;
  color: var(--text);
  text-decoration: none;
  letter-spacing: -0.02em;
}

.logo:hover { color: var(--text); }

.site-nav {
  display: flex;
  align-items: center;
  gap: 8px;
}

.site-nav a {
  color: var(--text-dim);
  text-decoration: none;
  font-size: 0.95rem;
}

.site-nav .nav-link {
  padding: 10px 6px;
  border-radius: 6px;
}

.site-nav a:hover { color: var(--text); }

/* Below 560px, keep only the CTA — "How It Works" / "Services" text
   links are hidden to prevent header overflow/wrap on narrow phones
   (the page is one screen of content anyway, both sections are one
   scroll away). */
.site-nav .nav-link { display: none; }

.nav-cta {
  background: linear-gradient(135deg, var(--violet-fill-1) 0%, var(--violet-fill-2) 100%);
  color: var(--text) !important;
  padding: 10px 16px;
  border-radius: 999px;
  font-weight: 600;
  box-shadow: 0 0 0 1px var(--border-strong);
}

.nav-cta:hover {
  box-shadow: 0 0 0 1px var(--border-strong), 0 0 18px rgba(139, 92, 246, 0.55);
}

@media (min-width: 560px) {
  .site-nav { gap: 20px; }
  .site-nav .nav-link { display: inline-block; }
}

/* ---------- Hero / Intake ---------- */

.hero {
  padding: 88px 0 72px;
  text-align: center;
  position: relative;
}

.hero-sub {
  max-width: 560px;
  margin: 0 auto 32px;
  font-size: 1.05rem;
}

.intake-form {
  max-width: 720px;
  margin: 0 auto;
  text-align: left;
  position: relative;
}

/* Honeypot: visually hidden but present in DOM/tab order excluded */
.hp-field {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.hero-input-row {
  display: flex;
  flex-direction: column;
  gap: 10px;
  position: relative;
}

/* The "radial hub" — the intake field is the glowing core the whole
   page radiates from. Pure CSS: a blurred radial-gradient disc sitting
   behind the input row, plus a tight ring on the input's own border/
   box-shadow. Glow is on the SHAPE, never on the text inside it. */
.hero-input-row::before {
  content: "";
  position: absolute;
  inset: -40px -20px;
  z-index: -1;
  background: radial-gradient(circle at 50% 50%, rgba(168, 85, 247, 0.30) 0%, rgba(139, 92, 246, 0.16) 38%, transparent 72%);
  filter: blur(6px);
  animation: core-breathe 5s ease-in-out infinite;
}

@keyframes core-breathe {
  0%, 100% { opacity: 0.75; transform: scale(1); }
  50% { opacity: 1; transform: scale(1.04); }
}

@media (prefers-reduced-motion: reduce) {
  .hero-input-row::before { animation: none; opacity: 0.9; }
}

/* An author-origin `display` rule on this same element (immediately
   above) beats the UA-stylesheet `[hidden]` rule in the cascade (author
   beats UA; a `display` value set on a hidden element overrides the
   browser's default `[hidden] { display: none }`). js/main.js sets
   `heroInputRow.hidden = true` after the form expands, but without this
   override the row stays visible, duplicating the visitor's text under
   two buttons. This rule must stay AFTER the base `.hero-input-row` rule
   above (source order) with matching specificity (single class +
   attribute selector) so it wins. */
.hero-input-row[hidden] {
  display: none;
}

.hero-input {
  width: 100%;
  padding: 18px 20px;
  font-size: 1.1rem;
  border-radius: var(--radius);
  border: 1px solid var(--border-interactive);
  background: var(--bg-elevated);
  color: var(--text);
  box-shadow: 0 0 0 1px rgba(139, 92, 246, 0.12);
}

.hero-input:-webkit-autofill {
  -webkit-box-shadow: 0 0 0 1000px var(--bg-elevated) inset;
  -webkit-text-fill-color: var(--text);
  caret-color: var(--text);
}

.btn {
  display: inline-block;
  border: none;
  cursor: pointer;
  border-radius: var(--radius);
  font-weight: 600;
  font-size: 1rem;
  padding: 16px 24px;
  text-decoration: none;
  text-align: center;
}

.btn-primary {
  background: linear-gradient(135deg, var(--violet-fill-1) 0%, var(--violet-fill-2) 100%);
  color: var(--text);
  box-shadow: 0 0 0 1px var(--border-strong), 0 4px 20px rgba(124, 58, 237, 0.35);
}

.btn-primary:hover {
  box-shadow: 0 0 0 1px var(--border-strong), 0 4px 28px rgba(168, 85, 247, 0.55);
}

.btn-secondary {
  background: transparent;
  color: var(--text);
  /* --border-strong (0.42 alpha) only computed to ~1.72:1 against
     the page background — below the 3:1 WCAG 1.4.11 floor for a UI
     component's own boundary (this button has no fill, so its border IS
     its only visible edge). This higher-alpha value is scoped to this
     button only (not folded into --border-strong globally, which other
     elements use purely decoratively) and computes to ~3.34:1 against
     the page's darkest realistic background (--bg-2 #0A0A18). */
  border: 1px solid rgba(139, 92, 246, 0.8);
}

.btn-secondary:hover { border-color: var(--violet); color: var(--violet-hot); }

/* Real disabled state — visually distinct, no hover-brighten, cursor
   communicates "not clickable" while a submission is in flight.
   `pointer-events: none` is deliberately NOT used here — it suppresses
   hit-testing entirely, which means `cursor: not-allowed` below would
   never actually render (a browser can't paint a cursor for pointer
   events it isn't testing). The `disabled` attribute on a real <button>
   already prevents any click from doing anything, so pointer-events
   suppression isn't needed for function — leaving it off is what makes
   the visual cursor cue actually work. */
.btn:disabled,
.btn[disabled] {
  opacity: 0.55;
  cursor: not-allowed;
  box-shadow: none;
}

.btn-primary:disabled:hover,
.btn-primary[disabled]:hover {
  box-shadow: none;
}

/* Focus states: violet core ring, always visible, never removed
   without an equal-or-better replacement. Meets the WCAG 1.4.11 non-text
   3:1 floor against every background it appears on in this file, but the
   margin is NOT uniform: --violet #8B5CF6 computes ~4.77:1 on --bg-1,
   ~4.64:1 on --bg-2, ~4.46:1 on --bg-elevated, and only ~3.18:1 on
   --bg-card #2C2C47 (reachable via the no-JS success page's focusable
   link) — thin but compliant. Do not lighten --bg-card further without
   re-checking this pair; 0.18 is the entire remaining margin. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible {
  outline: 2px solid var(--violet);
  outline-offset: 2px;
}

.btn-submit { width: 100%; margin-top: 8px; }

/* Expanded intake fields: hidden until JS reveals them.
   No-JS visitors see them by default. The 'js-enhanced' class is set
   pre-paint by an inline <head> script (to avoid a collapse-after-paint
   flash), re-confirmed by js/main.js once it actually runs end to end,
   and removed again by the script tag's onerror handler (or by
   main.js's own early-exit guard) if the script fails to load or run —
   so a broken/blocked main.js falls back to the fully-visible no-JS
   layout instead of getting stuck collapsed with nothing to reveal it. */
.intake-expanded {
  margin-top: 20px;
  display: block;
}

html.js-enhanced .intake-expanded[data-collapsed="true"] {
  display: none;
}

.field {
  margin-bottom: 16px;
}

.field label {
  display: block;
  font-size: 0.9rem;
  color: var(--text-dim);
  margin-bottom: 6px;
}

/* 0.7 opacity on --text-dim rendered at ~4.02:1 (below AA at this
   0.9rem/14.4px size) — bumped to 0.85 (~5.45:1) so the "(optional)"
   markers on the lead form clear AA with real margin. */
.optional { font-weight: 400; opacity: 0.85; }

.field input,
.field textarea,
.field select {
  width: 100%;
  padding: 12px 14px;
  border-radius: 8px;
  border: 1px solid var(--border-interactive);
  background: var(--bg-elevated);
  color: var(--text);
  font-family: inherit;
  /* 16px minimum — iOS Safari auto-zooms the viewport on focus for any
     input font-size under 16px, which jars the layout mid-funnel. */
  font-size: 1rem;
}

/* Browser-default placeholder color (~#757575, 3.91:1 against
   --bg-elevated / --bg-card) fails WCAG AA (needs 4.5:1). --text-dim
   (#9B9BB0) computes to ~6.9:1 against --bg-elevated (#10101C) and
   ~4.96:1 against --bg-card (#2C2C47) — both clear AA. Applies to the
   hero input, "Tell us more" textarea, and timeline field (all share
   these background/placeholder rules). No low-contrast placeholder
   tricks. */
.hero-input::placeholder,
.field input::placeholder,
.field textarea::placeholder {
  color: var(--text-dim);
  opacity: 1; /* Firefox lowers placeholder opacity by default */
}

.field input:-webkit-autofill,
.field textarea:-webkit-autofill {
  -webkit-box-shadow: 0 0 0 1000px var(--bg-elevated) inset;
  -webkit-text-fill-color: var(--text);
  caret-color: var(--text);
}

.field-row {
  display: flex;
  flex-direction: column;
  gap: 0;
}

@media (min-width: 640px) {
  .field-row {
    flex-direction: row;
    gap: 16px;
  }
  .field-row .field { flex: 1; }

  .hero-input-row {
    flex-direction: row;
  }
  .hero-input { flex: 1; }
  .hero-input-row .btn { flex-shrink: 0; }
}

.field-consent {
  margin-bottom: 16px;
}

.consent-label {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 0.9rem;
  color: var(--text-dim);
  cursor: pointer;
}

.consent-label input[type="checkbox"] {
  width: auto;
  margin-top: 3px;
  flex-shrink: 0;
}

.form-fallback-note {
  font-size: 0.85rem;
  text-align: center;
  margin-top: 14px;
}

.form-error {
  color: var(--danger);
  font-size: 0.9rem;
  margin-top: 10px;
}

/* TRIPWIRE round-4 re-gate (Blocker 3): the swapped hero heading/
   subheadline is the actual scrollIntoView() target on JS success (see
   site/js/main.js scrollToConfirmation()) — this is what needs clearance
   from the sticky header, not #intake-success alone. Matches
   .how-it-works/.services's own scroll-margin-top; header occupies
   y=0-72px, so this gives ~16px of breathing room. */
#hero-headline {
  scroll-margin-top: 88px;
}

.intake-success {
  max-width: 560px;
  margin: 32px auto 0;
  padding: 24px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-card);
  box-shadow: 0 0 0 1px rgba(139, 92, 246, 0.08);
  /* Kept as a fallback scroll-margin for direct navigation to this
     element (e.g. the no-JS ?sent=1 success page, or a future caller
     that scrolls straight here) — the JS happy-path itself now scrolls
     to #hero-headline instead, see the rule above. */
  scroll-margin-top: 88px;
}

.intake-success h2 { color: var(--success); }

/* ---------- How It Works ---------- */
/* Section accent: amber (Accent A). Cyan does not appear anywhere in
   this section — one accent per view. */

.how-it-works {
  padding: 64px 0;
  border-top: 1px solid var(--border);
  /* Sticky header is ~70-72px tall — without this, the header clips the
     top of this section when a visitor lands here via the nav anchor. */
  scroll-margin-top: 88px;
}

.how-it-works h2 { text-align: center; margin-bottom: 40px; }

.steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr;
  gap: 24px;
}

@media (min-width: 760px) {
  .steps { grid-template-columns: repeat(4, 1fr); }
}

.step {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 24px 20px;
}

.step-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 999px;
  background: rgba(245, 158, 11, 0.14);
  border: 1px solid rgba(245, 158, 11, 0.55);
  color: var(--amber);
  font-weight: 700;
  margin-bottom: 14px;
}

/* ---------- Services ---------- */
/* Section accent: cyan (Accent B). Amber does not appear anywhere in
   this section — one accent per view. */

.services {
  padding: 64px 0 80px;
  border-top: 1px solid var(--border);
  /* Sticky header is ~70-72px tall — without this, the header clips the
     top of this section when a visitor lands here via the nav anchor. */
  scroll-margin-top: 88px;
}

.services h2 { text-align: center; margin-bottom: 40px; }

.service-cards {
  display: grid;
  grid-template-columns: 1fr;
  gap: 20px;
}

@media (min-width: 760px) {
  .service-cards { grid-template-columns: repeat(3, 1fr); }
}

.service-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-top: 2px solid rgba(34, 211, 238, 0.6);
  border-radius: var(--radius);
  padding: 28px 24px;
}

.services-cta {
  text-align: center;
  margin-top: 40px;
}

/* ---------- Footer ---------- */

.site-footer {
  border-top: 1px solid var(--border);
  padding: 32px 0;
}

.footer-inner {
  text-align: center;
}

.footer-brand {
  color: var(--text);
  font-weight: 600;
  margin-bottom: 6px;
}

.footer-contact { margin: 0; font-size: 0.9rem; }

.footer-legal {
  margin: 10px 0 0;
  font-size: 0.8rem;
}

/* ---------- Legal pages (privacy / terms) ---------- */

.legal-page h1 { margin-bottom: 0.3em; }

.legal-page .legal-updated {
  font-size: 0.85rem;
  margin-bottom: 2em;
}

.legal-page h2 {
  font-size: 1.25rem;
  margin-top: 2em;
}

.legal-page ul { color: var(--text-dim); }

.legal-page .legal-note {
  margin-top: 2.5em;
  padding: 16px 20px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-card);
  font-size: 0.9rem;
}
