/*
Theme Name: YA By The Bay
Theme URI: https://www.yabythebay.org/
Author: OJ Amplify
Description: Custom theme for YA By The Bay, Tampa Bay's youth literacy nonprofit. Ported from the approved static build. Zero plugins: copy is editable from wp-admin, forms are captured natively.
Version: 1.0.0
Requires at least: 6.0
Requires PHP: 7.4
License: Proprietary
Text Domain: yabtb
*/

/* ------------------------------------------------------------------
   GENERATED FILE, DO NOT EDIT.

   Written by wp-theme/build/extract_style.py from the <style> block in
   Concept\index.html. Edit Concept\_design\components\*.css, run
   _photo-library/sync_shared.py, then re-run the extractor. Hand edits
   here are lost silently on the next run.

   The static build spliced this block into all twelve pages, which meant
   138 KB of identical CSS downloaded again on every page. Here it is one
   file, enqueued once, cached across the whole site.
   ------------------------------------------------------------------ */

/* ============================================================
   YA BY THE BAY - FESTIVAL 2027
   Design System v1.0  |  oja-web-design  |  2026-06-18
   Style: Semi-flat + Coastal Maximalism accent layer
   Font pairing: Fraunces (display, literary Didone-warmth)
                 + Plus Jakarta Sans (humanist sans body)
                 + Caveat (script accents, matched to her brush lettering 2026-09-10)
   Self-hosted woff2 fonts expected at /fonts/
   Google Fonts fallback documented below.
   ============================================================ */

/* ============================================================
   SELF-HOSTED @font-face DECLARATIONS
   Latin-subset woff2 files live in /fonts/ (about 127 KB total).
   No third-party font requests, so no GDPR exposure and no
   render-blocking round trip to fonts.googleapis.com.
   The seo-page-builder rewrites the src url() prefix for
   subfolder pages (../ paths) automatically.
   ============================================================ */

@font-face {
  font-family: 'Fraunces';
  src: url('assets/fonts/fraunces-variable.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Plus Jakarta Sans';
  src: url('assets/fonts/plus-jakarta-sans-variable.woff2') format('woff2');
  font-weight: 200 800;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Caveat';
  src: url('assets/fonts/caveat-variable.woff2') format('woff2');
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}

/* ============================================================
   DESIGN TOKENS (:root)
   Semantic names only. Never reference a token by hue/value.
   ============================================================ */
:root {

  /* --- FONTS --- */
  --display: 'Fraunces', Georgia, 'Times New Roman', serif;
  --body: 'Plus Jakarta Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --script: 'Caveat', cursive;

  /* --- COLOR TOKENS: LIGHTS (surface / background group) --- */
  --surf:       #FBF7F0; /* warm off-white, dominant 60% surface */
  --surf-dim:   #F2EBE0; /* slightly warmer tint for alternating sections */
  --surf-teal:  #EBF5F4; /* very pale teal tint for subtle section variety */

  /* --- COLOR TOKENS: DARKS (text / dark section group) --- */
  --ink:        #1A2E35; /* warm dark navy, primary text */
  --ink-mid:    #2C4A54; /* dark teal-navy, subheadings in dark sections */
  --ever:       #0E2228; /* deep dark bay night, dark section backgrounds */

  /* --- COLOR TOKENS: ACCENTS --- */
  /* Teal (30% brand hue) - matched to the client's kit art (badge-teal #08716E) */
  --teal:       #08716E; /* kit teal - verified 5.57:1 on --surf (AA) */
  --teal-deep:  #075F58; /* hover / active teal - 7.06:1 on --surf */
  --teal-light: #279B98; /* medium teal, large-text use - 3.16:1 on --surf */
  --teal-tint:  #BAE3E2; /* pale teal tint for decorative fills */

  /* Coral (10% CTA accent) - matched to the client's kit art (sunglasses/badge #DD5747) */
  --coral:      #DD5747; /* kit coral CTA fill - 3.56:1 on surf, 4.33:1 on ever */
  --coral-deep: #C43524; /* legible-on-light coral - 5.07:1 on --surf (AA) */
  --coral-hover:#DA4635; /* button hover state - 4.01:1 on --surf */
  --coral-tint: #F5D0CB; /* pale coral tint for decorative fills */

  /* Amber (secondary warm accent, used for date/highlight badges) */
  --amber:      #D4830A; /* warm amber - verified 4.6:1+ on --surf */
  --amber-light:#F9C364; /* amber tint for fills, not small text */

  /* --- COLOR TOKENS: UTILITY --- */
  --muted:      #5C6E73; /* secondary / supporting text - 4.72:1 on --surf (AA) */
  --muted-lt:   #8A9FA5; /* very supporting text, large text only (3:1+ on surf) */

  /* --- COLOR TOKENS: LINE / BORDER --- */
  --line:       rgba(26, 46, 53, 0.12);   /* standard hairline on light surfaces */
  --line-soft:  rgba(26, 46, 53, 0.07);   /* very soft divider */
  --line-strong: rgba(26, 46, 53, 0.24);  /* visible border: form inputs, dashed slots */
  --line-dark:  rgba(251, 247, 240, 0.15); /* hairline on dark / teal backgrounds */

  /* --- RADIUS --- */
  --r-sm: 8px;   /* tight radius (photo frames, form inputs, small chips) */
  --r:    14px;  /* standard component radius (cards, inputs) */
  --r-lg: 24px;  /* large radius (hero card, featured panels) */
  --r-xl: 40px;  /* pill sections, RSVP band shape accents */
  --r-pill: 100px; /* buttons and badge pills */

  /* --- SHADOW --- */
  --shadow:    0 4px 24px -6px rgba(14, 34, 40, 0.14),
               0 1px 4px -1px rgba(14, 34, 40, 0.08);
  --shadow-lg: 0 16px 48px -12px rgba(14, 34, 40, 0.22),
               0 4px 12px -4px rgba(14, 34, 40, 0.10);
  --shadow-card: 0 2px 12px -3px rgba(14, 34, 40, 0.10);

  /* --- LAYOUT --- */
  --maxw:  1240px;
  --gut:   clamp(20px, 5vw, 80px);
  --nav-h: 108px; /* sized to seat an 88px logo with breathing room */

  /* --- FLUID TYPE SCALE (ratio 1.333 - Perfect Fourth) --- */
  /* Base 16-18px, hero H1 pushed to 4.5-6rem for festival stopping power */
  --step-sm:  clamp(0.813rem, 0.793rem + 0.10vw, 0.875rem);  /* 13-14px, captions */
  --step-0:   clamp(1rem, 0.970rem + 0.15vw, 1.063rem);       /* 16-17px, body */
  --step-1:   clamp(1.063rem, 0.990rem + 0.37vw, 1.250rem);   /* 17-20px, lead */
  --step-2:   clamp(1.250rem, 1.100rem + 0.75vw, 1.563rem);   /* 20-25px, h4 */
  --step-3:   clamp(1.563rem, 1.320rem + 1.21vw, 2.063rem);   /* 25-33px, h3 */
  --step-4:   clamp(2.000rem, 1.650rem + 1.75vw, 2.750rem);   /* 32-44px, h2 */
  --step-5:   clamp(2.500rem, 1.850rem + 3.25vw, 3.750rem);   /* 40-60px, h1 interior */
  --step-hero: clamp(3.000rem, 1.600rem + 7.00vw, 6.000rem);  /* 48-96px, hero H1 */
  --step-script: clamp(2.2rem, 1.5rem + 3.5vw, 4.5rem);       /* script accent */

  /* --- FLUID SPACING SCALE (8-point base) --- */
  --sp-1:  clamp(4px,  0.5vw,  8px);
  --sp-2:  clamp(8px,  1vw,   16px);
  --sp-3:  clamp(12px, 1.5vw, 20px);
  --sp-4:  clamp(16px, 2vw,   24px);
  --sp-5:  clamp(24px, 3vw,   40px);
  --sp-6:  clamp(32px, 4.5vw, 60px);
  --sp-7:  clamp(48px, 7vw,   96px);
  --sp-8:  clamp(64px, 10vw, 140px);

  /* --- MOTION TOKENS --- */
  --ease-out:   cubic-bezier(0.22, 1, 0.36, 1);
  --ease-brand: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-spring:cubic-bezier(0.34, 1.56, 0.64, 1);  /* subtle overshoot for CTAs */
  --dur-fast:   150ms;
  --dur-mid:    280ms;
  --dur-slow:   480ms;
  --dur-reveal: 560ms;
}

/* ============================================================
   RESET AND BASE
   ============================================================ */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

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

body {
  font-family: var(--body);
  font-size: var(--step-0);
  line-height: 1.6;
  color: var(--ink);
  background: var(--surf);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: clip;
}

img, video, svg {
  display: block;
  max-width: 100%;
}

a {
  color: var(--teal);
  text-decoration: underline;
  text-decoration-color: transparent;
  text-underline-offset: 3px;
  transition: color var(--dur-fast) var(--ease-out),
              text-decoration-color var(--dur-fast) var(--ease-out);
}
a:hover, a:focus-visible {
  color: var(--teal-deep);
  text-decoration-color: currentColor;
}

/* ============================================================
   SCROLL PROGRESS BAR
   ============================================================ */
.scroll-prog {
  position: fixed;
  top: 0; left: 0;
  height: 3px;
  width: 0%;
  background: linear-gradient(90deg, var(--teal), var(--coral));
  z-index: 200;
  pointer-events: none;
  transition: width 80ms linear;
}

/* ============================================================
   LAYOUT UTILITIES
   ============================================================ */
.wrap {
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gut);
}

.pad    { padding-block: var(--sp-8); }
.pad-sm { padding-block: var(--sp-7); }
.pad-xs { padding-block: var(--sp-6); }

/* ============================================================
   REVEAL ON SCROLL (IntersectionObserver target)
   ============================================================ */
.reveal {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity var(--dur-reveal) var(--ease-out),
              transform var(--dur-reveal) var(--ease-out);
}
.reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
}
.reveal-scale {
  opacity: 0;
  transform: scale(0.96);
  transition: opacity var(--dur-reveal) var(--ease-out),
              transform var(--dur-reveal) var(--ease-out);
}
.reveal-scale.is-visible {
  opacity: 1;
  transform: scale(1);
}

/* Stagger siblings: set --i via inline style or nth-child JS */
.stagger { transition-delay: calc(var(--i, 0) * 70ms); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .reveal, .reveal-scale {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
}

/* ============================================================
   GRAIN / TEXTURE OVERLAY (decorative, aria-hidden)
   ============================================================ */
.grain::after {
  content: '';
  position: absolute;
  inset: 0;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.75' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.04'/%3E%3C/svg%3E");
  background-repeat: repeat;
  background-size: 200px;
  pointer-events: none;
  z-index: 1;
  opacity: 0.4;
}
.grain > * { position: relative; z-index: 2; }

/* ============================================================
   NAVIGATION / HEADER
   ============================================================ */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  height: var(--nav-h);
  background: rgba(251, 247, 240, 0.97);
  border-bottom: 1px solid var(--line);
  transition: box-shadow var(--dur-mid) var(--ease-out),
              background var(--dur-mid) var(--ease-out);
}
.site-header.scrolled {
  box-shadow: 0 2px 16px -4px rgba(14, 34, 40, 0.12);
  background: rgba(251, 247, 240, 0.97);
}

.nav-inner {
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gut);
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-5);
}

/* Logo: minimum 80px tall per OJA house rule */
.nav-logo {
  display: flex;
  align-items: center;
  text-decoration: none;
  flex-shrink: 0;
}
.nav-logo img {
  /* House rule: header logos render 80px to 100px tall. Size up when unsure. */
  height: clamp(64px, 7vw, 88px);
  width: auto;
  object-fit: contain;
}

.nav-links {
  display: flex;
  align-items: center;
  list-style: none;
  gap: var(--sp-5);
}
.nav-links a {
  font-size: var(--step-sm);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink);
  padding-block: var(--sp-1);
  border-bottom: 2px solid transparent;
  transition: color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out);
}
.nav-links a:hover,
.nav-links a:focus-visible {
  color: var(--teal);
  border-bottom-color: var(--teal);
}
.nav-links a.active,
.nav-links a[aria-current="page"] {
  color: var(--teal);
  border-bottom-color: var(--coral);
}

/* Nav CTA button */
.nav-cta {
  flex-shrink: 0;
}

/* Mobile nav toggle */
.nav-toggle {
  display: none;
  flex-direction: column;
  gap: 5px;
  background: none;
  border: none;
  cursor: pointer;
  padding: var(--sp-2);
  border-radius: var(--r);
  transition: background var(--dur-fast) var(--ease-out);
}
.nav-toggle:hover { background: var(--line); }
.nav-toggle span {
  display: block;
  width: 24px;
  height: 2px;
  background: var(--ink);
  border-radius: 2px;
  transition: transform var(--dur-mid) var(--ease-out),
              opacity var(--dur-mid) var(--ease-out);
}
.nav-toggle[aria-expanded="true"] span:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}

/* Mobile menu drawer */
.nav-drawer {
  display: none;
  position: fixed;
  inset: 0;
  top: var(--nav-h);
  background: var(--surf);
  padding: var(--sp-6) var(--gut);
  z-index: 99;
  transform: translateX(100%);
  transition: transform var(--dur-mid) var(--ease-out);
  overflow-y: auto;
}
.nav-drawer.is-open {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  transform: translateX(0);
}
.nav-drawer a {
  font-size: var(--step-2);
  font-weight: 700;
  color: var(--ink);
  text-decoration: none;
  padding-block: var(--sp-3);
  border-bottom: 1px solid var(--line);
}
.nav-drawer a:last-of-type { border-bottom: none; }

/* 959, not 767: between those widths the desktop nav has no room and
   "Students & Teachers" wrapped to three lines, pushing the header to
   80px of stacked text on every page. */
@media (max-width: 959px) {
  .nav-links, .nav-cta { display: none; }
  .nav-toggle { display: flex; }
}
.nav-links a { white-space: nowrap; }

/* ============================================================
   BREADCRUMB (.crumb)
   Place inside <nav aria-label="Breadcrumb"> above page <h1>
   ============================================================ */
.crumb {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-1);
  list-style: none;
  font-size: var(--step-sm);
  color: var(--muted);
  padding-block: var(--sp-3);
}
.crumb a {
  color: var(--teal);
  text-decoration: none;
  font-weight: 500;
}
.crumb a:hover { text-decoration: underline; }
.crumb li + li::before {
  content: '/';
  color: var(--muted-lt);
  margin-right: var(--sp-1);
}
.crumb li[aria-current="page"] {
  color: var(--ink);
  font-weight: 600;
}

/* ============================================================
   TYPOGRAPHY ELEMENTS
   ============================================================ */
h1, h2, h3, h4, h5, h6 {
  font-family: var(--display);
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: var(--ink);
}
h1 { font-size: var(--step-5); font-weight: 900; }
h2 { font-size: var(--step-4); font-weight: 700; }
h3 { font-size: var(--step-3); font-weight: 700; }
h4 { font-size: var(--step-2); font-weight: 600; }
h5 { font-size: var(--step-1); font-weight: 600; }
h6 { font-size: var(--step-0); font-weight: 600; }

p {
  max-width: 70ch;
  line-height: 1.65;
}

.lead {
  font-size: var(--step-1);
  line-height: 1.55;
  color: var(--ink-mid);
  max-width: 60ch;
}

/* Eyebrow label: small caps above a heading */
.eyebrow {
  display: inline-block;
  font-family: var(--body);
  font-size: var(--step-sm);
  font-weight: 700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--coral-deep);
  margin-bottom: var(--sp-3);
}
.eyebrow-teal {
  color: var(--teal);
}

/* Script accent: festival name only, never in nav or body */
.script-accent {
  font-family: var(--script);
  font-size: var(--step-script);
  font-weight: 400;
  line-height: 1.1;
  color: var(--coral);
  display: block;
}

/* Pull quote */
.pull-quote {
  font-family: var(--display);
  font-size: var(--step-3);
  font-style: italic;
  font-weight: 600;
  color: var(--teal);
  border-left: 4px solid var(--coral);
  padding-left: var(--sp-5);
  margin-block: var(--sp-6);
  max-width: 50ch;
}

/* ============================================================
   BUTTONS (.btn + variants)
   All buttons use pill radius for youthful brand fit.
   ============================================================ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  font-family: var(--body);
  font-size: var(--step-0);
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.02em;
  padding: 14px 28px;
  border-radius: var(--r-pill);
  border: 2px solid transparent;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: background var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-spring),
              box-shadow var(--dur-fast) var(--ease-out);
  -webkit-user-select: none;
  user-select: none;
}
.btn:focus-visible {
  outline: 3px solid var(--teal);
  outline-offset: 3px;
}
.btn:active { transform: scale(0.97); }

/* Primary: coral-deep fill - AA accessible (5.8:1) on all conversion CTAs */
.btn-primary {
  background: var(--coral-deep);
  color: #fff;
  border-color: var(--coral-deep);
}
.btn-primary:hover, .btn-primary:focus-visible {
  background: var(--coral-hover);
  border-color: var(--coral-hover);
  transform: translateY(-2px);
  box-shadow: 0 8px 24px -6px rgba(181, 61, 16, 0.45);
  color: #fff;
  text-decoration: none;
}

/* Primary large: hero RSVP, dominates visual weight */
.btn-primary-lg {
  font-size: var(--step-1);
  padding: 18px 40px;
}
.btn-primary-lg:hover {
  transform: translateY(-3px);
  box-shadow: 0 12px 32px -6px rgba(181, 61, 16, 0.50);
}

/* Secondary: teal fill */
.btn-secondary {
  background: var(--teal);
  color: #fff;
  border-color: var(--teal);
}
.btn-secondary:hover, .btn-secondary:focus-visible {
  background: var(--teal-deep);
  border-color: var(--teal-deep);
  transform: translateY(-2px);
  box-shadow: 0 8px 24px -6px rgba(22, 110, 102, 0.40);
  color: #fff;
  text-decoration: none;
}

/* Ghost: outline on light surfaces */
.btn-ghost {
  background: transparent;
  color: var(--teal);
  border-color: var(--teal);
}
.btn-ghost:hover, .btn-ghost:focus-visible {
  background: var(--teal);
  color: #fff;
  transform: translateY(-2px);
  text-decoration: none;
}

/* Ghost light: outline for use on dark / teal backgrounds */
.btn-ghost-light {
  background: transparent;
  color: var(--surf);
  border-color: var(--surf);
}
.btn-ghost-light:hover, .btn-ghost-light:focus-visible {
  background: var(--surf);
  color: var(--ink);
  transform: translateY(-2px);
  text-decoration: none;
}

/* Sponsor / donate: amber variant, subordinate to coral RSVP */
.btn-amber {
  background: transparent;
  color: var(--amber);
  border-color: var(--amber);
}
.btn-amber:hover, .btn-amber:focus-visible {
  background: var(--amber);
  color: var(--surf);
  transform: translateY(-2px);
  text-decoration: none;
}

/* Disabled state */
.btn[disabled], .btn[aria-disabled="true"] {
  opacity: 0.45;
  pointer-events: none;
  transform: none;
}

/* ============================================================
   HERO SECTION (.hero)
   Aurora coastal gradient hero with no photo required.
   ============================================================ */
.hero {
  position: relative;
  min-height: 92vh;
  display: flex;
  align-items: center;
  overflow: hidden;
  background: var(--ever);
}

/* Wave SVG divider at bottom of hero */
.hero-wave {
  position: absolute;
  bottom: -1px;
  left: 0;
  width: 100%;
  z-index: 2;
  line-height: 0;
}
.hero-wave svg { display: block; width: 100%; height: auto; }

.hero-inner {
  position: relative;
  z-index: 3;
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gut);
  padding-block: var(--sp-8);
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-6);
}

.hero-content {
  max-width: 740px;
}

.hero-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-family: var(--body);
  font-size: var(--step-sm);
  font-weight: 700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--coral);
  background: rgba(232, 93, 43, 0.15);
  border: 1px solid rgba(232, 93, 43, 0.30);
  padding: 6px 14px;
  border-radius: var(--r-pill);
  margin-bottom: var(--sp-4);
}

.hero h1 {
  font-size: var(--step-hero);
  font-weight: 900;
  letter-spacing: -0.03em;
  line-height: 1.05;
  color: #fff;
  margin-bottom: var(--sp-5);
}

.hero-sub {
  font-size: var(--step-1);
  line-height: 1.6;
  color: rgba(251, 247, 240, 0.85);
  max-width: 56ch;
  margin-bottom: var(--sp-6);
}

.hero-cta-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3);
}

/* Credential badges below hero CTA */
.hero-credentials {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
  margin-top: var(--sp-5);
}
.cred-badge {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--step-sm);
  color: rgba(251, 247, 240, 0.75);
  font-weight: 500;
}
.cred-badge svg, .cred-badge .cred-icon {
  width: 18px;
  height: 18px;
  color: var(--teal-light);
  flex-shrink: 0;
}

@media (max-width: 767px) {
  .hero { min-height: 100svh; }
  .hero h1 { font-size: clamp(2.4rem, 8vw, 3.5rem); }
}

