/* ===========================================================================
   Circular Textile Alliance — site stylesheet
   Ported from the Figma Make design "Redesign Institutional Website"
   (file pYrwXChqTORzVAjL3X3DI5). Tokens below mirror that file's `@theme`
   block one-for-one; the handful of deliberate deviations are marked
   `DEVIATION:` and listed in full in README.md.
   =========================================================================== */

/* --- Fonts: self-hosted (SIL OFL). Licences in assets/fonts/. ------------- */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 300 600;
  font-display: swap;
  src: url('../fonts/inter-normal-300-600-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 300 600;
  font-display: swap;
  src: url('../fonts/inter-normal-300-600-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/playfair-display-normal-400-700-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/playfair-display-normal-400-700-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Playfair Display';
  font-style: italic;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/playfair-display-italic-400-700-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Playfair Display';
  font-style: italic;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/playfair-display-italic-400-700-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* --- Design tokens ------------------------------------------------------- */
:root {
  --font-serif: 'Playfair Display', Georgia, 'Times New Roman', serif;
  --font-sans: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;

  --cream: #faf8f3;
  --cream-dark: #f2ede3;
  --cream-darker: #ede6d8;   /* card hover on --cream-dark */
  --ink: #1a2b28;
  --ink-deep: #111e1b;       /* footer */
  --ink-light: #3a4f4b;
  --peach: #e8936a;
  --peach-hover: #d67a55;
  --sage: #7eada0;
  --sage-light: #a8c5bd;
  --sage-dark: #547870;
  --border: #d8d0c4;
  --border-soft: #ede8df;

  /* DEVIATION (contrast). The Figma's muted/accent text tones fail WCAG AA on
     the cream backgrounds. These keep the exact hue + saturation and lower only
     lightness until each clears 4.5:1. The undarkened tokens above stay in use
     for fills, rules and dots, where contrast rules don't apply. */
  --ink-muted: #5f6f6c;      /* was #6b7e7a — 3.68:1 on --cream-dark */
  --peach-text: #b34d1c;     /* was #e8936a — 2.04:1 on --cream-dark */
  --sage-text: #4a7469;      /* was #7eada0 — 2.15:1 on --cream-dark */

  --wrap: 80rem;             /* Tailwind max-w-7xl */
  --gutter: 1.5rem;          /* px-6 */
  --section-y: 2rem;         /* was 7rem — the sections sat far too far apart */
  --ease: 0.2s ease;
}

@media (min-width: 64em) {
  :root { --gutter: 2.5rem; }  /* lg:px-10 */
}

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

html {
  scroll-behavior: smooth;
  /* Fixed 5rem header must not cover the target of an in-page jump. */
  scroll-padding-top: 5rem;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

img, svg { display: block; max-width: 100%; }
img { height: auto; }
h1, h2, h3, h4, p, ul, ol, figure, dl, dd { margin: 0; }
ul, ol { list-style: none; padding: 0; }
a { color: inherit; }
button, input { font: inherit; color: inherit; }

::-webkit-scrollbar { width: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
* { scrollbar-width: thin; scrollbar-color: var(--border) transparent; }

/* --- Accessibility helpers ----------------------------------------------- */
/* DEVIATION (a11y): the Figma has no focus styling and no skip link. Both are
   additive — neither changes the resting appearance of the page. */
.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%);
  white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute; left: var(--gutter); top: 0;
  z-index: 100; transform: translateY(-120%);
  padding: 0.75rem 1.25rem;
  background: var(--ink); color: var(--cream);
  font-size: 0.8125rem; font-weight: 500; letter-spacing: 0.06em;
  text-transform: uppercase; text-decoration: none;
  transition: transform var(--ease);
}
.skip-link:focus { transform: translateY(0); }

:focus-visible {
  outline: 2px solid var(--peach);
  outline-offset: 3px;
}
.on-dark :focus-visible,
.site-footer :focus-visible { outline-color: var(--sage-light); }

/* --- Layout -------------------------------------------------------------- */
.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section { padding-block: var(--section-y); }
.section--cream { background: var(--cream); }
.section--cream-dark { background: var(--cream-dark); }
.section--ink { background: var(--ink); }

/* --- Eyebrow (rule + label), used by every section ----------------------- */
.eyebrow {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.eyebrow::before {
  content: "";
  flex: none;
  width: 32px;
  height: 1px;
  background: currentColor;
  opacity: 0.85;
}
.eyebrow--peach { color: var(--peach-text); }
.eyebrow--peach::before { background: var(--peach); opacity: 1; }
.eyebrow--sage { color: var(--sage); }          /* on ink — 5.90:1, unchanged */
.eyebrow--sage::before { background: var(--sage); }

/* --- Headings ------------------------------------------------------------ */
.h-display,
.h-section {
  font-family: var(--font-serif);
  font-weight: 500;
  color: var(--ink);
  text-wrap: balance;
}
.h-display {
  font-size: clamp(2.5rem, 6vw, 5.25rem);
  line-height: 1.08;
}
.h-section {
  font-size: clamp(2rem, 3.5vw, 3rem);
  line-height: 1.18;
}
.h-display em, .h-section em { font-style: italic; }
.h-display .accent { color: var(--peach); font-style: italic; }
.h-section .accent { color: var(--sage-text); font-style: italic; }
.on-dark .h-display, .on-dark .h-section { color: var(--cream); }
.on-dark .h-section .accent { color: var(--sage); }

/* --- Buttons and text links ---------------------------------------------- */
.btn {
  display: inline-block;
  padding: 0.75rem 1.75rem;
  border: 1px solid transparent;
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  text-align: center;
  cursor: pointer;
  transition: background var(--ease), color var(--ease), border-color var(--ease);
}
/* DEVIATION (contrast): the Figma sets cream text on the peach fill — 2.25:1.
   Ink on the same fill is 6.19:1, so the brand fill is preserved exactly and
   only the label colour changes. */
.btn--primary { background: var(--peach); color: var(--ink); }
.btn--primary:hover { background: var(--peach-hover); }

/* DEVIATION (contrast): the Figma's 0.3 alpha gives the control boundary
   2.61:1 against the ink ground; WCAG 1.4.11 asks for 3:1. */
.btn--ghost-light { border-color: rgb(250 248 243 / 0.4); color: var(--cream); }
.btn--ghost-light:hover { border-color: rgb(250 248 243 / 0.7); }

.btn--outline-ink {
  padding: 0.5rem 1.25rem;
  border: 1.5px solid currentColor;
}
.btn--outline-ink:hover { background: var(--ink); color: var(--cream); border-color: var(--ink); }
.on-dark .btn--outline-ink:hover { background: var(--cream); color: var(--ink); border-color: var(--cream); }

.link-rule {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding-bottom: 2px;
  border-bottom: 1px solid currentColor;
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--ease);
}
.link-rule:hover { color: var(--peach-text); }

/* Placeholder affordances -------------------------------------------------
   DEVIATION (a11y): ~25 links in the Figma point at href="#", which scrolls to
   the top of the page — a broken affordance, not a neutral one. They render
   identically here but are inert and announced as unavailable until a real
   destination exists. Replace `<span class="ph">` with `<a href="…">` to wire
   one up; nothing else needs to change. See README.md. */
.ph { cursor: not-allowed; }
.ph:hover { color: inherit; }
button.ph[disabled] { opacity: 1; }   /* keep the designed contrast, not the UA's grey */

/* --- Header / navigation ------------------------------------------------- */
.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 50;
  transition: background 0.3s ease, box-shadow 0.3s ease, backdrop-filter 0.3s ease;
}
/* Two ways into the light treatment: scrolled down any page, or resting on a
   page that has no dark hero to sit over. Without the second, publications.html
   painted cream wordmark and cream nav links onto a cream section — "Circular
   Textile" vanished and only the sage "Alliance" survived. */
.site-header.is-scrolled,
.site-header--solid {
  background: rgb(250 248 243 / 0.96);
  box-shadow: 0 1px 0 var(--border);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
}

.site-header__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  height: 5rem;
}

