/* ==========================================================================
   Judy for BHUSD 2026 — components
   Reproduces HomePage.png and Vision.png. Every value traces to a
   measurement; see JUDY.md §2 for the geometry and QUESTIONS.md for the
   open items.
   ========================================================================== */

/* ---- Reset --------------------------------------------------------------- */

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

body, h1, h2, h3, p, ul, ol, figure, blockquote {
  margin: 0;
  padding: 0;
}

ul, ol { list-style: none; }

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

/* Must outrank the rule above, or the inline icon sprite renders as a
   150px-tall block at the top of every page. */
[hidden] { display: none !important; }

a { color: inherit; text-decoration: none; }

body {
  background: var(--page);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
}

:focus-visible {
  outline: 3px solid var(--orange);
  outline-offset: 3px;
}

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip-link {
  position: absolute;
  left: var(--s-4); top: var(--s-4);
  z-index: 100;
  padding: var(--s-2) var(--s-4);
  background: var(--white);
  color: var(--teal-dark);
  font: 600 var(--fs-nav)/1 var(--font-label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  transform: translateY(-200%);
}
.skip-link:focus { transform: none; }

/* ---- Layout primitives --------------------------------------------------- */

.wrap {
  width: min(100% - var(--s-6), var(--wrap, var(--wrap-cards)));
  margin-inline: auto;
}

.icon {
  width: 1em;
  height: 1em;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Brand marks are filled, not stroked. */
.icon--brand { stroke: none; fill: currentColor; }

/* Orange rule with a star, centred. The comp draws it three ways: centred
   under a heading, left-aligned and short, and full width in the hero. */
.ornament {
  margin: 0.25rem 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  color: var(--orange);
}
.ornament::before,
.ornament::after {
  content: "";
  height: 1px;
  width: 3.5rem;
  background: currentColor;
}
.ornament__star { width: 0.4rem; height: 0.4rem; fill: currentColor; stroke: none; flex: none; }

.ornament--left { justify-content: flex-start; }
.ornament--left::after { display: none; }
.ornament--left::before { width: 2.25rem; }

.ornament--wide::before,
.ornament--wide::after { width: 100%; }

/* ---- Buttons ------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 0.79em 1.92em;
  border: 1px solid transparent;
  border-radius: var(--radius);
  font-family: var(--font-label);
  font-size: var(--fs-nav);
  font-weight: 600;
  letter-spacing: var(--track-label);
  line-height: 1.15;
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}

/* Hover states are not in a flat comp. Each is its own brand swatch darkened,
   except the teal button, which hovers to Dark Teal — the sheet supplies the
   darker step, so no new colour is invented. */
.btn--orange { background: var(--orange); color: var(--white); }
.btn--orange:hover { background: #da510d; }

.btn--teal { background: var(--teal-button); color: var(--white); }
.btn--teal:hover { background: var(--teal-dark); }

.btn--dark { background: var(--teal-dark); color: var(--white); }
.btn--dark:hover { background: #003737; }

.btn--sm { padding: 0.34em 0.78em; }

/* The two social buttons in the Follow Judy card carry the platforms' own
   colours rather than the campaign palette (tokens.css). Hover darkens each
   by the same step the brand buttons above use. */
.btn--ig { background: var(--ig-orange); color: var(--white); }
.btn--ig:hover { background: #d94a2c; }

.btn--fb { background: var(--fb-blue); color: var(--white); }
.btn--fb:hover { background: #0d63d2; }

.btn--outline {
  background: transparent;
  color: var(--white);
  border-color: rgba(255, 255, 255, .8);
}
.btn--outline:hover { background: rgba(255, 255, 255, .12); }

/* ---- Wordmark ------------------------------------------------------------ */

.wordmark { display: block; }
.wordmark img { width: 100%; height: auto; }

.wordmark--header { width: 10.125rem; }   /* 162px, measured */
.wordmark--footer { width: 10.625rem; }

/* ---- Site header --------------------------------------------------------- */

.site-header {
  --wrap: var(--wrap-header);
  position: relative;
  z-index: 3;
}

/* The comp sets the header edge to edge and off-centre: the wordmark sits
   19px from the left and the DONATE button 61px from the right. Built as
   drawn; flagged in QUESTIONS.md as a probable comp artefact. The
   asymmetry is desktop-only — below 1024 it would starve the content. */
.site-header__inner {
  width: 100%;
  display: flex;
  align-items: center;
  gap: var(--s-5);
  padding-block: 0.875rem;
  padding-inline: var(--s-4);
}

@media (min-width: 64em) {
  .site-header__inner { padding-inline: 1.1875rem 3.8125rem; }
}

.site-nav {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 2.05rem;
}

.site-nav__link {
  position: relative;
  font-family: var(--font-label);
  font-size: var(--fs-nav);
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  padding-block: 0.4em;
  white-space: nowrap;
}

.site-nav__link[aria-current="page"]::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 2px;
  background: var(--orange);
}

.site-nav__cta { margin-left: 0.5rem; padding: 0.6em 1.24em; }

/* The homepage nav sits inside the hero band rather than above it, so it is
   lifted out of flow and the hero reserves the space. */
.site-header--overlay {
  position: absolute;
  inset-inline: 0;
  top: 0;
  color: var(--white);
}

/* Solid white bar above the Vision hero photograph. */
.site-header--solid {
  background: var(--white);
  color: var(--teal-dark);
}

.nav-toggle { display: none; }

/* ---- Homepage hero ------------------------------------------------------- */

.hero {
  position: relative;
  isolation: isolate;
  background: var(--teal-dark);
  color: var(--white);
  overflow: hidden;
}

/* The comp's backdrop: a broad lighter pool behind the portrait, warm bokeh
   discs, and concentric rings sweeping off the right edge. Drawn rather than
   cropped so it stays sharp at any width (IMG2VIBE §6).

   The gradient is now the two brand teals doing exactly what they are named
   for: a Dark Teal base with a Primary Teal pool lifted over it. The 45% stop
   is the one value between them that is on neither swatch. */
.hero__backdrop {
  position: absolute;
  inset: 0;
  z-index: -2;
  background:
    radial-gradient(38rem 26rem at 62% 62%, #006666 0%, #005a5a 45%, transparent 78%),
    radial-gradient(20rem 20rem at 88% 20%, rgba(0, 102, 102, .55) 0%, transparent 70%),
    var(--teal-dark);
}

.hero__bokeh {
  position: absolute;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  opacity: .55;
}
/* The warm discs are Light Orange — the one brand swatch the comps gave no
   obvious home, and the only warm light in the hero. */
.hero__bokeh span {
  position: absolute;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(254, 135, 76, .85), rgba(254, 135, 76, 0) 70%);
  filter: blur(1px);
}

.hero__rings {
  position: absolute;
  inset: 0;
  z-index: -1;
  color: rgba(255, 255, 255, .07);
  pointer-events: none;
}

.hero__inner {
  --wrap: var(--wrap-header);
  position: relative;
  min-height: 22.25rem;                 /* 356px — the measured band */
}

.hero__copy {
  position: relative;
  z-index: 1;
  max-width: 31rem;
  padding-left: 9.8125rem;              /* text column begins at x=177 */
  padding-top: 7.375rem;                /* cap of line one lands at y=126 */
  padding-bottom: 1.1875rem;
}

.hero__title {
  font-family: var(--font-display);
  font-size: var(--fs-hero);
  font-weight: 400;
  line-height: var(--lh-tight);
  letter-spacing: var(--track-display);
  text-transform: uppercase;
  text-shadow: 0 2px 10px rgba(0, 0, 0, .35);
}
.hero__title em { font-style: normal; color: var(--orange); }

.hero__rule { margin: 0.45rem 0 0.55rem; max-width: 18.75rem; }

.hero__sub {
  font-size: var(--fs-lead-sm);
  line-height: 1.35;
}
.hero__sub strong {
  display: block;
  color: var(--orange);
  font-weight: 700;
  font-style: italic;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  margin-top: 1.25rem;
}

/* The portrait is taller than the band and is clipped by it, exactly as in
   the comp — hence absolute placement plus overflow on .hero. */
.hero__portrait {
  position: absolute;
  right: 5.0625rem;
  top: 4.5rem;              /* clears the nav */
  width: 19.2rem;
}
.hero__portrait img {
  width: 100%;
  height: auto;
  display: block;
}

/* ---- Section frame ------------------------------------------------------- */

.section { position: relative; }
.section--white   { background: var(--page); }
.section--surface { background: var(--surface); }
.section--dark    { background: var(--teal-dark); color: var(--white); }

.section__head { text-align: center; }

.section__title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--fs-h2-sm);
  line-height: var(--lh-tight);
  letter-spacing: var(--track-display);
  text-transform: uppercase;
  color: var(--teal-dark);
}

.section__intro {
  max-width: 21rem;
  margin: 0.1875rem auto 0;
  line-height: 1.35;
  color: var(--teal-dark);
}

/* ---- Stats --------------------------------------------------------------- */

.stats { padding-block: var(--section-y); }
.stats .section__head { margin-bottom: 0.25rem; }
.stats__inner { --wrap: var(--wrap-stats); }

.stats__grid {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 0.46875rem;   /* 7.5px, measured between card borders */
}

.stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
  padding: 0.8125rem 0.4rem 0.5rem;
  background: var(--card);
  border: 1px solid var(--card-border);
  border-radius: var(--radius);
  text-align: center;
}

.stat__icon { font-size: 1.875rem; color: var(--teal-dark); }

.stat__figure {
  font-family: var(--font-display);
  font-size: var(--fs-stat);
  font-weight: 400;
  line-height: 1;
  color: var(--orange);
}

.stat__caption {
  margin-top: 0.25rem;
  font-family: var(--font-label);
  font-size: var(--fs-caption);
  font-weight: 600;
  letter-spacing: 0.04em;
  line-height: 1.55;
  text-transform: uppercase;
  color: var(--teal-dark);
}

.stat--summary { justify-content: center; gap: 0.55rem; }
.stat--summary .stat__caption { line-height: 1.5; }
.stat__standard {
  font-family: var(--font-label);
  font-size: var(--fs-nav);
  font-weight: 700;
  letter-spacing: 0.03em;
  line-height: 1.3;
  text-transform: uppercase;
  color: var(--orange-ink);   /* 11px label — text, so it darkens as .letter strong does */
}

/* ---- About --------------------------------------------------------------- */

.about { padding-block: var(--section-y); }
.about__inner {
  --wrap: var(--wrap-about);
  display: grid;
  grid-template-columns: 15.3125rem minmax(0, 1fr);
  gap: 1.5rem;
  align-items: start;
}

.about__portrait {
  border-radius: var(--radius-lg);
  overflow: hidden;
  aspect-ratio: 245 / 375;
}
.about__portrait img {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 50% 20%;
}

.about__title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--fs-h2);
  line-height: var(--lh-tight);
  letter-spacing: var(--track-display);
  text-transform: uppercase;
  color: var(--teal-dark);
}