/* ============================================================
   EVENT DATE / KEY FACTS STRIP (.facts-strip)
   A compact horizontal band of key festival facts.
   Appears directly below hero or at top of first interior section.
   ============================================================ */
.facts-strip {
  background: var(--teal);
  color: #fff;
  padding-block: var(--sp-5);
}
.facts-strip .wrap {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--sp-6);
}
.fact-item {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  text-align: left;
}
.fact-icon {
  width: 40px;
  height: 40px;
  background: rgba(255,255,255,0.15);
  border-radius: var(--r);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.25rem;
  flex-shrink: 0;
}
.fact-label {
  font-size: var(--step-sm);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  opacity: 0.75;
  display: block;
  line-height: 1.2;
}
.fact-value {
  font-family: var(--display);
  font-size: var(--step-2);
  font-weight: 700;
  line-height: 1.2;
  display: block;
}

@media (max-width: 639px) {
  .facts-strip .wrap { flex-direction: column; align-items: flex-start; }
}

/* ============================================================
   FEATURE / CONTENT CARD (.fcard)
   General-purpose content card for sections.
   ============================================================ */
.fcard {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--sp-6);
  box-shadow: var(--shadow-card);
  transition: transform var(--dur-mid) var(--ease-brand),
              box-shadow var(--dur-mid) var(--ease-out);
}
.fcard:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
}
.fcard-icon {
  width: 48px;
  height: 48px;
  border-radius: var(--r);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: var(--sp-4);
  font-size: 1.5rem;
}
.fcard-icon-teal { background: var(--surf-teal); color: var(--teal); }
.fcard-icon-coral { background: var(--coral-tint); color: var(--coral-deep); }
.fcard-icon-amber { background: rgba(212, 131, 10, 0.10); color: var(--amber); }

.fcard h3 {
  font-size: var(--step-2);
  font-weight: 700;
  margin-bottom: var(--sp-3);
}
.fcard p {
  font-size: var(--step-0);
  color: var(--muted);
  line-height: 1.6;
}

/* Teal variant */
.fcard-teal {
  background: var(--surf-teal);
  border-color: rgba(22, 110, 102, 0.15);
}
/* Coral accent variant */
.fcard-coral {
  background: var(--coral-tint);
  border-color: rgba(232, 93, 43, 0.15);
}
/* Dark variant for use on --ever sections */
.fcard-dark {
  background: rgba(255,255,255,0.06);
  border-color: var(--line-dark);
  color: var(--surf);
}
.fcard-dark h3 { color: #fff; }
.fcard-dark p  { color: rgba(251,247,240,0.75); }

/* ============================================================
   BENTO FEATURE GRID (.bento)
   Mixed-size bento cards for "at a glance" festival features.
   ============================================================ */
.bento {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: clamp(12px, 1.5vw, 20px);
}
.bento-1  { grid-column: span 12; }
.bento-6  { grid-column: span 6; }
.bento-4  { grid-column: span 4; }
.bento-8  { grid-column: span 8; }
.bento-3  { grid-column: span 3; }

@media (max-width: 959px) {
  .bento-6, .bento-4, .bento-8, .bento-3 { grid-column: span 6; }
}
@media (max-width: 639px) {
  .bento-6, .bento-4, .bento-8, .bento-3, .bento-1 { grid-column: span 12; }
}

/* ============================================================
   AUTHOR SPOTLIGHT CARD (.author-card)
   For featured author / co-founder profile sections.
   ============================================================ */
.author-card {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: var(--shadow-card);
  display: flex;
  flex-direction: column;
  transition: transform var(--dur-mid) var(--ease-brand),
              box-shadow var(--dur-mid) var(--ease-out);
}
.author-card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
}
.author-img {
  aspect-ratio: 3 / 4;
  background: var(--surf-teal);
  overflow: hidden;
}
.author-img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* Placeholder when no photo is provided */
.author-img-placeholder {
  aspect-ratio: 3 / 4;
  background: linear-gradient(160deg, var(--surf-teal) 0%, var(--teal-tint) 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--teal);
  font-size: 3rem;
}
.author-body {
  padding: var(--sp-5);
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  flex: 1;
}
.author-name {
  font-family: var(--display);
  font-size: var(--step-2);
  font-weight: 700;
  color: var(--ink);
  line-height: 1.2;
}
.author-title {
  font-size: var(--step-sm);
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--coral-deep);
}
.author-bio {
  font-size: var(--step-0);
  color: var(--muted);
  line-height: 1.6;
  margin-top: var(--sp-2);
}
.author-tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin-top: var(--sp-3);
}
.tag {
  font-size: var(--step-sm);
  font-weight: 600;
  padding: 4px 10px;
  border-radius: var(--r-pill);
  background: var(--surf-teal);
  color: var(--teal-deep);
  border: 1px solid rgba(22, 110, 102, 0.15);
}
.tag-coral {
  background: var(--coral-tint);
  color: var(--coral-deep);
  border-color: rgba(181, 61, 16, 0.15);
}

/* ============================================================
   SCHEDULE / AGENDA BLOCK (.schedule)
   Timeline-style layout for the festival program.
   ============================================================ */
.schedule {
  display: flex;
  flex-direction: column;
  gap: 0;
}
.schedule-day {
  border-bottom: 1px solid var(--line);
  padding-bottom: var(--sp-6);
  margin-bottom: var(--sp-6);
}
.schedule-day:last-child {
  border-bottom: none;
  margin-bottom: 0;
  padding-bottom: 0;
}
.schedule-day-header {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  margin-bottom: var(--sp-5);
}
.schedule-day-label {
  font-family: var(--display);
  font-size: var(--step-3);
  font-weight: 900;
  color: var(--teal);
}
.schedule-day-date {
  font-size: var(--step-sm);
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.schedule-item {
  display: grid;
  grid-template-columns: 100px 1fr;
  gap: var(--sp-4);
  padding-block: var(--sp-4);
  border-left: 3px solid var(--line);
  padding-left: var(--sp-5);
  margin-left: 50px;
  position: relative;
  transition: border-color var(--dur-fast) var(--ease-out);
}
.schedule-item::before {
  content: '';
  position: absolute;
  left: -7px;
  top: 50%;
  transform: translateY(-50%);
  width: 11px;
  height: 11px;
  background: var(--surf);
  border: 2px solid var(--teal);
  border-radius: 50%;
  transition: background var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out);
}
.schedule-item:hover { border-left-color: var(--coral); }
.schedule-item:hover::before {
  background: var(--coral);
  border-color: var(--coral);
}
.schedule-time {
  font-size: var(--step-sm);
  font-weight: 700;
  color: var(--teal);
  padding-top: 2px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.schedule-content h3 {
  font-size: var(--step-1);
  font-weight: 700;
  color: var(--ink);
  margin-bottom: var(--sp-1);
}
.schedule-content p {
  font-size: var(--step-sm);
  color: var(--muted);
  max-width: none;
}
.schedule-badge {
  display: inline-block;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: var(--r-pill);
  margin-top: var(--sp-2);
}
.schedule-badge-keynote {
  background: var(--coral-tint);
  color: var(--coral-deep);
}
.schedule-badge-workshop {
  background: var(--surf-teal);
  color: var(--teal-deep);
}
.schedule-badge-panel {
  background: rgba(212, 131, 10, 0.12);
  color: var(--amber);
}

@media (max-width: 639px) {
  .schedule-item {
    grid-template-columns: 1fr;
    margin-left: 20px;
    padding-left: var(--sp-4);
  }
}

/* ============================================================
   PROCESS / STEP BLOCK (.step)
   Numbered steps for "how it works" or journey sections.
   ============================================================ */
.steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--sp-5);
}
.step {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--sp-6);
  box-shadow: var(--shadow-card);
  position: relative;
  transition: transform var(--dur-mid) var(--ease-brand),
              box-shadow var(--dur-mid) var(--ease-out);
}
.step:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow);
}
.step-num {
  font-family: var(--display);
  font-size: clamp(2.5rem, 5vw, 4rem);
  font-weight: 900;
  line-height: 1;
  color: var(--teal-tint);
  margin-bottom: var(--sp-3);
  display: block;
}
.step h3 {
  font-size: var(--step-2);
  font-weight: 700;
  margin-bottom: var(--sp-3);
  color: var(--ink);
}
.step p {
  font-size: var(--step-0);
  color: var(--muted);
  max-width: none;
}

/* ============================================================
   TESTIMONIAL / SOCIAL-PROOF CARD (.tcard)
   Quote-based social proof from students, teachers, or press.
   ============================================================ */
.tcard {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--sp-6);
  box-shadow: var(--shadow-card);
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
}
.tcard-quote {
  font-family: var(--display);
  font-size: var(--step-1);
  font-style: italic;
  font-weight: 600;
  color: var(--ink);
  line-height: 1.5;
  position: relative;
}
.tcard-quote::before {
  content: '\201C';
  font-size: 3.5rem;
  line-height: 0.5;
  color: var(--teal-tint);
  font-family: var(--display);
  display: block;
  margin-bottom: var(--sp-2);
}
.tcard-attr {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin-top: auto;
}
.tcard-avatar {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--surf-teal);
  overflow: hidden;
  flex-shrink: 0;
}
.tcard-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.tcard-name {
  font-size: var(--step-0);
  font-weight: 700;
  color: var(--ink);
  line-height: 1.3;
}
.tcard-role {
  font-size: var(--step-sm);
  color: var(--muted);
}

/* Teal variant for dark sections */
.tcard-dark {
  background: rgba(255,255,255,0.07);
  border-color: var(--line-dark);
}
.tcard-dark .tcard-quote { color: var(--surf); }
.tcard-dark .tcard-name  { color: #fff; }
.tcard-dark .tcard-role  { color: rgba(251,247,240,0.65); }

/* ============================================================
   FAQ ACCORDION (.faq)
   Per W3C APG Accordion pattern. Content in DOM = fully indexed.
   ============================================================ */
.faq {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
}
.faq-item {
  border-bottom: 1px solid var(--line);
}
.faq-item:last-child { border-bottom: none; }

.faq-trigger {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: var(--sp-5) var(--sp-6);
  background: #fff;
  border: none;
  cursor: pointer;
  text-align: left;
  font-family: var(--body);
  font-size: var(--step-1);
  font-weight: 600;
  color: var(--ink);
  transition: background var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out);
}
.faq-trigger:hover, .faq-trigger:focus-visible {
  background: var(--surf);
  color: var(--teal);
}
.faq-trigger:focus-visible {
  outline: 3px solid var(--teal);
  outline-offset: -3px;
}

.faq-icon {
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--surf-teal);
  color: var(--teal);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform var(--dur-mid) var(--ease-brand),
              background var(--dur-fast) var(--ease-out);
  font-size: 1rem;
  font-weight: 700;
  line-height: 1;
}
/* Open state: solid coral disc with a white cross (5.4:1). The tinted
   disc with a coral cross measured 3.8:1 once the first home question
   opened by default (her Sep 10 note #66). */
.faq-trigger[aria-expanded="true"] .faq-icon {
  transform: rotate(45deg);
  background: var(--coral-deep);
  color: #fff;
}

.faq-panel {
  overflow: hidden;
  max-height: 0;
  transition: max-height var(--dur-slow) var(--ease-out);
}
.faq-panel[aria-hidden="false"],
.faq-panel.is-open {
  max-height: 600px;
}
.faq-panel-inner {
  padding: 0 var(--sp-6) var(--sp-6);
  background: var(--surf);
}
.faq-panel-inner p {
  font-size: var(--step-0);
  color: var(--muted);
  line-height: 1.7;
  max-width: none;
}

/* ============================================================
   RSVP / REGISTRATION CTA BAND (.rsvp-band)
   Dominant visual weight - the most important conversion block.
   Uses coral + teal gradient. Must dominate every page.
   ============================================================ */
.rsvp-band {
  position: relative;
  overflow: hidden;
  background: linear-gradient(140deg, #841C10 0%, #AE2717 30%, #C43524 65%, #DD5747 100%);
  padding-block: var(--sp-8);
  isolation: isolate;
}
.rsvp-band::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 60% 80% at 100% 50%, rgba(22,110,102,0.35) 0%, transparent 55%),
    radial-gradient(ellipse 40% 60% at 0% 50%, rgba(14,34,40,0.25) 0%, transparent 50%);
  z-index: 0;
}
.rsvp-band .wrap {
  position: relative;
  z-index: 1;
  text-align: center;
  max-width: 780px;
}
.rsvp-band-eyebrow {
  display: inline-block;
  font-family: var(--body);
  font-size: var(--step-sm);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #fff;
  margin-bottom: var(--sp-4);
}
.rsvp-band h2 {
  font-size: var(--step-5);
  font-weight: 900;
  color: #fff;
  letter-spacing: -0.025em;
  line-height: 1.1;
  margin-bottom: var(--sp-4);
}
.rsvp-band-sub {
  font-size: var(--step-1);
  color: #fff;
  max-width: 52ch;
  margin-inline: auto;
  margin-bottom: var(--sp-6);
  line-height: 1.55;
}
.rsvp-band-cta-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--sp-4);
}
.rsvp-band .btn-primary {
  background: #fff;
  color: var(--coral-deep);
  border-color: #fff;
  font-size: var(--step-1);
  padding: 18px 44px;
}
.rsvp-band .btn-primary:hover {
  background: var(--surf);
  border-color: var(--surf);
  color: var(--coral-deep);
  box-shadow: 0 16px 40px -8px rgba(14,34,40,0.30);
}
.rsvp-band .btn-ghost-light {
  font-size: var(--step-1);
  padding: 18px 40px;
}
.rsvp-band-note {
  font-size: var(--step-sm);
  color: #fff;
  margin-top: var(--sp-4);
}

/* ============================================================
   SECONDARY CTA BAND (.cta-band)
   Teal variant for sponsor/donate / secondary conversions.
   Always subordinate to .rsvp-band in visual weight.
   ============================================================ */
.cta-band {
  position: relative;
  overflow: hidden;
  background: var(--ever);
  padding-block: var(--sp-7);
  isolation: isolate;
}
.cta-band::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 70% 60% at 10% 50%, rgba(22,110,102,0.35) 0%, transparent 60%),
    radial-gradient(ellipse 50% 70% at 90% 50%, rgba(232,93,43,0.15) 0%, transparent 55%);
  z-index: 0;
}
.cta-band .wrap {
  position: relative;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-6);
}
.cta-band-text h2 {
  font-size: var(--step-4);
  color: #fff;
  margin-bottom: var(--sp-3);
}
.cta-band-text p {
  font-size: var(--step-0);
  color: rgba(251,247,240,0.75);
  max-width: 50ch;
}
.cta-band-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  flex-shrink: 0;
}

@media (max-width: 767px) {
  .cta-band .wrap { flex-direction: column; }
  .cta-band-text h2 { font-size: var(--step-3); }
}

/* ============================================================
   STATS BAND (.stats-band)
   Impact numbers: students reached, authors, schools, etc.
   ============================================================ */
.stats-band {
  background: var(--surf-dim);
  padding-block: var(--sp-7);
  border-block: 1px solid var(--line);
}
.stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--sp-6);
  text-align: center;
}
.stat-item {}
.stat-num {
  font-family: var(--display);
  font-size: clamp(2.5rem, 5vw, 4.5rem);
  font-weight: 900;
  color: var(--teal);
  line-height: 1;
  display: block;
  letter-spacing: -0.03em;
}
.stat-num span { color: var(--coral); } /* for "+" suffix */
.stat-label {
  font-size: var(--step-sm);
  font-weight: 600;
  letter-spacing: 0.04em; /* 0.06em pushed "Directly with Students" past its 5-column cell */
  text-transform: uppercase;
  color: var(--muted);
  margin-top: var(--sp-2);
  display: block;
}

/* ============================================================
   SPONSOR / PARTNER LOGO BAR (.sponsors)
   Static grid of sponsor logos. No auto-scroll carousel.
   Per components-features.md 6b: static preferred over marquee.
   ============================================================ */
.sponsors {
  padding-block: var(--sp-6);
  background: var(--surf);
}
.sponsors-label {
  text-align: center;
  font-size: var(--step-sm);
  font-weight: 700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: var(--sp-5);
}
.sponsors-grid {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--sp-6);
}
.sponsor-slot {
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0.55;
  filter: grayscale(1);
  transition: opacity var(--dur-fast) var(--ease-out),
              filter var(--dur-fast) var(--ease-out);
}
.sponsor-slot:hover { opacity: 1; filter: grayscale(0); }
.sponsor-slot img {
  height: 100%;
  width: auto;
  max-width: 140px;
  object-fit: contain;
}
/* Placeholder when no sponsor logo is provided */
.sponsor-placeholder {
  height: 44px;
  width: 120px;
  background: var(--surf-dim);
  border: 1px dashed var(--line);
  border-radius: var(--r);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--step-sm);
  color: var(--muted-lt);
}

/* ============================================================
   NEWSLETTER INLINE SIGNUP (.nl-signup)
   Single-field email capture. Lightweight, no ESP script needed
   at this layer - form posts to server endpoint.
   ============================================================ */
.nl-signup {
  background: var(--surf-teal);
  border: 1px solid rgba(22, 110, 102, 0.18);
  border-radius: var(--r-lg);
  padding: var(--sp-7) var(--sp-6);
  text-align: center;
}
.nl-signup h3 {
  font-size: var(--step-3);
  font-weight: 700;
  margin-bottom: var(--sp-3);
}
.nl-signup p {
  font-size: var(--step-0);
  color: var(--muted);
  margin-bottom: var(--sp-5);
  margin-inline: auto;
}
.nl-form {
  display: flex;
  gap: var(--sp-2);
  max-width: 480px;
  margin-inline: auto;
}
.nl-input {
  flex: 1;
  height: 52px;
  padding-inline: var(--sp-4);
  border: 2px solid var(--line);
  border-radius: var(--r-pill);
  background: #fff;
  font-family: var(--body);
  font-size: var(--step-0);
  color: var(--ink);
  transition: border-color var(--dur-fast) var(--ease-out);
}
.nl-input:focus {
  outline: none;
  border-color: var(--teal);
  box-shadow: 0 0 0 3px rgba(22, 110, 102, 0.15);
}
.nl-input::placeholder { color: var(--muted-lt); }

@media (max-width: 479px) {
  .nl-form { flex-direction: column; }
  .nl-input { height: 48px; }
}

/* ============================================================
   CO-FOUNDER CREDENTIAL BAND (.cred-band)
   Trust signal for educators and sponsors. Sorboni Banerjee
   credential, nonprofit status, venue confirmation.
   ============================================================ */
.cred-band {
  background: var(--ever);
  padding-block: var(--sp-7);
  position: relative;
  overflow: hidden;
}
.cred-band::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 60% 80% at 80% 50%, rgba(22,110,102,0.20) 0%, transparent 60%);
}
.cred-band .wrap {
  position: relative;
  z-index: 1;
}
.cred-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--sp-5);
}
.cred-item {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-4);
  padding: var(--sp-5);
  background: rgba(255,255,255,0.05);
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: var(--r-lg);
  box-shadow: 0 4px 20px -6px rgba(0,0,0,0.35), 0 1px 4px rgba(0,0,0,0.20);
}
.cred-item-icon {
  width: 44px;
  height: 44px;
  border-radius: var(--r);
  background: rgba(22,110,102,0.25);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.25rem;
  flex-shrink: 0;
  color: var(--teal-light);
}
.cred-item h3 {
  font-size: var(--step-0);
  font-weight: 700;
  color: #fff;
  margin-bottom: 4px;
}
.cred-item p {
  font-size: var(--step-sm);
  color: rgba(251,247,240,0.65);
  max-width: none;
}

/* ============================================================
   SECTION DIVIDER (wave SVG) - reusable
   .wave-divider is a container; fill the SVG fill to match
   the target background color via .wave-fill attribute.
   ============================================================ */
.wave-divider {
  line-height: 0;
  overflow: hidden;
}
.wave-divider svg {
  display: block;
  width: 100%;
  height: auto;
}

/* ============================================================
   FOOTER
   ============================================================ */
.site-footer {
  background: var(--ever);
  color: rgba(251, 247, 240, 0.80);
  padding-top: var(--sp-8);
  padding-bottom: var(--sp-6);
}
.footer-grid {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1fr;
  gap: var(--sp-6);
  margin-bottom: var(--sp-7);
}
.footer-brand .nav-logo img {
  /* The tagline lockup ships on an opaque white background, so it rendered
     as a white box on the dark footer. The primary mark is the only lockup
     with real transparency. */
  width: clamp(190px, 20vw, 240px);
  height: auto;
  opacity: 1;
  margin-bottom: var(--sp-4);
  border-radius: 0;
  background: none;
  padding: 0;
}
.footer-brand p {
  font-size: var(--step-sm);
  color: rgba(251,247,240,0.60);
  max-width: 34ch;
  line-height: 1.65;
}
.footer-nonprofit {
  font-size: var(--step-sm);
  color: rgba(251,247,240,0.45);
  margin-top: var(--sp-3);
}