.brand {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  text-decoration: none;
  flex: none;
}
.brand__mark { width: auto; height: 2.5rem; }
.brand__name {
  font-family: var(--font-serif);
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  line-height: 1.2;
}
.brand__name span { display: block; }
.brand__name .is-alliance { color: var(--sage); }

/* DEVIATION (contrast): over the dark hero the Figma renders the wordmark and
   nav links in --ink (#1A2B28) on a near-black photograph — roughly 1.1:1. The
   header starts in a light-on-dark state and swaps to the Figma's ink-on-cream
   once scrolled, which is what the scrolled design already shows. */
.site-header .brand__name { color: var(--cream); }
.site-header .brand__name .is-alliance { color: var(--sage-light); }
.site-header .nav__link,
.site-header .btn--outline-ink { color: var(--cream); }

.site-header.is-scrolled .brand__name,
.site-header--solid .brand__name { color: var(--ink); }
.site-header.is-scrolled .brand__name .is-alliance,
.site-header--solid .brand__name .is-alliance { color: var(--sage-text); }
.site-header.is-scrolled .nav__link,
.site-header--solid .nav__link { color: var(--ink-light); }
.site-header.is-scrolled .btn--outline-ink,
.site-header--solid .btn--outline-ink { color: var(--ink); }

/* The two rules above set the button's resting colour at a higher specificity
   than `.btn--outline-ink:hover`, so the generic hover rule could not repaint
   the label — hovering the scrolled header filled the button with --ink while
   the text stayed --ink, rendering it invisible. Each header state needs its
   own hover pair, at matching specificity. */
