/* ============================================================
   Civic Lattice — Layout & reusable patterns
   Container, section rhythm, buttons, header, footer.
   These are deliberately page-agnostic: every future page
   (Platform, Pricing, Pilot, About…) should be built from these.
   ============================================================ */

/* ---- Container --------------------------------------------- */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.container--narrow { max-width: 860px; }

/* ---- Section rhythm ---------------------------------------- */
.section { padding-block: var(--section-y); }
.section--alt { background: var(--paper-2); }
.section--ink {
  background: var(--ink-surface);
  color: var(--on-ink-2);
}
.section--ink h1, .section--ink h2, .section--ink h3 { color: var(--on-ink); }
.section--ink .eyebrow { color: var(--accent-on-ink); }
.section--ink a:not(.btn) { color: var(--accent-on-ink); }
.section--ink a:not(.btn):hover { color: var(--on-ink); }

.section--hairline { border-top: 1px solid var(--line); }

.section__head { max-width: 46rem; }
.section__head > * + * { margin-top: var(--sp-4); }
.section__body { margin-top: clamp(2.25rem, 1rem + 4vw, 3.5rem); }

/* ---- Eyebrow label ----------------------------------------- */
.eyebrow {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--accent-ink);
}
.eyebrow::before {
  content: '';
  flex: 0 0 auto;
  width: 22px;
  height: 1px;
  background: currentColor;
}

/* ---- Lead paragraph ---------------------------------------- */
.lead {
  font-size: var(--fs-lead);
  line-height: 1.56;
  color: var(--ink-2);
  max-width: var(--measure);
}
.section--ink .lead { color: var(--on-ink-2); }

.muted { color: var(--ink-3); }

/* ---- Buttons ------------------------------------------------
   <a> when it navigates, <button> when it acts. Both share .btn. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: 46px;
  padding: 0 var(--sp-5);
  border: 1px solid transparent;
  border-radius: var(--r);
  font-size: var(--fs-sm);
  font-weight: 500;
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color var(--dur) var(--ease),
              border-color var(--dur) var(--ease),
              color var(--dur) var(--ease);
}

.btn--primary { background: var(--accent-ink); color: var(--paper); }
.btn--primary:hover { background: var(--accent-deep); color: var(--paper); }

.btn--ghost {
  background: transparent;
  border-color: var(--line);
  color: var(--ink);
}
.btn--ghost:hover { border-color: var(--ink-3); color: var(--ink); background: var(--paper-2); }

.btn--on-ink { background: var(--paper); color: var(--ink); }
.btn--on-ink:hover { background: var(--paper-3); color: var(--ink); }

.btn--ghost-on-ink {
  background: transparent;
  border-color: var(--on-ink-line);
  color: var(--on-ink);
}
.btn--ghost-on-ink:hover { border-color: var(--on-ink-2); color: var(--on-ink); }

.btn--sm { min-height: 38px; padding: 0 var(--sp-4); font-size: var(--fs-xs); }

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
}

/* ---- Status chip (non-interactive) -------------------------- */
.status {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-4) var(--sp-2) var(--sp-3);
  border: 1px solid var(--accent-line);
  background: var(--accent-wash);
  border-radius: var(--r-pill);
  font-size: var(--fs-xs);
  font-weight: 500;
  color: var(--accent-ink);
}
.status__dot {
  flex: 0 0 auto;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--accent);
}
.section--ink .status {
  background: rgba(232, 51, 109, 0.12);
  border-color: rgba(232, 51, 109, 0.45);
  color: var(--accent-on-ink);
}

/* ============================================================
   HEADER
   ============================================================ */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(255, 255, 255, 0.86);
  backdrop-filter: saturate(180%) blur(12px);
  -webkit-backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.site-header.is-scrolled { border-bottom-color: var(--line); }

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-5);
  min-height: var(--header-h);
}

/* ---- Brand lockup ------------------------------------------
   The Lattice wordmark, as vector (assets/LatticeColor.svg, and White for the
   dark footer). It has to stay vector: the letterforms are hairline outlines,
   and a raster copy of them aliases into something that reads as pixelated the
   moment the mark is drawn large. */