.footer-col h4 {
  font-family: var(--body);
  font-size: var(--step-sm);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(251,247,240,0.50);
  margin-bottom: var(--sp-4);
}
.footer-col ul {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}
.footer-col a {
  font-size: var(--step-sm);
  color: rgba(251,247,240,0.72);
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease-out);
}
.footer-col a:hover { color: var(--teal-light); }
.footer-col a.active { color: var(--coral); }

.footer-bottom {
  border-top: 1px solid var(--line-dark);
  padding-top: var(--sp-5);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
}
.footer-copyright {
  font-size: var(--step-sm);
  color: rgba(251,247,240,0.40);
}
.footer-legal {
  display: flex;
  gap: var(--sp-4);
  list-style: none;
}
.footer-legal a {
  font-size: var(--step-sm);
  color: rgba(251,247,240,0.40);
  text-decoration: none;
}
.footer-legal a:hover { color: rgba(251,247,240,0.72); }

@media (max-width: 959px) {
  .footer-grid { grid-template-columns: 1fr 1fr; }
  .footer-brand { grid-column: span 2; }
}
@media (max-width: 639px) {
  .footer-grid { grid-template-columns: 1fr; }
  .footer-brand { grid-column: span 1; }
}

/* ============================================================
   SECTION HEADER UTILITY (.sec-head)
   Reusable heading block for sections.
   ============================================================ */
.sec-head {
  text-align: center;
  max-width: 680px;
  margin-inline: auto;
  margin-bottom: var(--sp-7);
}
.sec-head h2 { margin-bottom: var(--sp-4); }
.sec-head p {
  font-size: var(--step-1);
  color: var(--muted);
  margin-inline: auto;
}
.sec-head-left {
  text-align: left;
  margin-inline: 0;
}

/* ============================================================
   ALTERNATING FEATURE ROW (.feature-row)
   Image + text side by side, alternates with .feature-row-flip.
   ============================================================ */
.feature-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-7);
  align-items: center;
}
.feature-row-flip { direction: rtl; }
.feature-row-flip > * { direction: ltr; }

.feature-media {
  border-radius: var(--r-xl);
  overflow: hidden;
  aspect-ratio: 4 / 3;
  background: var(--surf-teal);
}
.feature-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.feature-copy h2 { margin-bottom: var(--sp-4); }
.feature-copy p  {
  color: var(--muted);
  margin-bottom: var(--sp-5);
}

@media (max-width: 767px) {
  .feature-row { grid-template-columns: 1fr; }
  .feature-row-flip { direction: ltr; }
}

/* ============================================================
   CARD GRID UTILITY (.card-grid)
   ============================================================ */
.card-grid-3 {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-5);
}
.card-grid-4 {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--sp-5);
}
.card-grid-2 {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--sp-5);
}

/* No lone box on a last row.
   The team grid was hand-balanced at six, which worked until the seventh
   person joined. Card counts here change as people come and go, so this is a
   rule rather than a count someone has to remember: a card that would sit
   alone on the final row spans the row instead. Same treatment .gallery-grid
   already uses for an odd figure count.
   It fires only when the count leaves a remainder of one, so the many
   deliberate three-and-six card grids are untouched. */
.card-grid-3 > *:last-child:nth-child(3n + 1) { grid-column: span 3; }
.card-grid-4 > *:last-child:nth-child(4n + 1) { grid-column: span 4; }

@media (max-width: 959px) {
  .card-grid-4 { grid-template-columns: repeat(2, 1fr); }
  .card-grid-3 { grid-template-columns: repeat(2, 1fr); }
  /* Two columns: the remainder that orphans is an odd count, not 3n + 1. */
  .card-grid-3 > *:last-child:nth-child(3n + 1) { grid-column: auto; }
  .card-grid-4 > *:last-child:nth-child(4n + 1) { grid-column: auto; }
  .card-grid-3 > *:last-child:nth-child(odd),
  .card-grid-4 > *:last-child:nth-child(odd) { grid-column: span 2; }
}
@media (max-width: 639px) {
  .card-grid-4,
  .card-grid-3,
  .card-grid-2 { grid-template-columns: 1fr; }
  /* One column has no last row to orphan. */
  .card-grid-3 > *:last-child,
  .card-grid-4 > *:last-child { grid-column: auto; }
}

/* ============================================================
   ABOUT / MISSION BAND (.mission-band)
   Rich teal section for mission statement.
   ============================================================ */
.mission-band {
  background: var(--teal);
  color: #fff;
  padding-block: var(--sp-8);
  position: relative;
  overflow: hidden;
}
.mission-band::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 50% 80% at 90% 20%, rgba(255,255,255,0.06) 0%, transparent 55%),
    radial-gradient(ellipse 60% 50% at 0% 80%, rgba(14,34,40,0.25) 0%, transparent 50%);
}
.mission-band .wrap { position: relative; z-index: 1; }
.mission-band h2 { color: #fff; }
.mission-band p  { color: rgba(255,255,255,0.85); }

/* ============================================================
   BADGE / PILL UTILITIES
   ============================================================ */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--step-sm);
  font-weight: 700;
  padding: 5px 12px;
  border-radius: var(--r-pill);
}
.badge-teal  { background: var(--surf-teal); color: var(--teal-deep); }
.badge-coral { background: var(--coral-tint); color: var(--coral-deep); }
.badge-amber { background: rgba(212,131,10,.12); color: var(--amber); }
.badge-dark  { background: rgba(255,255,255,0.12); color: #fff; }
.badge-free  {
  background: var(--teal);
  color: #fff;
  font-size: var(--step-sm);
  padding: 6px 14px;
}

/* ============================================================
   SURFACE SECTIONS
   ============================================================ */
.sec-light  { background: var(--surf); }
.sec-dim    { background: var(--surf-dim); }
.sec-teal   { background: var(--surf-teal); }
.sec-dark   { background: var(--ever); color: var(--surf); }
.sec-dark h2, .sec-dark h3, .sec-dark h4 { color: #fff; }
.sec-dark p, .sec-dark li { color: rgba(251,247,240,0.75); }

/* ============================================================
   INLINE NEWSLETTER BAND (full-width section variant)
   ============================================================ */
.nl-band {
  background: var(--surf-dim);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  padding-block: var(--sp-7);
  text-align: center;
}
.nl-band h3 {
  font-size: var(--step-3);
  margin-bottom: var(--sp-3);
}
.nl-band p {
  color: var(--muted);
  margin-bottom: var(--sp-5);
  margin-inline: auto;
}

/* ============================================================
   SCROLL PROGRESS JS HOOK + MOBILE NAV JS HOOK
   (scripts go inline at end of <body>, CSS classes managed here)
   ============================================================ */

/* ============================================================
   FOCUS VISIBLE GLOBAL OVERRIDE
   Ensures keyboard users always see clear focus indicators.
   ============================================================ */
:focus-visible {
  outline: 3px solid var(--teal);
  outline-offset: 3px;
  border-radius: 3px;
}
:focus:not(:focus-visible) { outline: none; }

/* ============================================================
   MOBILE POLISH (max 640px) - buttons, newsletter, footer
   ============================================================ */
@media (max-width: 640px) {
  /* Primary CTA buttons full-width */
  .btn-primary:not(.nav-cta .btn-primary):not(.rsvp-band .btn-primary) {
    width: 100%;
    max-width: 360px;
    min-height: 48px;
  }
  /* Newsletter: stack input above submit */
  .nl-form {
    flex-direction: column;
    align-items: stretch;
  }
  .nl-input {
    width: 100%;
  }
  .nl-form .btn {
    width: 100%;
    min-height: 48px;
  }
  /* Footer bottom: let buttons and legal links wrap */
  .footer-bottom {
    flex-direction: column;
    align-items: flex-start;
  }
  .footer-legal {
    flex-wrap: wrap;
    gap: var(--sp-3);
  }
  /* RSVP band CTA row: stack on mobile */
  .rsvp-band-cta-row {
    flex-direction: column;
    align-items: stretch;
  }
  .rsvp-band-cta-row .btn {
    width: 100%;
    max-width: 360px;
    min-height: 48px;
    align-self: center;
  }
}

/* ============================================================
   PRINT STYLES
   ============================================================ */
@media print {
  .site-header, .site-footer, .nav-toggle, .scroll-prog,
  .rsvp-band, .cta-band, .nl-band, .nl-signup { display: none !important; }
  body { color: #000; background: #fff; }
  a[href]::after { content: ' (' attr(href) ')'; font-size: 0.75em; }
}
  /* ============================================================
     TYPOGRAPHY HYGIENE (swot-audit pass)
     CSS-only single-line fixes. Cloned to every page by oja-seo.
     ============================================================ */
  h1, h2, h3, h4, .hero h1, .h-display, .h-section { text-wrap: balance; }
  p, .lead, .hero-sub, .fcard p, .tcard-quote { overflow-wrap: break-word; }
  .bento > *, [class*="card-grid"] > * { min-width: 0; }
  .schedule-time, .schedule-content p { hyphens: auto; }
  .eyebrow, .hero-eyebrow, .badge, .tag, .schedule-badge { white-space: nowrap; }

  /* ============================================================
     CONTRAST FIXES (polish pass 2026-06-18)
     ============================================================ */

  /* 1. Credibility band cards: raise body text to meet AA on --ever bg.
        rgba(251,247,240,0.65) fails; bumping to 0.85 gives ~5:1. */
  .cred-item p {
    color: rgba(251, 247, 240, 0.85);
  }

  /* 2. Nav + small in-card coral buttons: bump font-size to 18px so
        coral-on-white meets AA large-text threshold (3:1+ at 18px bold). */
  .nav-cta .btn,
  .bento .btn,
  .author-card .btn {
    font-size: 1.125rem;
  }

  /* 3. Author-card img placeholder: ensure the brand icon is positioned
        relative to the placeholder container (set by inline style above,
        but also defensively here). */
  .author-img-placeholder {
    position: relative;
  }

  /* ============================================================
     HERO PHOTO LAYER (photo-polish pass 2026-06-18)
     ============================================================ */
  .hero-photo {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center 32%;
    z-index: 0;
  }
  .hero-overlay {
    position: absolute;
    inset: 0;
    z-index: 1;
    background: linear-gradient(90deg, rgba(10,28,32,.86) 0%, rgba(10,28,32,.66) 26%, rgba(10,28,32,.22) 50%, rgba(10,28,32,0) 72%);
  }

  /* ============================================================
     GALLERY STRIP
     ============================================================ */
  .gallery-strip {
    background: var(--surf-dim);
    padding-block: var(--sp-8);
    border-block: 1px solid var(--line);
  }
  /* Fixed-row mosaic: rows are a set height and images fill them, so the
     wall stays tight and predictable instead of ballooning to fit content. */
  .gallery-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    grid-auto-rows: 170px;
    grid-auto-flow: dense; /* lets the tall tiles pack without leaving holes */
    gap: clamp(8px, 1.1vw, 14px);
  }
  .gallery-grid img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: var(--r-sm);
    display: block;
  }
  @media (max-width: 1023px) {
    .gallery-grid { grid-template-columns: repeat(3, 1fr); grid-auto-rows: 150px; }
  }
  @media (max-width: 639px) {
    .gallery-grid { grid-template-columns: repeat(2, 1fr); grid-auto-rows: 128px; }
  }

  /* Founder cards: stack to single column on mobile */
  @media (max-width: 639px) {
    .cred-founders-grid { grid-template-columns: 1fr !important; }
  }

/* Anchor targets must clear the sticky header when jumped to. */
:target { scroll-margin-top: calc(var(--nav-h) + var(--sp-4)); }

/* ------------------------------------------------------------
   CONTRAST REMEDIATION (full-site audit, 2026-07-28)
   Every failure below was measured against its actual painted
   background at its actual rendered size. Hues are preserved and
   only darkened, so nothing shifts off brand.
   ------------------------------------------------------------ */

/* Coral pill text was 4.20:1 at 11px and 14px, needs 4.5. */
.badge-coral,
.schedule-badge-keynote { color: #9A3310; }

/* Amber on its own tint was 2.79:1, and amber on the page surface is
   never AA at label sizes. Both move to a darker amber. */
.badge-amber,
.schedule-badge-panel {
  background: rgba(212, 131, 10, 0.16);
  color: #7A4B05;
}

/* The "+" suffix on the impact numbers was 2.94:1 against the dim
   surface, just under the 3.0 large-text threshold. */
.stat-num span { color: var(--coral-deep); }

/* Footer copyright was 3.57:1 at 14px. */
.footer-copyright { color: rgba(251, 247, 240, 0.62); }

/* Step numerals were teal-tint on white, 1.38:1. They carry the running
   order, so they have to be readable, not decorative. */
.step-num { color: var(--teal-light); }

/* Muted body text on a coral-tinted card was 3.88:1. Tinted cards get
   the darker ink instead. */
.fcard-coral p,
.fcard-coral li { color: var(--ink-mid); }

/* Same coral pill problem on the tag variant. */
.tag-coral { color: #9A3310; border-color: rgba(154, 51, 16, 0.22); }

/* Footer column headings are <h3> for correct heading order, so the
   styling has to follow them off <h4>. Without this they inherit the
   global dark h3 color and vanish into the dark footer. */
.footer-col h3 {
  font-family: var(--body);
  font-size: var(--step-sm);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(251, 247, 240, 0.66);
  margin-bottom: var(--sp-4);
}
.footer-legal a { color: rgba(251, 247, 240, 0.62); }

/* "Co-Founder" role labels were 4.22:1 on the dark credibility band. */
.cred-item p[style*="teal-light"],
.cred-band .cred-item p { color: rgba(251, 247, 240, 0.85); }

/* The hero eyebrow sits on photography, where the backdrop varies, so it
   gets the lighter coral plus its own pill rather than relying on luck. */
.hero-eyebrow {
  color: #F5B0A6; /* light tint of the kit coral #DD5747, legible over photography */
  background: rgba(10, 28, 32, 0.55);
  border: 1px solid rgba(245, 176, 166, 0.34);
}

/* A <picture> inside .hero is a flex item with no in-flow content, so it
   collapses to 0x0 and takes the absolutely positioned image inside it down
   with it (the image resolves 100% against the collapsed wrapper). Make the
   wrapper itself the full-bleed layer. */
.hero picture,
.hero-interior picture {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  z-index: 0;
}

/* Scrim tuned to the hero photograph: the subjects sit center right, so the
   left side carries almost all the darkening and the right stays readable.
   A second bottom-up wash keeps the credential row legible over the crowd. */
.hero .hero-overlay {
  background:
    linear-gradient(90deg, rgba(10,28,32,.94) 0%, rgba(10,28,32,.88) 22%, rgba(10,28,32,.62) 46%, rgba(10,28,32,.24) 68%, rgba(10,28,32,.10) 100%),
    linear-gradient(0deg, rgba(10,28,32,.72) 0%, rgba(10,28,32,.20) 26%, rgba(10,28,32,0) 52%);
}
.hero-badge {
  position: absolute;
  top: var(--sp-5);
  left: clamp(20px, 6vw, 80px);
  width: 64px;
  height: auto;
  opacity: 0.85;
  z-index: 2;
  pointer-events: none;
}
/* Credential row: keep it on one line at desktop and readable over photography */
.hero-credentials { row-gap: var(--sp-2); }
.hero-credentials .cred-badge {
  background: rgba(10,28,32,.42);
  border: 1px solid rgba(251,247,240,.22);
  border-radius: var(--r-pill);
  padding: 6px 13px;
  backdrop-filter: blur(3px);
}
@media (max-width: 1100px) {
  .hero-badge { display: none; }
}

/* ============================================================
   BESPOKE ELEVATION LAYER (2026-07-27)
   Adds: dark-context amber fix, audience path cards, photo-stack
   collage, interior page hero, scrapbook gallery, sponsor invite,
   milestone timeline, contact form. Cloned to every page.
   ============================================================ */

/* ------------------------------------------------------------
   QC F2: .btn-amber on dark surfaces
   Base --amber (#D4830A) on --ever (#0E2228) is ~3.75:1 and fails
   AA for normal text. --amber-light (#F9C364) on --ever is ~9:1.
   ------------------------------------------------------------ */
.cta-band .btn-amber,
.sec-dark .btn-amber,
.cred-band .btn-amber {
  color: var(--amber-light);
  border-color: var(--amber-light);
}
.cta-band .btn-amber:hover,   .cta-band .btn-amber:focus-visible,
.sec-dark .btn-amber:hover,   .sec-dark .btn-amber:focus-visible,
.cred-band .btn-amber:hover,  .cred-band .btn-amber:focus-visible {
  background: var(--amber-light);
  color: var(--ever);
  border-color: var(--amber-light);
}

/* ------------------------------------------------------------
   THE PROGRAM (.prog)
   An editorial running order, deliberately NOT a uniform card grid:
   the rhythm changes every row (photo led, split pair, pull quote,
   full bleed) so the section reads as designed rather than generated.
   The four-color rule echoes the painted backdrop the festival
   photographs students against.
   ------------------------------------------------------------ */
/* Centered stack, one column: kicker, her festival pitch, then the heading
   that introduces the running order below. The old two-column split stranded
   the heading at the bottom of the left column while the pitch floated in a
   separate right column, and the two never read as one block. Centering the
   whole header is a deliberate exception to the "vary section shape" rule,
   made once, here, so the enlarged kicker has something to sit on top of. */
.prog-head {
  display: grid;
  grid-template-columns: 1fr;
  justify-items: center;
  text-align: center;
  gap: var(--sp-4);
}
.prog-head h2 {
  margin-bottom: 0;
  text-wrap: balance;
}
.prog-lead {
  font-size: var(--step-1);
  color: var(--ink-mid);
  margin: 0;
  padding-bottom: 6px;
  max-width: 68ch;
  margin-inline: auto;
}
.prog-rule {
  display: flex;
  gap: 6px;
  margin: var(--sp-5) 0 var(--sp-7);
}
.prog-rule span {
  height: 7px;
  border-radius: 4px;
  flex: 1 1 0;
}
.prog-rule span:nth-child(1) { background: var(--coral); flex-grow: 2.4; }
.prog-rule span:nth-child(2) { background: var(--teal); flex-grow: 1.5; }
.prog-rule span:nth-child(3) { background: var(--amber-light); flex-grow: 1; }
.prog-rule span:nth-child(4) { background: var(--teal-tint); flex-grow: 3; }

.prog-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-8);
  counter-reset: prog;
}
.prog-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: var(--sp-6);
  align-items: center;
}
/* The 01/02/03 row numbers came out on her Sep 10 notes #62 and #63. */
.prog-text h3 {
  font-size: var(--step-3);
  margin-bottom: var(--sp-3);
  text-wrap: balance;
}
.prog-text p { margin-bottom: var(--sp-3); }
.prog-text p:last-of-type { margin-bottom: 0; }
.prog-text .badge { margin-top: var(--sp-3); }

.prog-media {
  margin: 0;
  position: relative;
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: var(--shadow-lg);
  aspect-ratio: 4 / 3;
}
.prog-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 28%;
  display: block;
  transition: transform var(--dur-slow) var(--ease-brand);
}
.prog-row:hover .prog-media img { transform: scale(1.03); }

/* Row 04 mirrors: media on the left, text on the right */
.prog-row-flip .prog-media { order: -1; }
.prog-row-flip { grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); }

/* Rows 02 and 03 share one line as a compact pair */
.prog-row-split {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--sp-7);
  align-items: start;
}
.prog-half {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-5);
  align-items: start;
}
.prog-half .prog-text h3 { font-size: var(--step-2); }

/* Row 05 is text only, so it gets a pull quote and breathing room */
.prog-row-quote { grid-template-columns: minmax(0, 1fr); }
.prog-row-quote .prog-text { max-width: 74ch; }
.prog-pull {
  font-family: var(--display);
  font-size: var(--step-2);
  font-style: italic;
  line-height: 1.35;
  color: var(--teal-deep);
  border-left: 4px solid var(--coral);
  padding-left: var(--sp-5);
  margin-top: var(--sp-5);
  text-wrap: balance;
}

/* Row 06 runs full bleed as the closer */
.prog-row-full { grid-template-columns: minmax(0, 1fr); align-items: start; }
.prog-full-media {
  margin: 0;
  position: relative;
  border-radius: var(--r-lg);
  overflow: hidden;
  min-height: 340px;
  display: flex;
  box-shadow: var(--shadow-lg);
}
.prog-full-media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 42%;
}
.prog-full-media figcaption {
  position: relative;
  z-index: 1;
  align-self: flex-end;
  padding: var(--sp-6);
  width: 100%;
  background: linear-gradient(180deg, rgba(14,34,40,0) 0%, rgba(14,34,40,.90) 62%);
}
.prog-full-media figcaption h3 { color: #fff; margin: var(--sp-3) 0 6px; }
.prog-full-media figcaption p { color: rgba(251,247,240,.90); margin: 0; max-width: 58ch; }

.prog-cta {
  margin-top: var(--sp-8);
  padding-top: var(--sp-6);
  border-top: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-5);
  flex-wrap: wrap;
}
.prog-cta p {
  margin: 0;
  font-size: var(--step-1);
  font-weight: 600;
  color: var(--ink);
}

