/* ============================================================
   LAYOUT — the horizontal canvas, header and wayfinding rail
   ------------------------------------------------------------
   Spatial model: the site is one wide strip of full-height
   panels. Home sits at centre. Moving toward the campaign
   audience travels LEFT; moving toward volunteers travels RIGHT.
   Only translate/opacity/scale are animated (compositor-safe).
   ============================================================ */

.viewport {
  position: fixed;
  inset: 0;
  overflow: hidden;
}

/* Stage carries the "pull back to travel" scale. */
.stage {
  height: 100%;
  transform: scale(1);
  transform-origin: 50% 46%;
  transition: transform var(--dur-state) var(--ease-out);
  will-change: transform;
}
.stage.is-travelling { transform: scale(var(--travel-scale, .93)); }

/* Track carries the horizontal travel. */
.track {
  --panel-count: 6;
  --index: 2;
  display: flex;
  height: 100%;
  width: calc(var(--panel-count) * 100%);
  transform: translate3d(calc(var(--index) * -100% / var(--panel-count)), 0, 0);
  transition: transform var(--dur-move) var(--ease-in-out);
  will-change: transform;
}

.panel {
  flex: 0 0 calc(100% / var(--panel-count));
  height: 100%;
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior-y: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-gutter: stable;
  padding-top: calc(var(--header-h) + var(--rail-h));
  content-visibility: auto;
  contain-intrinsic-size: auto 100vh;
  visibility: hidden;            /* keeps inactive panels out of tab order */
  transition: visibility 0s linear var(--dur-move);
}
.panel.is-active,
.panel.is-transitioning {
  visibility: visible;
  transition-delay: 0s;
}

@media (min-width: 860px) {
  .panel { padding-top: var(--header-h); }
}

.panel__inner { min-height: 100%; display: flex; flex-direction: column; }
.panel__body { flex: 1; }

/* Panel heading target for post-navigation focus */
.panel__anchor:focus { outline: none; }