.about__creds {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.55rem;
  margin-top: 0.45rem;
  font-size: var(--fs-creds);
  font-weight: 700;
  color: var(--teal-dark);
}
.about__creds li { display: flex; align-items: center; gap: 0.55rem; }
.about__creds li + li::before {
  content: "";
  width: 0.3rem; height: 0.3rem;
  border-radius: 50%;
  background: var(--orange);
}

.letter { margin-top: 0.7rem; }
.letter p + p { margin-top: 0.25rem; }
/* Orange read as text at body size, so it takes the darkened variant to stay
   legible. Swap to var(--orange) for exact brand orange at 2.9:1. */
.letter strong { font-weight: 400; color: var(--orange-ink); }

.letter__signature {
  margin-top: 0.5rem;
  width: 10rem;
}

.about__cta { margin-top: 0.3125rem; }

/* ---- Experience ---------------------------------------------------------- */

.experience { padding-block: var(--section-y); }
.experience .section__head { margin-bottom: 0.35rem; }
.experience__inner { --wrap: var(--wrap-exp); }
.experience .section__title { font-size: var(--fs-h2-xs); }

/* Four columns, not the comp's five: the Industry Leadership pillar was
   removed on the client's instruction 2026-08-05. */
.experience__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}

.pillar {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
  padding-inline: 0.9rem;
  text-align: center;
}
.pillar + .pillar { border-left: 1px solid var(--rule); }