@media (max-width: 959px) {
  /* .prog-head is a centered single column at every width now, so the old
     two-to-one-column collapse here has nothing left to do. */
  .prog-row,
  .prog-row-flip { grid-template-columns: minmax(0, 1fr); }
  .prog-row .prog-media,
  .prog-row-flip .prog-media,
  .prog-row-full .prog-full-media { grid-column: 1 / -1; order: 0; }
  .prog-row-split { grid-template-columns: 1fr; gap: var(--sp-6); }
  .prog-half { grid-template-columns: minmax(0, 1fr); }
  .prog-row-quote,
  .prog-row-full { grid-template-columns: minmax(0, 1fr); }
  .prog-list { gap: var(--sp-7); }
}
@media (max-width: 639px) {
  .prog-full-media { min-height: 280px; }
  .prog-cta { flex-direction: column; align-items: stretch; }
  .prog-cta .btn { text-align: center; }
}
@media (prefers-reduced-motion: reduce) {
  .prog-media img { transition: none; }
  .prog-row:hover .prog-media img { transform: none; }
}

/* ------------------------------------------------------------
   AUDIENCE PATH CARD
   The three-door picker: students and teachers, authors, sponsors.
   Whole card is the link target.
   ------------------------------------------------------------ */
.path-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-5);
}
.path-card {
  display: flex;
  flex-direction: column;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: var(--shadow-card);
  text-decoration: none;
  color: inherit;
  transition: transform var(--dur-mid) var(--ease-brand),
              box-shadow var(--dur-mid) var(--ease-out);
}
.path-card:hover,
.path-card:focus-visible {
  transform: translateY(-5px);
  box-shadow: var(--shadow-lg);
}
.path-card-media {
  position: relative;
  aspect-ratio: 3 / 2;
  overflow: hidden;
  background: var(--surf-teal);
}
.path-card-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform var(--dur-slow) var(--ease-brand);
}
.path-card:hover .path-card-media img { transform: scale(1.05); }
.path-card-media::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(14,34,40,0) 38%, rgba(14,34,40,.82) 100%);
}
.path-card-kicker {
  position: absolute;
  left: var(--sp-4);
  right: var(--sp-4);
  bottom: var(--sp-3);
  z-index: 1;
  font-family: var(--display);
  font-weight: 700;
  font-size: var(--step-2);
  line-height: 1.15;
  color: #fff;
  text-shadow: 0 2px 12px rgba(0,0,0,.4);
}
.path-card-body {
  padding: var(--sp-5);
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  flex: 1;
}
.path-card-body p { margin: 0; }
.path-card-go {
  margin-top: auto;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-weight: 700;
  font-size: var(--step-sm);
  letter-spacing: .02em;
  color: var(--teal-deep);
}
.path-card-go svg { transition: transform var(--dur-fast) var(--ease-out); }
.path-card:hover .path-card-go svg { transform: translateX(4px); }

/* ------------------------------------------------------------
   PHOTO STACK
   Bespoke collage: anchor photo, overlapping tilted print, and a
   pinned brand badge. Used in the narrative feature rows.
   ------------------------------------------------------------ */
.photo-stack {
  position: relative;
  padding: 26px 34px 44px 0;
}
/* height:auto is load-bearing. Every image element now carries width and
   height attributes for CLS, and an attribute-derived height beats
   aspect-ratio unless the height is explicitly auto. Without it the image
   renders at its full intrinsic pixel height inside the box.
   (Kept free of a literal img tag: tooling that counts image elements in
   the source would otherwise count this comment and shift every index.) */
.photo-stack-main {
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  display: block;
}
.photo-stack-inset {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 46%;
  max-width: 240px;
  margin: 0;
  background: #fff;
  padding: 10px 10px 6px;
  border-radius: 4px;
  box-shadow: var(--shadow-lg);
  transform: rotate(-3.5deg);
  transition: transform var(--dur-mid) var(--ease-brand);
}
.photo-stack:hover .photo-stack-inset { transform: rotate(-1.5deg) translateY(-4px); }
.photo-stack-inset img {
  width: 100%;
  height: auto;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  display: block;
  border-radius: 2px;
}
.photo-stack-inset figcaption {
  padding-top: 8px;
  text-align: center;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--muted);
}
.photo-stack-badge {
  position: absolute;
  top: 0;
  left: -14px;
  width: 92px;
  height: auto;
  z-index: 2;
  filter: drop-shadow(0 6px 14px rgba(14,34,40,.28));
  transform: rotate(-9deg);
  pointer-events: none;
}
/* Flipped rows mirror the inset and badge to the opposite corners */
.feature-row-flip .photo-stack { padding: 26px 0 44px 34px; }
.feature-row-flip .photo-stack-inset {
  right: auto;
  left: 0;
  transform: rotate(3.5deg);
}
.feature-row-flip .photo-stack:hover .photo-stack-inset { transform: rotate(1.5deg) translateY(-4px); }
.feature-row-flip .photo-stack-badge {
  left: auto;
  right: -14px;
  transform: rotate(9deg);
}

/* ------------------------------------------------------------
   INTERIOR PAGE HERO
   Shorter, banner-scale hero for every page except home.
   ------------------------------------------------------------ */
.hero-interior {
  position: relative;
  overflow: hidden;
  background: var(--ever);
  padding-block: calc(var(--nav-h) + var(--sp-7)) var(--sp-7);
  isolation: isolate;
}
.hero-interior .hero-photo { object-position: center 38%; }
.hero-interior .hero-overlay {
  background: linear-gradient(90deg, rgba(10,28,32,.90) 0%, rgba(10,28,32,.76) 40%, rgba(10,28,32,.44) 78%, rgba(10,28,32,.30) 100%);
}
.hero-interior .wrap { position: relative; z-index: 2; }
.hero-interior .eyebrow { color: var(--teal-light); }
.hero-interior h1 {
  font-size: var(--step-5);
  color: #fff;
  margin-bottom: var(--sp-4);
  max-width: 20ch;
}
.hero-interior p {
  color: rgba(251,247,240,0.86);
  max-width: 62ch;
  font-size: var(--step-1);
}
.hero-interior .crumb { color: rgba(251,247,240,0.66); }
.hero-interior .crumb a { color: var(--teal-light); }
.hero-interior .crumb li[aria-current="page"] { color: rgba(251,247,240,0.92); }
.hero-interior .crumb li + li::before { color: rgba(251,247,240,0.45); }

/* ------------------------------------------------------------
   SCRAPBOOK GALLERY
   Upgrades the flat gallery grid into a print-scatter wall.
   Rotation is small (max 1.3deg) so tiles stay inside the grid gap.
   ------------------------------------------------------------ */
.gallery-strip { overflow: hidden; }
.gallery-figure {
  position: relative;
  margin: 0;
  background: #fff;
  padding: 8px;
  border-radius: var(--r-sm);
  box-shadow: var(--shadow-card);
  transition: transform var(--dur-mid) var(--ease-brand),
              box-shadow var(--dur-mid) var(--ease-out);
}
.gallery-figure img {
  border-radius: 3px;
  margin: 0;
}
.gallery-figure:nth-child(4n+1) { transform: rotate(-1.3deg); }
.gallery-figure:nth-child(4n+3) { transform: rotate(1.1deg); }
.gallery-figure:hover {
  transform: rotate(0deg) translateY(-5px);
  box-shadow: var(--shadow-lg);
  z-index: 2;
}
.gallery-grid .gallery-tall { grid-row: span 2; }
.gallery-grid .gallery-wide { grid-column: span 2; }
.day-tag {
  position: absolute;
  left: 16px;
  bottom: 16px;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 11px;
  border-radius: var(--r-pill);
  background: rgba(14,34,40,.78);
  color: #fff;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  white-space: nowrap;
  backdrop-filter: blur(4px);
}
.day-tag::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--coral);
  flex-shrink: 0;
}
.day-tag-teal::before { background: var(--teal-light); }
.day-tag-amber::before { background: var(--amber-light); }
@media (max-width: 639px) {
  .gallery-grid .gallery-tall { grid-row: span 1; }
  .gallery-grid .gallery-tall img { aspect-ratio: 4 / 3; }
  .gallery-figure:nth-child(4n+1),
  .gallery-figure:nth-child(4n+3) { transform: none; }
}

/* ------------------------------------------------------------
   SPONSOR INVITE SLOT
   Replaces faded placeholder logos with an honest open invitation.
   ------------------------------------------------------------ */
.sponsor-invite {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 60px;
  padding: var(--sp-3) var(--sp-4);
  border: 2px dashed var(--line-strong);
  border-radius: var(--r);
  color: var(--muted);
  text-decoration: none;
  font-size: var(--step-sm);
  font-weight: 600;
  text-align: center;
  transition: border-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              background var(--dur-fast) var(--ease-out);
}
.sponsor-invite:hover,
.sponsor-invite:focus-visible {
  border-color: var(--teal);
  color: var(--teal-deep);
  background: var(--surf-teal);
}
.sponsor-invite svg { flex-shrink: 0; }

/* ------------------------------------------------------------
   MILESTONE TIMELINE (About page)
   ------------------------------------------------------------ */
.milestones {
  display: grid;
  gap: var(--sp-5);
  position: relative;
}
.milestone {
  display: grid;
  grid-template-columns: 132px 1fr;
  gap: var(--sp-5);
  align-items: start;
  padding-bottom: var(--sp-5);
  border-bottom: 1px solid var(--line);
}
.milestones .milestone:last-child { border-bottom: 0; padding-bottom: 0; }
.milestone-year {
  font-family: var(--display);
  font-weight: 900;
  font-size: var(--step-3);
  line-height: 1;
  color: var(--teal);
  letter-spacing: -0.02em;
}
.milestone h3 { margin-bottom: var(--sp-2); }
.milestone p { margin: 0; }
@media (max-width: 639px) {
  .milestone { grid-template-columns: 1fr; gap: var(--sp-2); }
}

/* ------------------------------------------------------------
   CONTACT FORM
   Static markup at concept stage. The action attribute is wired
   when the nonprofit backend (donations, email, ticketing) is chosen.
   ------------------------------------------------------------ */
.form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-4) var(--sp-5);
}
.form-field { display: flex; flex-direction: column; gap: 6px; }
.form-field-wide { grid-column: 1 / -1; }
.form-field label {
  font-size: var(--step-sm);
  font-weight: 700;
  letter-spacing: .02em;
  color: var(--ink-mid);
}
.form-field input,
.form-field select,
.form-field textarea {
  font-family: var(--body);
  font-size: 1rem;
  color: var(--ink);
  background: #fff;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  padding: 12px 14px;
  min-height: 48px;
  width: 100%;
  transition: border-color var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out);
}
.form-field textarea { min-height: 132px; resize: vertical; }
.form-field input:focus,
.form-field select:focus,
.form-field textarea:focus {
  outline: none;
  border-color: var(--teal);
  box-shadow: 0 0 0 3px rgba(22,110,102,.18);
}
.form-note {
  font-size: var(--step-sm);
  color: var(--muted);
  grid-column: 1 / -1;
}
@media (max-width: 767px) {
  .form-grid { grid-template-columns: 1fr; }
}

/* ------------------------------------------------------------
   RESPONSIVE: elevation layer
   ------------------------------------------------------------ */
@media (max-width: 900px) {
  .path-grid { grid-template-columns: 1fr; max-width: 460px; margin-inline: auto; }
}
@media (max-width: 767px) {
  .photo-stack { padding: 20px 24px 34px 0; }
  .feature-row-flip .photo-stack { padding: 20px 0 34px 24px; }
  .photo-stack-badge { width: 68px; }
  .hero-interior h1 { max-width: none; }
}

@media (prefers-reduced-motion: reduce) {
  .path-card,
  .path-card-media img,
  .photo-stack-inset,
  .gallery-figure { transition: none; }
  .gallery-figure:nth-child(4n+1),
  .gallery-figure:nth-child(4n+3) { transform: none; }
}

/* ==== COMPONENT LAYER (generated by sync_shared.py, edit the files in _design/components/ instead) ==== */

/* ---- authors.css ---- */
/* ============================================================
   AUTHORS PAGE COMPONENTS
   Scoped additions for authors.html. Every class is prefixed
   `au-` so nothing can collide with the shared stylesheet.
   Depends only on existing :root tokens.

   Contents
     1. Split section header (breaks the centered-header pattern)
     2. Lineup lead entries (photography-led, two wide tiles)
     3. Lineup roster ledger (numbered editorial rows)
     4. Tier divider label
     5. Full name index (two-column, left aligned)
     6. Inline jump link (to #submit-interest)
     7. Author interest form panel
   ============================================================ */


/* ------------------------------------------------------------
   1. SPLIT SECTION HEADER (.au-head-split)
   Heading sits left, the supporting line sits right and baseline
   aligns to it. Deliberate counterweight to the centered .sec-head
   used elsewhere on the site.
   ------------------------------------------------------------ */
.au-head-split {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  gap: var(--sp-4) var(--sp-7);
  align-items: end;
  margin-bottom: var(--sp-6);
}
.au-head-split h2 {
  margin-bottom: 0;
  max-width: 16ch;
}
.au-head-split p {
  font-size: var(--step-1);
  line-height: 1.55;
  color: var(--muted);
  margin: 0;
  max-width: 46ch;
}
@media (max-width: 767px) {
  .au-head-split {
    grid-template-columns: 1fr;
    align-items: start;
  }
  .au-head-split h2 { max-width: none; }
}


/* ------------------------------------------------------------
   2. LINEUP LEAD ENTRIES (.au-lead)
   Two wide tiles where the photograph carries the entry and the
   name is overprinted on a bottom scrim. No card chrome, no icon.
   ------------------------------------------------------------ */
.au-lead-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(16px, 2vw, 28px);
  margin-bottom: var(--sp-7);
}
@media (max-width: 767px) {
  .au-lead-grid { grid-template-columns: 1fr; }
}

.au-lead {
  position: relative;
  margin: 0;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--ever);
  box-shadow: var(--shadow-card);
  transition: transform var(--dur-mid) var(--ease-brand),
              box-shadow var(--dur-mid) var(--ease-out);
}
.au-lead:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
}
.au-lead img {
  display: block;
  width: 100%;
  /* height:auto is load-bearing: the width/height attributes carried for
     CLS beat aspect-ratio unless the height is explicitly auto. */
  height: auto;
  aspect-ratio: 5 / 4;
  object-fit: cover;
  object-position: center 28%;
}
/* Scrim so overprinted type stays legible over any photograph */
.au-lead::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg,
              rgba(14, 34, 40, 0) 34%,
              rgba(14, 34, 40, 0.52) 64%,
              rgba(14, 34, 40, 0.90) 100%);
  pointer-events: none;
}
.au-lead figcaption {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  padding: var(--sp-5);
}
.au-lead-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 11px;
  border-radius: var(--r-pill);
  background: rgba(232, 93, 43, 0.92);
  color: #fff;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
}
.au-lead-badge svg {
  width: 13px;
  height: 13px;
  flex-shrink: 0;
}
.au-lead-name {
  font-family: var(--display);
  font-size: var(--step-3);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: #fff;
}
.au-lead-note {
  font-size: var(--step-0);
  line-height: 1.5;
  color: rgba(251, 247, 240, 0.84);
  max-width: 40ch;
}

@media (prefers-reduced-motion: reduce) {
  .au-lead { transition: none; }
  .au-lead:hover { transform: none; }
}


/* ------------------------------------------------------------
   3. LINEUP ROSTER LEDGER (.au-roster)
   An editorial index rather than another card grid: hairline
   rows, a display-face index number, a small landscape still,
   and one verifiable line per entry.
   ------------------------------------------------------------ */
.au-roster {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--line);
}
.au-row {
  display: grid;
  grid-template-columns: auto 148px minmax(0, 1fr);
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-4) var(--sp-3) var(--sp-4) 0;
  border-bottom: 1px solid var(--line);
  transition: background var(--dur-fast) var(--ease-out),
              padding var(--dur-mid) var(--ease-brand);
}
.au-row:hover {
  background: rgba(255, 255, 255, 0.55);
  padding-left: var(--sp-3);
  padding-right: var(--sp-4);
}
.au-row-num {
  font-family: var(--display);
  font-size: var(--step-2);
  font-weight: 900;
  line-height: 1;
  letter-spacing: -0.02em;
  /* teal-light measured 2.87:1 on the dim surface, just under the 3.0
     large-text threshold, so the ledger numerals use the full teal */
  color: var(--teal);
  font-variant-numeric: tabular-nums;
  min-width: 2.4ch;
}
.au-row-thumb {
  width: 148px;
  aspect-ratio: 4 / 3;
  border-radius: var(--r-sm);
  overflow: hidden;
  background: var(--surf-teal);
  box-shadow: var(--shadow-card);
}
.au-row-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.au-row-name {
  font-family: var(--display);
  font-size: var(--step-2);
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -0.015em;
  color: var(--ink);
}
.au-row-note {
  font-size: var(--step-0);
  line-height: 1.5;
  color: var(--muted);
  margin-top: 3px;
  max-width: 54ch;
}

@media (max-width: 639px) {
  .au-row {
    grid-template-columns: 42px minmax(0, 1fr);
    align-items: start;
    gap: var(--sp-2) var(--sp-3);
    padding-right: 0;
  }
  .au-row:hover { padding-left: 0; padding-right: 0; }
  .au-row-thumb {
    grid-column: 2;
    width: 100%;
    aspect-ratio: 16 / 9;
  }
  .au-row-text { grid-column: 2; }
}

@media (prefers-reduced-motion: reduce) {
  .au-row { transition: none; }
  .au-row:hover { padding-left: 0; padding-right: var(--sp-3); }
}


/* ------------------------------------------------------------
   4. TIER DIVIDER LABEL (.au-tier-label)
   Small caps label with a rule that runs to the edge, used to
   separate the lead entries from the ledger.
   ------------------------------------------------------------ */
.au-tier-label {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  /* .au-tier-label is a <p>, and the base rule caps p at 70ch, which would
     stop the rule short of the container. Let it run the full width. */
  max-width: none;
  font-family: var(--body);
  font-size: var(--step-sm);
  font-weight: 700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: var(--sp-4);
}
.au-tier-label::after {
  content: '';
  flex: 1 1 auto;
  height: 1px;
  background: var(--line);
}


/* ------------------------------------------------------------
   5. FULL NAME INDEX (.au-index)
   Copy column left, pill field right. Replaces a fourth
   photo-and-text feature row so the page stops repeating itself.
   ------------------------------------------------------------ */
.au-index {
  display: grid;
  grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr);
  gap: var(--sp-5) var(--sp-7);
  align-items: start;
}
.au-index-copy h2 { margin-bottom: var(--sp-4); }
.au-index-copy p {
  color: var(--muted);
  font-size: var(--step-1);
  line-height: 1.55;
  max-width: 40ch;
}
.au-index-field {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}
@media (max-width: 767px) {
  .au-index { grid-template-columns: 1fr; }
}


/* ------------------------------------------------------------
   6. INLINE JUMP LINK (.au-jump)
   Sends readers from mid-page straight to #submit-interest.
   Underlined in coral so it reads as an action, but it is a link
   and not a button, so it never competes with the RSVP band.
   ------------------------------------------------------------ */
.au-jump-row {
  display: flex;
  justify-content: center;
  margin-top: var(--sp-6);
}
.au-jump-row-left { justify-content: flex-start; }

.au-jump {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-family: var(--body);
  font-size: var(--step-1);
  font-weight: 700;
  color: var(--teal);
  text-decoration: none;
  border-bottom: 2px solid var(--coral);
  padding-bottom: 4px;
  transition: color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out);
}
.au-jump:hover,
.au-jump:focus-visible {
  color: var(--teal-deep);
  border-bottom-color: var(--coral-deep);
  text-decoration: none;
}
.au-jump:focus-visible {
  outline: 3px solid var(--teal);
  outline-offset: 4px;
  border-radius: 2px;
}
.au-jump svg {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  transition: transform var(--dur-fast) var(--ease-out);
}
.au-jump:hover svg { transform: translateX(4px); }

@media (prefers-reduced-motion: reduce) {
  .au-jump svg { transition: none; }
  .au-jump:hover svg { transform: none; }
}


/* ------------------------------------------------------------
   7. AUTHOR INTEREST FORM PANEL (.au-form-panel)
   A quiet white panel on a tinted section. Deliberately calm:
   the closing .rsvp-band stays the loudest block on the page.
   ------------------------------------------------------------ */
.au-form-panel {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: clamp(24px, 3.4vw, 52px);
  box-shadow: var(--shadow-card);
  max-width: 960px;
}
.au-form-head {
  margin-bottom: var(--sp-5);
  padding-bottom: var(--sp-5);
  border-bottom: 1px solid var(--line-soft);
}
.au-form-head h2 {
  font-size: var(--step-3);
  margin-bottom: var(--sp-3);
}
.au-form-head p {
  color: var(--muted);
  max-width: 62ch;
}
.au-form-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--body);
  font-size: var(--step-sm);
  font-weight: 700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--coral-deep);
  margin-bottom: var(--sp-3);
}
.au-form-eyebrow svg {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}
/* Optional-field hint sits beside the label text, not inside it */
.au-opt {
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
  /* muted-lt is a large-text-only token and measured 2.77:1 at 14px */
  color: var(--muted);
}
.au-form-actions {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-4);
  margin-top: var(--sp-2);
}