.site-header .btn--outline-ink:hover {
  background: var(--cream);
  color: var(--ink);
  border-color: var(--cream);
}
.site-header.is-scrolled .btn--outline-ink:hover,
.site-header--solid .btn--outline-ink:hover {
  background: var(--ink);
  color: var(--cream);
  border-color: var(--ink);
}

.nav {
  display: flex;
  align-items: center;
  gap: 2rem;
  margin-left: auto;
}
.nav__link {
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  transition: color var(--ease);
}
.nav__link:hover { color: var(--peach); }
.site-header.is-scrolled .nav__link:hover,
.site-header--solid .nav__link:hover { color: var(--peach-text); }

.nav-toggle {
  display: none;
  flex-direction: column;
  gap: 6px;
  padding: 0.5rem;
  margin-right: -0.5rem;
  background: none;
  border: 0;
  cursor: pointer;
  /* Lifted above .nav-mobile, which reaches up around it. */
  position: relative;
  z-index: 2;
}
.nav-toggle__bar {
  display: block;
  width: 22px;
  height: 1.5px;
  background: var(--cream);
  transition: transform var(--ease), opacity var(--ease), background var(--ease);
}
.site-header.is-scrolled .nav-toggle__bar,
.site-header--solid .nav-toggle__bar { background: var(--ink); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(1) { transform: translateY(7.5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(3) { transform: translateY(-7.5px) rotate(-45deg); }
/* Open, the bars sit on the cream panel. Over the hero the header is still in
   its light state, so without this the X would be cream on cream. */
.nav-toggle[aria-expanded="true"] .nav-toggle__bar { background: var(--ink); }

/* A panel hung off the right of the bar rather than a full-bleed sheet. 16rem
   is a quarter of 64em, the width at which the disclosure first appears; the
   70vw cap keeps it inside a narrow phone, where a literal quarter would be
   too narrow to read. */
/* The panel starts at the top of the bar and reaches down, so the toggle sits
   on top of it rather than above it — closing it is a click on the X inside its
   own panel. The toggle is lifted out of the panel's stacking order to stay
   visible and clickable. */
.nav-mobile {
  position: absolute;
  top: 0.75rem;
  right: calc(var(--gutter) - 0.5rem);
  z-index: 1;
  width: min(16rem, 70vw);
  max-height: calc(100svh - 1.5rem);
  overflow-y: auto;
  text-align: right;
  background: var(--cream);
  border: 1px solid var(--border);
  box-shadow: 0 12px 28px rgb(26 43 40 / 0.14);
  /* Top padding clears the toggle, which overlaps the panel's first rows.
     Bottom padding is 0 on purpose: a scroll container's bottom padding is not
     part of its scrollable overflow in every engine, which clipped the last
     item's border clean off. The space is a margin on the last child instead. */
  padding: 3rem 1rem 0;
  opacity: 1;
  transform: translateY(0);
  /* allow-discrete keeps the element painted while the exit runs; browsers
     without it simply swap instantly, which is the old behaviour. */
  transition: opacity 160ms ease, transform 160ms ease,
              display 160ms allow-discrete;
}
.nav-mobile[hidden] {
  display: none;
  opacity: 0;
  transform: translateY(-0.5rem);
}
@starting-style {
  .nav-mobile { opacity: 0; transform: translateY(-0.5rem); }
}
/* Scoped to the list. As `.nav-mobile a` this also matched "Become a Member",
   and at (0,1,1) it outranked `.btn--outline-ink` at (0,1,0): the button took
   the divider's `border-bottom: 1px solid var(--border-soft)` in place of its
   own bottom edge, which is the missing border. */
.nav-mobile nav a {
  display: block;
  padding: 0.75rem 0;
  border-bottom: 1px solid var(--border-soft);
  font-size: 0.875rem;
  font-weight: 500;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink);
  text-decoration: none;
}
.nav-mobile nav a:hover { color: var(--peach-text); }
.nav-mobile .btn { margin-top: 1.25rem; width: 100%; }
.nav-mobile > :last-child { margin-bottom: 1.25rem; }

/* The panel is cream in every header state, so the button inside it is ink in
   every header state. `.site-header .btn--outline-ink` (0,2,0) paints it cream
   for the over-hero header — cream on cream, which is the button vanishing
   entirely at the top of the page. These win at (0,3,0) and (0,3,1). */
.site-header .nav-mobile .btn--outline-ink { color: var(--ink); }
.site-header .nav-mobile .btn--outline-ink:hover {
  background: var(--ink);
  color: var(--cream);
  border-color: var(--ink);
}

/* --- Hero ---------------------------------------------------------------- */
.hero { position: relative; background: var(--ink); }
/* The photograph lives here and nowhere else. */
.hero__stage {
  position: relative;
  overflow: hidden;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}
/* Flat ink under the statement copy: no photograph behind it, so the contrast
   pairs the suite measures against --ink are the pairs that actually render. */
.hero__statement { background: var(--ink); padding-block: 1rem 4rem; }
.hero__statement-inner { display: grid; gap: 3.5rem 2rem; }
.hero__media {
  position: absolute;
  inset: 0;
  /* Backing colour shows through until the photograph paints, so the hero
     degrades to flat ink rather than a blank band. */
  background-color: var(--ink);
  background-image: url('../img/photos/1711_MEX_HONGHO_GARMENT_02-hero.webp');
  background-size: cover;
  background-position: center 30%;
  opacity: 0.22;
}
.hero__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, var(--ink) 35%, transparent 70%);
}
/* Decorative rings echoing the logo mark. */
.hero__ring {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
}
.hero__ring--lg {
  top: 12%; right: -8%;
  width: 520px; height: 520px;
  border: 1.5px solid rgb(126 173 160 / 0.18);
}
.hero__ring--sm {
  top: 22%; right: -2%;
  width: 320px; height: 320px;
  border: 1.5px solid rgb(232 147 106 / 0.14);
}
.hero__inner {
  position: relative;
  padding-block: 8rem 6rem;
}
.hero .eyebrow { margin-bottom: 2rem; }