.pillar__icon { font-size: 1.6rem; color: var(--teal-dark); }

.pillar__title {
  font-size: var(--fs-title);
  font-weight: 700;
  line-height: 1.3;
  color: var(--teal-dark);
}

.pillar__body { line-height: 1.3; }

.pillar__figure {
  font-family: var(--font-display);
  font-size: var(--fs-stat);
  font-weight: 400;
  line-height: 1.1;
  color: var(--orange);
}

/* ---- CTA band ------------------------------------------------------------ */

.cta {
  background: var(--teal-dark);
  color: var(--white);
  padding-block: var(--section-y);
  overflow: hidden;
  position: relative;
}

.cta::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(30rem 12rem at 8% 50%, rgba(0, 102, 102, .5), transparent 70%),
    radial-gradient(24rem 10rem at 96% 40%, rgba(0, 102, 102, .45), transparent 72%);
  pointer-events: none;
}

/* Off-centre in the comp exactly as the header is: content runs 88px from
   the left edge and stops 158px short of the right. Built as drawn, and
   desktop-only for the same reason as the header. */
.cta__inner {
  width: 100%;
  padding-inline: var(--s-5);
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-5);
}

.cta__title {
  font-size: var(--fs-cta);
  font-weight: 700;
  line-height: 1.28;
}
.cta__title span { display: block; color: var(--orange); }

.cta__body { margin-top: 0.1875rem; line-height: 1.3; }

.cta__actions {
  display: flex;
  align-items: center;
  gap: 1.1875rem;
  flex-shrink: 0;
}
.cta__actions .btn { padding: 0.67em 2em; min-width: 7.25rem; min-height: 2.5rem; }

@media (min-width: 64em) {
  .cta__inner { padding-inline: 5.5rem 9.875rem; }
}

/* ---- Feature cards ------------------------------------------------------- */

.cards { padding-block: var(--section-y); }
.cards__inner {
  --wrap: var(--wrap-cards);
  display: grid;
  grid-template-columns: 308fr 244fr 301fr;   /* measured card widths */
  gap: 0.625rem;
  align-items: stretch;
}

.card {
  display: flex;
  flex-direction: column;
  padding: 0.6875rem 1.0625rem 0.5rem;
  background: var(--card);
  border: 1px solid var(--card-border);
  border-radius: var(--radius);
}

.card__title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--fs-h3);
  line-height: 1.12;
  letter-spacing: var(--track-display);
  text-transform: uppercase;
  color: var(--teal-dark);
}