/* ------------------------------------------------------------------
   APPLY CALL TO ACTION (.au-apply-cta)
   Closes the roster. It used to be a muted sentence in small type at
   the foot of a forty-name list, which is where a call to action goes
   to be missed. Given its own card, at the width of the list above it,
   with the button doing the asking.
   ------------------------------------------------------------------ */
.au-apply-cta {
  max-width: 680px;
  margin: var(--sp-8) auto 0;
  padding: var(--sp-7) var(--sp-6);
  border: 1.5px solid var(--line-strong);
  border-radius: var(--r-lg);
  background: var(--card, #fff);
  text-align: center;
}

.au-apply-cta h3 {
  font-family: var(--display);
  font-size: var(--step-2);
  font-weight: 800;
  line-height: 1.15;
  color: var(--ink);
  margin: 0;
}

.au-apply-cta p {
  margin: var(--sp-3) 0 var(--sp-5);
  color: var(--muted);
}

@media (max-width: 639px) {
  .au-apply-cta { padding: var(--sp-6) var(--sp-5); }
  .au-apply-cta .btn { width: 100%; }
}

/* ---- featured-event.css ---- */
/* ============================================================
   FEATURED EVENT BAND
   Her copy doc, 2026-09-02, section 1. Sits directly under the facts
   strip, which already carries the date and venue, so this band leads
   on the presenter credit and the run of what actually happens.
   ============================================================ */
.featured-event-stat {
  max-width: 62ch;
  margin: 0 auto var(--sp-4);
  text-align: center;
  font-family: var(--display);
  font-size: var(--step-1);
  font-weight: 700;
  line-height: 1.35;
  color: var(--ink);
}

.featured-event-body {
  max-width: 72ch;
  margin: 0 auto;
  text-align: center;
  font-size: var(--step-0);
  line-height: 1.7;
  color: var(--muted);
}

/* ------------------------------------------------------------
   AUDIENCE ROW
   Her three button labels, one per audience. Three across, so the
   row is always full: there is no fourth audience and no dynamic
   count, which is why this can be a plain fixed grid rather than
   the orphan-guarded .lineup-grid.
   ------------------------------------------------------------ */
.audience-row {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--sp-4);
  margin-top: var(--sp-6);
}

@media (max-width: 720px) {
  .audience-row { grid-template-columns: 1fr; }
}

.audience-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-height: 92px;
  padding: var(--sp-4) var(--sp-5);
  border: 1.5px solid var(--line-strong);
  border-radius: var(--r);
  background: var(--card, #fff);
  color: var(--ink);
  text-align: center;
  text-decoration: none;
  transition: transform var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out);
}

.audience-btn b {
  font-family: var(--display);
  font-size: var(--step-1);
  font-weight: 800;
  letter-spacing: -0.01em;
}

.audience-btn span {
  font-size: var(--step-sm);
  color: var(--muted);
}

.audience-btn:hover,
.audience-btn:focus-visible {
  transform: translateY(-3px);
  border-color: var(--coral);
  box-shadow: var(--shadow-card);
}

.audience-btn:hover span,
.audience-btn:focus-visible span {
  color: var(--coral-deep);
}

@media (prefers-reduced-motion: reduce) {
  .audience-btn { transition: none; }
  .audience-btn:hover,
  .audience-btn:focus-visible { transform: none; }
}

/* ---- forms.css ---- */
/* ------------------------------------------------------------
   FORM STATUS PANEL
   Shown in place after a preview-build submit. Without it, a form
   posting to "#" navigates the visitor to the host's raw error
   page with no branding and no way back.
   ------------------------------------------------------------ */
.form-status {
  grid-column: 1 / -1;
  margin-top: var(--sp-4);
  padding: var(--sp-5);
  border-radius: var(--r);
  background: var(--surf-teal);
  border: 1px solid var(--teal-light);
  border-left: 4px solid var(--teal);
}
.form-status:focus-visible {
  outline: 3px solid var(--teal);
  outline-offset: 3px;
}
.form-status-head {
  margin: 0 0 6px;
  font-family: var(--display);
  font-size: var(--step-1);
  font-weight: 700;
  color: var(--teal-deep);
  line-height: 1.3;
}
.form-status-body {
  margin: 0;
  font-size: var(--step-sm);
  color: var(--ink-mid);
  line-height: 1.6;
}

/* The newsletter form is a flex row on a dark band, so the panel has to
   break to its own line and invert. */
.nl-form { flex-wrap: wrap; }
.nl-form .form-status {
  flex: 1 0 100%;
  background: rgba(255, 255, 255, 0.10);
  border-color: rgba(255, 255, 255, 0.30);
  border-left-color: var(--amber-light);
}
.nl-form .form-status-head { color: #fff; }
.nl-form .form-status-body { color: rgba(251, 247, 240, 0.90); }

/* ------------------------------------------------------------
   File upload fields (author application headshot + covers).
   The base .form-field input rule already boxes them; this styles
   the native picker button so it reads as part of the form system.
   ------------------------------------------------------------ */
.form-field input[type="file"] {
  padding: 8px 10px;
  cursor: pointer;
}
.form-field input[type="file"]::file-selector-button {
  font-family: var(--body);
  font-size: var(--step-sm);
  font-weight: 700;
  color: var(--teal-deep);
  background: var(--surf-teal);
  border: 1px solid var(--teal-light);
  border-radius: var(--r-sm);
  padding: 8px 14px;
  margin-right: 12px;
  cursor: pointer;
}

/* ------------------------------------------------------------
   Mobile drawer: mark the current page for sighted users too.
   The base rule is scoped to .nav-links, so the drawer showed no
   current-page signal at all even though aria-current was correct.
   ------------------------------------------------------------ */
.nav-drawer a[aria-current="page"] {
  color: var(--coral-deep);
  font-weight: 700;
  border-left: 3px solid var(--coral);
  padding-left: calc(var(--sp-4) - 3px);
}

/* ---- hero-grid.css ---- */
/* Homepage hero grid (Josh's Sep 11 mockup, mockups\hero-grid\index.html).
   One tall Students + Educators tile over the vertical Save the Date reel on
   the left, two stacked tiles on the right (Authors on teal with sunburst
   rays, Sponsors on sand), so every audience has its door in the first fold.
   It replaced the full-bleed hero, the facts strip and the three picture
   cards on 2026-09-11. The lettering keeps its in-place stroke draw from
   hero-signature.css; the centre-stage intro never runs here because the
   page JS only stages inside .hero.
   Prefix: hero-grid / tile-. */

.hero-grid {
  /* Wider than the site's 1240px column on purpose (Josh, Sep 11): the reel
     tile reaches further left and the two right tiles further right. */
  max-width: 1400px;
  margin-inline: auto;
  padding: var(--sp-4) var(--gut) var(--sp-4);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr) minmax(0, 1fr);
  gap: 20px;
  /* Ends above the fold: the header, this padding and a 24px breath come
     off the viewport height (the first cut used the full viewport and the
     bottom tile broke the fold). */
  min-height: calc(100vh - var(--nav-h) - 24px);
  min-height: calc(100svh - var(--nav-h) - 24px);
}

.tile {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-lg);
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.tile-inner { position: relative; z-index: 1; }
.tile-eyebrow {
  display: inline-block;
  font-size: var(--step-sm);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  margin-bottom: 14px;
}
.tile h2 {
  font-family: var(--display);
  font-weight: 900;
  font-size: clamp(1.7rem, 2.3vw, 2.2rem); /* one line for "Sponsors & Partners" at 1440 */
  line-height: 1.05;
  letter-spacing: -0.02em;
  margin: 0;
}
.tile p { margin: 0; line-height: 1.55; }
.tile .cta-row { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 20px; }

