/*
  AgencyLadder — shared site chrome: header (nav + hamburger) and footer.

  ── WHY THIS FILE EXISTS (ODO-32, KING JOE direct, 2026-08-21) ────────────────────────────────
  "THE HEADER MENU IS ONLY AVAILABLE ON HOMEPAGE??????????? IT IS SIGN IN DASHBOARD AWARE???????????"
  Every page used to hand-roll its own header (`.topbar` in six static pages, `.dir-topbar` in
  the directory, `.detail-topbar` on the listing page) — a fix made in one never reached the
  other five. This is the ONE definition. public/js/chrome.js renders into the two mount points
  every page now carries (`#chromeHeader` / `#chromeFooter`) using ONLY the classes below, so
  fixing the header once fixes it everywhere.

  No media queries (DESIGN-SYSTEM §4). The nav does not have a viewport breakpoint at all — it
  has three CONTAINER-DRIVEN modes, applied as a class by chrome.js after it measures whether the
  full link row actually fits the header's available width (a hidden nowrap ruler, the same
  technique public/index.html's rotateText() already uses for the hero CTA). The safe default,
  before that JS measurement ever runs, is the NARROWEST mode — mobile-first, so a slow script
  load never flashes an overflowing desktop nav:

    (default / .nav-mode-minimal)  wordmark …………………………………………… [≡]
    .nav-mode-compact              wordmark …………………… [List ($1)] [≡]
    .nav-mode-full                 wordmark   Board Directory How it works Sign in   [List your agency for $1]
*/

:root {
  --gutter: clamp(16px, 8.989px + 1.798vw, 32px);
}

/* =========================================================================
   HEADER
   ========================================================================= */
/* The WRAPPER is what sticks, not just the header inside it.
   ------------------------------------------------------------------------------------------------
   `.site-header` has had `position: sticky; top: 0` all along and it never worked. Measured in a
   browser: `#chromeHeader` is a static block exactly 69px tall, and `.site-header` inside it is
   also 69px. A sticky element can only stick WITHIN ITS PARENT'S BOX, so with zero spare room it
   left the viewport the instant the wrapper did. Scrolling 900px put the header at top: -900.

   That is why reading the CSS said "sticky" while the page said otherwise, and why this survived
   several passes: the declaration was right, its containing block was wrong.

   Making the wrapper sticky gives the header a containing block that spans the document, so it
   pins for real. `.site-header` keeps its own sticky declaration harmlessly, and the wrapper takes
   the z-index so the drawer scrim (z 30+) still covers it. */
#chromeHeader {
  position: sticky;
  top: 0;
  z-index: 20;
}

.site-header {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--header-bg);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--border);
}

.site-header-inner {
  max-width: 1200px;
  margin: 0 auto;
  padding: 12px var(--gutter);
  display: flex;
  flex-wrap: nowrap;
  justify-content: space-between;
  align-items: center;
  gap: 14px;
}

.wordmark {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 0 0 auto;
  cursor: pointer;
  min-width: 0;
}

/* Ladder mark: two rails, three rungs, inline <svg> per DESIGN-SYSTEM §8 — the one sanctioned
   exception to "no icon set". Uniform on every page (KING JOE: "THE LOGO SHOULD BE UNIFORM
   GLOWING LADDER LIKE THE HOMEPAGE ON EVERY PAGE"). currentColor so it inherits --accent, and it
   reuses the SAME `pls` keyframe the live dot already uses rather than inventing a second one. */
.wordmark-ladder {
  width: 10px;
  height: 14px;
  color: var(--accent);
  fill: currentColor;
  flex: none;
  display: block;
  animation: pls 2s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
  /* The one prefers-reduced-motion query in this codebase (DESIGN-SYSTEM §4's own carve-out) —
     an accessibility feature query, not a layout breakpoint. */
  .wordmark-ladder {
    animation: none;
  }
}

.wordmark-text {
  font: 800 var(--fs-wordmark) / 1 var(--font-sans);
  letter-spacing: var(--ls-wordmark);
  color: var(--text);
  white-space: nowrap;
}