/* On-ink copy. Sage for the headings, cream for the body — the intro sits at
   0.75 so the mission and vision, at full cream, read as the firmer statements. */
.hero__subhead {
  font-family: var(--font-serif);
  font-size: clamp(1.375rem, 2.2vw, 1.75rem);
  font-weight: 600;
  line-height: 1.35;
  color: var(--sage);
  margin-bottom: 1.5rem;
}
.hero__body {
  font-size: 1rem;
  line-height: 1.8;
  color: rgb(250 248 243 / 0.75);
}
.hero__body + .hero__body { margin-top: 1.25rem; }

.hero__pillars {
  display: grid;
  gap: 2.25rem;
  align-content: start;
}
.pillar { border-left: 2px solid var(--sage); padding-left: 1.5rem; }
.pillar__title {
  font-family: var(--font-serif);
  font-size: 1.25rem;
  font-weight: 500;
  line-height: 1.3;
  color: var(--sage);
  margin-bottom: 0.75rem;
}
.pillar__body {
  font-size: 1rem;
  line-height: 1.8;
  color: var(--cream);
}
/* --- About / Who we are -------------------------------------------------- */
.about__title { margin-top: 1.25rem; margin-bottom: 3rem; }

.about__lede {
  max-width: 54rem;
  margin-top: 1.75rem;
  font-size: 1.0625rem;
  line-height: 1.8;
  color: var(--ink-light);
}
.about__block { max-width: 54rem; margin-top: 3rem; }
/* DEVIATION (contrast): the reference renders these subheads in the undarkened
   brand values, which are 2.15:1 (sage) and 2.04:1 (peach) on cream — failures
   at any size. The -text variants keep the hue and reach 4.51:1. */
.about__subhead {
  font-family: var(--font-serif);
  font-size: 1.25rem;
  font-weight: 600;
  line-height: 1.3;
  color: var(--sage-text);
  margin-bottom: 1rem;
}
.about__subhead--peach { color: var(--peach-text); }
.about__body {
  font-size: 1.0625rem;
  line-height: 1.8;
  color: var(--ink-light);
}
.about__list {
  margin-top: 1.25rem;
  display: grid;
  gap: 0.625rem;
  font-size: 1.0625rem;
  line-height: 1.6;
  color: var(--ink-light);
}
/* ul carries list-style: none from the reset, so the marker is drawn here —
   a peach dot, matching the eyebrow rule rather than the browser's bullet. */