.card__rule { margin: 0.375rem 0 0.5rem; }

.card__body { line-height: 1.4; }
.card__body + .card__body { margin-top: 0.5rem; }
.card__body strong { font-weight: 400; color: var(--orange-ink); }  /* as .letter strong */

/* Five orange icon-and-label pairs inside the first card. */
.principles {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 0.3rem;
  margin: 0.5rem 0 0.6rem;
  text-align: center;
}
.principle { display: flex; flex-direction: column; align-items: center; gap: 0.4rem; }
.principle__icon { font-size: 1.5625rem; color: var(--orange); }
.principle__label { line-height: 1.2; }

.card--centred { text-align: center; }
.card--centred .card__rule { justify-content: center; }
.card__spacer { flex: 1; }
.card__cta { align-self: center; margin-top: 0.6rem; }

/* Follow Judy card — two handle rows, Instagram then Facebook. The rows are
   deliberately identical in mark size and type so neither platform reads as
   the secondary one (client-directed 2026-08-16); only the vertical rhythm is
   tightened, so two rows cost about what one used to. */
.card__handle {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  margin: 0.7rem 0 0;
  font-size: var(--fs-title);
  font-weight: 700;
  color: var(--teal-dark);
}
.card__handle + .card__handle { margin-top: 0.35rem; }
.card__handle .icon { font-size: 1.7rem; }

/* Both marks are the official brand glyphs on the official brand ground: the
   Instagram gradient and the Facebook blue disc. A flat fill would not be the
   Instagram mark, so it is a clipped background and the glyph stays vector. */
.ig-mark,
.fb-mark {
  width: 1.7rem; height: 1.7rem;
  border-radius: 22%;
  color: var(--white);
  display: grid;
  place-items: center;
  flex: none;
}
.ig-mark {
  background: radial-gradient(circle at 30% 107%,
    #fdf497 0%, #fdf497 5%, #fd5949 45%, #d6249f 60%, #285AEB 90%);
}
/* The Facebook mark is a white f knocked out of a blue disc. The sprite
   symbol is the whole disc, so the f shows whatever sits behind it — a white
   ground is painted inside the circle (and only inside, so no rim shows at
   the edge) rather than letting the card fill stand in for white. */
.fb-mark {
  color: var(--fb-blue);
  background: radial-gradient(circle, var(--white) 0 46%, transparent 47%);
}
.fb-mark .icon { font-size: 1.7rem; }
.ig-mark .icon { font-size: 1.15rem; }

/* The comp's five post thumbnails were removed on the client's instruction
   2026-08-05; the card is the handles and the buttons. */

/* Two buttons where the comp drew one. They sit side by side and wrap to a
   stack rather than overflow the narrowest card in the row. */
.card__cta--pair {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.4rem;
}

/* ---- Footer -------------------------------------------------------------- */

.site-footer {
  background: var(--teal-dark);
  color: var(--white);
  padding-block: 1.9rem 1.3rem;
}

.site-footer__inner {
  --wrap: var(--wrap-header);
  display: grid;
  grid-template-columns: 13.75rem repeat(3, minmax(0, 1fr)) 1.25fr;
  gap: 1.5rem;
  align-items: start;
}

.site-footer__col { position: relative; padding-left: 1.5rem; }
.site-footer__col::before {
  content: "";
  position: absolute;
  left: 0; top: 0.1rem; bottom: 0.1rem;
  width: 1px;
  background: rgba(255, 255, 255, .22);
}

.site-footer__heading {
  font-size: var(--fs-title);
  font-weight: 600;
  color: var(--teal-light);
  margin-bottom: 0.55rem;
}

.site-footer__list { display: grid; gap: 0.34rem; font-size: var(--fs-creds); }
.site-footer__list a:hover { color: var(--teal-light); }

.site-footer__social {
  display: flex;
  gap: 0.7rem;
  margin-bottom: 0.6rem;
}
.site-footer__social .icon { font-size: 1.35rem; }
.site-footer__social a:hover { color: var(--teal-light); }

.site-footer__contact { font-size: var(--fs-creds); display: grid; gap: 0.34rem; }
.site-footer__contact p + p { margin-top: 0.55rem; }

.site-footer__legal {
  --wrap: var(--wrap-header);
  margin-top: 1.1rem;
  text-align: center;
}

/* Legally required disclosure. Do not restyle smaller, lighter, or
   lower-contrast than the comp, and do not move it (IMG2VIBE §2.1). */
.disclaimer {
  font-size: var(--fs-creds);
  color: var(--white);
}

/* Privacy Policy, added 2026-08-17. Fine print: set a step below the
   disclosure above it (--fs-nav against --fs-creds) and placed after it, so
   the legally fixed string stays the larger and first thing in this strip
   (§2.1). Kept at full white — 9.7:1 on Dark Teal — because "small" here is
   size, not contrast; the underline is what marks it as a link. */
.site-footer__fineprint {
  margin-top: 0.5rem;
  font-size: var(--fs-nav);
}
.site-footer__fineprint a { text-decoration: underline; }
.site-footer__fineprint a:hover { color: var(--teal-light); }

/* ---- Vision page: hero band ---------------------------------------------- */

/* Padding, not a margin on the band: a margin would collapse out of this
   box and leave a white gap where the photograph should be. */
/* Full-bleed geometry is measured against the page width, so it is written in
   vw — never rem. The root scale is clamped (tokens.css), so a rem length stops
   shrinking below 896px while the photo keeps shrinking with the viewport, and
   the difference opens as a band of bare background. See JUDY.md §5. */
.vision-hero {
  /* Band top edge: 253/1024 of the width in the comp. The floor keeps the
     photo a readable height on a phone instead of a 100px strip. */
  --photo: max(24.707vw, 8rem);

  /* The other two full-bleed lengths, named because three rules have to
     agree on them (IMG2VIBE §9). --overlap is how far the photo runs on
     behind the band; --clip is how deep the diagonal cuts at the right
     edge. --overlap must stay the larger of the two, or the diagonal cuts
     into bare background instead of into the photograph. */
  --overlap: 4.492vw;   /* 46/1024 in the comp */
  --clip:    3.83vw;    /* 39/1024 in the comp — the 2.2° edge */

  position: relative;
  padding-top: var(--photo);
  background: #cdc7bd;
  color: var(--white);
  isolation: isolate;
}

/* The photo, not a parent background, so its height is a length we control
   rather than one implied by the file's aspect ratio. It runs 46/1024 of the
   width past the band's top edge because the comp tucks that much of it
   behind the diagonal. */
.vision-hero::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: calc(var(--photo) + var(--overlap));
  z-index: -1;
  background: url('../img/vision-hero.webp') no-repeat center;
  background-size: cover;
}