.brand {
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
  text-decoration: none;
}
.brand img {
  display: block;
  height: 26px;
  width: auto;
}
.site-footer .brand img { height: 24px; }

/* ---- Brand settles into the bar ---------------------------
   At the top of the page there is no bar at all: just the wordmark, large,
   sitting on the page. Scrolling condenses it — the panel and hairline appear,
   the navigation fades in with them, and the wordmark shrinks to its usual
   size. Desktop only; on a phone the nav is dropped anyway and the bar has no
   room to give.

   Two details that matter. The wordmark scales with `transform`, not `height`,
   so the browser never re-rasterises the PNG mid-animation and the shrink is
   composited rather than laid out. And the whole thing keys off one class with
   a scroll dead band behind it (see site.js), so it cannot chatter.

   Reduced motion drops the transitions and leaves the condensed state, which
   is the right place to rest. */
@media (min-width: 700px) {
  .site-header.can-condense {
    background: transparent;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
  .site-header.is-scrolled {
    background: rgba(255, 255, 255, 0.86);
    backdrop-filter: saturate(180%) blur(12px);
    -webkit-backdrop-filter: saturate(180%) blur(12px);
  }

  .site-header__inner {
    min-height: calc(var(--header-h) + 28px);
    transition: min-height 320ms var(--ease);
  }
  .site-header.is-scrolled .site-header__inner { min-height: var(--header-h); }

  .site-header .brand img {
    height: 54px;
    transform-origin: left center;
    transition: transform 320ms var(--ease);
  }
  /* 26 / 54 — the size the wordmark has everywhere else on the site. */
  .site-header.is-scrolled .brand img { transform: scale(0.4815); }

  /* The links arrive with the bar; Sign in stays put at every scroll position,
     so the way into the application is never more than a glance away.
     `visibility` is held until the fade finishes so nothing invisible is
     clickable or reachable by keyboard — except that a keyboard user who tabs
     into the header gets it back immediately, bar and all. `can-condense` is
     set by site.js, so with no script the bar simply stays as it always was. */
  .site-header.can-condense .nav {
    opacity: 0;
    visibility: hidden;
    transition: opacity 220ms var(--ease), visibility 0s linear 220ms;
  }
  .site-header.is-scrolled .nav,
  .site-header:focus-within .nav {
    opacity: 1;
    visibility: visible;
    transition-delay: 0s;
  }
  .site-header:focus-within {
    background: rgba(255, 255, 255, 0.86);
    backdrop-filter: saturate(180%) blur(12px);
    -webkit-backdrop-filter: saturate(180%) blur(12px);
  }
}

@media (max-width: 400px) {
  .brand img { height: 22px; }
}

.site-header__actions {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin-left: auto;
  flex: 0 0 auto;
}

/* ---- Nav -----------------------------------------------------
   Three in-page anchors only. On phones they are dropped rather than
   hidden behind a hamburger: the page is one short scroll, and the two
   things worth reaching from the header — pricing status and Sign In —
   stay put at every width. */
.nav { display: none; margin-left: auto; }
@media (min-width: 880px) { .nav { display: flex; align-items: center; } }

.nav__list {
  display: flex;
  align-items: center;
  gap: var(--sp-6);
  list-style: none;
  padding: 0;
  margin: 0;
}
.nav__link {
  position: relative;
  display: inline-block;
  padding-block: var(--sp-2);
  font-size: var(--fs-sm);
  color: var(--ink-2);
  text-decoration: none;
}
.nav__link:hover { color: var(--ink); }
.nav__link::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 2px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur) var(--ease);
}
.nav__link:hover::after { transform: scaleX(1); }

/* ---- Menu button -------------------------------------------
   The four in-page links are dropped below 880px, where there is no room for
   them in the bar. This reaches them. It sits left of the wordmark and only
   exists when there is script to open it — `has-menu` is set by site.js — so
   a scripted page never shows a control that cannot work.

   Three bars that fold into a cross. `currentColor` so it inherits the header's
   ink, and a 40px box so the tap target clears the 24px minimum with room. */
