/* Vector Political — landing page styles
   Tokens mirror design-spec.md §2–§3. Keep in sync with scripts/network.js palette. */

:root {
  --bg:          #F4F0E8;
  --bg-header:   #F6F3EB;
  --ink:         #152133;
  --ink-soft:    #2B333F;
  --slate:       #5E7088;
  --green:       #2E4B33;
  --green-dark:  #243C29;
  --on-green:    #F4F0E8;
  --rule:        rgba(21, 33, 51, 0.12);

  --gutter: clamp(1.5rem, 6vw, 6rem);

  --serif: "Playfair Display", Georgia, "Times New Roman", serif;
  --sans:  "Hanken Grotesk", system-ui, sans-serif;
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink-soft);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  min-height: 100vh;
}

/* ---------- Hero ---------- */
.hero {
  display: grid;
  grid-template-columns: minmax(0, 42fr) minmax(0, 58fr);
  align-items: center;
  min-height: 100vh;
  overflow-x: clip;
}

.hero__text {
  /* top-aligned (not centered) so there's no large empty band above the headline;
     the tall illustration column stays vertically centered. */
  align-self: start;
  padding: clamp(3rem, 7vh, 6.5rem) clamp(1rem, 3vw, 3rem)
           clamp(2rem, 5vw, 4rem) var(--gutter);
  max-width: 42rem;
}

.headline {
  font-family: var(--serif);
  font-weight: 800;
  font-size: clamp(3.4rem, 8.6vw, 9rem);
  line-height: 0.92;
  letter-spacing: -0.012em;
  color: var(--ink);
  margin: 0;
}
.headline span { display: block; }

.subhead {
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(1.35rem, 2.5vw, 2.15rem);
  line-height: 1.18;
  color: var(--slate);
  margin: 1.6rem 0 0;
  max-width: 34rem;
}

.lede {
  font-family: var(--sans);
  font-weight: 400;
  font-size: clamp(1.05rem, 1.35vw, 1.3rem);
  line-height: 1.55;
  color: var(--ink-soft);
  margin: 1.5rem 0 0;
  max-width: 30rem;
}

/* editorial text link: ink label + drawn arrow, green underline draws in on hover */
.cta {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.95rem;
  margin-top: 2.6rem;
  padding-bottom: 0.5rem;      /* room for the underline */
  color: var(--ink);
  font-family: var(--sans);
  font-weight: 600;
  font-size: clamp(1.15rem, 1.5vw, 1.45rem);
  letter-spacing: 0.01em;
  text-decoration: none;
  transition: color .3s ease;
}
.cta::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1.5px;
  background: var(--green);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .5s cubic-bezier(.2, .7, .2, 1);
}
.cta__arrow {
  width: clamp(2.3rem, 3vw, 2.9rem);
  height: auto;
  overflow: visible;
  transition: transform .35s cubic-bezier(.2, .7, .2, 1);
}
.cta:hover { color: var(--green); }
.cta:hover::after { transform: scaleX(1); }
.cta:hover .cta__arrow { transform: translateX(7px); }
.cta:focus-visible { outline: 2px solid var(--green); outline-offset: 6px; border-radius: 2px; }

/* ---------- Network illustration ---------- */
.hero__art {
  align-self: stretch;      /* fill the full hero height, top to bottom */
  min-height: 100%;
  overflow: hidden;
  /* bleed leftward toward the text so the field stretches across the page */
  margin-left: clamp(-9rem, -7vw, -3rem);
}
#network {
  /* fill the box and bleed off all edges (slice) so the graphic reaches the
     very top/bottom of the window instead of being letterboxed */
  width: 100%;
  height: 100%;
  display: block;
}

.net-path {
  fill: none;
  stroke-linecap: round;
}
.net-node {
  transform-box: fill-box;
  transform-origin: center;
}

/* ---------- Load animation ---------- */
@keyframes fadeUp {
  from { opacity: 0; transform: translateY(18px); }
  to   { opacity: 1; transform: translateY(0); }
}
.reveal { opacity: 0; animation: fadeUp .9s cubic-bezier(.2,.7,.2,1) forwards; }
.reveal.d1 { animation-delay: .05s; }
.reveal.d2 { animation-delay: .15s; }
.reveal.d3 { animation-delay: .28s; }
.reveal.d4 { animation-delay: .40s; }
.reveal.d5 { animation-delay: .52s; }