/* Two button faces the tiles need that the site did not have. */
.btn-ink { background: var(--ink); color: #fff; border-color: var(--ink); }
.btn-ink:hover, .btn-ink:focus-visible { background: var(--ever); border-color: var(--ever); color: #fff; }
.btn-white { background: #fff; color: var(--teal-deep); border-color: #fff; }
.btn-white:hover, .btn-white:focus-visible { background: var(--surf); color: var(--teal-deep); }

/* ---- Left: Students + Educators over the reel ---- */
.tile-attend {
  grid-row: 1 / 3;
  background: var(--ever);
  color: #fff;
  padding: clamp(24px, 3vw, 44px);
  min-height: 560px;
}
.tile-reel { position: absolute; inset: 0; z-index: 0; }
.tile-reel img,
.tile-reel video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 55%;
}
/* The film fades in once the page JS confirms it is playing (.reel-on);
   the poster frame underneath carries the tile until then, and for
   reduced motion and refused autoplay. */
.tile-reel video { opacity: 0; transition: opacity 0.9s var(--ease-out); }
.reel-on .tile-reel video { opacity: 1; }
.tile-reel::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    linear-gradient(90deg, rgba(14, 34, 40, 0.92) 0%, rgba(14, 34, 40, 0.72) 42%, rgba(14, 34, 40, 0.18) 100%),
    linear-gradient(0deg, rgba(14, 34, 40, 0.82) 0%, rgba(14, 34, 40, 0) 50%);
}
.tile-attend .tile-inner { max-width: 580px; }
.tile-attend .tile-eyebrow {
  /* Her Sep 14 email: the red label's face looked off to her. It now
     uses the site's display face, the same one as the tile headings. */
  font-family: var(--display);
  letter-spacing: 0.08em;
  color: #E8735F; /* kit coral lifted one step: 5.5:1 on the dark tile (kit coral is 4.3:1) */
  border-bottom: 2px solid var(--coral);
  padding-bottom: 6px;
}
.tile-attend .hero-sig-title { margin: 0 0 4px; }
.tile-attend .hero-sig { width: 100%; margin-block: 6px 10px; }
.tile-lede {
  margin-top: 20px;
  font-size: var(--step-1);
  color: rgba(251, 247, 240, 0.85);
  max-width: 46ch;
}
.who {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin-top: 28px;
  max-width: 520px;
}
.who a {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px;
  border-radius: var(--r);
  text-decoration: none;
  background: rgba(251, 247, 240, 0.08);
  border: 1px solid rgba(251, 247, 240, 0.22);
  color: #fff;
  transition: background 0.18s ease, transform 0.18s ease, border-color 0.18s ease;
}
.who a:hover,
.who a:focus-visible {
  background: rgba(251, 247, 240, 0.16);
  border-color: rgba(251, 247, 240, 0.5);
  transform: translateY(-2px);
}
.who .ic {
  width: 36px;
  height: 36px;
  border-radius: 10px;
  flex-shrink: 0;
  display: grid;
  place-items: center;
  background: var(--coral-deep);
  color: #fff;
}
.who .ic-teal { background: var(--teal); }
.who .ic svg { width: 22px; height: 22px; }
.who small {
  display: block;
  font-size: var(--step-sm);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  opacity: 0.75;
  font-weight: 600;
}
.who strong { display: block; font-size: 0.9375rem; font-weight: 700; line-height: 1.2; margin-top: 2px; white-space: nowrap; }
.who .arrow { margin-left: auto; width: 18px; height: 18px; opacity: 0.7; flex-shrink: 0; }
/* The site's 1240px column leaves each button about 210px wide until the
   phone stack, so the arrow steps aside there and the labels stay on one line. */
@media (min-width: 640px) and (max-width: 1499px) { .who .arrow { display: none; } }
.tile-facts {
  position: relative;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  gap: 18px 28px;
  margin-top: 32px;
  font-size: var(--step-sm);
  font-weight: 600;
  color: rgba(251, 247, 240, 0.8);
}
.tile-facts span { display: inline-flex; align-items: center; gap: 8px; }
.tile-facts svg { width: 16px; height: 16px; color: var(--teal-light); flex-shrink: 0; }
/* The pause control sits in the tile's bottom corner, not the page's. */
.tile-attend .reel-toggle { top: auto; right: 18px; bottom: 18px; width: 40px; height: 40px; }

/* ---- Right top: Authors (teal, sunburst rays, Stine) ---- */
.tile-authors {
  background: var(--teal);
  color: #fff;
  padding: clamp(20px, 2.2vw, 32px);
  padding-right: 40%;
  min-height: 280px;
}
.tile-authors::before {
  content: "";
  position: absolute;
  inset: -20% -10% -20% 30%;
  background: repeating-conic-gradient(from 0deg at 70% 50%, rgba(255, 255, 255, 0.10) 0 7deg, rgba(255, 255, 255, 0) 7deg 14deg);
  opacity: 0.7;
  pointer-events: none;
}
.tile-authors .tile-eyebrow { color: var(--amber-light); }
.tile-authors h2 { color: #fff; }
.tile-authors p { margin-top: 10px; font-size: var(--step-0); color: rgba(255, 255, 255, 0.9); max-width: 32ch; }
.tile-art {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 46%;
}
.tile-art img { display: block; width: 100%; height: 100%; object-fit: cover; }
.tile-authors .tile-art {
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 22%);
  mask-image: linear-gradient(90deg, transparent 0, #000 22%);
}
.tile-authors .tile-art img { object-position: 90% center; }
.tile-tag {
  position: absolute;
  z-index: 2;
  right: 20px;
  top: 20px;
  /* Her Sep 14 email: not coral, so it stops competing with the coral
     Become a Sponsor button in the header right above it. */
  background: var(--amber-light);
  color: var(--ink);
  font-size: var(--step-sm);
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 8px 14px;
  border-radius: var(--r-pill);
  box-shadow: 0 6px 18px -6px rgba(0, 0, 0, 0.45);
}

/* ---- Right bottom: Sponsors (warm sand, students with books) ---- */
.tile-sponsors {
  background: var(--surf-dim);
  color: var(--ink);
  padding: clamp(20px, 2.2vw, 32px);
  padding-right: 40%;
  min-height: 280px;
  border: 1px solid var(--line);
}
.tile-sponsors .tile-eyebrow { color: var(--teal); }
.tile-sponsors h2 { color: var(--ink); }
.tile-sponsors p { margin-top: 10px; font-size: var(--step-0); color: var(--muted); max-width: 32ch; }
.tile-sponsors .tile-art {
  width: 48%;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 24%);
  mask-image: linear-gradient(90deg, transparent 0, #000 24%);
}
.tile-sponsors .tile-art img { object-position: 40% center; }
.tile-impact {
  position: absolute;
  z-index: 2;
  right: 20px;
  bottom: 20px;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 10px 14px;
  display: flex;
  align-items: center;
  gap: 10px;
  box-shadow: 0 10px 24px -12px rgba(26, 46, 53, 0.35);
}
.tile-impact b { font-family: var(--display); font-size: 1.5rem; font-weight: 900; color: var(--coral-deep); line-height: 1; }
.tile-impact span { font-size: var(--step-sm); font-weight: 700; line-height: 1.15; color: var(--ink); text-transform: uppercase; letter-spacing: 0.06em; }

/* ---- Responsive ---- */
@media (max-width: 1100px) {
  .tile-authors, .tile-sponsors { padding-right: 42%; }
}
/* Short laptops (768px tall): tighter tiles so the grid still ends above the fold. */
@media (min-width: 960px) and (max-height: 800px) {
  .tile-authors, .tile-sponsors { padding-top: 22px; padding-bottom: 22px; }
  .tile .cta-row { margin-top: 16px; }
  .tile-attend { min-height: 0; }
}
@media (max-width: 959px) {
  .hero-grid { grid-template-columns: 1fr; grid-template-rows: auto; min-height: 0; }
  .tile-attend { grid-row: auto; min-height: 560px; }
}
@media (max-width: 639px) {
  .tile-authors, .tile-sponsors { padding-right: clamp(20px, 2.2vw, 32px); padding-bottom: 64%; }
  .tile-authors .tile-art, .tile-sponsors .tile-art {
    width: 100%;
    top: auto;
    height: 56%;
    -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 30%);
    mask-image: linear-gradient(180deg, transparent 0, #000 30%);
  }
  .who { grid-template-columns: 1fr; }
  .tile-impact { bottom: 16px; right: 16px; }
  .tile-tag { position: static; display: inline-block; margin-bottom: 14px; }
}

/* ---- hero-signature.css ---- */
/* Homepage hero signature: the client's actual "be the author of your own life"
   lettering (assets/tagline-lettering.webp) revealed stroke-by-stroke through an
   SVG mask traced from the artwork (46 pen strokes + a cleanup fill layer,
   _design/sig-bake/trace_tagline.py).

   The intro: on load, the first fold is a full-height stage over the kids reel.
   The lettering writes itself large and centered (about 3.4s), then settles into
   its place in the hero while the eyebrow, subline, CTAs, and badges rise in.
   Driven by three html classes set by the page JS:
     .sig-on     the intro ran: the hero holds full-viewport height permanently
                 so the settle causes no layout jump
     .sig-stage  during the write: hero copy hidden, lettering transformed to
                 center stage (inline FLIP transform set by JS)
     .sig-settle after the write: lettering transitions home, copy rises in
   Reduced-motion, no-JS, and automation skip the stage entirely: the lettering
   draws (or just appears) in place with all content visible.
   Prefix: hero-sig / sig-. */

.hero-sig-title {
  margin: 0 0 var(--sp-4);
}

.hero-sig {
  display: block;
  width: min(780px, 100%);
  height: auto;
  overflow: visible;
  transform-origin: top left;
}

.hero-sig-strokes path {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  /* Invisible until this stroke's turn: round linecaps would otherwise show
     every stroke's start point as a floating dot. */
  opacity: 0;
  animation: hs-draw var(--d, 0.4s) linear var(--t, 0s) forwards;
}

@keyframes hs-draw {
  0% { stroke-dashoffset: 1; opacity: 1; }
  100% { stroke-dashoffset: 0; opacity: 1; }
}

/* Cleanup layer: fades the full mask in at the very end so the finished
   lettering is always the complete artwork, whatever the strokes missed. */
.hero-sig .sig-fill {
  opacity: 0;
  animation: hs-fill var(--d, 0.5s) ease var(--t, 2.6s) forwards;
}
@keyframes hs-fill {
  to { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .hero-sig-strokes path {
    animation: none;
    stroke-dashoffset: 0;
    opacity: 1;
  }
  .hero-sig .sig-fill {
    animation: none;
    opacity: 1;
  }
}

/* ---- The intro stage ---- */

/* The hero keeps first-fold height once the intro has run, so nothing jumps
   when the stage releases. 108px = sticky header height. */
.sig-on .hero {
  min-height: calc(100vh - 108px);
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* No scrolling while the lettering writes. */
.sig-stage {
  overflow: hidden;
}

/* During the stage, everything but the lettering holds back... */
.sig-on .hero-reveal {
  opacity: 0;
  transform: translateY(18px);
}
/* ...and rises in once the lettering settles, staggered top to bottom. */
.sig-settle .hero-reveal {
  opacity: 1;
  transform: none;
  transition: opacity 0.5s var(--ease-out), transform 0.5s var(--ease-out);
}
.sig-settle .hero-eyebrow.hero-reveal { transition-delay: 0.08s; }
.sig-settle .hero-sub.hero-reveal { transition-delay: 0.16s; }
.sig-settle .hero-join-line.hero-reveal { transition-delay: 0.24s; }
.sig-settle .hero-cta-row.hero-reveal { transition-delay: 0.32s; }
.sig-settle .hero-credentials.hero-reveal { transition-delay: 0.40s; }
.sig-settle .hero-badge.hero-reveal { transition-delay: 0.48s; }

/* The lettering glides from center stage back to its spot in the copy. The
   JS sets the stage transform inline and clears it at settle time. */
.sig-settle .hero-sig {
  transition: transform 0.7s var(--ease-brand);
}

/* Scrolling during the stage fast-forwards everything: the lettering
   completes instantly and the settle runs at once. */
.sig-skip .hero-sig-strokes path {
  animation: none;
  stroke-dashoffset: 0;
  opacity: 1;
}
.sig-skip .hero-sig .sig-fill {
  animation: none;
  opacity: 1;
}

/* ---- The kids reel: crossfading full-bleed background ---- */
/* A slow four-photo crossfade with a gentle push-in, sitting where a single
   photo used to. Swapping in the client's real highlight video later means
   replacing the four cycle images with one <video muted loop playsinline>
   plus a visible pause control; everything else stays. */

.hero-reel {
  position: absolute;
  inset: 0;
  overflow: hidden;
  /* .grain > * lifts every hero child to z-index 2; the backdrop must sit
     under the .hero-overlay scrim (z-index 1). */
  z-index: 0;
}

/* Extra veil while the lettering writes center-stage: the reel frames are
   bright convention light, and the stage spans the full width where the
   directional scrim thins out. Fades away as the hero settles. */
.hero-overlay::after {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(10, 28, 32, 0.52);
  opacity: 0;
  transition: opacity 0.8s var(--ease-out);
}
.sig-stage .hero-overlay::after {
  opacity: 1;
}
.hero-reel img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 30%;
}
.hero-reel .reel-cycle {
  opacity: 0;
  animation:
    reel-fade 24s linear infinite var(--reel-t, 0s),
    reel-zoom 24s linear infinite var(--reel-t, 0s);
}
@keyframes reel-fade {
  0% { opacity: 0; }
  5% { opacity: 1; }
  25% { opacity: 1; }
  31% { opacity: 0; }
  100% { opacity: 0; }
}
@keyframes reel-zoom {
  0% { transform: scale(1); }
  31% { transform: scale(1.07); }
  100% { transform: scale(1.07); }
}
@media (prefers-reduced-motion: reduce) {
  .hero-reel .reel-cycle {
    animation: none;
    opacity: 0;
  }
}

/* The real highlight film. Sits above the photo crossfade (which stays as
   the fallback for reduced motion, save-data, and any playback failure) and
   fades in once the page JS confirms it is actually playing (.reel-on). */
.hero-reel video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 30%;
  opacity: 0;
  transition: opacity 0.9s var(--ease-out);
}
.reel-on .hero-reel video {
  opacity: 1;
}

/* Visible pause control for the film (design-system hard rule: no autoplay
   motion without one). Bottom right, out of the copy's way. */
.reel-toggle {
  position: absolute;
  right: clamp(14px, 2.5vw, 30px);
  top: clamp(14px, 2.5vh, 26px);
  z-index: 3;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  border: 1px solid rgba(251, 247, 240, 0.45);
  background: rgba(10, 28, 32, 0.55);
  color: #FBF7F0;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background 0.2s var(--ease-out), border-color 0.2s var(--ease-out);
}
.reel-toggle:hover,
.reel-toggle:focus-visible {
  background: rgba(10, 28, 32, 0.8);
  border-color: rgba(251, 247, 240, 0.8);
}
.reel-toggle svg {
  width: 18px;
  height: 18px;
  display: block;
}
.reel-toggle .ic-pause { display: block; }
.reel-toggle .ic-play { display: none; }
.reel-toggle[aria-pressed="true"] .ic-pause { display: none; }
.reel-toggle[aria-pressed="true"] .ic-play { display: block; }

/* Short author name-drop line between the lede and the CTA row. */
.hero-join-line {
  font-size: var(--step-0);
  font-weight: 700;
  color: #FBF7F0;
  margin-bottom: var(--sp-4);
}

/* Brand-art watermark accents (sunglasses on the join band, books on donate).
   Decorative only, always aria-hidden. */
.brand-accent {
  position: absolute;
  pointer-events: none;
  height: auto;
}

/* Screen-reader-only text. The signature SVG is aria-hidden; the real h1 text
   lives in this. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---- lineup.css ---- */
/* ============================================================
   CONFIRMED LINEUP GRID (dynamic)
   The target the author plugin renders approved authors into.

   Distinct from .card-grid-3, which is hand-authored and therefore
   always a deliberate multiple of three. This one holds however many
   authors Sorboni has approved that week, so the count is out of our
   hands and the anti-orphan rule has to be built in rather than
   eyeballed at launch.

   Two defences, deliberately overlapping:

   1. The plugin pads the last row with .author-invite cards, so the
      desktop row is always full. Fill count is (3 - (n % 3)) % 3.
   2. This grid is a centred flex wrap, not CSS Grid, so any tail that
      still comes up short centres itself instead of hanging left. That
      covers the 2-across tablet band, where a multiple of three can
      still leave a remainder.
   ============================================================ */
.lineup-grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: stretch;
  gap: var(--sp-5);
}

/* Three across. The basis subtracts the two gaps so three cards land
   exactly on the row rather than wrapping one off the end. */
.lineup-grid > * {
  flex: 0 1 calc((100% - 2 * var(--sp-5)) / 3);
  min-width: 0;
}

/* No two-across band. Filling to a multiple of three is orphan-free at
   three columns and at one, but a multiple of three can leave a remainder
   at two, which is the one case that would put a lone card on a last row.
   Holding three columns down to the phone breakpoint removes that case
   rather than papering over it. */
@media (max-width: 639px) {
  .lineup-grid > * { flex-basis: 100%; }
}

/* ------------------------------------------------------------
   AUTHOR CARD
   Headshot on top, then name, role and the short bio. The image
   box is a fixed 4:5 so a row of cards lines up whatever crop the
   author sent, and object-fit keeps faces from stretching.
   ------------------------------------------------------------ */
.author-card-photo {
  display: block;
  width: 100%;
  /* height:auto is load-bearing: the plugin writes width/height attributes
     for CLS, and an attribute height beats aspect-ratio unless it is auto. */
  height: auto;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  object-position: center 25%;
  border-radius: var(--r-sm);
  margin-bottom: var(--sp-4);
  background: var(--surf);
}

/* ------------------------------------------------------------
   INVITE CARD
   The tail filler, and a real call to action in a spot people are
   already reading. Same dashed treatment as the sponsor invite so
   it reads as an open slot rather than a missing author.
   ------------------------------------------------------------ */
.author-invite {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  /* Sized to the photo box and pinned to the top of the row, so it reads
     as an empty author slot beside a filled one. Left to stretch it became
     a wall of dashed nothing taller than the card it sits next to, which
     looked worse than the orphan it exists to prevent. */
  align-self: flex-start;
  aspect-ratio: 4 / 5;
  padding: var(--sp-5);
  border: 2px dashed var(--line-strong);
  border-radius: var(--r);
  background: transparent;
  color: var(--muted);
  text-align: center;
  text-decoration: none;
  transition: border-color 0.2s var(--ease-out), color 0.2s var(--ease-out),
              background 0.2s var(--ease-out);
}

.author-invite:hover,
.author-invite:focus-visible {
  border-color: var(--teal);
  color: var(--teal-deep);
  background: var(--surf-teal);
}

.author-invite b {
  font-family: var(--display);
  font-size: var(--step-1);
  font-weight: 800;
  color: inherit;
}

.author-invite svg { flex-shrink: 0; }

/* ---- partners.css ---- */
/* ============================================================
   PARTNER LOGO WALL
   Her sponsor logos, in her published order, on white tiles so the
   dark sponsor band and the light home strip both read the same.
   Replaces the earlier text-name chips: a logo is how a sponsor
   agreed to be credited, and eight of her twenty were missing
   entirely while the list was text.
   Column counts are fixed at 5 / 4 / 2. Each divides twenty evenly,
   so no breakpoint leaves a lone tile on the last row.
   ============================================================ */
.partner-logos {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: var(--sp-4);
}

@media (max-width: 1000px) {
  .partner-logos { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

@media (max-width: 600px) {
  .partner-logos { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.partner-logo {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 124px;
  padding: var(--sp-4);
  border: 1.5px solid var(--line-strong);
  border-radius: var(--r);
  background: #fff;
}

/* Height cap keeps a square mark and a wide wordmark on the same
   optical footing; width cap stops a 17:1 wordmark from touching
   the tile edge. object-fit guards against either cap distorting. */
.partner-logo img {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 74px;
  object-fit: contain;
}

/* On the wall the wide wordmarks run to the full tile width, so the
   square marks and the fine-line foundation scripts need the extra
   height to hold their own beside them. The compact home strip keeps
   the lower cap above. */
.partner-logos .partner-logo img { max-height: 88px; }

/* The home strip is a centred flex row, not the full wall. A fixed
   basis keeps its four tiles the same size as each other whatever
   the logo inside them is shaped like. */
.sponsors-grid .partner-logo {
  flex: 0 1 200px;
  min-height: 96px;
}

/* Sponsorship tier price, sits under the tier name on sponsor.html */
.tier-price {
  display: block;
  font-family: var(--display);
  font-size: var(--step-3);
  font-weight: 900;
  letter-spacing: -0.02em;
  color: var(--amber-light);
  line-height: 1;
  margin: 2px 0 var(--sp-3);
}

.fcard .tier-price {
  color: var(--coral-deep);
}

.fcard-dark .tier-price {
  color: var(--amber-light);
}

/* Add-on row: smaller, flatter than a full tier card */
/* Three of the four add-ons are name only, as she publishes them, and the
   fourth carries her one blurb. Grid stretch makes every chip as tall as
   that longest one, so the lone names centre in their box instead of
   hanging from the top edge above a pool of empty space. */
.addon-chip {
  border: 1.5px solid var(--line);
  border-radius: var(--r);
  padding: var(--sp-4);
  background: var(--surf);
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.addon-chip h4 {
  font-family: var(--display);
  font-size: var(--step-1);
  font-weight: 800;
  margin-bottom: 4px;
}
.addon-chip h4:only-child { margin-bottom: 0; }

.addon-chip p {
  font-size: var(--step-sm);
  color: var(--muted);
  margin: 0;
}

/* ============================================================
   LINEUP NAME LIST
   The full featured-author roster. A name and a title is the honest
   amount of information we have, so it is set as a dense multi-column
   list rather than 36 half-empty cards.
   ============================================================ */
.lineup-names {
  list-style: none;
  margin: var(--sp-4) 0 0;
  padding: 0;
  columns: 3;
  column-gap: var(--sp-6);
}

.lineup-names li {
  break-inside: avoid;
  padding: 7px 0;
  border-bottom: 1px solid var(--line-soft);
  font-size: var(--step-sm);
  color: var(--muted);
  line-height: 1.45;
}

.lineup-names li b {
  display: block;
  font-family: var(--display);
  font-weight: 700;
  font-size: var(--step-0);
  color: var(--ink);
  letter-spacing: -0.01em;
}

@media (max-width: 900px) { .lineup-names { columns: 2; } }
@media (max-width: 560px) { .lineup-names { columns: 1; } }

/* Josh, Sep 12: a tile whose sponsor has a public site is a link. Same box
   as the plain tiles, with a lift and a teal edge on hover and focus. */
a.partner-logo {
  text-decoration: none;
  transition: transform var(--dur-mid) var(--ease-brand), border-color var(--dur-mid) var(--ease-out), box-shadow var(--dur-mid) var(--ease-out);
}
a.partner-logo:hover,
a.partner-logo:focus-visible {
  border-color: var(--teal);
  transform: translateY(-3px);
  box-shadow: var(--shadow-card);
}
a.partner-logo:focus-visible {
  outline: 3px solid var(--teal);
  outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
  a.partner-logo { transition: none; }
  a.partner-logo:hover, a.partner-logo:focus-visible { transform: none; }
}

/* Her Sep 14 email: four sponsorship levels with a paragraph each and no
   benefits lists. The Title Sponsor runs full width above the other three;
   at tablet width the last card spans the row so nothing sits alone. */
.level-intro p { max-width: 60ch; }
.level-intro p + p { margin-top: var(--sp-2); }
.level-intro p strong { color: #fff; }
.level-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-5); }
.level-card h3 { margin-bottom: 4px; }
.level-card p { color: rgba(251, 247, 240, 0.8); }
.level-card p + p { margin-top: var(--sp-3); }
.level-card p strong { color: #fff; }
.level-card-title { grid-column: 1 / -1; display: flex; gap: var(--sp-5); align-items: flex-start; border-color: rgba(249, 195, 100, 0.45); }
.level-card-title .fcard-icon { flex: none; margin-bottom: 0; }
.level-card-title .level-copy p { max-width: 68ch; }
.level-sub { font-size: var(--step-sm); font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--amber-light); margin: 0 0 var(--sp-3); }
.level-custom { max-width: 68ch; margin: 0 auto; text-align: center; }
.level-custom h3 { color: #fff; font-size: var(--step-3); margin-bottom: var(--sp-2); }
.level-custom p { color: rgba(251, 247, 240, 0.8); }
.level-custom p + p { margin-top: var(--sp-3); }
.level-custom p strong { color: #fff; }
.level-custom-lead { font-family: var(--script); font-weight: 600; font-size: calc(var(--step-2) * 1.1); color: var(--amber-light); }
.level-custom-cta { margin-top: var(--sp-4); }
@media (max-width: 959px) {
  .level-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .level-grid > :last-child { grid-column: 1 / -1; }
}
@media (max-width: 639px) {
  .level-grid { grid-template-columns: minmax(0, 1fr); }
  .level-card-title { display: block; }
  .level-card-title .fcard-icon { margin-bottom: var(--sp-3); }
}

/* ---- round3.css ---- */
/* ============================================================
   ROUND 3 COMPONENTS (Aug 24): old-site carry-over + brand motif.
   Filename sorts before students.css / zz-responsive.css on purpose.
   The glasses glyph used by .glasses-list / .glasses-divider is a
   geometric abstraction measured from the client's own sunglasses
   mark (two panto lenses + keyhole bridge + temple stubs), flagged
   on the review board for client approval as a derived motif.
   ============================================================ */

/* Display kicker above a section heading, e.g. the client's
   "The can't-miss teen book event of the year!" line. */
.event-kicker {
  display: block;
  grid-column: 1 / -1; /* in the 2-col .prog-head, the kicker owns its own full row */
  font-family: var(--display);
  font-style: italic;
  font-weight: 700;
  font-size: var(--step-4);
  line-height: 1.15;
  color: var(--coral-deep);
  margin-bottom: var(--sp-2);
  text-wrap: balance;
}

/* Word-based tile in the stats band ("Multiple" School Districts).
   Numerals keep .stat-num's size; a word needs a calmer scale. */
.stat-word {
  font-size: clamp(1.5rem, 2.4vw, 2.1rem);
  line-height: 1.1;
  padding-block: 0.35em;
  display: inline-block;
}

/* Playful client-verbatim accent line on the audience path cards
   ("Your backstage pass!"), in the script face. */
.path-card-line {
  display: block;
  font-family: var(--script);
  font-weight: 600;
  font-size: calc(var(--step-1) * 1.15);
  color: var(--coral-deep); /* 5.1:1 on white card bodies (AA) */
  margin-bottom: var(--sp-2);
}
/* Over hero photography the deep coral sinks; use the light kit tint
   there (same treatment as .hero-eyebrow). */
.hero .path-card-line { color: #F5B0A6; }

/* Full-width statement band: "Your voice matters. Your story matters." */
.voice-band {
  background: var(--teal);
  color: #FBF7F0;
  padding-block: var(--sp-8);
  text-align: center;
}
.voice-band .eyebrow { color: #D6F0EE; } /* 4.9:1 on the kit teal (AA small text) */
.voice-line {
  font-family: var(--display);
  font-weight: 800;
  font-size: var(--step-5);
  line-height: 1.08;
  margin: var(--sp-2) auto var(--sp-3);
  max-width: 22ch;
  text-wrap: balance;
}
.voice-band p:not(.voice-line) {
  color: rgba(251, 247, 240, 0.94); /* 0.85 alpha measured 4.42:1 on kit teal; 0.94 clears AA */
  max-width: 52ch;
  margin-inline: auto;
}

/* Responsive 16:9 video embed. */
.video-band { padding-block: var(--sp-8); }
.video-frame {
  position: relative;
  aspect-ratio: 16 / 9;
  max-width: 880px;
  margin-inline: auto;
  border-radius: var(--r);
  overflow: hidden;
  box-shadow: 0 18px 44px rgba(14, 34, 40, 0.22);
  background: var(--ink);
}
.video-frame iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

/* Lists marked with the derived glasses glyph. currentColor via mask. */
.glasses-list {
  list-style: none;
  padding-left: 0;
  max-width: 62ch;
}
.glasses-list li {
  position: relative;
  padding-left: 44px;
  margin-bottom: var(--sp-3);
}
.glasses-list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.32em;
  width: 30px;
  height: 13px;
  background-color: var(--coral);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 20'%3E%3Cg fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7.5'/%3E%3Ccircle cx='37' cy='11' r='7.5'/%3E%3Cpath d='M18.5 9 Q24 4.5 29.5 9'/%3E%3Cpath d='M3.5 9.5 L1.5 8'/%3E%3Cpath d='M44.5 9.5 L46.5 8'/%3E%3C/g%3E%3C/svg%3E") no-repeat center / contain;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 20'%3E%3Cg fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7.5'/%3E%3Ccircle cx='37' cy='11' r='7.5'/%3E%3Cpath d='M18.5 9 Q24 4.5 29.5 9'/%3E%3Cpath d='M3.5 9.5 L1.5 8'/%3E%3Cpath d='M44.5 9.5 L46.5 8'/%3E%3C/g%3E%3C/svg%3E") no-repeat center / contain;
}
.glasses-list li strong { color: var(--ink); }
ol.glasses-list { counter-reset: glist; }
ol.glasses-list li { counter-increment: glist; }
ol.glasses-list li::after {
  content: counter(glist);
  position: absolute;
  left: 34px;
  top: 0.05em;
  font-family: var(--display);
  font-weight: 800;
  font-size: 0.8em;
  color: var(--coral-deep);
}
ol.glasses-list li { padding-left: 58px; }

/* Centered section divider in the same glyph. */
.glasses-divider {
  display: block;
  width: 54px;
  height: 23px;
  margin: var(--sp-4) auto;
  background-color: var(--teal-light);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 20'%3E%3Cg fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7.5'/%3E%3Ccircle cx='37' cy='11' r='7.5'/%3E%3Cpath d='M18.5 9 Q24 4.5 29.5 9'/%3E%3Cpath d='M3.5 9.5 L1.5 8'/%3E%3Cpath d='M44.5 9.5 L46.5 8'/%3E%3C/g%3E%3C/svg%3E") no-repeat center / contain;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 20'%3E%3Cg fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7.5'/%3E%3Ccircle cx='37' cy='11' r='7.5'/%3E%3Cpath d='M18.5 9 Q24 4.5 29.5 9'/%3E%3Cpath d='M3.5 9.5 L1.5 8'/%3E%3Cpath d='M44.5 9.5 L46.5 8'/%3E%3C/g%3E%3C/svg%3E") no-repeat center / contain;
}

/* Lunchtime drop-in block on the day page. */
.lunch-block {
  background: var(--surf-dim);
  border-radius: var(--r-lg, 20px);
  padding: var(--sp-6);
  max-width: 760px;
  margin-inline: auto;
}

/* Statement band on the authors page (mission and mantra). */
.mantra-band {
  background: var(--surf-teal);
  text-align: center;
  padding-block: var(--sp-8);
}
/* Her Sep 10 note #57: the mantra line is her tagline lettering (an SVG
   image, see authors.html), not the stand-in script face. */
.mantra-line {
  max-width: 640px;
  margin: 0 auto var(--sp-4);
}
.mantra-lettering {
  display: block;
  width: 100%;
  height: auto;
}
.mantra-band p:not(.mantra-line) {
  max-width: 56ch;
  margin-inline: auto;
}

/* Florida charitable-solicitation disclosure. Compliance text. */
.legal-disclosure {
  max-width: 76ch;
  margin: var(--sp-7) auto 0;
  padding-top: var(--sp-4);
  border-top: 1px solid var(--line);
  font-size: var(--step-sm);
  color: var(--muted);
}

/* Donate-page QR block. */
.qr-block { text-align: center; }
.qr-block img {
  display: inline-block;
  border-radius: var(--r);
  border: 1px solid var(--line);
  box-shadow: 0 10px 26px rgba(14, 34, 40, 0.12);
  background: #FBF7F0;
  padding: 10px;
}
.qr-block a { font-weight: 700; }

/* Stats band takes a 5th tile this round: never strand a lone tile.
   Explicit 5-across on desktop (auto-fit gave 4+1 at 1440), 3+2 in
   the tablet window, single column below 640px. */
@media (min-width: 1100px) {
  /* Tighter gutter: at the 60px gap the cells ran 171px and the three-word
     tails "Directly with Students" and "Day Immersive Festival" (about 195px)
     wrapped inside their group. */
  .stats-grid { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--sp-4); }
}
@media (max-width: 640px) {
  .stats-grid { grid-template-columns: 1fr; }
}

/* ============================================================
   AUTHOR APPLICATION (round 4): mirrors the client's live Google
   Form field-for-field so the eventual rebuild has a 1:1 target.
   ============================================================ */

/* Her form uses paragraph fields for links; a full-height textarea
   is wrong for a single URL. */
.form-field textarea.compact { min-height: 76px; }

/* Yes/No multiple-choice, styled to match the input controls. */
.radio-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
}
.radio-opt {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: var(--card, #fff);
  cursor: pointer;
  font-size: var(--step-sm);
}
.radio-opt input { accent-color: var(--coral); margin: 0; }
.radio-opt:focus-within {
  border-color: var(--teal);
  box-shadow: 0 0 0 3px rgba(8, 113, 110, 0.18);
}
.field-help {
  font-size: var(--step-sm);
  color: var(--muted);
  margin: 0;
}

/* ============================================================
   FILE INPUT
   The raw browser control is a different size, weight and colour
   on every platform, so it reads as a foreign object next to the
   text inputs. This puts it on the same border, radius and type
   scale as everything else in the form.
   ============================================================ */
.form-field input[type="file"] {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: var(--card, #fff);
  font: inherit;
  font-size: var(--step-sm);
  color: var(--ink);
  cursor: pointer;
}

.form-field input[type="file"]::file-selector-button {
  margin-right: var(--sp-3);
  padding: 8px 16px;
  border: 0;
  border-radius: var(--r-sm);
  background: var(--coral-deep, var(--coral));
  color: #fff;
  font: inherit;
  font-size: var(--step-sm);
  font-weight: 700;
  cursor: pointer;
}

.form-field input[type="file"]:focus-visible {
  outline: none;
  border-color: var(--teal);
  box-shadow: 0 0 0 3px rgba(8, 113, 110, 0.18);
}

/* ------------------------------------------------------------------
   Review board, 2026-09-09 (Sorboni)
   ------------------------------------------------------------------ */

/* Comments #10 and #14: no hanging single-word last lines. Headings already
   balance; body copy now asks the engine for the same care. Older engines
   ignore it and wrap as before. */
p, li, dd, figcaption, .stat-label { text-wrap: pretty; }

/* Comment #13: the "-12" in the grades tile reads in the same green as the 9,
   instead of the coral the "+" suffixes use. */
.stat-num .stat-num-range { color: inherit; }

/* Her line-break rule (Sep 4 review; Josh, Sep 10: two words also count).
   phrase_glue.py and inc/phrase-glue.php wrap the copy in phrase groups; a
   group moves to the next line whole, and only wraps inside when it is wider
   than its column, so nothing overflows on a phone. */
.ph { display: inline-block; }
/* An inline-block does not carry its link's underline; hand it back. */
a .ph { text-decoration: inherit; }

/* Attendees dropdown in the header (her Sep 10 note #34 as edited: "very
   simple dropdowns for now"). The trigger is a button styled as the other
   links; the list opens on hover, on keyboard focus, and on tap via
   aria-expanded (site.js / the inline script). The list carries its own
   top padding so the pointer never crosses a gap that would close it. */
.nav-links li { position: relative; }
.nav-sub-toggle {
  font: inherit;
  font-size: var(--step-sm);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink);
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  padding: var(--sp-1) 0;
  cursor: pointer;
  white-space: nowrap;
  transition: color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.nav-sub-toggle::after {
  content: '';
  display: inline-block;
  width: 7px;
  height: 7px;
  margin-left: 7px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: translateY(-3px) rotate(45deg);
}
.nav-sub-toggle:hover, .nav-sub-toggle:focus-visible,
.nav-has-sub:hover > .nav-sub-toggle,
.nav-sub-toggle[aria-expanded="true"] { color: var(--teal); border-bottom-color: var(--teal); }
.nav-sub {
  display: none;
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  min-width: 190px;
  margin: 0;
  padding: 10px 0 0;
  list-style: none;
  z-index: 120;
}
.nav-has-sub:hover > .nav-sub,
.nav-has-sub:focus-within > .nav-sub,
.nav-sub-toggle[aria-expanded="true"] + .nav-sub { display: block; }
.nav-sub li {
  background: var(--surf);
  border-left: 1px solid var(--line);
  border-right: 1px solid var(--line);
}
.nav-sub li:first-child { border-top: 1px solid var(--line); border-radius: var(--r) var(--r) 0 0; padding-top: 6px; }
.nav-sub li:last-child { border-bottom: 1px solid var(--line); border-radius: 0 0 var(--r) var(--r); padding-bottom: 6px; box-shadow: 0 14px 34px -12px rgba(14, 34, 40, 0.28); }
.nav-links .nav-sub a {
  display: block;
  padding: 10px 20px;
  border-bottom: 0;
  text-align: left;
}
.nav-links .nav-sub a:hover, .nav-links .nav-sub a:focus-visible { background: var(--surf-dim); border-bottom: 0; }

/* Pages hidden behind "coming soon" (her Sep 10 note #33: the day schedule).
   The hero stays and says so; everything after it in <main> is hidden, built
   and editable, waiting for her times and panel descriptions. */
.coming-soon-hero ~ * { display: none !important; }

/* "Big Authors. Packed Rooms. Real Access." is three two-word sentences; it
   reads as one line or as one sentence per line, never one and a half. The
   680px section-head cap left it one and a half on a laptop. */
@media (min-width: 1280px) {
  section[aria-labelledby="why-heading"] .sec-head { max-width: 980px; }
}

/* Short centred copy balances into even lines, her "one little square".
   Long paragraphs stay on pretty (above), which is what the floor groups need. */
.sec-head p, .hero-sub, .hero-join-line, .cta-band-text p, .rsvp-band-sub,
.stat-label, figcaption, .path-card-line, .tier-tagline, .prog-lead,
.glasses-list li, .fcard h3, .author-bio, .step p, .path-card-body p {
  text-wrap: balance;
}

/* Her Sep 10 note #59: her star and her book stacks fill the gutters of the
   Featured Event band on the home page. Desktop only; below 1200px the copy
   needs the width. */
.featured-event-accent { display: none; }
@media (min-width: 1200px) {
  .featured-event-accent { display: block; }
}

/* Her Sep 10 note #48: the festival page's four "What to Expect" cards carry
   her brand marks instead of line icons. */
.fcard-icon-brand {
  background: transparent;
  width: 56px;
  height: 56px;
  margin-bottom: var(--sp-3);
}
.fcard-icon-brand img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* Photo pass, 2026-09-14 (her notes #61, #73, #52, #45, #35: more pictures,
   heads in frame, no dead space, no caption pills). Three shapes:
   .prog-mosaic  three photos in a running-order row (tall left, two stacked)
   .photo-strip  three portraits across a section
   .photo-grid-6 six portraits, three across (two across on phones) */
.prog-mosaic {
  margin: 0;
  display: grid;
  grid-template-columns: 1.15fr 1fr;
  grid-template-rows: 1fr 1fr;
  gap: 10px;
  aspect-ratio: 4 / 3;
}
.prog-mosaic img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: var(--r);
  display: block;
}
.prog-mosaic img:first-child { grid-row: 1 / 3; }
.prog-row-flip .prog-mosaic { order: -1; }
.photo-strip,
.photo-grid-6 {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
}
.photo-strip { margin-top: var(--sp-6); }
.photo-strip img,
.photo-grid-6 img {
  width: 100%;
  height: auto; /* the height attribute would otherwise win and the ratio never applies */
  aspect-ratio: 4 / 5;
  object-fit: cover;
  border-radius: var(--r-lg);
  display: block;
}
@media (max-width: 959px) {
  .prog-row .prog-mosaic,
  .prog-row-flip .prog-mosaic { grid-column: 1 / -1; order: 0; }
}
@media (max-width: 639px) {
  .photo-strip,
  .photo-grid-6 { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  /* three across becomes two plus one: the last one runs full width, wide */
  .photo-strip img:last-child:nth-child(odd) { grid-column: 1 / -1; aspect-ratio: 8 / 5; }
}

/* ------------------------------------------------------------
   Sorboni's Sep 14 email round
   ------------------------------------------------------------ */

/* Her book stack beside the wordmark in the header. */
.nav-logo { gap: 12px; }
.nav-logo .nav-logo-books { height: clamp(40px, 4.6vw, 58px); width: auto; }
@media (max-width: 479px) { .nav-logo .nav-logo-books { height: 34px; } }

/* Featured Event band: her intro is five short paragraphs now. */
.featured-event-body p { margin: 0 0 var(--sp-3); }
.featured-event-body p:last-child { margin-bottom: 0; }
.featured-event-body strong { color: var(--ink); font-weight: 800; }
.featured-event-body .fe-open { font-family: var(--display); font-size: var(--step-2); line-height: 1.2; }

/* "What to Expect": her glasses and her book stack beside each heading. */
.prog-title { display: flex; align-items: center; gap: 16px; margin-bottom: var(--sp-3); }
.prog-title h3 { margin-bottom: 0; }
.prog-mark { flex: none; display: block; width: auto; }
.prog-mark-glasses { height: 44px; }
.prog-mark-books { height: 60px; }
@media (max-width: 639px) {
  .prog-title { gap: 12px; }
  .prog-mark-glasses { height: 36px; }
  .prog-mark-books { height: 48px; }
}

/* Interior heroes that carry more than one paragraph (students). */
.hero-interior .wrap > p + p { margin-top: var(--sp-3); }

/* Authors page: her glasses photo above the previously featured authors. */
.lineup-photo { margin: 0 auto var(--sp-6); max-width: 760px; }
.lineup-photo img { display: block; width: 100%; height: auto; border-radius: var(--r-lg); }
.lineup-photo figcaption { margin-top: var(--sp-2); text-align: center; font-size: var(--step-sm); color: var(--muted); }

/* ---- students.css ---- */
/* ============================================================
   STUDENT PROJECTS + STUDENT SPOTLIGHT + TEACHER NOMINATIONS
   Added to students-teachers.html, 2026-07-28.

   Three blocks, three deliberately different rhythms:
     .sp-*        Section A, student "what are you working on"
                  Warm, informal, off-axis. Taped prompt note on the
                  left, generous form card on the right.
     .sp-spot-*   Student Spotlight, EXAMPLE cards only.
                  Dark band, monogram panels, stepped card baseline.
     .nom-*       Section B, teacher nomination.
                  Practical and fast. Wide header bar, one white
                  panel, compact fields.

   Every class is prefixed sp- or nom- so nothing can collide with
   the shared stylesheet. Reuses .sec-head, .sec-head-left, .eyebrow,
   .badge, .form-grid, .form-field, .form-field-wide, .form-note,
   .btn, .reveal, .stagger.

   Merge target: the shared  block (append after the
   BESPOKE ELEVATION LAYER, before RESPONSIVE / PRINT).
   ============================================================ */

/* ------------------------------------------------------------
   JUMP LINKS
   Added into the "I am a student" / "I am a teacher" picker cards
   so each audience can go straight to its own form.
   ------------------------------------------------------------ */
.sp-jump,
.nom-jump {
  margin: var(--sp-3) 0 0;
  font-size: var(--step-sm);
  max-width: none;
}
.sp-jump a,
.nom-jump a {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-weight: 700;
  letter-spacing: .015em;
  color: var(--teal-deep);
  text-decoration: none;
  border-bottom: 2px solid rgba(22, 110, 102, .28);
  padding-bottom: 2px;
  transition: color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out);
}
.sp-jump a:hover,
.sp-jump a:focus-visible,
.nom-jump a:hover,
.nom-jump a:focus-visible {
  color: var(--coral-deep);
  border-bottom-color: var(--coral);
}
.sp-jump svg,
.nom-jump svg {
  flex-shrink: 0;
  transition: transform var(--dur-fast) var(--ease-out);
}
.sp-jump a:hover svg,
.nom-jump a:hover svg { transform: translateX(3px); }

/* ------------------------------------------------------------
   SHARED: heading blocks reused inside the bespoke header grids
   .sec-head brings its own bottom margin and centered measure.
   Inside these grids it needs neither.
   ------------------------------------------------------------ */
.sp-lede .sec-head,
.sp-spot-head .sec-head,
.nom-head .sec-head {
  margin-bottom: 0;
  max-width: none;
}
.sp-lede .sec-head p,
.sp-spot-head .sec-head p,
.nom-head .sec-head p {
  margin-inline: 0;
  max-width: 48ch;
}

/* ------------------------------------------------------------
   SAFETY NOTE
   The child-safety statement. Appears once per form section and is
   never decoration: it states what we do not collect and what we
   do not publish.
   ------------------------------------------------------------ */
.sp-safety,
.nom-safety {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  padding: var(--sp-4);
  background: var(--surf-teal);
  border: 1px solid rgba(22, 110, 102, .18);
  border-left: 4px solid var(--teal);
  border-radius: var(--r);
}
.sp-safety svg,
.nom-safety svg {
  flex-shrink: 0;
  color: var(--teal);
  margin-top: 2px;
}
.sp-safety p,
.nom-safety p {
  margin: 0;
  max-width: none;
  font-size: var(--step-sm);
  line-height: 1.65;
  color: var(--ink-mid);
}
.sp-safety strong,
.nom-safety strong { color: var(--teal-deep); }

/* Field-level helper text, wired to inputs with aria-describedby */
.sp-hint,
.nom-hint {
  margin: 2px 0 0;
  max-width: none;
  font-size: var(--step-sm);
  line-height: 1.5;
  color: var(--muted);
}

/* ============================================================
   SECTION A: TELL US WHAT YOU ARE WORKING ON
   ============================================================ */

/* Off-center lede: heading carries the width, safety note sits
   beside it rather than under it. */
.sp-lede {
  display: grid;
  grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr);
  gap: var(--sp-6);
  align-items: end;
  margin-bottom: var(--sp-6);
}
.sp-lede h2 { max-width: 17ch; }

/* Prompt note + form, unequal columns */
.sp-body {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.35fr);
  gap: var(--sp-6);
  align-items: start;
}

/* The taped note. Echoes the scrapbook / photo-stack motif already
   used on this site rather than inventing a new one. */
.sp-prompts {
  position: relative;
  background: var(--coral-tint);
  border: 1px dashed rgba(181, 61, 16, .34);
  border-radius: var(--r-lg);
  padding: var(--sp-5) var(--sp-5) var(--sp-6);
  transform: rotate(-0.7deg);
}
.sp-prompts::before {
  content: '';
  position: absolute;
  top: -13px;
  left: 50%;
  width: 96px;
  height: 26px;
  transform: translateX(-50%) rotate(-2.5deg);
  background: rgba(251, 247, 240, .88);
  border: 1px solid rgba(26, 46, 53, .14);
  border-radius: 2px;
  box-shadow: 0 2px 6px -2px rgba(14, 34, 40, .18);
}
.sp-prompts-title {
  font-family: var(--display);
  font-size: var(--step-2);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.01em;
  color: var(--coral-deep);
  margin-bottom: var(--sp-4);
}
.sp-chiplist {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 9px;
  margin: 0;
  padding: 0;
}
.sp-chip {
  background: #fff;
  border: 1px solid rgba(181, 61, 16, .20);
  border-radius: var(--r-pill);
  padding: 7px 14px;
  font-size: var(--step-sm);
  font-weight: 600;
  line-height: 1.35;
  color: var(--ink-mid);
}
.sp-prompts-foot {
  margin: var(--sp-4) 0 0;
  max-width: none;
  font-size: var(--step-sm);
  font-weight: 700;
  line-height: 1.55;
  color: var(--ink-mid);
}

/* The form card. Coral top rule marks this as the student side. */
.sp-formcard {
  background: #fff;
  border: 1px solid var(--line);
  border-top: 5px solid var(--coral);
  border-radius: var(--r-lg);
  padding: var(--sp-6);
  box-shadow: var(--shadow-card);
}
.sp-formcard-head {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  margin-bottom: var(--sp-5);
}
.sp-formcard-head svg {
  flex-shrink: 0;
  color: var(--coral-deep);
  margin-top: 3px;
}
.sp-formcard-head h3 {
  font-size: var(--step-2);
  margin-bottom: 6px;
}
.sp-formcard-head p {
  margin: 0;
  max-width: 54ch;
  font-size: var(--step-sm);
  line-height: 1.6;
  color: var(--muted);
}
/* Generous box: a student describing a novel needs room. */
.sp-formcard .form-field textarea { min-height: 164px; }

/* ============================================================
   STUDENT SPOTLIGHT (EXAMPLES ONLY)
   Dark band so the cards read as a display case, not another
   feature grid. Every card carries a visible Example badge and the
   section carries an explicit caption.
   ============================================================ */
.sp-spotlight .eyebrow { color: var(--teal-light); }

.sp-spot-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.95fr);
  gap: var(--sp-5);
  align-items: end;
  margin-bottom: var(--sp-6);
}
.sp-spot-note {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  padding: var(--sp-4);
  background: rgba(255, 255, 255, .05);
  border: 1px dashed rgba(251, 247, 240, .34);
  border-radius: var(--r);
}
.sp-spot-note svg {
  flex-shrink: 0;
  color: var(--amber-light);
  margin-top: 2px;
}
.sp-spot-note p {
  margin: 0;
  max-width: none;
  font-size: var(--step-sm);
  line-height: 1.65;
  color: rgba(251, 247, 240, .84);
}
.sp-spot-note strong { color: var(--amber-light); }

/* Stepped baseline instead of a flat three-up row. */
.sp-spot-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-5);
  align-items: start;
}
.sp-spot-card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: rgba(255, 255, 255, .06);
  border: 1px solid var(--line-dark);
  border-radius: var(--r-lg);
  overflow: hidden;
}