.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  margin-left: -9px;
  padding: 0;
  border: 0;
  border-radius: 10px;
  background: none;
  color: var(--ink);
  cursor: pointer;
  /* The button paints its own press state, so the platform's blue flash on tap
     would only fight it. */
  -webkit-tap-highlight-color: transparent;
}
.nav-toggle:active { background: var(--paper-2); }
@media (hover: hover) {
  .nav-toggle:hover { background: var(--paper-2); }
}
.nav-toggle__box { position: relative; display: block; width: 20px; height: 14px; }
.nav-toggle__box span {
  position: absolute;
  left: 0;
  right: 0;
  height: 2px;
  border-radius: 2px;
  background: currentColor;
  transition: transform 240ms var(--ease), opacity 140ms linear;
}
.nav-toggle__box span:nth-child(1) { top: 0; }
.nav-toggle__box span:nth-child(2) { top: 6px; }
.nav-toggle__box span:nth-child(3) { top: 12px; }
.is-menu-open .nav-toggle__box span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.is-menu-open .nav-toggle__box span:nth-child(2) { opacity: 0; }
.is-menu-open .nav-toggle__box span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

/* Below 880px the bar shows the button, and opening it drops the same nav
   element down as a panel — one list of links, not a second copy of them. */
@media (max-width: 879px) {
  .site-header.has-menu .nav-toggle { display: inline-flex; }
  /* Only the gap between the button and the wordmark: the actions are pushed
     right by their own auto margin. */
  .site-header__inner { gap: var(--sp-4); }

  .site-header.is-menu-open {
    background: rgba(255, 255, 255, 0.96);
    backdrop-filter: saturate(180%) blur(12px);
    -webkit-backdrop-filter: saturate(180%) blur(12px);
  }
  .site-header.is-menu-open .nav {
    display: block;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    margin: 0;
    padding-block: var(--sp-3) var(--sp-4);
    background: var(--paper);
    border-bottom: 1px solid var(--line);
    /* Outranks the condensed-bar fade, which reaches down to 700px. */
    opacity: 1;
    visibility: visible;
  }
  .site-header.is-menu-open .nav__list {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
  }
  .site-header.is-menu-open .nav__link {
    display: block;
    padding: var(--sp-3) clamp(1.25rem, 5vw, 2.5rem);
    font-size: 1rem;
    color: var(--ink);
  }
  /* The sliding underline belongs to a row of links, not a stacked list. */
  .site-header.is-menu-open .nav__link::after { content: none; }
  .site-header.is-menu-open .nav__link:hover { background: var(--paper-2); }
}

/* ---- Header utilities -------------------------------------- */
@media (max-width: 560px) { .brand img { height: 22px; } }
@media (max-width: 380px) { .brand img { height: 20px; } }

/* ============================================================
   FOOTER
   ============================================================ */
.site-footer {
  background: var(--ink-surface);
  color: var(--on-ink-2);
  padding-block: var(--sp-9) var(--sp-6);
  font-size: var(--fs-sm);
}
.site-footer .brand { color: var(--on-ink); }
.site-footer .brand:hover { color: var(--on-ink); }

.site-footer__top {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) repeat(2, minmax(0, 1fr));
  gap: var(--sp-8) var(--sp-6);
  padding-bottom: var(--sp-7);
  border-bottom: 1px solid var(--on-ink-line);
}
.site-footer__tagline {
  margin-top: var(--sp-4);
  max-width: 34ch;
  color: var(--on-ink-2);
}

.footer-nav h2 {
  font-family: var(--font-sans);
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--on-ink-2);
  margin-bottom: var(--sp-4);
}
.footer-nav ul { list-style: none; padding: 0; margin: 0; display: grid; gap: var(--sp-3); }
.footer-nav a { color: var(--on-ink); text-decoration: none; }
.footer-nav a:hover { color: var(--accent-on-ink); text-decoration: underline; }

.site-footer__bottom a { color: var(--accent-on-ink); }
.site-footer__bottom a:hover { color: var(--on-ink); }

.site-footer__bottom {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3) var(--sp-5);
  justify-content: space-between;
  align-items: center;
  padding-top: var(--sp-5);
  font-size: var(--fs-xs);
  color: var(--on-ink-2);
}

@media (max-width: 899px) {
  .site-footer__top { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .site-footer__top > :first-child { grid-column: 1 / -1; }
}
@media (max-width: 479px) {
  .site-footer__top { grid-template-columns: 1fr; }
}