.site-header-right {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 0 1 auto;
  min-width: 0;
}

/* Inline link row — only shown in nav-mode-full. Never wraps; when it doesn't fit, chrome.js
   drops the whole header into compact/minimal mode instead of letting it wrap onto a second
   line (that WAS the old bug — "the nav renders as a right-aligned stack of links overlapping
   the wordmark"). */
.site-nav-links {
  display: none;
  align-items: center;
  gap: 4px;
  flex-wrap: nowrap;
  white-space: nowrap;
}

.nav-link {
  font: 600 14px / 1 var(--font-sans);
  color: var(--text-muted);
  padding: 15px 12px;
  border-radius: 7px;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color .15s ease, color .15s ease;
}

.nav-link:hover {
  background: var(--inset);
  color: var(--text);
}

.nav-link.is-active {
  color: var(--text);
}

.nav-cta-inline {
  display: none;
  white-space: nowrap;
  flex: none;
}

/* Hamburger — 44px tap target floor (§5.1), shown by default (the safe mobile-first state) and
   hidden only once nav-mode-full is confirmed to fit. */
.nav-toggle {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  width: 44px;
  height: 44px;
  flex: none;
  border-radius: var(--radius-btn);
  border: 1px solid var(--border-loud);
  background: transparent;
  cursor: pointer;
  transition: border-color .15s ease, background-color .15s ease;
}

.nav-toggle:hover {
  border-color: var(--text);
  background: var(--inset);
}

.nav-toggle-bar {
  width: 18px;
  height: 2px;
  border-radius: 1px;
  background: var(--text);
  transition: transform .2s ease, opacity .2s ease;
}

.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* Mode escalation — each step ADDS to the safe default above rather than overriding it, so a
   renderer that never runs (JS disabled, a throw before the measurement) still shows a working,
   if minimal, header — never a broken or overflowing one. */
.site-header-inner.nav-mode-compact .nav-cta-inline { display: inline-flex; }

.site-header-inner.nav-mode-full .site-nav-links { display: flex; }
.site-header-inner.nav-mode-full .nav-cta-inline { display: inline-flex; }
.site-header-inner.nav-mode-full .nav-toggle { display: none; }

/* =========================================================================
   NAV DRAWER — full-height panel, slides from the right. Not the §5.7 bottom
   sheet (this is persistent navigation chrome, not a transient bid sheet)
   but reuses its scrim value and its rise easing rather than inventing a
   third motion curve.
   ========================================================================= */
.nav-scrim {
  position: fixed;
  inset: 0;
  z-index: 45;
  background: var(--modal-backdrop);
  opacity: 0;
  pointer-events: none;
  transition: opacity .25s ease;
}

.nav-scrim.is-open {
  opacity: 1;
  pointer-events: auto;
}

.nav-drawer {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 46;
  width: min(320px, 86vw);
  background: var(--card);
  border-left: 1px solid var(--border-loud);
  padding: 16px;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  transform: translateX(100%);
  transition: transform .3s var(--ease-rise);
}

.nav-drawer.is-open {
  transform: translateX(0);
}

.nav-drawer-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex: none;
}