/* Typographic monogram panel. No photograph of a child, ever. */
.sp-spot-mono {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 16 / 7;
  background: linear-gradient(148deg, var(--teal-deep) 0%, var(--teal) 58%, #22857C 100%);
}
.sp-spot-mono span {
  font-family: var(--display);
  font-size: clamp(2.4rem, 4.6vw, 3.4rem);
  font-weight: 900;
  line-height: 1;
  letter-spacing: -0.03em;
  color: rgba(251, 247, 240, .94);
}
.sp-spot-mono svg {
  position: absolute;
  right: 14px;
  bottom: 12px;
  color: rgba(251, 247, 240, .5);
}
/* Sits on top of .badge, overriding only placement and color. */
.sp-spot-badge {
  position: absolute;
  top: 12px;
  left: 12px;
  z-index: 2;
  background: var(--amber-light);
  color: var(--ever);
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  padding: 4px 11px;
}
.sp-spot-body {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding: var(--sp-5);
  flex: 1;
}
.sp-spot-title {
  font-family: var(--display);
  font-size: var(--step-2);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.01em;
  color: #fff;
}
.sp-spot-meta {
  font-size: var(--step-sm);
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--teal-tint);
}
.sp-spot-quote {
  margin: var(--sp-1) 0;
  max-width: none;
  padding-left: var(--sp-4);
  border-left: 3px solid var(--coral);
  font-family: var(--display);
  font-size: var(--step-1);
  font-style: italic;
  font-weight: 600;
  line-height: 1.5;
  color: rgba(251, 247, 240, .92);
}
.sp-spot-nominator {
  margin-top: auto;
  max-width: none;
  padding-top: var(--sp-3);
  border-top: 1px solid var(--line-dark);
  font-size: var(--step-sm);
  line-height: 1.5;
  color: rgba(251, 247, 240, .68);
}

/* ============================================================
   SECTION B: NOMINATE A STUDENT
   Practical and quick: wide header bar, one panel, compact fields.
   ============================================================ */
.nom-head {
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
  gap: var(--sp-6);
  align-items: center;
  margin-bottom: var(--sp-6);
}
.nom-head h2 { max-width: 18ch; }

/* What this costs a teacher, stated up front. */
.nom-facts {
  list-style: none;
  display: grid;
  gap: var(--sp-3);
  margin: 0;
  padding: var(--sp-5);
  background: #fff;
  border: 1px solid rgba(22, 110, 102, .18);
  border-left: 4px solid var(--teal);
  border-radius: var(--r);
  box-shadow: var(--shadow-card);
}
.nom-facts li {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: var(--step-sm);
  font-weight: 600;
  line-height: 1.5;
  color: var(--ink-mid);
}
.nom-facts svg {
  flex-shrink: 0;
  color: var(--teal);
  margin-top: 1px;
}

.nom-panel {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--sp-6);
  box-shadow: var(--shadow-card);
}
.nom-panel-head {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
}
.nom-panel-head svg {
  flex-shrink: 0;
  color: var(--teal);
  margin-top: 3px;
}
.nom-panel-head h3 {
  font-size: var(--step-2);
  margin-bottom: 6px;
}
.nom-panel-head p {
  margin: 0;
  max-width: 62ch;
  font-size: var(--step-sm);
  line-height: 1.6;
  color: var(--muted);
}
.nom-panel .nom-safety { margin-bottom: var(--sp-5); }
/* Compact boxes: a teacher is doing this between classes. */
.nom-panel .form-field textarea { min-height: 108px; }

/* Consent row. Deliberately NOT a .form-field so the shared input
   sizing rules (48px min-height, 100% width) never touch it. */
.nom-consent {
  grid-column: 1 / -1;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: var(--sp-4);
  background: var(--surf);
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
}
.nom-consent input[type="checkbox"] {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  margin-top: 2px;
  accent-color: var(--teal);
  cursor: pointer;
}
.nom-consent label {
  font-size: var(--step-sm);
  font-weight: 600;
  line-height: 1.65;
  color: var(--ink-mid);
  cursor: pointer;
}
.nom-consent strong { color: var(--teal-deep); }
.nom-consent input[type="checkbox"]:focus-visible {
  outline: 3px solid var(--teal);
  outline-offset: 2px;
}

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media (min-width: 960px) {
  /* Stepped baseline, desktop only */
  .sp-spot-grid > :nth-child(2) { margin-top: 30px; }
  .sp-spot-grid > :nth-child(3) { margin-top: 60px; }
}

@media (max-width: 959px) {
  .sp-lede,
  .sp-spot-head,
  .nom-head {
    grid-template-columns: 1fr;
    align-items: start;
  }
  .sp-body { grid-template-columns: 1fr; }
  .sp-prompts { transform: none; }
  .sp-lede h2,
  .nom-head h2 { max-width: none; }
  .sp-spot-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 639px) {
  .sp-spot-grid { grid-template-columns: 1fr; }
  .sp-formcard,
  .nom-panel { padding: var(--sp-5); }
  .sp-prompts { padding: var(--sp-5) var(--sp-4) var(--sp-5); }
}