/* ---------- Header ---------- */
.header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: var(--z-header);
  height: var(--header-h);
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding-inline: var(--gutter);
  background: rgba(255,255,255,.92);
  backdrop-filter: saturate(1.4) blur(10px);
  border-bottom: var(--border-hair) solid var(--color-border);
}
@supports not (backdrop-filter: blur(2px)) { .header { background: #fff; } }

.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  text-decoration: none;
  color: var(--color-text);
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  letter-spacing: var(--tracking-tight);
  line-height: 1.05;
  padding: var(--space-2);
  margin-left: calc(var(--space-2) * -1);
  border-radius: var(--radius-md);
  min-height: var(--touch-min);
}
.brand__mark { width: 34px; height: 34px; flex: none; }
/* The wordmark is sized against the mark rather than against the old
   two-line lockup. The mark's artwork sits between y=12 and y=78 of its
   100 unit box, so about 22px of the 34px square is ink, and Lexend's
   0.7031em cap height puts a ~30px size level with that.

   It is hidden below 1200px, which fixes a collision that predates this
   change rather than one it introduced. From 860px the rail becomes a
   575px pill centred in the header, so the space left of it is
   (100vw - 575px) / 2, and that runs out fast: at 1100px the old 17px
   wordmark already slid under the rail, and at 880px it was cut off after
   "Texas". Below 1200px the mark alone carries the header, which is
   legible on its own and costs nothing in the accessibility tree, since
   the link's aria-label already reads the full name.

   The width term is derived rather than guessed: the name measures about
   10.05px per point of font size, so the largest size that clears the
   rail is roughly (0.472 * 100vw - 384px) / 10.05. */
.brand__name { font-size: 1.0625rem; }   /* colour inherits --color-text from .brand */
/* Only the middle word carries brand blue. The accessible name is unaffected,
   because the link's aria-label already supplies the full wordmark, so the
   split is purely visual. Blue reads 9.43:1 on the header. */
.brand__accent { color: var(--color-brand); }
/* Hidden only in the band where the rail is inline but the viewport is
   still narrow. Below 860px the rail drops to its own full-width row, so
   the header has the whole width and the wordmark fits comfortably. */
@media (min-width: 860px) and (max-width: 1199px) {
  .brand__name { display: none; }
}
@media (min-width: 1200px) {
  .brand__name { font-size: clamp(1.0625rem, calc(4.6vw - 37px), 1.9rem); }
}

.header__spacer { flex: 1; }
/* Specificity has to beat .btn's own display rule in components.css */
.header .header__cta { display: none; }
@media (min-width: 860px) {
  /* Shown only on a branch. On home it stays hidden, because the fork
     section a short scroll below already asks the question the button
     would have to guess at. This also covers the moment before the router
     has set data-side, so the button never appears with a stale label. */
  [data-side="campaign"]  .header .header__cta,
  [data-side="volunteer"] .header .header__cta { display: inline-flex; }
}

/* ---------- Standalone pages ----------
   The privacy policy sits outside the canvas: no rail, no travel, no
   router, and no JavaScript at all. So its header is in normal flow rather
   than fixed, because there is no panel scrolling underneath it that it
   needs to stay clear of, and there is no rail below it to leave room for. */
.page-header {
  display: flex;
  align-items: center;
  padding: var(--space-3) var(--gutter);
  background: var(--color-bg);
  border-bottom: var(--border-hair) solid var(--color-border);
}
.page-main { padding-block: var(--space-7) var(--space-8); }
.page-back { margin-bottom: var(--space-7); }
.page-back--end { margin: var(--space-8) 0 0; }

/* Legal prose is a single column of running text, so the display sizes the
   panels use would overwhelm it. h2 drops from --fs-3xl to --fs-xl and the
   body takes the muted colour the rest of the site uses for running copy. */
.prose h2 { font-size: var(--fs-xl); margin-top: var(--space-7); }
.prose h2:first-child { margin-top: 0; }
.prose p { color: var(--color-text-muted); }
.prose-list {
  list-style: none; padding: 0;
  display: grid; gap: var(--space-3);
  margin: 0 0 var(--space-4);
  color: var(--color-text-muted);
}
.prose-list li { padding-left: var(--space-4); border-left: 2px solid var(--color-rule); }

/* ---------- Wayfinding rail: the site's compass ---------- */
.rail {
  position: fixed;
  top: var(--header-h);
  left: 0; right: 0;
  z-index: calc(var(--z-header) + 1);
  height: var(--rail-h);
  display: flex;
  align-items: stretch;
  background: var(--color-bg);
  border-bottom: var(--border-hair) solid var(--color-border);
}
@media (min-width: 860px) {
  .rail {
    top: 0;
    height: var(--header-h);
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    width: auto;
    background: none;
    border: 0;
    padding: var(--space-2) 0;
    align-items: center;
  }
}

.rail__track {
  position: relative;
  display: flex;
  flex: 1;
  gap: 0;
  padding: 4px;
}
@media (min-width: 860px) {
  .rail__track {
    flex: none;
    background: var(--grey-100);
    border-radius: var(--radius-pill);
    gap: 0;
  }
}

/* The sliding "you are here" marker */
.rail__marker {
  position: absolute;
  top: 4px; bottom: 4px; left: 0;
  width: var(--marker-w, 33.333%);
  background: var(--color-text);
  border-radius: var(--radius-sm);
  transform: translate3d(var(--marker-x, 0), 0, 0);
  transition: transform var(--dur-move) var(--ease-spring),
              width var(--dur-move) var(--ease-spring),
              background-color var(--dur-state) var(--ease-out);
  pointer-events: none;
}
@media (min-width: 860px) { .rail__marker { border-radius: var(--radius-pill); } }
.rail[data-here="campaigns"]  .rail__marker { background: var(--path-campaign); }
.rail[data-here="volunteers"] .rail__marker { background: var(--path-volunteer); }

.rail__btn {
  position: relative;
  z-index: 1;
  flex: 1;
  min-width: 0;
  min-height: var(--touch-min);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  background: none;
  border: 0;
  cursor: pointer;
  font-family: var(--font-display);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--color-text-muted);
  border-radius: var(--radius-sm);
  transition: color var(--dur-state) var(--ease-out);
  white-space: nowrap;
}
@media (min-width: 860px) {
  .rail__btn { flex: none; padding-inline: var(--space-5); border-radius: var(--radius-pill); }
}
.rail__btn:hover { color: var(--color-text); }
.rail__btn[aria-current="true"] { color: var(--color-text-inverse); }
.rail__btn .arrow { transition: transform var(--dur-state) var(--ease-out); flex: none; }
.rail__btn--left:hover .arrow  { transform: translateX(-3px); }
.rail__btn--right:hover .arrow { transform: translateX(3px); }
.rail__label-short { display: none; }
@media (max-width: 520px) {
  .rail__label-long { display: none; }
  .rail__label-short { display: inline; }
}