/* JS-driven graph reveal */
.net-path {
  transition: stroke-dashoffset 1.7s cubic-bezier(.4,0,.2,1);
}
.net-node {
  transform: scale(0);
  opacity: 0;
  transition: transform .7s cubic-bezier(.34,1.56,.64,1), opacity .6s ease;
}
.net-node.in { transform: scale(1); opacity: 1; }

/* continuous, subtle life in the graph */
.node-wrap { will-change: transform; }
@keyframes drift {
  to { transform: translate(var(--dx, 0), var(--dy, 0)); }
}
@keyframes nodePulse {
  to { opacity: 0.4; }
}

/* ---------- Responsive ---------- */
@media (max-width: 960px) {
  /* The art slides BEHIND the text: the hero becomes a single stacking area,
     the illustration fills it absolutely, and the text is overlaid on top.
     The art's left edge is pinned to the text gutter, and network.js reframes
     the SVG so the hub (its origin) sits at that same edge — so the left of the
     text and the left of the animation line up, with the field fanning right
     behind the copy. */
  .hero {
    display: block;
    position: relative;
    min-height: 100vh;
  }
  .hero__text {
    position: relative;
    z-index: 1;
    max-width: none;
    padding: clamp(2.5rem, 11vh, 5rem) var(--gutter) clamp(3rem, 9vh, 5rem);
  }
  .hero__art {
    position: absolute;
    inset: 0 0 0 var(--gutter);   /* left edge sits at the text gutter */
    margin-left: 0;
    min-height: 0;
    opacity: 0.5;
    z-index: 0;
    pointer-events: none;
  }
  #network { height: 100%; }
}

@media (max-width: 560px) {
  .cta { width: 100%; justify-content: space-between; }
}

@media (prefers-reduced-motion: reduce) {
  .reveal { animation: none; opacity: 1; transform: none; }
  .net-path { transition: none; }
  .net-node { transition: none; transform: scale(1); opacity: 1; }
  .node-wrap { animation: none !important; }
  .cta, .cta__arrow, .cta::after { transition: none; }
}

/* ============================================================
   Contact modal — "Vector converge"
   ============================================================ */
.modal {
  padding: 0;
  border: none;
  background: transparent;
  overflow: visible;                 /* let the converging field spill past the card */
  max-width: min(92vw, 460px);
  width: 100%;
  color: var(--ink-soft);
}
.modal::backdrop {
  background: rgba(244, 240, 232, 0.55);   /* warm cream veil, not harsh black */
  backdrop-filter: blur(7px) saturate(115%);
  -webkit-backdrop-filter: blur(7px) saturate(115%);
  animation: modalBackdrop .4s ease both;
}
@keyframes modalBackdrop { from { opacity: 0; } to { opacity: 1; } }

.modal__net {
  position: absolute;
  inset: -90px;
  width: calc(100% + 180px);
  height: calc(100% + 180px);
  z-index: 0;
  pointer-events: none;
}
.mpath { fill: none; stroke-linecap: round; }
.mnode {
  transform-box: fill-box;
  transform-origin: center;
  transform: scale(0);
  opacity: 0;
  transition: transform .6s cubic-bezier(.34, 1.56, .64, 1), opacity .5s ease;
}
.mnode.in { transform: scale(1); opacity: 1; }

.modal__card {
  position: relative;
  z-index: 1;
  background: var(--bg);
  border: 1px solid var(--rule);
  border-radius: 4px;
  box-shadow: 0 34px 90px -34px rgba(21, 33, 51, 0.4);
  padding: clamp(1.9rem, 4vw, 2.8rem);
}
.modal[open] .modal__card { animation: modalIn .55s cubic-bezier(.2, .7, .2, 1) both; }
@keyframes modalIn {
  from { opacity: 0; transform: translateY(18px) scale(.985); }
  to   { opacity: 1; transform: none; }
}