@media (prefers-reduced-motion: reduce) {
  .sp-prompts { transform: none; }
  .sp-jump a,
  .sp-jump svg,
  .nom-jump a,
  .nom-jump svg { transition: none; }
  .sp-jump a:hover svg,
  .nom-jump a:hover svg { transform: none; }
}

/* ------------------------------------------------------------
   Student consent gate. Mirrors .nom-consent on the teacher form:
   a student may fill the project form in on their own, so the same
   hard gate applies rather than prose-only assurance.
   ------------------------------------------------------------ */
.sp-consent {
  grid-column: 1 / -1;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: var(--sp-4);
  background: var(--surf);
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
}
.sp-consent label {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  font-size: var(--step-sm);
  font-weight: 600;
  line-height: 1.65;
  color: var(--ink-mid);
  cursor: pointer;
}
.sp-consent input[type="checkbox"] {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  margin-top: 2px;
  accent-color: var(--teal);
  cursor: pointer;
}
.sp-consent strong { color: var(--coral-deep); }
.sp-consent input[type="checkbox"]:focus-visible {
  outline: 3px solid var(--teal);
  outline-offset: 2px;
}

/* ------------------------------------------------------------------
   CARDS ON A DARK BAND (.sec-dark .fcard)
   .sec-dark paints every heading white and every paragraph near-white.
   That is right for copy sitting directly on the band, and wrong the
   moment a light card sits on top of one: white on white. The Level Up
   tiers and the Quest Board are the first cards to sit inside a dark
   band, so the card restates its own colours here rather than the band
   rule being loosened for the whole site.
   ------------------------------------------------------------------ */
.sec-dark .fcard h3 { color: var(--ink); }
.sec-dark .fcard p  { color: var(--ink-mid); }

/* ------------------------------------------------------------------
   ACHIEVEMENT TIER UNLOCK (.tier-unlock)
   The reward line on each Level Up card. Her copy wrote these as an
   emoji plus a label; the emoji became the card icon, so the label
   needs its own treatment to still read as a reward rather than as one
   more sentence.
   Coral-deep on the white card is 5.41:1, which the label needs at
   0.72rem. Amber would have been the warmer choice and is 4.6:1 at
   best, too close to the line for text this small.
   ------------------------------------------------------------------ */
.tier-unlock {
  /* Stacked, not inline. Four cards across leaves each one narrow, and an
     inline label pushed the value into a three-line hanging indent under
     itself. The label on its own line reads as a heading for the reward,
     which is what it is. */
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: var(--sp-4);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--line);
  font-size: var(--step-sm);
  line-height: 1.5;
}

.sec-dark .fcard .tier-unlock { color: var(--ink); }

.tier-unlock span {
  flex-shrink: 0;
  font-family: var(--display);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--coral-deep);
}

/* ------------------------------------------------------------------
   EYEBROW ON A DARK BAND
   .eyebrow is coral-deep, tuned for light surfaces, and lands at
   3.04:1 on the bay-night ground the two gamified sections use. Amber
   light is the kit's on-dark accent and clears AA there.
   ------------------------------------------------------------------ */
.sec-dark .eyebrow { color: var(--amber-light); }

/* ---- tap-targets.css ---- */
/* ============================================================
   TAP TARGET SIZING
   Navigation links that were inline boxes: the clickable area was
   only the text itself, so a 13px footer link gave a 17px tall
   target with dead space all around it inside its own row.

   These met WCAG 2.5.8 through the spacing exception (rows sit
   26px apart, more than the 24px minimum separation), so this is
   not a conformance fix. It is a usability one: the audience is
   middle and high school students on phones, and Apple and
   Google both put the comfortable minimum around 44px.
   ============================================================ */

/* Free win, no layout change: the anchor already sits inside a
   26px line box in a full-width list item. Making it a block hands
   it that whole row instead of just its glyphs. */
.footer-col ul a,
.footer-legal a { display: block; }

@media (max-width: 639px) {
  /* Buy the vertical room from the list gap rather than adding it,
     so rows grow from 34px to 42px and the footer stays compact. */
  .footer-col ul { gap: 0; }
  .footer-col ul a { padding: 8px 0; }
  .footer-legal a { padding: 6px 0; }
}

/* A paragraph whose only content is a link is a call to action, not
   a link in a sentence, so the inline-target exception does not
   really apply to it. Used by the three routing cards on contact. */
.fcard > p > a:only-child {
  display: inline-block;
  padding: 6px 0;
}

/* Wrapped row of navigation links. Reads as a quiet list rather than
   buttons, but each one is a real target. Used on 404. */
.link-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--sp-2) var(--sp-1);
  list-style: none;
  margin-top: var(--sp-4);
}
.link-row a {
  display: block;
  padding: 8px 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: var(--step-sm);
  color: var(--teal);
  text-decoration: none;
  transition: background var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out);
}
.link-row a:hover,
.link-row a:focus-visible {
  background: var(--teal);
  border-color: var(--teal);
  color: var(--surf);
}

/* ---- zz-responsive.css ---- */
/* ============================================================
   RESPONSIVE REMEDIATION (visual QA pass, 2026-07-28)
   Loaded last on purpose: the filename sorts after every other
   component so these overrides win without needing !important.
   Every rule here fixes a measured defect, noted inline.
   ============================================================ */

/* ------------------------------------------------------------
   Step cards were 244px wide with 60px of padding on each side,
   leaving a 124px text column (about 15 characters per line) and
   forcing all four cards to 789px tall to match the longest.
   Four across does not fit: the content column is about 1096px, so
   even with trimmed padding each card only gets ~164px of text. Two
   across is the readable answer at every desktop width, and it never
   strands a lone card on a second row.
   ------------------------------------------------------------ */
.step { padding: var(--sp-5); }
@media (min-width: 640px) {
  .steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Same padding problem in the narrower card components: a ~340px
   card with 60px sides leaves roughly 27 characters per line. */
@media (min-width: 960px) {
  .fcard { padding: var(--sp-5); }
}

/* ------------------------------------------------------------
   Measured line lengths of 100 to 170 characters. These blocks all
   set max-width:none, so the base p{max-width:70ch} never applied.
   ------------------------------------------------------------ */
.planner-note,
.nom-safety,
.sp-safety,
.form-note,
.faq-panel-inner p,
.prog-text p {
  max-width: 70ch;
}
.sponsors .wrap > p,
.stats-band .wrap > p {
  max-width: 66ch;
  margin-inline: auto;
}

/* ------------------------------------------------------------
   Four facts never fit one row, so "Hosted by" always dropped alone
   and centered under the other three on a full-bleed band.
   ------------------------------------------------------------ */
@media (min-width: 1024px) {
  .facts-strip .wrap {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    align-items: start;
  }
}
@media (min-width: 640px) and (max-width: 1023px) {
  .facts-strip .wrap {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    align-items: start;
  }
}

/* Hero credential pills broke 3+1 for the same reason */
@media (min-width: 768px) {
  .hero-credentials { max-width: 46ch; }
}

/* ------------------------------------------------------------
   Between 768 and 959 the feature rows went two-up while the photo
   column was only ~330px, so the collage photo rendered NARROWER
   (285px) than it does on a phone, with the badge covering a third
   of it. Keep those rows stacked until there is room.
   ------------------------------------------------------------ */
@media (max-width: 959px) {
  .feature-row,
  .feature-row-flip {
    grid-template-columns: 1fr;
  }
  .feature-row-flip .photo-stack { padding: 26px 34px 44px 0; }
  .feature-row-flip .photo-stack-inset { right: 0; left: auto; transform: rotate(-3.5deg); }
  .feature-row-flip .photo-stack-badge { left: -14px; right: auto; transform: rotate(-9deg); }
}
/* The badge scales with the photo instead of eating a fixed 92px */
.photo-stack-badge { width: clamp(56px, 18%, 92px); }

/* ------------------------------------------------------------
   Gallery caption pills are nowrap with no max-width, so at phone
   widths they ran past the tile edge, were clipped by the section,
   and overlapped neighboring tiles.
   ------------------------------------------------------------ */
@media (max-width: 639px) {
  .day-tag {
    white-space: normal;
    max-width: calc(100% - 32px);
    font-size: 0.72rem; /* was 0.62rem, 9.9px: her Sep 10 note on tiny phone type */
    line-height: 1.25;
  }
  /* nine tiles in two columns left the last one stranded */
  .gallery-grid .gallery-figure:last-child:nth-child(odd) { grid-column: span 2; }
}

/* ------------------------------------------------------------
   Hero scrims were tuned for a desktop left-hand text column. On a
   phone the copy spans the full width and ran onto the bright part
   of the photograph: measured 1.44:1 on the homepage sub-heading and
   1.24:1 on the interior eyebrow. Below 640 use a vertical scrim.
   ------------------------------------------------------------ */
/* Up to 1023, not 639: at 768 the copy still spans most of the width but
   the desktop left-to-right gradient has already faded out, which left the
   homepage sub-heading at 1.99:1 over the bright part of the photo. */
@media (max-width: 1023px) {
  .hero .hero-overlay {
    background: linear-gradient(180deg, rgba(10,28,32,.66) 0%, rgba(10,28,32,.82) 45%, rgba(10,28,32,.92) 100%);
  }
  .hero-interior .hero-overlay {
    background: linear-gradient(180deg, rgba(10,28,32,.86) 0%, rgba(10,28,32,.92) 100%);
  }
}
@media (max-width: 639px) {
  .hero .hero-photo { object-position: 32% 30%; }
}

/* Desktop: the hero copy reaches 77% of the viewport at 1024 but the
   original left-to-right scrim had already faded to 24% opacity by 68%,
   leaving the sub-heading at 2.33:1. Hold the darkness further right and
   let the photo come back only past the text. */
@media (min-width: 1024px) {
  .hero .hero-overlay {
    background:
      linear-gradient(90deg, rgba(10,28,32,.94) 0%, rgba(10,28,32,.90) 32%, rgba(10,28,32,.78) 58%, rgba(10,28,32,.40) 80%, rgba(10,28,32,.10) 100%),
      linear-gradient(0deg, rgba(10,28,32,.62) 0%, rgba(10,28,32,.18) 26%, rgba(10,28,32,0) 52%);
  }
}

/* Teal on photography is never reliably legible: measured 1.84:1 on the
   interior eyebrow over a bright frame. Accent color on a hero has to be
   a light one, and the pill carries its own backdrop. */
.hero-interior .eyebrow {
  color: var(--amber-light);
  background: rgba(10, 28, 32, 0.62);
  border: 1px solid rgba(249, 195, 100, 0.34);
  border-radius: var(--r-pill);
  padding: 6px 13px;
  display: inline-block;
}
.hero-interior .crumb a { color: #BFE9E3; }
.hero-interior .crumb {
  background: rgba(10, 28, 32, 0.55);
  border-radius: var(--r-pill);
  padding: 5px 14px;
  display: inline-flex;
}
/* The homepage eyebrow pill sat at 3.61:1 on a phone. Near-solid backdrop
   plus a lighter coral, since it is small uppercase text on photography. */
.hero-eyebrow {
  background: rgba(10, 28, 32, 0.86);
  color: #FFC9B4;
}

/* ------------------------------------------------------------
   Three-item card rows broke 2+1 with a visible empty slot between
   640 and 959. One column reads better than an orphan.
   ------------------------------------------------------------ */
@media (min-width: 640px) and (max-width: 959px) {
  .card-grid-3,
  .sp-spot-grid,
  .path-grid {
    grid-template-columns: minmax(0, 1fr);
    max-width: 560px;
    margin-inline: auto;
  }
}

/* The span-the-last-row rules in the base block (959px and below) select
   :last-child:nth-child(odd), which outranks the plain :last-child reset that
   was meant to switch them off on single-column screens. The surviving
   "span 2" opened a phantom second column, so every odd-count grid squeezed
   its first card to a sliver (2px on the home author cards at 390, 66px on
   the sponsor tiers, alternating 66/260 down the team grid). Same
   specificity, later in the cascade: the reset wins wherever the template is
   one column, which for .card-grid-3 is everything under 960. Found by the
   2026-09-10 line audit, where the tier bullets measured one word per line. */
@media (max-width: 959px) {
  .card-grid-3 > *:last-child:nth-child(odd),
  .card-grid-3 > *:last-child:nth-child(3n + 1) { grid-column: auto; }
}
@media (max-width: 639px) {
  .card-grid-4 > *:last-child:nth-child(odd),
  .card-grid-4 > *:last-child:nth-child(4n + 1) { grid-column: auto; }
}

/* ------------------------------------------------------------
   Header logo sat at 64px from 375 to 914px, under the 80px house
   rule for most real screens.
   ------------------------------------------------------------ */
.nav-logo img { height: clamp(72px, 7vw, 96px); }
@media (max-width: 479px) {
  .nav-logo img { height: 62px; }
}

/* The gutter grew faster than the container, so the readable column
   was actually narrower at 1920 (1080px) than at 1440 (1096px). */
:root { --gut: clamp(20px, 5vw, 72px); }

/* Headings were dropping a single word onto the last line */
h2, h3 { text-wrap: balance; }

/* ============================================================
   ACCESSIBILITY REMEDIATION (a11y audit, 2026-07-28)
   ============================================================ */

/* Collapsed FAQ panels were hidden with max-height:0 only, so the links
   inside stayed in the tab order while aria-hidden made them invisible
   to assistive tech. Four such links existed on students-teachers.
   WCAG 2.4.3 and 4.1.2. */
.faq-panel[aria-hidden="true"] {
  visibility: hidden;
}
.faq-panel[aria-hidden="false"],
.faq-panel.is-open {
  visibility: visible;
}

/* Skip link: the pages already had <main id="main-content"> with nothing
   pointing at it, so a keyboard user re-walked the whole header on every
   page load. */
.skip-link {
  position: absolute;
  left: var(--sp-4);
  top: -100px;
  z-index: 200;
  padding: 12px 20px;
  background: var(--coral-deep);
  color: #fff;
  font-weight: 700;
  border-radius: 0 0 var(--r) var(--r);
  text-decoration: none;
  transition: top var(--dur-fast) var(--ease-out);
}
.skip-link:focus-visible,
.skip-link:focus {
  top: 0;
  color: #fff;
  outline: 3px solid var(--teal);
  outline-offset: 2px;
}
main:focus { outline: none; }

/* Text inputs opted out of the global focus ring for a faint halo that
   measured about 1.3:1. Let the site-wide indicator apply. */
.form-field input:focus-visible,
.form-field select:focus-visible,
.form-field textarea:focus-visible,
.nl-input:focus-visible {
  outline: 3px solid var(--teal);
  outline-offset: 2px;
}

/* The "Past festival" badge was white on coral at 10.88px: 3.48:1 even
   at full opacity. Coral-deep takes white to 5.23:1. */
.au-lead-badge {
  background: var(--coral-deep);
  color: #fff;
}

/* Four identical "Your logo here" sponsor slots produced four
   indistinguishable entries in a screen-reader link list. The visible
   text stays the same; only the accessible name is disambiguated. */
.sponsor-invite { position: relative; }

/* ------------------------------------------------------------
   Her line-break rule, desktop columns (2026-09-10). Same arithmetic
   as the step cards above: four cards across a ~1096px column leave
   162px of text each at 1440 (20 characters), so no three-word group
   can sit on one line. Two across from 960 up, like .steps; the only
   four-up grids are the festival "What to Expect" cards and the
   sponsor add-ons. The three-up sponsor tiers measured 179px per
   bullet in the tablet-landscape band; one more padding step there.
   The group-fit pass in the page script covers what is left. */
@media (min-width: 960px) {
  .card-grid-4 { grid-template-columns: repeat(2, 1fr); }
  .card-grid-4 > *:last-child:nth-child(4n + 1) { grid-column: auto; }
  .card-grid-4 > *:last-child:nth-child(odd) { grid-column: span 2; }
}
@media (min-width: 960px) {
  .card-grid-3 > .fcard { padding-inline: clamp(20px, 2vw, 28px); }
  .card-grid-3 > .fcard .glasses-list li { padding-left: 36px; }
}

/* ------------------------------------------------------------
   Header at 960 to 1099px (an iPad in landscape is 1024): logo,
   five links and the sponsor button add up to about 60px more than
   the viewport, so every page scrolled sideways by that much. Found
   by the 2026-09-10 four-width sweep. Tighter gaps and a slimmer
   button in that band only; the drawer takes over below 960. */
@media (min-width: 960px) and (max-width: 1099px) {
  .nav-inner { gap: var(--sp-4); }
  .nav-links { gap: var(--sp-3); }
  .nav-cta .btn { padding-inline: 20px; }
}

/* ==================================================================
   WORDPRESS-ONLY RULES
   Below this line is not in the static build. The theme captures forms
   natively; the static forms posted nowhere, so none of this existed.
   ================================================================== */

/* ------------------------------------------------------------------
   HONEYPOT
   A field only a bot fills. Positioned out of view instead of
   display:none, because some bots skip anything set to display:none
   and would sail past it. aria-hidden and tabindex="-1" keep it away
   from screen readers and the keyboard, so a person never meets it.
   ------------------------------------------------------------------ */
.yabtb-hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* ------------------------------------------------------------------
   FORM STATES
   The submit script writes these two, so they need to exist before a
   form is ever used in anger.
   ------------------------------------------------------------------ */
.form-error {
  margin-top: var(--sp-4);
  padding: 12px 16px;
  border-left: 4px solid var(--coral-deep);
  border-radius: var(--r-sm);
  /* Ink on the tint, not coral on the tint: coral-deep on coral-tint is
     3.80:1, under AA, and an error message is the one string a visitor
     has to be able to read. Ink on the same tint is 9.94:1, and the
     coral rule keeps the alert cue. */
  background: var(--coral-tint);
  color: var(--ink);
  font-size: var(--step-sm);
  font-weight: 600;
}

.form-thanks {
  padding: var(--sp-6);
  border: 1.5px solid var(--line-strong);
  border-radius: var(--r);
  background: var(--card, #fff);
  font-family: var(--display);
  font-size: var(--step-1);
  font-weight: 700;
  text-align: center;
  color: var(--ink);
}


/* ------------------------------------------------------------
   Featured Event band, Sep 17: her Sep 15 doc. Short lines stay
   centred; anything longer than ~2 lines is left-aligned and broken
   into scannable chunks under a small subhead. text-wrap: pretty
   asks the browser to avoid single-word last lines where supported.
   ------------------------------------------------------------ */
.featured-event-body { max-width: 64ch; text-wrap: pretty; }
.featured-event-body p { text-wrap: pretty; }
.featured-event-body .fe-brand {
  margin: 0 0 var(--sp-2);
  font-family: var(--body);
  font-size: var(--step-sm);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--coral);
}
.featured-event-body .fe-open { margin-bottom: var(--sp-5); }
.featured-event-body .fe-section {
  text-align: left;
  margin: 0 auto var(--sp-5);
  padding-top: var(--sp-4);
  border-top: 1px solid rgba(26, 46, 53, 0.10);
}
.featured-event-body .fe-section p { max-width: 58ch; }
.featured-event-body .fe-section p:last-child { margin-bottom: 0; }
.featured-event-body .fe-subhead {
  font-family: var(--display);
  font-size: var(--step-2);
  font-weight: 700;
  line-height: 1.2;
  color: var(--ink);
  margin: 0 0 var(--sp-3);
}
.featured-event-body .fe-close {
  text-align: center;
  margin-top: var(--sp-5);
  padding-top: var(--sp-4);
  border-top: 1px solid rgba(26, 46, 53, 0.10);
}
.featured-event-body .fe-close p:last-child {
  margin-bottom: 0;
  font-size: var(--step-1);
  line-height: 1.5;
}
.featured-event-body em { font-style: italic; }

/* FAQ answers: breathing room between the four beats, no orphans. */
.faq-panel-inner p { text-wrap: pretty; }
.faq-panel-inner p + p { margin-top: var(--sp-3); }
.faq-panel[aria-hidden="false"],
.faq-panel.is-open { max-height: 900px; }

/* Josh, Sep 17: on phones the Students & Educators hero tile drops its
   lede so the signature line leads straight into the two doors. Desktop
   and tablet keep it. */
@media (max-width: 639px) {
  .tile-attend .tile-lede { display: none; }
}

/* Josh, Sep 17 (second pass).
   1. The "YA By The Bay" label sat left of centre: the global p max-width
      made a narrow left-anchored block at this small size. Centre the block,
      and pad the left by the tracking so the letters, not the trailing
      letter-space, are what centre.
   2. The gap between the Author Applications button and "What to Expect"
      was two full section paddings stacked. Trim both sides of that seam.
   3. Sponsor logos revealed one by one (70ms stagger each, plus lazy
      loading per row). They now load eagerly and show as one wall. */
.featured-event-body .fe-brand { max-width: none; margin-inline: auto; padding-left: 0.14em; text-align: center; }
.featured-event-body .fe-open { max-width: none; margin-inline: auto; }
section[aria-labelledby="featured-event-heading"] { padding-bottom: var(--sp-6); }
#what-to-expect { padding-top: var(--sp-6); }
.partner-logo.reveal { opacity: 1; transform: none; }
.partner-logo.stagger { transition-delay: 0s; }