.about__list li {
  position: relative;
  padding-left: 1.5rem;
}
.about__list li::before {
  content: "";
  position: absolute;
  left: 0.25rem;
  top: 0.65em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--peach);
}
.about__block .btn { margin-top: 0.5rem; }
.on-dark .about__list { color: rgb(250 248 243 / 0.85); }

/* Hairline grid: the 1px gap over a border-coloured bed draws the rules. */
.principles {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
}
/* Five cards into an even grid leaves a hole, and in a hairline grid a hole is
   not empty space — it is a block of the --border bed showing through. The last
   card spans the remainder of its row instead, which also suits it: it carries
   the longest body of the five. */
.principle {
  background: var(--cream);
  padding: 2rem;
  transition: background var(--ease);
}
.principle:hover { background: var(--cream-dark); }
.principle__number {
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  color: var(--sage-text);
  margin-bottom: 0.75rem;
}
.principle__title {
  font-family: var(--font-serif);
  font-size: 1.0625rem;
  font-weight: 500;
  line-height: 1.3;
  margin-bottom: 0.75rem;
}
.principle__body {
  font-size: 0.875rem;
  line-height: 1.7;
  color: var(--ink-muted);
}

/* A hairline closing one section off from the next, where the tightened
   section rhythm alone no longer reads as a break. */
.rule {
  border: 0;
  border-top: 1px solid var(--border);
  margin-top: 2.5rem;
}

/* --- Shared section head (title left, "all …" link right) ---------------- */
.section-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 2rem;
  margin-bottom: 4rem;
}
.section-head .eyebrow { margin-bottom: 1.25rem; }

/* --- Programs ------------------------------------------------------------ */
/* Long-form now rather than a card grid: seven areas, each a heading and its
   own prose, with the figures that belong to two of them. */
.programs__title { margin-top: 1.25rem; }
.prog__intro { max-width: 54rem; margin-top: 2.5rem; }
.progs { margin-top: 4rem; }
.prog + .prog {
  margin-top: 3.5rem;
  padding-top: 3.5rem;
  border-top: 1px solid var(--border);
}
.prog__title {
  font-family: var(--font-serif);
  font-size: clamp(1.5rem, 2.4vw, 1.875rem);
  font-weight: 500;
  line-height: 1.2;
  color: var(--ink);
  margin-bottom: 1.25rem;
}
.prog__content { max-width: 54rem; }
.prog__body {
  font-size: 1.0625rem;
  line-height: 1.8;
  color: var(--ink-light);
}
.prog__body + .prog__body { margin-top: 1.25rem; }
.about__list + .prog__body { margin-top: 1.5rem; }
.prog__cue { margin-top: 1.5rem; }

.prog__figures {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
  margin-top: 2.5rem;
}
.prog__figure { border: 1px solid var(--border); }
/* The diagram has a real alpha channel: the drawn sheet of paper is opaque and
   everything around it is transparent, so it sits straight on the section's
   ground. (Until 0.14.2 it was an opaque white rectangle and needed a cream
   plate and a rule to stop it floating; with transparency those would only box
   the sheet back in.) */
.prog__diagram {
  margin: 2.5rem auto 0;
  max-width: 40rem;
}

/* --- Members ------------------------------------------------------------- */
/* Peach carries the headings here, per the supplied reference: 6.21:1 on --ink,
   so it clears AA for normal text, not only for the large sizes it is used at. */
.mem__lead { margin-top: 1.25rem; color: var(--peach); }
.mem__intro { max-width: 54rem; margin-top: 2rem; }
.mem__block { max-width: 54rem; margin-top: 3.5rem; }
.mem__head {
  font-family: var(--font-serif);
  font-size: clamp(1.5rem, 2.4vw, 1.875rem);
  font-weight: 500;
  line-height: 1.2;
  color: var(--peach);
  margin-bottom: 1.25rem;
}
.mem__head--cream { color: var(--cream); }
.mem__body {
  font-size: 1.0625rem;
  line-height: 1.8;
  color: rgb(250 248 243 / 0.85);
}
.mem__body + .mem__body { margin-top: 1.25rem; }
.mem__body--after-list { margin-top: 1.5rem; }
.mem__who { margin-top: 1.25rem; }