/* The band's top edge is a straight diagonal measured at
   y = 366 + 0.0383x in the 1024-wide comp — 2.2 degrees, not a curve.
   3.83vw holds that angle at every width; 2.4rem only held it while the
   root scale was still tracking the viewport. */
.vision-hero__band {
  position: relative;
  padding-block: var(--section-y);
  background: var(--teal-band);
  clip-path: polygon(0 0, 100% var(--clip), 100% 100%, 0 100%);
}

.vision-hero__band::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    radial-gradient(60% 90% at 92% 30%, rgba(255, 255, 255, .05), transparent 60%),
    radial-gradient(45% 70% at 78% 85%, rgba(0, 0, 0, .18), transparent 65%);
  pointer-events: none;
}

/* Two concentric sweeps off the right edge, the wordmark's swoosh enlarged. */
.vision-hero__sweep {
  position: absolute;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  color: rgba(255, 255, 255, .055);
  pointer-events: none;
}

.vision-hero__inner { --wrap: var(--wrap-vision); }

.vision-hero__eyebrow {
  font-size: var(--fs-eyebrow);
  font-weight: 500;
  color: var(--teal-light);
}

.vision-hero__rule {
  width: 3.5rem;
  height: 2px;
  background: var(--orange);
  margin: 0.75rem 0 1.5rem;
}

.vision-hero__title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--fs-hero-alt);
  line-height: var(--lh-tight);
  letter-spacing: var(--track-display);
  text-transform: uppercase;
  text-shadow: 0 2px 12px rgba(0, 0, 0, .3);
}
.vision-hero__title span { color: var(--teal-light); }

.vision-hero__ornament {
  max-width: 33.25rem;
  margin: 1.1rem 0 1.4rem;
  color: rgba(255, 255, 255, .35);
}
.vision-hero__ornament .ornament__star { color: var(--orange); }

.vision-hero__body {
  font-size: var(--fs-lead);
  line-height: 1.53;
  max-width: 37rem;
}

/* ---- Vision page: mission ------------------------------------------------ */

.mission {
  background: var(--surface-alt);
  padding-block: var(--section-y);
}
.mission__inner { --wrap: var(--wrap-vision); }

.mission__title {
  font-size: var(--fs-h2-mission);
  font-weight: 600;
  color: var(--teal-dark);
  line-height: 1.3;
}

.mission__rule { margin: 0.6875rem 0 0.8125rem; }

.mission__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: 1.8125rem;
}

.mission__col { display: grid; align-content: start; }

.mission__item {
  display: grid;
  grid-template-columns: 4.5625rem minmax(0, 1fr);
  gap: 1.5625rem;
  padding-block: 1rem;
}
.mission__item + .mission__item { border-top: 1px solid var(--rule); }

.mission__disc {
  width: 4.5625rem; height: 4.5625rem;
  border-radius: 50%;
  background: var(--disc);
  color: var(--teal-dark);
  display: grid;
  place-items: center;
}
.mission__disc .icon { font-size: 2.3rem; }

.mission__heading {
  font-size: var(--fs-mission-item);
  font-weight: 600;
  line-height: 1.29;
  color: var(--teal-dark);
  margin-bottom: 0.5rem;
}