.modal__close {
  position: absolute;
  top: 1.1rem;
  right: 1.1rem;
  width: 2rem;
  height: 2rem;
  display: grid;
  place-items: center;
  border: none;
  background: transparent;
  color: var(--slate);
  cursor: pointer;
  border-radius: 50%;
  transition: color .25s ease, background .25s ease;
}
.modal__close svg { width: 15px; height: 15px; }
.modal__close:hover { color: var(--ink); background: rgba(21, 33, 51, 0.06); }
.modal__close:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }

.modal__eyebrow {
  font-family: var(--sans);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--slate);
  margin: 0 0 0.6rem;
}
.modal__title {
  font-family: var(--serif);
  font-weight: 700;
  font-size: clamp(1.8rem, 3.2vw, 2.4rem);
  line-height: 1.05;
  color: var(--ink);
  margin: 0;
}
.modal__sub {
  font-family: var(--sans);
  font-size: 1rem;
  line-height: 1.5;
  color: var(--ink-soft);
  margin: 0.7rem 0 0;
  max-width: 30rem;
}

.modal__form { margin-top: 0.6rem; }

/* underline-only fields with a floating label + green focus underline */
.field { position: relative; margin-top: 1.7rem; }
.field input,
.field textarea {
  width: 100%;
  border: none;
  border-bottom: 1.5px solid var(--rule);
  background: transparent;
  font-family: var(--sans);
  font-size: 1.02rem;
  color: var(--ink);
  padding: 0.45rem 0;
  outline: none;
  resize: none;
}
.field label {
  position: absolute;
  left: 0;
  top: 0.45rem;
  font-family: var(--sans);
  font-size: 1.02rem;
  color: var(--slate);
  pointer-events: none;
  transform-origin: left top;
  transition: transform .25s ease, color .25s ease;
}
.field label span { color: var(--slate); opacity: 0.7; }
.field input:focus + label,
.field input:not(:placeholder-shown) + label,
.field textarea:focus + label,
.field textarea:not(:placeholder-shown) + label {
  transform: translateY(-1.45rem) scale(0.8);
  color: var(--green);
}
.field::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1.5px;
  background: var(--green);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .4s cubic-bezier(.2, .7, .2, 1);
}
.field:focus-within::after { transform: scaleX(1); }

/* submit reuses the editorial arrow-link language */
.modal__submit {
  margin-top: 2rem;
  display: inline-flex;
  align-items: center;
  gap: 0.9rem;
  padding: 0 0 0.4rem;
  border: none;
  background: transparent;
  color: var(--ink);
  font-family: var(--sans);
  font-weight: 600;
  font-size: 1.1rem;
  letter-spacing: 0.01em;
  cursor: pointer;
  position: relative;
  transition: color .3s ease;
}
.modal__submit::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1.5px;
  background: var(--green);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .5s cubic-bezier(.2, .7, .2, 1);
}
.modal__submit .cta__arrow {
  width: 2.6rem; height: auto; overflow: visible;
  transition: transform .35s cubic-bezier(.2, .7, .2, 1);
}
.modal__submit:hover { color: var(--green); }
.modal__submit:hover::after { transform: scaleX(1); }
.modal__submit:hover .cta__arrow { transform: translateX(7px); }
.modal__submit:focus-visible { outline: 2px solid var(--green); outline-offset: 6px; border-radius: 2px; }

.modal__success { text-align: left; padding: 0.5rem 0; }
.modal__success .modal__done { margin-top: 1.6rem; }

/* Honeypot: kept in the DOM for bots, removed from view/flow and a11y tree. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px; height: 1px;
  overflow: hidden;
}

.modal__error {
  margin: 1.1rem 0 0;
  color: #BC6A4E;
  font-family: var(--sans);
  font-size: 0.9rem;
  line-height: 1.4;
}

/* Sending state: dim the submit and show a wait cursor. */
.modal__submit[aria-busy="true"] { opacity: 0.55; cursor: wait; }

@media (max-width: 560px) {
  .modal { max-width: 94vw; }
  .modal__card { padding: 1.6rem 1.3rem; }
}

@media (prefers-reduced-motion: reduce) {
  .modal::backdrop { animation: none; }
  .modal[open] .modal__card { animation: none; }
  .mnode { transition: none; transform: scale(1); opacity: 1; }
  .mpath { transition: none; }
  .field label, .field::after,
  .modal__submit, .modal__submit::after, .modal__submit .cta__arrow { transition: none; }
}