/* --- Board --------------------------------------------------------------- */
.board { display: grid; gap: 2.5rem; margin-top: 0.5rem; }
.board__group { border-top: 1px solid rgb(216 208 196 / 0.15); padding-top: 1.5rem; }
.board__label {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  margin-bottom: 1.25rem;
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.board__dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; flex: none; }
/* Three distinct tones on ink, all clearing AA: 6.21 / 5.90 / 8.02 to 1. */
.board__group--exec { color: var(--peach); }
.board__group--member { color: var(--sage); }
.board__group--advisory { color: var(--sage-light); }

/* Columns rather than a grid: names flow down one column and into the next, so
   a group of seven fills 3/2/2 instead of leaving a ragged final row. */
.board__people {
  color: var(--cream);
  font-size: 1rem;
  line-height: 1.6;
}
.board__people li { break-inside: avoid; }
.board__people li + li { margin-top: 0.625rem; }

/* --- Why join ------------------------------------------------------------ */
.why { display: grid; gap: 2rem; margin-top: 0.5rem; }
.why__item { max-width: 34rem; }
.why__title {
  font-family: var(--font-serif);
  font-size: 1.125rem;
  font-weight: 500;
  color: var(--sage);
  margin-bottom: 0.5rem;
}
.why__body {
  font-size: 1rem;
  line-height: 1.75;
  color: rgb(250 248 243 / 0.85);
}

/* --- Publications page --------------------------------------------------- */
.pubpage { padding-top: calc(var(--section-y) + 5rem); }
.pubpage__title { margin-top: 1.25rem; margin-bottom: 0; }
/* --- Publications -------------------------------------------------------- */
.pubs {
  display: grid;
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
}
.pub {
  display: grid;
  grid-template-columns: 160px 1fr auto;
  gap: 2.5rem;
  align-items: center;
  padding: 2rem 2.5rem;
  background: var(--cream);
  transition: background var(--ease);
}
.pub:hover { background: var(--cream-dark); }
/* The four entries are external resources with no supplied description, year
   or page count, so the left rail names the host instead — which also tells a
   reader that the link leaves this site. */
.pub__source {
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  color: var(--ink-muted);
  word-break: break-word;
}
.pub__title {
  font-family: var(--font-serif);
  font-size: 1.0625rem;
  font-weight: 500;
  line-height: 1.35;
  margin-bottom: 0.6rem;
}
.pub__title a { text-decoration: none; }
.pub__title a:hover { color: var(--peach-text); }
.pub__aside { text-align: right; }
.pub__download {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.4rem 1rem;
  border: 1px solid var(--border);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
}

/* --- Newsletter ---------------------------------------------------------- */
.newsletter {
  margin-top: 4rem;
  padding: 3rem;
  background: var(--ink);
  display: grid;
  /* minmax(0,1fr), not the default `auto`: a percentage max-width inside an
     auto track is cyclic, so the track resolved to the form's 26rem and blew
     past the viewport on a phone. A 0 minimum lets the track actually shrink. */
  grid-template-columns: minmax(0, 1fr);
  gap: 2rem;
  align-items: center;
}
.newsletter__title {
  font-family: var(--font-serif);
  font-size: 1.375rem;
  font-weight: 500;
  color: var(--cream);
  margin-bottom: 0.5rem;
}
.newsletter__note {
  font-size: 0.875rem;
  color: rgb(250 248 243 / 0.65);
}
.newsletter__form { width: 100%; max-width: 26rem; }
.newsletter__field { display: flex; align-items: stretch; }
.newsletter__input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 0.8rem 1.15rem;
  background: rgb(250 248 243 / 0.08);
  /* DEVIATION (contrast): 0.4, not the Figma's 0.2 — a text field's boundary
     needs 3:1 against its ground under WCAG 1.4.11. */
  border: 1px solid rgb(250 248 243 / 0.4);
  border-right: none;
  font-size: 0.875rem;
  color: var(--cream);
  transition: background var(--ease), border-color var(--ease);
}
.newsletter__input::placeholder { color: rgb(250 248 243 / 0.55); }
.newsletter__input:hover { border-color: rgb(250 248 243 / 0.55); }
.newsletter__input:focus {
  background: rgb(250 248 243 / 0.12);
  border-color: var(--sage-light);
}
.newsletter__input:focus-visible { outline-offset: -3px; }
.newsletter__submit { flex: 0 0 auto; padding-inline: 1.5rem; }

/* Reserve the message row. Without a floor here the panel grows on submit and,
   because the row is centre-aligned, the heading beside it visibly jumps. */