.mission__body {
  font-size: var(--fs-mission-body);
  line-height: 1.5;
  color: var(--ink);
}

/* ---- Events page --------------------------------------------------------
   Not in either comp. Started 2026-08-16 as a template — the hero photograph
   is still the priorities one and the content area is deliberately empty
   pending the event copy. */

/* The events hero: the priorities hero with the photograph removed entirely
   and only its title kept, acting as the page header. Client-directed
   2026-08-16 — an events listing does not need a full-bleed image, and
   without one the content starts immediately under the site header.

   The 2.2° diagonal top edge is kept. It was drawn to cut across a
   photograph, but it reads as the site's own idiom against the white header
   too, so the band still belongs to the same family as the priorities page.
   Flatten it by removing the clip-path override below if that is not wanted.

   Nothing here needs --overlap any more: with no photograph there is nothing
   for the band to have to cover. Those properties stay on .vision-hero for
   the priorities page, which still uses them. */
.vision-hero--slim {
  padding-top: 0;
  background: var(--page);
}
.vision-hero--slim::before { content: none; }

/* --s-5 rather than the --section-y every other band uses: it holds one
   line, and the brief was to keep it tight. */
.vision-hero--slim .vision-hero__band { padding-block: var(--s-5); }

/* The content area. The min-height that held this band open while it was
   empty came out on 2026-08-16, when the invitation went in — it sizes to
   its content now, like every other band. */
.events {
  background: var(--surface-alt);
  padding-block: var(--section-y);
}
.events__inner { --wrap: var(--wrap-vision); }

/* The event list — client-directed 2026-08-31, when the prior events went
   back on the page newest first. It was a single centred poster before that.

   A plain stack: the posters differ in aspect ratio (0.800, 0.714, 0.715) and
   a grid would either crop them or leave ragged gaps, and there are three of
   them, so a column costs nothing in scanning effort. --s-8 between items is
   wide enough that two invitations never read as one composite.

   The list markers come off because the artwork is the item; the <ul> is here
   for structure, not for bullets. */
.events__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--s-8);
}

/* The invitation, placed as supplied and centred. The current artwork is 1080
   wide against this 32rem box — 2.11x, the first to clear 2x — and it ships at
   native width (build-assets.py); the box is unchanged through all five
   artworks, because the poster's size on the page is a design decision and
   the file's resolution is not. Nothing is drawn on top of it
   and it is not cropped — it is the client's artwork, reproduced. */
.invite {
  max-width: 32rem;
  margin-inline: auto;
}

/* LIVE again since 2026-09-17 on the current poster only — Sushi, Sake &
   School Talk links to its Mailchimp RSVP form. The archived posters below it
   carry no link. (Dormant 2026-08-31 to 2026-09-17, while no current event
   had a form.)

   The whole poster is the RSVP link, and it needs to look
   clickable without anything being drawn over the artwork, so the affordance
   is the cursor, a small lift on hover and a focus ring — nothing that
   touches the image. */
.invite__link {
  display: block;
  transition: transform .18s ease, box-shadow .18s ease;
}
.invite__link:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 24px rgba(0, 32, 32, .22);
}
.invite__link:focus-visible { outline-offset: 4px; }

.invite img { width: 100%; height: auto; }

/* ---- Prose block --------------------------------------------------------
   For pages that are copy rather than components — Get Involved, 2026-08-16.
   Neither comp has one, so the type sizes borrow from the priorities hero's
   lead and the mission body rather than inventing a new scale. */
.prose { max-width: 42rem; }

.prose__lead {
  font-size: var(--fs-lead);
  line-height: 1.5;
  color: var(--ink);
}

.prose__contact {
  margin-top: 1.25rem;
  font-family: var(--font-label);
  font-size: var(--fs-h3);
  font-weight: 600;
  letter-spacing: .01em;
}
.prose__contact a {
  color: var(--teal-button);
  border-bottom: 2px solid var(--orange);
  padding-bottom: 2px;
  transition: color .15s ease;
}
.prose__contact a:hover { color: var(--orange-ink); }

/* ---- Launch party popup -------------------------------------------------
   Not in either comp. Added 2026-08-16, on every page but events.html.
   A <dialog>, so the backdrop, the focus trap and Escape are the browser's
   job rather than ours — see js/promo.js. */
/* The dialog is sized to the artwork's own box, width *and* height, because
   the invitation is a tall poster (846x1184 since 2026-08-25; 751x1050 and
   848x1186 before it, where the oldest popup crop was near-square — all
   three posters' aspect ratios agree to within 0.1%, so no swap has moved
   anything on screen, but these two numbers are the artwork's and must
   follow it). Capping the image's height
   instead would leave
   the dialog wider than the picture inside it, and the close button — which is
   positioned off the dialog's corner — would float away from the artwork.
   Third term: the width a full-height poster occupies, so it never runs off
   the bottom of a short window. */