.nav-drawer-close {
  width: 36px;
  height: 36px;
  flex: none;
  border-radius: var(--radius-btn);
  border: 1px solid var(--border-loud);
  background: transparent;
  color: var(--text);
  font: 500 14px/1 var(--font-mono);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.nav-drawer-close:hover {
  border-color: var(--text);
  background: var(--inset);
}

.nav-drawer-cta {
  margin-top: 18px;
  flex: none;
  display: block;
  width: 100%;
  text-align: center;
}

.nav-drawer-links {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: 18px;
}

.nav-drawer-link {
  display: flex;
  align-items: center;
  min-height: 44px;
  padding: 12px 10px;
  border-radius: var(--radius-btn);
  font: 600 16px / 1.3 var(--font-sans);
  color: var(--text);
  cursor: pointer;
  transition: background-color .15s ease, color .15s ease;
}

.nav-drawer-link:hover,
.nav-drawer-link:focus-visible {
  background: var(--inset);
}

.nav-drawer-link.is-active {
  color: var(--accent);
}

/* =========================================================================
   FOOTER — one definition, three columns (Product / Company / Legal). NEVER
   Admin or 404 (PROTOTYPE-SPEC.md, ruling above §2 — asked for, removed,
   restored by accident, removed again; do not re-add them a third time).
   ========================================================================= */
.site-footer {
  border-top: 1px solid var(--border);
  margin-top: 26px;
  background: var(--page);
}

.site-footer-inner {
  max-width: 1200px;
  margin: 0 auto;
  padding: 44px var(--gutter) 30px;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 36px;
  justify-content: space-between;
}

.footer-brand {
  flex: 1 1 260px;
  max-width: 340px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.footer-note {
  font: 400 14.5px / 1.55 var(--font-sans);
  color: var(--footer-muted);
  text-wrap: pretty;
}

.footer-columns {
  flex: 2 1 400px;
  display: flex;
  flex-wrap: wrap;
  gap: 44px;
}

.footer-col {
  flex: 1 1 130px;
  min-width: 130px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.footer-col .kicker {
  padding-bottom: 8px;
  color: var(--footer-muted);
}

.footer-link {
  font: 500 14.5px / 1 var(--font-sans);
  color: var(--text);
  padding: 15px 0;
  display: block;
  cursor: pointer;
  transition: color .15s ease;
}

.footer-link:hover {
  color: var(--accent);
}

.site-footer-bottom {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 var(--gutter) 30px;
  display: flex;
  flex-direction: column;
  gap: 0;
}

.footer-tribute {
  margin-top: 36px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 11px;
  padding: 18px 20px;
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  align-items: center;
  justify-content: space-between;
}

.footer-tribute-text {
  font: 400 14.5px / 1.5 var(--font-sans);
  color: var(--footer-muted);
  max-width: 620px;
}

.footer-tribute-anchor {
  font-weight: 700;
  color: var(--accent);
}

/* Two tributes now, so the buttons need their own flex context. It wraps rather than shrinks:
   at 390px the pair drops under the sentence instead of squeezing two 13.5px labels into a row
   that cannot hold them. */
.footer-tribute-btns {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.footer-tribute-btn {
  font: 700 13.5px / 1 var(--font-sans);
  color: var(--text);
  border: 1px solid var(--border-loud);
  padding: 12px 15px;
  border-radius: var(--radius-btn);
  white-space: nowrap;
  transition: border-color .15s ease, color .15s ease;
}

.footer-tribute-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
}

/* The sitewide payment disclosure. Centered and narrow so it reads as a statement of terms
   rather than another column of footer links, and deliberately quiet: this is the small print
   that has to be present and legible, not something competing with the board for attention. */
.footer-disclosure {
  max-width: 62rem;
  margin: 0 auto;
  padding: 20px 0 4px;
  border-top: 1px solid var(--border);
  text-align: center;
}
.footer-disclosure p {
  margin: 0 0 10px;
  font: 400 12.5px/1.6 var(--font-sans);
  color: var(--text-dim);
}
.footer-disclosure p:last-child { margin-bottom: 0; }
.footer-disclosure b { color: var(--text-muted); font-weight: 600; }
.footer-disclosure a { color: var(--text-muted); text-decoration: underline; }

/* Sits directly under the disclosure. A visible, working support address is one of the few
   things a card issuer weighs when deciding a dispute: 'did the merchant make it possible to
   contact them first'. It is also just the right thing to have on a page asking for money. */
/* Company identity, sitewide. Same centered column as the disclosure above it, and the same
   deliberately quiet weight: this has to be present and legible, not loud. */
.footer-company {
  max-width: 62rem;
  margin: 0 auto 4px;
  padding: 12px 0 0;
  text-align: center;
}
.footer-company p {
  margin: 0 0 6px;
  font: 400 12.5px/1.6 var(--font-sans);
  color: var(--text-dim);
}
.footer-company p:last-child { margin-bottom: 0; }
.footer-company b { color: var(--text-muted); font-weight: 600; }
.footer-company a { color: var(--text-muted); text-decoration: underline; }
.footer-company a:hover { color: var(--accent); }

.footer-legal-row {
  margin-top: 26px;
  padding-top: 22px;
  border-top: 1px solid var(--border);
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  justify-content: space-between;
  align-items: center;
}

.footer-copyright {
  font: 500 13px / 1.5 var(--font-mono);
  color: var(--footer-muted);
}

.footer-copyright b {
  color: var(--text);
}

.footer-meta {
  font: 500 13px / 1 var(--font-mono);
  color: var(--footer-muted);
  font-variant-numeric: tabular-nums;
}

/* ============================================================================
   NAV MODE — THE ONE PERMITTED MEDIA QUERY IN THIS CODEBASE

   DESIGN-SYSTEM §4 says "no media queries anywhere", and that rule is right for
   LAYOUT: flex-wrap with `flex: N 1 basis` and min-width floors handles every
   板 layout in the product without one.

   A hamburger is not layout. It is TWO DIFFERENT NAVIGATION PATTERNS, and you
   cannot conditionally present one without a viewport test. The previous
   attempt measured scrollWidth while toggling classes, which reads before
   layout settles and concluded the full nav did not fit at 1280 — putting a
   hamburger on DESKTOP, which is exactly the thing nobody wants.

   KING JOE, 2026-08-21: "WHAT THE FUCK IS A HAMBURGER DOING ON DESKTOP. I WAS
   MENTIONING A GLOBAL MENU ON DESKTOP AND HAMBURGER ON MOBILE"

   So: one query, one job, stated plainly. 860px is where the full nav plus the
   lime CTA stops fitting beside the wordmark. Everything else in the codebase
   still uses flex and clamp.
   ============================================================================ */

/* MOBILE FIRST — hamburger by default, full nav is the enhancement. */
.site-nav-links { display: none; }
.nav-toggle { display: inline-flex; }

@media (min-width: 860px) {
  .site-nav-links { display: flex; }
  .nav-toggle { display: none; }
  .nav-panel { display: none !important; }   /* drawer can never be open at desktop width */
  .nav-cta-inline { display: inline-flex; }
}

/* ── MOBILE HEADER ORDER: logo, then the money CTA, then the hamburger ──────
   KING JOE: "on mobile it should be LOGO then right list ($1) then hamburger.
   hamburger opens other things. on desktop no worries full bleed."

   The CTA carries BOTH labels and CSS picks one, rather than JS swapping
   textContent. The JS swap used to live in computeNavMode(), which measured
   layout and was replaced by the 860px query — so the swap silently stopped
   happening and mobile kept rendering "List your agency for $1", which is wide
   enough to push the hamburger out of the bar entirely. One mechanism, one
   place, no drift.
   ------------------------------------------------------------------------- */

.cta-full { display: none; }
.cta-compact { display: inline; }

/* Never let the bar wrap: the hamburger belongs on the same row as the logo. */
.site-header-inner { flex-wrap: nowrap; }
.site-header-right { flex-wrap: nowrap; gap: 8px; }
.nav-cta-inline { white-space: nowrap; flex: 0 1 auto; min-width: 0; }
.nav-toggle { flex: none; }
.wordmark { flex: 0 1 auto; min-width: 0; }
.wordmark-text { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

@media (min-width: 860px) {
  .cta-full { display: inline; }
  .cta-compact { display: none; }
}

/* The CTA is visible ALWAYS. It was `display:none` by default and only revealed by the
   nav-mode-* classes that the 860px query replaced, so removing that JS silently hid the one
   element that makes money. Mobile-first: shown by default, never gated on a class. */
.nav-cta-inline { display: inline-flex !important; }