/* ---------- Depth breadcrumb (shown on detail panels) ---------- */
/* The back control points the way the site will actually move. Campaign
   panels sit west of home, so leaving one travels east: the control lives
   on the right and its arrow points right. Volunteer panels sit east, so
   the mirror applies. Direction, position and motion always agree. */
.depthbar {
  position: sticky;
  top: 0;
  z-index: var(--z-raised);
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--gutter);
  background: rgba(255,255,255,.94);
  backdrop-filter: blur(8px);
  border-bottom: var(--border-base) solid var(--color-border);
  font-size: var(--fs-sm);
}
.depthbar--east { justify-content: flex-end; }
.depthbar--west { justify-content: flex-start; }
.panel--campaign .depthbar { border-bottom-color: var(--path-campaign-edge); }
.panel--volunteer .depthbar { border-bottom-color: var(--path-volunteer-edge); }
.depthbar__crumbs { color: var(--color-text-muted); display: none; gap: var(--space-2); align-items: center; flex-wrap: wrap; }
@media (min-width: 720px) { .depthbar__crumbs { display: flex; } }
.depthbar .btn-back span { white-space: nowrap; }
.depthbar__crumbs a { color: var(--color-text-muted); }
.depthbar__crumbs a:hover { color: var(--color-text); }
.depthbar__sep { color: var(--color-rule); }
.depthbar__current { color: var(--color-text); font-weight: var(--fw-semibold); }

/* ---------- Footer ---------- */
.footer {
  background: var(--color-footer);
  color: rgba(255,255,255,.82);
  padding-block: var(--space-6) var(--space-5);
  border-top: var(--border-heavy) solid var(--color-accent);
}
.footer a {
  color: #fff;
  position: relative;
  text-decoration: none;
}
.footer a::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: -3px; height: 2px;
  background: var(--color-accent);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--dur-state) var(--ease-out);
}
.footer a:hover::after,
.footer a:focus-visible::after { transform: scaleX(1); }

/* Footer links were 27px tall, under the 44px minimum this design system
   sets for every target. Growing them with padding alone would not work,
   because an inline box does not reserve that space in layout, so the hit
   areas of stacked links would overlap by about 5px and the wrong link
   would take the tap. inline-flex makes the height real, so the list
   spaces itself correctly and nothing overlaps. */
.footer li a {
  display: inline-flex;
  align-items: center;
  min-height: var(--touch-min);
}
/* The underline is positioned against the link box, and that box is now
   taller than the text sitting inside it, so pull the rule back up to the
   letters. Half the leftover height, less the original 3px offset. The
   static value is the answer at the current line-height, and the calc
   replaces it where the lh unit is supported so it survives a type change. */
.footer li a::after {
  bottom: 5.5px;
  bottom: calc((var(--touch-min) - 1lh) / 2 - 3px);
}
.footer__grid { display: grid; gap: var(--space-6); }
@media (min-width: 760px) { .footer__grid { grid-template-columns: 1.4fr 1fr 1fr; } }
.footer h3 { color: #fff; font-size: var(--fs-sm); text-transform: uppercase;
  letter-spacing: var(--tracking-caps); font-weight: var(--fw-semibold); }
.footer ul { list-style: none; padding: 0; margin: 0; }
.footer li + li { margin-top: var(--space-3); }
.footer__legal {
  margin-top: var(--space-6); padding-top: var(--space-5);
  border-top: 1px solid rgba(255,255,255,.16);
  font-size: var(--fs-sm); color: rgba(255,255,255,.6);
  display: flex; flex-wrap: wrap; gap: var(--space-4); justify-content: space-between;
}
/* The privacy link inherits the legal row's own colour and size instead of
   the white treatment `.footer a` gives the column links above it, so the
   row still reads as one line of fine print. It keeps the shared underline
   on hover, and takes the 44px minimum target every other link on the site
   carries. */
.footer__legal a {
  color: inherit;
  display: inline-flex;
  align-items: center;
  min-height: var(--touch-min);
}