.newsletter__status {
  min-height: 1.25rem;
  margin-top: 0.6rem;
  font-size: 0.8125rem;
  line-height: 1.35;
  color: var(--sage-light);
}
.newsletter__form[aria-busy="true"] .newsletter__submit { cursor: progress; }

/* Mailchimp's honeypot field. Moved off-canvas, the way Mailchimp's own embed
   does it, rather than display:none, which form-filling bots look for. Overflow
   to the left of the page is not scrollable, so this adds no scrollbar. */
.newsletter__trap {
  position: absolute;
  left: -5000px;
}

/* --- Footer -------------------------------------------------------------- */
.site-footer { background: var(--ink-deep); color: var(--cream); }
.site-footer__main { padding-block: 5rem 4rem; }
.site-footer__grid { display: grid; gap: 3rem; }
.site-footer .brand { margin-bottom: 1.5rem; }
.site-footer .brand__mark { height: 2.25rem; }
.site-footer .brand__name { color: rgb(250 248 243 / 0.9); font-size: 0.75rem; letter-spacing: 0.05em; }
.site-footer__blurb {
  font-size: 0.875rem;
  line-height: 1.75;
  /* DEVIATION (contrast): Figma alpha .45 → 4.25:1. */
  color: rgb(250 248 243 / 0.6);
  margin-bottom: 2rem;
}
.social { display: flex; gap: 0.75rem; flex-wrap: wrap; }
.social span {
  display: inline-block;
  padding: 0.4rem 0.875rem;
  border: 1px solid rgb(250 248 243 / 0.25);
  font-size: 0.6875rem;
  letter-spacing: 0.05em;
  color: rgb(250 248 243 / 0.6);
}

/* Sized to their content and pushed together rather than split across the
   full nine columns, which left a canyon between the two lists. */
.footer-cols { display: grid; grid-template-columns: repeat(2, 1fr); gap: 2rem; }
.footer-col__title {
  font-family: var(--font-sans);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  /* DEVIATION (contrast): Figma alpha .40 → 3.63:1. */
  color: rgb(250 248 243 / 0.6);
  margin-bottom: 1.25rem;
}
.footer-col ul { display: flex; flex-direction: column; gap: 0.625rem; }
.footer-col li { font-size: 0.875rem; color: rgb(250 248 243 / 0.6); }
.footer-col a { text-decoration: none; transition: color var(--ease); }
.footer-col a:hover { color: var(--cream); }

.site-footer__bottom { border-top: 1px solid rgb(250 248 243 / 0.08); }
.site-footer__bottom .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1rem;
  padding-block: 1.5rem;
}
/* DEVIATION (contrast): Figma alpha .30 → 2.61:1. */
.site-footer__legal, .site-footer__policies { font-size: 0.75rem; color: rgb(250 248 243 / 0.55); }
.site-footer__policies { display: flex; gap: 2rem; flex-wrap: wrap; }
/* Buttons, not links: each opens a dialog rather than going anywhere. They are
   styled to read as the quiet footer text they replaced. */
.policy-open {
  padding: 0;
  background: none;
  border: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  transition: color var(--ease);
}
.policy-open:hover { color: var(--cream); }

/* --- Policy dialogs ------------------------------------------------------ */
/* <dialog> + showModal() gives centring, a backdrop, focus containment and
   Escape for free; only the appearance and the animation are ours. */
.policy {
  width: min(38rem, calc(100vw - 2 * var(--gutter)));
  max-height: 85svh;
  /* Scrolls itself, so the closing space is a margin on the last child — a
     scroll container's bottom padding is not reliably part of its overflow. */
  overflow-y: auto;
  padding: 0;
  border: 1px solid var(--border);
  background: var(--cream);
  color: var(--ink);
  opacity: 0;
  transform: translateY(0.75rem) scale(0.98);
  transition: opacity 180ms ease, transform 180ms ease,
              display 180ms allow-discrete, overlay 180ms allow-discrete;
}
.policy[open] { opacity: 1; transform: none; }
@starting-style {
  .policy[open] { opacity: 0; transform: translateY(0.75rem) scale(0.98); }
}
.policy::backdrop {
  background: rgb(17 30 27 / 0.55);
  opacity: 0;
  transition: opacity 180ms ease, display 180ms allow-discrete,
              overlay 180ms allow-discrete;
}
.policy[open]::backdrop { opacity: 1; }
@starting-style {
  .policy[open]::backdrop { opacity: 0; }
}
.policy__inner { padding: 2rem 2rem 0; }
.policy__title {
  font-family: var(--font-serif);
  font-size: 1.5rem;
  font-weight: 500;
  line-height: 1.2;
  margin-bottom: 1.25rem;
}
.policy__body p {
  font-size: 1rem;
  line-height: 1.75;
  color: var(--ink-light);
}
.policy__body p + p { margin-top: 1rem; }
.policy__close { margin-block: 1.75rem 2rem; }