.promo {
  /* The artwork's intrinsic size. These follow the file on every swap — the
     dialog is sized by this ratio against the viewport, so a new invitation
     at a different shape needs them updated or the poster stops fitting.
     2026-08-31 (Vino & Vision) is the first swap where the ratio actually
     moved twice running. Three artworks sat at 0.714–0.715, then Vino &
     Vision at 1080/1350 = 0.800, and now 789/1184 = 0.666 — the narrowest
     poster yet, so the height cap binds sooner than it ever has and the
     short viewports are the tight cases again. probe-promo.py's sweep is the
     check. */
  --promo-w: 789;
  --promo-h: 1184;
  padding: 0;
  border: 0;
  background: transparent;
  width: min(30rem, calc(100vw - 2rem),
             calc((100vh - 4rem) * var(--promo-w) / var(--promo-h)));
  max-width: none;
  overflow: visible;
  color: var(--white);
}
/* dvh where it exists: on a phone the URL bar makes 100vh taller than the
   window, which would push the poster's foot under it. */
@supports (height: 100dvh) {
  .promo {
    width: min(30rem, calc(100vw - 2rem),
               calc((100dvh - 4rem) * var(--promo-w) / var(--promo-h)));
  }
}

.promo::backdrop { background: rgba(0, 32, 32, .68); }

/* The retired popup crop carried its own rounded corners in its alpha
   channel; every invitation since is a plain rectangle, so the radius is
   drawn here instead — on the wrapper, which clips the image to it.

   The wrapper is a <div>, not an <a>, since 2026-08-31: the current artwork
   has no destination (client-directed). This rule is what makes the element
   worth keeping anyway — it carries the radius and the shadow, so the poster
   would lose both if the wrapper went away with the link. The
   :focus-visible rule below is dormant until a destination returns. */
.promo__link {
  display: block;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: 0 12px 40px rgba(0, 32, 32, .45);
}
.promo__link:focus-visible { outline-offset: 4px; }

/* Height is the dialog's job, not the image's — see .promo above. */
.promo img {
  display: block;
  width: 100%;
  height: auto;
}

/* Sits inside the artwork's top-right corner, over the blurred backdrop of
   the portrait — light in the final invitation, dark in the one before. Same
   idiom as the back-to-top control: a teal disc with a light ring, legible
   on either a light or a dark patch. */
.promo__close {
  position: absolute;
  top: .625rem;
  right: .625rem;
  z-index: 1;
  width: 2.25rem;
  height: 2.25rem;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: var(--teal-dark);
  box-shadow: 0 0 0 2px rgba(255, 255, 255, .85), 0 2px 8px rgba(0, 0, 0, .35);
  color: var(--white);
  cursor: pointer;
  transition: background .15s ease;
}
.promo__close:hover { background: var(--teal-button); }
.promo__close .icon { font-size: 1.125rem; }

/* ---- Back to top --------------------------------------------------------
   Not in either comp. Added 2026-08-04 because RESULTS and ABOUT JUDY scroll
   into the homepage rather than navigate, which leaves the nav off-screen.
   Shown only once the header has scrolled out of view; nav.js observes the
   header rather than watching a scroll threshold, so the trigger is the
   header's real position at any viewport. */
.to-top {
  position: fixed;
  right: 1.25rem;
  bottom: 1.25rem;
  z-index: 20;
  width: 2.75rem;
  height: 2.75rem;
  display: grid;
  place-items: center;
  padding: 0;
  /* The ring is what separates it from the footer, which is teal itself.
     Over the white bands the fill does that job on its own. */
  border: 1px solid rgba(255, 255, 255, .45);
  border-radius: 50%;
  background: var(--teal-button);
  color: var(--white);
  cursor: pointer;
  box-shadow: 0 2px 10px rgba(0, 0, 0, .28);
  opacity: 0;
  visibility: hidden;
  transform: translateY(0.5rem);
  transition: opacity .18s ease, transform .18s ease, visibility .18s, background-color .15s ease;
}
.to-top[data-visible="true"] {
  opacity: 1;
  visibility: visible;
  transform: none;
}
.to-top:hover { background: var(--teal-dark); }
.to-top .icon { font-size: 1.25rem; }

/* Minimum comfortable target on a phone, and clear of the thumb rail. */
@media (max-width: 47.9375em) {
  .to-top { width: 3rem; height: 3rem; right: 1rem; bottom: 1rem; }
}

@media (prefers-reduced-motion: reduce) {
  .to-top { transition: none; transform: none; }
}

/* ==========================================================================
   Responsive
   The comp is desktop only. Stacking order below is an interpretation, not
   a client decision — flagged in QUESTIONS.md.
   ========================================================================== */

@media (max-width: 63.9375em) {          /* < 1024 */
  .stats__grid   { grid-template-columns: repeat(3, 1fr); }
  .experience__grid { grid-template-columns: repeat(2, 1fr); }
  .pillar + .pillar { border-left: 0; }
  .pillar { padding-block: 1rem; border-top: 1px solid var(--rule); }
  .cards__inner  { grid-template-columns: 1fr 1fr; }
  .card:last-child { grid-column: 1 / -1; }
  .site-footer__inner { grid-template-columns: 1fr 1fr 1fr; }
  .site-footer__inner > :first-child { grid-column: 1 / -1; }
}