/* --- Breakpoints --------------------------------------------------------- */
@media (min-width: 40em) {   /* 640px */
  .footer-cols { grid-template-columns: repeat(2, minmax(0, max-content)); gap: 5rem; }
}

@media (min-width: 44em) {   /* 704px — two cards still read */
  .prog__content { padding-left: 2.5rem; }
  .prog__figures { grid-template-columns: 1fr 1fr; }
  .board__people { columns: 2; column-gap: 2.5rem; }
  .why { grid-template-columns: repeat(2, 1fr); }
  .principles { grid-template-columns: repeat(2, 1fr); }
  .principles .principle:last-child { grid-column: span 2; }
}

@media (min-width: 56em) {   /* 896px — below this the 26rem form crowds the copy */
  .newsletter { grid-template-columns: minmax(0, 1fr) 26rem; }
}

@media (min-width: 64em) {   /* 1024px — Tailwind `lg` */
  .board__people { columns: 3; column-gap: 3rem; }
  .why { grid-template-columns: repeat(3, 1fr); }
  /* Full width now, so the four read as one band rather than a 2x2 block. */
  .principles { grid-template-columns: repeat(3, 1fr); }
  .principles .principle:last-child { grid-column: span 2; }

  .hero__inner .h-display { max-width: 68%; }
  .hero__statement-inner { grid-template-columns: repeat(12, 1fr); column-gap: 5rem; }
  .hero__intro { grid-column: span 7; }
  .hero__pillars { grid-column: span 5; }

  .site-footer__grid { grid-template-columns: repeat(12, 1fr); }
  .site-footer__brand { grid-column: span 3; }
  .site-footer__links { grid-column: span 9; padding-left: 4rem; }
}

/* Below `lg` the desktop nav collapses into the disclosure menu. */
@media (max-width: 63.99em) {
  .nav, .site-header__bar .btn--outline-ink { display: none; }
  .nav-toggle { display: flex; }
  .hero__ring--lg { width: 340px; height: 340px; }
  .hero__ring--sm { width: 210px; height: 210px; }
}

@media (max-width: 48em) {   /* 768px */
  :root { --section-y: 1.5rem; }
  .pub {
    grid-template-columns: 1fr;
    gap: 1.25rem;
    padding: 1.75rem var(--gutter);
  }
  .pub__aside { text-align: left; }
  .newsletter { padding: 2rem var(--gutter); }
  .section-head { margin-bottom: 2.5rem; }
  .hero__inner { padding-block: 7rem 4rem; }
}

/* --- 404 ----------------------------------------------------------------- */
.notfound {
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  background: var(--ink);
  position: relative;
  overflow: hidden;
}
.notfound__inner { position: relative; }
.notfound__code {
  font-family: var(--font-serif);
  font-size: clamp(4rem, 14vw, 9rem);
  font-weight: 500;
  font-style: italic;
  line-height: 1;
  color: var(--peach);
  margin: 2rem 0 1.5rem;
}
/* Carried these from .hero__lede, which 0.4.0 deleted with the hero's lede
   paragraph — 404.html still referenced the class and lost its type with it. */
.notfound__lede {
  max-width: 34rem;
  margin-top: 1.25rem;
  font-size: 1rem;
  line-height: 1.7;
  color: rgb(250 248 243 / 0.65);
}
.notfound__actions { display: flex; gap: 1rem; flex-wrap: wrap; margin-top: 2.5rem; }

@media (max-width: 30em) {   /* 480px — no room for a button beside the field */
  .newsletter__field { flex-direction: column; align-items: stretch; }
  .newsletter__input { border-right: 1px solid rgb(250 248 243 / 0.4); }
  .newsletter__submit { margin-top: 0.5rem; }
  /* At this width the message wraps to two lines; reserve both so the panel
     still doesn't change height on submit. */
  .newsletter__status { min-height: 2.4rem; }
}

/* --- Motion / print ------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

@media print {
  .site-header, .nav-mobile, .skip-link, .newsletter { display: none !important; }
  .hero__stage { min-height: auto; }   /* else page 1 is all hero */
  .hero__media, .hero__ring { display: none; }
  body { background: #fff; color: #000; }
}