@media (max-width: 47.9375em) {          /* phones */
  .site-header__inner { padding-block: var(--s-3); gap: var(--s-3); }

  .nav-toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    margin-left: auto;
    padding: 0.5em 0.75em;
    background: none;
    border: 1px solid currentColor;
    border-radius: var(--radius-sm);
    color: inherit;
    font: 600 var(--fs-nav)/1 var(--font-label);
    letter-spacing: var(--track-label);
    text-transform: uppercase;
    cursor: pointer;
  }

  .site-nav {
    display: none;
    position: absolute;
    left: 0; right: 0; top: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    margin: 0;
    padding: var(--s-3) var(--s-4) var(--s-5);
    background: var(--teal-dark);
    color: var(--white);
  }
  .site-nav[data-open="true"] { display: flex; }
  .site-nav__link { padding-block: 0.75em; }
  .site-nav__link[aria-current="page"]::after { width: 2.5rem; right: auto; }
  .site-nav__cta { margin: var(--s-3) 0 0; }

  /* Back in flow on a phone — but `relative`, never `static`. The nav panel
     below is absolute at top:100%, so the header must remain its containing
     block; under `static` the panel resolved against the initial containing
     block and opened one viewport-height down the page, which reads exactly
     like a dead button and raises no console error. */
  .site-header--overlay {
    position: relative;
    inset-inline: auto;
    top: auto;
    background: var(--teal-dark);
  }

  .hero__inner { min-height: 0; display: grid; }
  .hero__copy { max-width: none; padding: var(--s-7) 0 var(--s-5); order: 2; }
  .hero__portrait {
    /* `relative`, not `static`, so the base line below is positioned against
       this box — and therefore the desktop offsets must be cleared by hand.
       Under `static` they were inert; under `relative` they become a 72px
       downward and 81px leftward shift of a box that is otherwise correctly
       placed, which puts the portrait behind the headline. */
    position: relative;
    top: auto;
    right: auto;
    order: 1;
    width: min(20rem, 80%);
    margin: var(--s-5) auto 0;
  }

  /* The cut-out is cropped square at the bottom. Above this breakpoint the
     portrait is absolute and the hero band's own bottom edge hides that cut,
     so it reads as standing behind the white section below. In flow it does
     not, and the crop floats. A full-bleed hairline at its base gives it a
     surface to rest on. 100vw is safe here: .hero clips its overflow, so the
     line ends at the viewport and adds no horizontal scroll. */
  .hero__portrait::after {
    content: "";
    position: absolute;
    left: 50%;
    bottom: 0;
    width: 100vw;
    height: 1px;
    transform: translateX(-50%);
    background: rgba(255, 255, 255, .32);
  }
  .hero__title { text-wrap: balance; }

  .stats { padding-block: var(--s-6); }
  .stats__grid { grid-template-columns: 1fr 1fr; gap: var(--s-3); }
  .section__intro { max-width: none; }

  .about { padding-block: var(--s-5) var(--s-7); }
  .about__inner { grid-template-columns: 1fr; gap: var(--s-5); }
  .about__portrait { max-width: 18rem; }

  .experience { padding-block: var(--s-6); }
  .experience__grid { grid-template-columns: 1fr; }

  .cta { padding-block: var(--s-6); }
  .cta__inner { flex-direction: column; align-items: flex-start; }
  .cta__actions { flex-wrap: wrap; }

  .cards { padding-block: var(--s-6); }
  .cards__inner { grid-template-columns: 1fr; gap: var(--s-5); }
  .card:last-child { grid-column: auto; }
  .principles { grid-template-columns: repeat(3, 1fr); row-gap: var(--s-4); }

  /* No margin-top and no clip override here: both are vw-derived above and
     stay correct at phone widths. A rem margin here was what opened the
     300px block of bare background below 768px. */
  .vision-hero__band { padding-block: var(--s-6) var(--s-7); }
  /* The slim band keeps its tight fit on a phone too — it holds one line,
     not a paragraph, and --overlap still governs its floor. */
  .vision-hero--slim .vision-hero__band { padding-block: var(--s-4); }
  .mission { padding-block: var(--s-7); }
  .events { padding-block: var(--s-7); }
  .mission__grid { grid-template-columns: 1fr; column-gap: 0; }
  .mission__col + .mission__col .mission__item:first-child {
    border-top: 1px solid var(--rule);
  }
  .mission__item { grid-template-columns: 3.5rem minmax(0, 1fr); gap: var(--s-4); }
  .mission__disc { width: 3.5rem; height: 3.5rem; }
  .mission__disc .icon { font-size: 1.75rem; }

  .site-footer__inner { grid-template-columns: 1fr; }
  .site-footer__col { padding-left: 0; }
  .site-footer__col::before { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
  }
}
