/* ============================================================
   NDA Online v2 — full redesign design system
   ui-ux-pro-max: Soft UI Evolution · Swiss grid · NDA brand tokens
   ============================================================ */

:root {
  --navy: #023A71; --navy-700: #06427C; --deep: #0B2447; --deep-2: #082C56;
  --maroon: #711D3A; --crimson: #8B1538; --sky: #94C5F8; --sky-100: #EAF3FE; --sky-50: #F2F8FE;
  --nav-rule: rgba(2,58,113,.12);
  --ink: #0E1526; --slate: #3B475A; --paper: #FAFCFE; --white: #FFFFFF;
  --font-head: 'Poppins', sans-serif; --font-body: 'Figtree', sans-serif;
  --r-sm: 10px; --r-md: 14px; --r-lg: 18px; --r-xl: 26px;
  --sh-sm: 0 1px 2px rgba(11,36,71,.06), 0 1px 6px rgba(11,36,71,.05);
  --sh-md: 0 4px 14px rgba(11,36,71,.10);
  --sh-lg: 0 12px 32px rgba(11,36,71,.16);
  --ease: cubic-bezier(.22,.8,.32,1); --t: 220ms;
  /* overshoots and settles — for a lift that should feel picked up rather than
     slid. Only ever on transform, never on colour or shadow, where the overshoot
     would land past the target value and read as a flicker. */
  --spring: cubic-bezier(.34,1.46,.52,1);
  --flow: clamp(40px, 4.6vw, 72px); --flow-sm: clamp(26px, 3vw, 44px);
  --ring: 0 0 0 3px rgba(148,197,248,.9), 0 0 0 5px rgba(2,58,113,.55);
}

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
body {
  margin: 0; font-family: var(--font-body); font-size: 18px; line-height: 1.7;
  color: var(--ink); background: var(--paper);
  -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility;
  overflow-x: clip;
}
img { max-width: 100%; height: auto; display: block; }
iframe { max-width: 100%; border: 0; }
a { color: var(--navy); }
::selection { background: var(--sky); color: var(--deep); }
:focus { outline: none; }
:focus-visible { box-shadow: var(--ring) !important; border-radius: 6px; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

h1, h2, h3, h4, h5, h6 { font-family: var(--font-head); letter-spacing: -.015em; line-height: 1.15; color: inherit; text-wrap: balance; margin: 0 0 .5em; }
h1 { font-size: clamp(36px, 5.4vw, 64px); font-weight: 700; }
h2 { font-size: clamp(26px, 3.4vw, 40px); font-weight: 700; }
h3 { font-size: clamp(20px, 2.2vw, 26px); font-weight: 600; }

.container { width: min(1440px, 100% - 40px); margin-inline: auto; }
.container--narrow { width: min(920px, 100% - 40px); margin-inline: auto; }
.section { padding-block: var(--flow); }
.section--tight { padding-block: var(--flow-sm); }
.section--dark { background: linear-gradient(180deg, var(--sky-50), var(--sky-100)); color: var(--ink); }
.section--dark .lead { color: var(--slate); }
.section--dark h2 { color: var(--navy); }
.section--tint { background: var(--sky-100); }

.eyebrow {
  font-family: var(--font-head); font-weight: 600; font-size: 13px;
  letter-spacing: .14em; text-transform: uppercase; color: var(--crimson);
  display: inline-flex; align-items: center; gap: 10px; margin-bottom: 14px;
}
.eyebrow::before { content: ""; width: 26px; height: 2px; background: var(--crimson); border-radius: 2px; }

.lead { font-size: clamp(19px, 1.7vw, 22px); color: var(--slate); max-width: 62ch; }

/* ---------- buttons ---------- */
.btn {
  font-family: var(--font-head); font-weight: 600; font-size: 15.5px;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 48px; padding: 12px 26px; border-radius: 999px;
  border: 1.5px solid transparent; cursor: pointer; text-decoration: none;
  transition: transform var(--t) var(--ease), box-shadow var(--t) var(--ease),
              background-color var(--t) var(--ease), color var(--t) var(--ease), border-color var(--t) var(--ease);
}
.btn:hover { transform: translateY(-1px); box-shadow: var(--sh-md); }
.btn:active { transform: translateY(0); box-shadow: var(--sh-sm); }
.btn--primary { background: var(--navy); color: var(--white); }
.btn--primary:hover { background: var(--navy-700); }
.btn--cta { background: linear-gradient(135deg, var(--maroon), var(--crimson)); color: var(--white); }
/* .35 navy on paper measures 1.98:1 — under WCAG 1.4.11's 3:1 for a control
   boundary, and an outline button's border IS its only boundary. .55 lands at
   3.2:1 on both --white and --paper without reading as a heavy stroke. */
.btn--ghost { border-color: rgba(2,58,113,.55); color: var(--navy); background: transparent; }
.btn--ghost:hover { border-color: var(--navy); background: var(--sky-100); }
.btn--light { background: var(--white); color: var(--navy); }
.btn--light { background: var(--navy); color: #fff; }
.btn--light:hover { background: var(--navy-700); }

/* ---------- top navigation ---------- */
.nav {
  position: sticky; top: 0; z-index: 200;
  border-bottom: 1px solid rgba(2,58,113,.08);
  transition: box-shadow var(--t) var(--ease);
}
/* pages carry their own embedded stylesheets; a stray centred rule reaching the
   header turned every dropdown into a column of centred text */
.nav, .nav__panel, .nav__item, .nav__formlink, .nav__feature, .nav__panel-head,
.footer, .footer__in, .footer__bar { text-align: left; }
/* the frosted-glass fill lives on a pseudo-element, not .nav itself: a
   backdrop-filter on .nav would make .nav a containing block for its own
   position:fixed descendants (the mobile menu overlay), collapsing it to
   the header's own height instead of the full viewport below it */
.nav::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: rgba(254,254,254,.9);
  -webkit-backdrop-filter: blur(14px) saturate(1.4); backdrop-filter: blur(14px) saturate(1.4);
}
.nav.is-scrolled { box-shadow: 0 2px 18px rgba(11,36,71,.09); }
.nav__in { display: flex; align-items: center; gap: 6px; min-height: 72px; }
.nav__logo img { width: 92px; height: auto; }
.nav__links { display: flex; align-items: center; gap: 2px; margin-left: 16px; }
.nav__links > div, .nav__group { position: relative; }
.nav__link {
  font-family: var(--font-head); font-weight: 500; font-size: 16.5px; color: var(--ink);
  text-decoration: none; padding: 10px 13px; border-radius: 10px;
  display: inline-flex; align-items: center; gap: 7px; line-height: 1.2; white-space: nowrap;
  transition: background-color var(--t) var(--ease), color var(--t) var(--ease);
  background: none; border: 0; cursor: pointer;
}
.nav__link:hover { background: var(--sky-100); color: var(--navy); }
.nav__link:focus-visible { outline: 3px solid var(--sky); outline-offset: 2px; }
/* open dropdown: the toggle becomes a solid pill so it is unmistakably the one
   that owns the panel below it (hover alone read as "nothing is selected") */
.nav__group.is-open > .nav__link { background: var(--navy); color: var(--white); }
.nav__group.is-open > .nav__link .nav__caret { transform: rotate(180deg); }
/* the plain links (Convention / News / Partners) answer hover the same way, so
   the whole bar reads with one vocabulary */
.nav__link:not(.nav__link--toggle):hover { background: var(--navy); color: var(--white); }
/* the section the visitor is currently in stays marked at all times */
.nav__link.is-current { color: var(--navy); font-weight: 600; box-shadow: inset 0 -3px 0 var(--crimson); border-radius: 10px 10px 4px 4px; }
.nav__group.is-open > .nav__link.is-current { color: var(--white); box-shadow: inset 0 -3px 0 var(--sky); }
.nav__caret { flex: 0 0 auto; transition: transform var(--t) var(--ease); }
.nav__panel {
  position: absolute; top: calc(100% + 10px); left: var(--panel-x, 0); min-width: 320px;
  background: var(--white); border: 1px solid rgba(2,58,113,.08); border-radius: var(--r-lg);
  box-shadow: var(--sh-lg); padding: 16px; display: none; z-index: 101;
  max-width: calc(100vw - 32px); max-height: min(calc(100vh - 96px), 760px); overflow: auto;
}
/* one panel at a time, and open state is the single source of truth: the old
   rules opened on :hover *and* :focus-within, so a clicked toggle stayed focused
   and its panel stayed open underneath whatever opened next. With JS the
   controller owns hover too, so Escape and click-to-close actually close.
   Without JS the pure-CSS hover/focus rules still expose every menu. */
.nav__group.is-open > .nav__panel { display: flex; gap: 18px; align-items: stretch; }
html:not(.js) .nav__group:hover > .nav__panel,
html:not(.js) .nav__group:focus-within > .nav__panel { display: flex; gap: 18px; align-items: stretch; }
/* the links sit on their own tinted plate inside the panel, so the menu reads as
   a designed surface rather than loose text floating on white */
.nav__itemgrid, .nav__formgrid {
  background: var(--sky-50); border: 1px solid var(--nav-rule); border-radius: 14px; padding: 8px;
}
/* item groups: the live site's labelled columns ("Who We Are" / "Events" /
   "Conventions") + a visually separated spotlight card. A 2-across list ran
   About's 16 links 8 rows deep and the panel scrolled inside itself; as
   short labelled columns every link is on screen and the grouping reads. */
/* nowrap deliberately: the panel is absolutely positioned, so its width is
   shrink-to-fit. A wrapping flex container reports one column as its intrinsic
   width, which collapses the whole panel to ~560px and stacks the columns. */
.nav__itemgrid {
  display: flex; align-items: stretch; gap: 0; min-width: 0;
}
.nav__col { flex: 1 1 0; min-width: 224px; padding: 4px 6px; }
.nav__col + .nav__col { border-left: 1px solid var(--nav-rule); }
.nav__col h5 {
  font-family: var(--font-head); font-weight: 700; font-size: 11.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--crimson); margin: 0 0 6px;
  padding: 0 8px 8px; border-bottom: 1px solid var(--nav-rule);
}
.nav__item {
  display: block; padding: 8px 12px; border-radius: 10px; text-decoration: none; color: var(--ink);
  border-bottom: 1px solid var(--nav-rule); position: relative;
  transition: background-color var(--t) var(--ease), box-shadow var(--t) var(--ease);
}
.nav__col > .nav__item:last-child { border-bottom: 0; }
.nav__item:hover, .nav__item:focus-visible { background: var(--sky-100); box-shadow: inset 3px 0 0 var(--navy); }
.nav__item.is-current { background: var(--sky-100); box-shadow: inset 3px 0 0 var(--crimson); }
.nav__item b { font-family: var(--font-head); font-weight: 600; font-size: 15.5px; display: block; color: var(--navy); line-height: 1.3; }
.nav__item span { font-size: 13.5px; color: var(--slate); line-height: 1.35; display: block; }
.nav__feature {
  flex: 0 0 240px; display: flex; flex-direction: column; gap: 8px; text-decoration: none;
  padding: 20px; border-radius: var(--r-md); color: var(--white);
  background: linear-gradient(160deg, var(--deep), var(--navy-700));
  border-left: 3px solid var(--sky); align-self: stretch;
}
.nav__feature-eyebrow { font-family: var(--font-head); font-size: 11.5px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--sky); }
.nav__feature b { font-family: var(--font-head); font-size: 17px; }
.nav__feature span:not(.nav__feature-eyebrow):not(.nav__feature-cta) { font-size: 14.5px; color: rgba(255,255,255,.86); line-height: 1.5; }
.nav__feature-cta { margin-top: auto; font-family: var(--font-head); font-weight: 600; font-size: 14.5px; color: var(--white); }
/* forms mega-panel: 21 links in a tidy multi-column list */
.nav__panel--forms { min-width: 1060px; flex-direction: column; gap: 0; }
.nav__group.is-open > .nav__panel--forms { display: flex; }
html:not(.js) .nav__group:hover > .nav__panel--forms,
html:not(.js) .nav__group:focus-within > .nav__panel--forms { display: flex; }
.nav__panel-head {
  font-family: var(--font-head); font-weight: 700; font-size: 15.5px; color: var(--navy);
  padding: 0 10px 8px; border-bottom: 1px solid rgba(2,58,113,.09); margin-bottom: 6px;
  display: flex; flex-direction: column; gap: 2px;
}
.nav__panel-head span { font-family: var(--font-body); font-weight: 400; font-size: 13.5px; color: var(--slate); text-transform: none; letter-spacing: 0; }
/* 21 forms in one flat list was a wall of text: they are clustered under labelled
   headings, with ruled columns so each cluster reads as its own section */
/* multi-column flow, not a 3×2 grid: on a grid every row was as tall as its
   tallest cluster, so short clusters left dead space under them */
/* 4 columns, not 3: at 3 the 21 links ran taller than the panel could show and
   the menu scrolled inside itself — the one thing these panels must never do */
.nav__formgrid {
  columns: 4; column-gap: 0; column-rule: 1px solid var(--nav-rule);
  display: block; min-width: 1000px;
}
.nav__formgroup { padding: 0 12px 14px; break-inside: avoid; -webkit-column-break-inside: avoid; }
.nav__formgroup h5 {
  font-family: var(--font-head); font-weight: 700; font-size: 11.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--crimson); margin: 0 0 8px;
  padding: 0 6px 8px; border-bottom: 1px solid var(--nav-rule);
}
.nav__formlink {
  display: block; padding: 7px 9px; border-radius: 8px; text-decoration: none;
  color: var(--ink); font-size: 14.5px; line-height: 1.35;
  transition: background-color var(--t) var(--ease), box-shadow var(--t) var(--ease);
}
.nav__formlink { display: flex; align-items: baseline; gap: 8px; justify-content: space-between; }
.nav__formlink > span:first-child { min-width: 0; }
.nav__formlink:hover, .nav__formlink:focus-visible { background: var(--sky-100); color: var(--navy); box-shadow: inset 3px 0 0 var(--navy); }
/* the year each form is actually for, from the form itself — a past year reads
   muted so a stale form is obvious next to a current one */
.formyear {
  flex: 0 0 auto; font-family: var(--font-head); font-weight: 700; font-size: 11.5px;
  letter-spacing: .04em; line-height: 1; padding: 5px 8px; border-radius: 999px;
  background: var(--sky-100); color: var(--navy); border: 1px solid rgba(2,58,113,.16);
}
.formyear.is-past { background: transparent; color: var(--slate); border-color: rgba(2,58,113,.18); }
/* badges sit together on the right so a gated form reads as one row, not two */
.nav__formmeta { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px; }
.nav__formmeta:empty { display: none; }
/* members-only: a lock, because these open the portal login rather than the
   form itself — the padlock is what warns you before you click */
.formlock {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border-radius: 999px;
  background: rgba(113,29,58,.08); color: var(--crimson);
  border: 1px solid rgba(113,29,58,.18);
}
.nav__formlink.is-gated:hover .formlock, .nav__formlink.is-gated:focus-visible .formlock {
  background: var(--crimson); color: #FEFEFE; border-color: var(--crimson);
}
.formitem h3 .formyear { vertical-align: middle; margin-left: 6px; }
.nav__spacer { flex: 1; }
/* action cluster: search + the three buttons share one row and one metric, so
   Log In / Join now / Donate Now are the same height and type size */
.nav__ctas { display: flex; align-items: center; gap: 10px; flex: 0 0 auto; }
.nav__search {
  display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px;
  border-radius: 999px; color: var(--navy); flex: 0 0 auto; border: 1.5px solid transparent;
  transition: background-color var(--t) var(--ease), border-color var(--t) var(--ease);
}
.nav__search:hover { background: var(--sky-100); border-color: rgba(2,58,113,.18); }
.nav__ctas .btn {
  min-height: 44px; height: 44px; padding: 0 20px; font-size: 15px; white-space: nowrap;
}
.nav__burger { display: none; background: none; border: 0; padding: 10px; cursor: pointer; border-radius: var(--r-sm); }
.nav__burger svg { display: block; }

/* laptop widths: the bar carries 7 sections + search + 3 buttons, so tighten the
   spacing before dropping to the burger rather than letting items collide */
@media (min-width: 1280px) and (max-width: 1439px) {
  .nav__link { font-size: 15.5px; padding: 10px 7px; }
  .nav__links { margin-left: 6px; gap: 0; }
  .nav__logo img { width: 84px; }
  .nav__ctas { gap: 6px; }
  .nav__ctas .btn { padding: 0 13px; font-size: 14.5px; }
  .nav__search { width: 40px; height: 40px; }
}

@media (max-width: 1279px) {
  .nav__in { flex-wrap: wrap; row-gap: 10px; padding-block: 10px; min-height: 0; }
  .nav__logo { margin-right: auto; }
  .nav__logo img { width: 84px; }
  .nav__spacer { display: none; }
  .nav__burger { display: block; }
  /* the action cluster dissolves so its four controls wrap as one row of header
     items: search + Log In ride beside the burger, the two CTAs take row two.
     As a nested flex row they stacked into three rows and made the bar 230px */
  .nav__ctas { display: contents; }
  .nav__logo { order: 1; }
  .nav__search { order: 2; width: 48px; height: 48px; }
  .nav__login { order: 3; }
  .nav__burger { order: 4; }
  .nav__ctas .btn--primary { order: 5; }
  .nav__ctas .btn--cta { order: 6; }
  .nav__ctas .btn--primary, .nav__ctas .btn--cta { flex: 1 1 42%; }
  .nav__links { order: 9; }
  .nav__ctas .btn { height: 48px; min-height: 48px; padding: 0 14px; }
  .nav__links {
    display: none; position: fixed; inset: var(--navH, 128px) 0 0 0; z-index: 99;
    background: var(--white); flex-direction: column; align-items: stretch; overflow: auto;
    padding: 16px 20px 40px; margin: 0; gap: 4px;
  }
  .nav__links.is-open { display: flex; }
  /* the drawer is an accordion: 62 links stacked open made it a mile-long scroll,
     and hover-to-open means nothing on touch */
  .nav__panel, html:not(.js) .nav__group:hover > .nav__panel { display: none; }
  .nav__group.is-open > .nav__panel, html:not(.js) .nav__group:focus-within > .nav__panel {
    position: static; display: flex; flex-direction: column; box-shadow: none; border: 0;
    padding: 4px 0 8px 12px; min-width: 0; max-width: none; max-height: none; gap: 8px;
  }
  /* the drawer stacks the columns; their headings stay, so the same grouping
     survives on touch. The vertical rules would hang off nothing here. */
  .nav__itemgrid { flex-direction: column; min-width: 0; }
  .nav__col + .nav__col { border-left: 0; border-top: 1px solid var(--nav-rule); margin-top: 6px; padding-top: 10px; }
  .nav__formgrid { columns: 1; column-rule: 0; min-width: 0; }
  .nav__formgroup { padding: 0 4px 14px; }
  .nav__feature { flex-basis: auto; }
  .nav__panel--forms, .nav__group.is-open > .nav__panel--forms { min-width: 0; }
  .nav__formgrid { grid-template-columns: 1fr; }
  .nav__link { font-size: 17.5px; padding: 12px 10px; width: 100%; text-align: left; justify-content: flex-start; }
  .nav__link .nav__caret { margin-left: auto; }
  .nav__group.is-open > .nav__link { background: var(--sky-100); color: var(--navy); }
}

/* Architects of Change ribbon */
.ribbon {
  background: linear-gradient(90deg, var(--maroon), var(--crimson));
  color: var(--white); font-family: var(--font-head); font-size: 14px;
  text-align: center; padding: 9px 42px; position: relative;
}
.ribbon a { color: var(--white); font-weight: 600; text-underline-offset: 3px; }
.ribbon__x { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); background: none; border: 0; color: var(--white); font-size: 18px; cursor: pointer; padding: 6px 10px; border-radius: 8px; }
.ribbon__x:hover { background: rgba(255,255,255,.15); }

/* ---------- heroes ---------- */
.hero { position: relative; color: var(--ink); overflow: clip; border-bottom: 1px solid rgba(2,58,113,.08); }
.hero__in { position: relative; z-index: 2; padding-block: clamp(76px, 10vw, 150px); }
/* a title-only hero has no image to stand next to, so the full-height padding
   just reads as an empty band above the first real section */
.hero:not(:has(.hero__media)) .hero__in { padding-block: clamp(52px, 6vw, 92px); }
.hero--home, .hero--plain, .hero--event, .hero--program, .hero--editorial {
  background:
    radial-gradient(1100px 480px at 88% -10%, rgba(148,197,248,.30), transparent 60%),
    linear-gradient(180deg, var(--white), var(--sky-50));
}
.hero--campaign {
  background:
    radial-gradient(1000px 480px at 85% -10%, rgba(139,21,56,.12), transparent 60%),
    linear-gradient(180deg, var(--white), var(--sky-50));
}
/* Ambient hero art. Every hero on the site is a short headline beside a single
   photograph, so on a wide screen the copy column is mostly bare paper — most of a
   1440px screen on the title-only pages. A slow drift of NDA-palette light over a
   fine dot field gives that space something to be. Decorative only: pointer-events
   off, painted below .hero__in (z-index 2), and held still on reduced motion.
   ::before deliberately — the coastal theme already owns .hero::after. */
.hero::before {
  content: ""; position: absolute; inset: -12% -8%; z-index: 0; pointer-events: none;
  background:
    radial-gradient(46% 54% at 15% 74%, rgba(148,197,248,.55), transparent 68%),
    radial-gradient(34% 44% at 41% 14%, rgba(2,58,113,.13), transparent 72%),
    radial-gradient(30% 38% at 3% 28%, rgba(139,21,56,.09), transparent 74%),
    radial-gradient(rgba(2,58,113,.15) 1.1px, transparent 1.2px) 0 0 / 24px 24px;
  -webkit-mask-image: radial-gradient(80% 88% at 26% 62%, #000 20%, transparent 76%);
  mask-image: radial-gradient(80% 88% at 26% 62%, #000 20%, transparent 76%);
  animation: heroAura 24s ease-in-out infinite alternate;
}
@keyframes heroAura {
  from { transform: translate3d(-1.5%, 1.5%, 0) scale(1); }
  to { transform: translate3d(2%, -2%, 0) scale(1.06); }
}
.hero h1 { color: var(--navy); }
.hero .lead { color: var(--slate); }
/* a media hero carrying nothing but a short title — see hero() in render.mjs for
   which heroes qualify and why */
.hero--bigtitle h1 { font-size: clamp(38px, 6.4vw, 92px); }
.hero__grid { display: grid; grid-template-columns: 1.05fr .95fr; gap: clamp(28px, 5vw, 64px); align-items: center; }
/* the crop sits low in the frame, not at `top`: NDA's photography is people shot
   with headroom — a graduate under an open sky, a stage lit from above — so
   anchoring the top of the file filled the slot with ceiling and cut the subject
   off at the chest. Skipping most of that headroom lifts the people up the frame. */
.hero__media img {
  border-radius: var(--r-xl); box-shadow: var(--sh-lg);
  width: 100%; height: clamp(360px, 38vw, 560px); object-fit: cover; object-position: center 58%; --framed: 1;
}
@media (max-width: 900px) { .hero__media img { height: min(56vw, 380px); } }
/* wide artwork (banners, flyers, app-instruction cards) keeps its own proportions
   instead of being cropped to the slot — see the heroFit measurement in render.mjs.
   Uncropped is not unbounded: a portrait poster (About Us ships a 2:3 one) grew the
   media column to 846px and, since the grid centres a two-line title beside it, left
   ~900px of empty paper down the left of the page. Capping the height keeps the whole
   artwork visible at a size the headline can stand next to, and the plate behind it
   gives a narrow image the width of the column instead of a gap either side. */
.hero__media--fit {
  display: grid; place-items: center; padding: clamp(16px, 2vw, 28px);
  border-radius: var(--r-xl);
  background: linear-gradient(155deg, rgba(148,197,248,.34), rgba(255,255,255,.62) 58%, rgba(2,58,113,.07));
  box-shadow: inset 0 0 0 1px rgba(2,58,113,.09);
  animation: heroFloat 9s ease-in-out infinite alternate;
}
.hero__media--fit img, .hero__media--fit img:where(*) {
  height: auto !important; object-fit: contain;
  width: auto !important; max-width: 100%; max-height: clamp(320px, 36vw, 500px); margin-inline: auto;
}
/* landscape artwork is the opposite problem to the portrait poster above. A 16:9
   photograph in the narrower half of a 1.05fr/.95fr grid is ~635px wide and so only
   ~357px tall, in a hero band the headline holds open to 560 — a shallow strip of
   picture with a whole column of white either side of it and above it, which is
   most of what a wide-screen visitor sees of the page. Wide files take the larger
   half of the grid and fill it edge to edge: same headline, same band, roughly
   twice the photograph. The plate shrinks to a hairline mount since there is no
   longer a gap for it to fill, and the height ceiling rises with the column so a
   wider image is still allowed to be a taller one. */
.hero__grid:has(.hero__media--wide) { grid-template-columns: minmax(0, .78fr) minmax(0, 1.22fr); }
.hero__media--wide { padding: clamp(8px, .9vw, 14px); }
.hero__media--wide img, .hero__media--wide img:where(*) {
  width: 100% !important; max-height: clamp(320px, 40vw, 620px);
}
@keyframes heroFloat { from { transform: translate3d(0, 6px, 0); } to { transform: translate3d(0, -6px, 0); } }
/* the inset: a second photograph from the same page, set into the gutter the hero
   used to leave empty. It reaches left of its own column so the composition runs
   across the hero instead of stopping at the halfway line. */
.hero__media { position: relative; }
.hero__inset {
  position: absolute; left: -16%; bottom: -7%; width: 46%; z-index: 2;
  border-radius: var(--r-lg); overflow: hidden;
  box-shadow: 0 22px 48px rgba(2,58,113,.22), 0 0 0 8px rgba(255,255,255,.92);
  animation: heroFloat 11s ease-in-out infinite alternate 1.4s;
}
.hero__inset img {
  width: 100% !important; height: clamp(140px, 15vw, 210px) !important;
  max-height: none !important; object-fit: cover; object-position: center 58%; --framed: 1;
  border-radius: 0; box-shadow: none; margin: 0;
}
@media (max-width: 900px) {
  .hero__inset { position: static; width: 66%; margin: -34px auto 0; display: block; }
  .hero__inset img { height: min(34vw, 170px) !important; }
}
.hero__actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 26px; }
.hero__meta { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 18px; }
/* counts lifted out of the page body (see heroStats in render.mjs) */
.hero__stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: clamp(14px, 1.6vw, 24px); margin: clamp(28px, 3vw, 44px) 0 0; max-width: 620px;
}
.hero__stat { border-top: 2px solid rgba(2,58,113,.16); padding-top: 14px; }
.hero__stat dt {
  font-family: var(--font-head); font-weight: 700; line-height: 1;
  font-size: clamp(30px, 3.4vw, 46px); color: var(--navy);
}
.hero__stat dd { margin: 8px 0 0; font-size: 14.5px; line-height: 1.45; color: var(--slate); }
.chip {
  font-family: var(--font-head); font-weight: 600; font-size: 14.5px;
  background: var(--sky-100); border: 1px solid rgba(2,58,113,.18);
  color: var(--navy); border-radius: 999px; padding: 7px 16px; display: inline-flex; gap: 8px; align-items: center;
}
/* the :has() selector above outweighs a bare .hero__grid, so the wide-art layout
   has to be unwound by name here or it survives into the single-column phone view */
@media (max-width: 900px) {
  .hero__grid, .hero__grid:has(.hero__media--wide) { grid-template-columns: 1fr; }
  .hero__media--wide img, .hero__media--wide img:where(*) { max-height: min(56vw, 380px); }
}
@media (prefers-reduced-motion: reduce) {
  .hero::before, .hero__media--fit { animation: none !important; }
}

/* ---------- cards & grids ---------- */
.grid { display: grid; gap: 22px; }
.grid--2 { grid-template-columns: repeat(2, 1fr); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
.grid--4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 991px) { .grid--3, .grid--4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 640px) { .grid--2, .grid--3, .grid--4 { grid-template-columns: 1fr; } }

.card {
  background: var(--white); border: 1px solid rgba(2,58,113,.08);
  border-radius: var(--r-lg); box-shadow: var(--sh-sm); overflow: hidden;
  display: flex; flex-direction: column;
}
a.card { text-decoration: none; color: inherit; transition: transform var(--t) var(--ease), box-shadow var(--t) var(--ease); }
a.card:hover { transform: translateY(-4px); box-shadow: var(--sh-lg); }
.card__media { aspect-ratio: 16/10; overflow: hidden; background: var(--sky-100); }
.card__media img { width: 100%; height: 100%; object-fit: cover; object-position: center top; }
/* partner cards: the mark fills the card's whole top half instead of floating as a
   90px thumbnail in the middle of it. contain rather than cover because these images
   run from wide wordmarks through square app icons to full site screenshots — cover
   would slice the ends off every wordmark. Whatever contain leaves over on one axis is
   filled by the same image, blown up and blurred behind it, so the media area still
   reads edge-to-edge on every card regardless of the source aspect ratio. */
.card__media--logo { position: relative; overflow: hidden; background: var(--white); }
.card__media--logo::before {
  content: ''; position: absolute; inset: -12%;
  background-image: var(--logo); background-size: cover; background-position: center;
  filter: blur(26px) saturate(1.15); opacity: .45; transform: scale(1.06);
}
.card__media--logo img {
  position: relative; object-fit: contain; object-position: center; padding: 0;
}
.card__body { padding: 22px; display: flex; flex-direction: column; gap: 8px; flex: 1; }
/* what the partner actually does, set larger than the company name it sits under —
   the name is the label, this is the pitch */
.card__tagline {
  font-family: var(--font-head); font-weight: 700;
  font-size: clamp(19px, 1.7vw, 22px); line-height: 1.18;
  letter-spacing: -0.01em; color: var(--navy); margin-top: -4px;
}
.card__body h3 { margin: 0; font-size: 19px; }
.card__body p { margin: 0; color: var(--slate); font-size: 15.5px; }
.card__foot { margin-top: auto; padding-top: 12px; font-family: var(--font-head); font-weight: 600; font-size: 14.5px; color: var(--crimson); }

.tile { background: var(--white); border-radius: var(--r-lg); border: 1px solid rgba(2,58,113,.08); box-shadow: var(--sh-sm); padding: 26px; }

/* stat tiles */
.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; }
@media (max-width: 900px) { .stats { grid-template-columns: repeat(2, 1fr); } }
.stat { text-align: center; padding: 26px 14px; border-radius: var(--r-lg); background: var(--white); border: 1px solid rgba(2,58,113,.12); box-shadow: var(--sh-sm); }
.stat b { font-family: var(--font-head); font-size: clamp(28px, 3vw, 40px); font-weight: 700; color: var(--navy); display: block; }
.stat span { font-size: 15px; color: var(--slate); }

/* logo rail */
.logos { display: flex; flex-wrap: wrap; gap: 18px 36px; align-items: center; justify-content: center; }
.logos img { max-height: 54px; width: auto; max-width: 150px; object-fit: contain; filter: grayscale(1) contrast(.85); opacity: .75; transition: filter var(--t) var(--ease), opacity var(--t) var(--ease); }
.logos img:hover { filter: none; opacity: 1; }

/* pillars (campaign) */
.pillars { display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; counter-reset: pillar; }
@media (max-width: 991px) { .pillars { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 600px) { .pillars { grid-template-columns: 1fr; } }
.pillar {
  counter-increment: pillar; background: var(--white);
  border: 1px solid rgba(2,58,113,.14); border-radius: var(--r-lg); padding: 26px 22px;
  box-shadow: var(--sh-sm);
  transition: transform var(--t) var(--ease), border-color var(--t) var(--ease), box-shadow var(--t) var(--ease);
}
.pillar:hover { transform: translateY(-4px); border-color: var(--sky); box-shadow: var(--sh-md); }
.pillar::before {
  content: "0" counter(pillar); font-family: var(--font-head); font-weight: 700; font-size: 15px;
  color: var(--navy); background: var(--sky-100); border-radius: 999px; padding: 4px 12px; display: inline-block; margin-bottom: 14px;
}
.pillar h3 { font-size: 19px; color: var(--navy); }

/* ---------- prose (re-housed page content) ---------- */
.prose { max-width: 76ch; margin-inline: auto; }
.prose--wide { max-width: none; }
/* full-bleed embed bands: see the .prose--bleed rules at the end of this file,
   which have to sit after the blanket max-width guard to land */
.prose h2 { margin-top: 1.6em; }
.prose h2:not(:first-child) { padding-top: .4em; }
.prose h3 { margin-top: 1.4em; }
.prose p { margin: 0 0 1.1em; }
.prose img { border-radius: var(--r-md); box-shadow: var(--sh-md); margin: 1.4em auto; }
.prose figure { margin: 1.6em 0; }
.prose figcaption { font-size: 14px; color: var(--slate); text-align: center; margin-top: 8px; }
/* Prose link styling must not reach a link that is already a button. `.prose a`
   (0,1,1) outranks `.cta-btn` / `.btn--primary` (0,1,0), so every button living
   inside imported body copy was repainted navy and underlined — including the
   white-on-navy pills in the career-centre and CTA panels, which then read navy
   on navy. (That failure is also what made the runtime guard repaint those
   buttons with a navy fill, turning one contrast bug into a worse one.)
   `:where()` holds the exclusion list at zero specificity, so this selector still
   weighs exactly what `.prose a` did and nothing else in the cascade shifts. */
   `.is-embed-btn` is added at build time by tagEmbedButtons() in render.mjs to
   any link the page's OWN stylesheet gives a background and a button shape —
   names like `.sg-logo-dl` carry neither "btn" nor "button", and enumerating
   them one incident at a time does not converge. */
.prose a:not(:where(.btn, .is-embed-btn, [class*="btn"], [class*="button"], [role="button"])) { color: var(--navy); text-decoration: underline; text-decoration-color: rgba(2,58,113,.35); text-underline-offset: 3px; }
.prose a:not(:where(.btn, .is-embed-btn, [class*="btn"], [class*="button"], [role="button"])):hover { color: var(--crimson); text-decoration-color: currentColor; }
.prose blockquote { border-left: 3px solid var(--crimson); margin: 1.6em 0; padding: .4em 0 .4em 1.2em; color: var(--slate); font-size: 1.05em; }
.prose ul, .prose ol { padding-left: 1.3em; margin: 0 0 1.2em; }
.prose li { margin-bottom: .4em; }
.prose iframe { border-radius: var(--r-md); box-shadow: var(--sh-md); margin: 1.4em auto; display: block; }
.prose hr { border: 0; border-top: 1px solid rgba(2,58,113,.12); margin: 2.4em 0; }
.prose table { border-collapse: collapse; width: 100%; font-size: 15px; }
.prose td, .prose th { border: 1px solid rgba(2,58,113,.14); padding: 10px 12px; text-align: left; }

/* legacy inline-styled embeds inherit the type system */
.prose [style*="font-family"] { font-family: var(--font-body) !important; }
.prose h1[style], .prose h2[style], .prose h3[style] { font-family: var(--font-head) !important; }

/* ---------- officer / partner profiles ---------- */
.profile { display: grid; grid-template-columns: 340px 1fr; gap: clamp(28px, 4vw, 56px); align-items: start; }
@media (max-width: 900px) { .profile { grid-template-columns: 1fr; } }
.profile__card { position: sticky; top: 96px; }
.profile__card img { border-radius: var(--r-lg); box-shadow: var(--sh-lg); width: 100%; object-fit: cover; }
.profile__office { margin-top: 14px; }

.person { text-align: left; }
.person .card__media { aspect-ratio: 4/4.6; }
.person .card__media img { object-position: top; }

/* ---------- gallery ---------- */
.masonry { columns: 3 300px; column-gap: 18px; }
.masonry img { border-radius: var(--r-md); margin-bottom: 18px; box-shadow: var(--sh-sm); width: 100%; cursor: zoom-in; transition: transform var(--t) var(--ease), box-shadow var(--t) var(--ease); }
.masonry img:hover { transform: scale(1.015); box-shadow: var(--sh-md); }

.lightbox { position: fixed; inset: 0; background: rgba(7,16,32,.9); display: none; align-items: center; justify-content: center; z-index: 300; padding: 4vmin; }
.lightbox.is-open { display: flex; }
.lightbox img { max-width: 92vw; max-height: 90vh; width: auto; height: auto; border-radius: var(--r-md); box-shadow: var(--sh-lg); }

/* ---------- generic modal (CRT teaser and any future data-modal-open target) ---------- */
.modal-overlay { position: fixed; inset: 0; background: rgba(7,16,32,.6); display: none; align-items: center; justify-content: center; z-index: 400; padding: 4vmin; }
.modal-overlay.is-open { display: flex; }
.modal-card {
  position: relative; background: var(--white); width: 100%; max-width: 640px; max-height: 88vh;
  overflow-y: auto; border-radius: var(--r-xl); box-shadow: var(--sh-lg); padding: 36px 34px 30px;
}
.modal-card__close {
  position: absolute; top: 14px; right: 14px; width: 34px; height: 34px; border-radius: 50%;
  border: 1px solid rgba(2,58,113,.14); background: var(--white); color: var(--navy);
  font-size: 20px; line-height: 1; cursor: pointer; display: flex; align-items: center; justify-content: center;
  transition: background 160ms var(--ease), transform 160ms var(--ease);
}
.modal-card__close:hover { background: var(--sky-50); transform: scale(1.05); }
.modal-card h3 { font-size: clamp(22px, 2.6vw, 28px); color: var(--deep); margin: 0 0 10px; padding-right: 30px; }
.modal-card > p { color: var(--slate); font-size: 15.5px; line-height: 1.6; margin: 0 0 22px; }

/* ---------- CTA band + footer ---------- */
.band {
  border-radius: var(--r-xl); padding: clamp(34px, 5vw, 64px);
  background: radial-gradient(700px 300px at 92% 0%, rgba(148,197,248,.28), transparent 60%), var(--white);
  border: 1px solid rgba(2,58,113,.12); border-left: 6px solid var(--navy);
  color: var(--ink); display: grid; grid-template-columns: 1.4fr auto; gap: 26px; align-items: center;
  box-shadow: var(--sh-md);
}
.band--maroon { border-left-color: var(--crimson); background: radial-gradient(700px 300px at 92% 0%, rgba(139,21,56,.10), transparent 60%), var(--white); }
.band h2 { margin: 0 0 6px; color: var(--navy); }
.band--maroon h2 { color: var(--crimson); }
.band p { margin: 0; color: var(--slate); }
.band__actions { display: flex; gap: 12px; flex-wrap: wrap; }
@media (max-width: 800px) { .band { grid-template-columns: 1fr; } }

.footer { background: linear-gradient(180deg, var(--deep), var(--deep-2)); color: rgba(255,255,255,.92); border-top: 3px solid var(--maroon); margin-top: var(--flow); }
.footer__in { display: grid; grid-template-columns: 1.3fr 1fr 1fr 1.2fr; gap: 32px; padding-block: clamp(44px, 6vw, 72px); }
@media (max-width: 900px) { .footer__in { grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px) { .footer__in { grid-template-columns: 1fr; } }
.footer h4 { color: var(--sky); font-size: 13.5px; letter-spacing: .12em; text-transform: uppercase; margin-bottom: 16px; }
.footer a { color: rgba(255,255,255,.92); text-decoration: none; display: block; padding: 6px 0; transition: color var(--t) var(--ease); font-size: 16px; }
.footer a:hover { color: var(--sky); }
.footer__brand img { width: 110px; margin-bottom: 14px; }
.footer__tag { font-size: 16px; color: rgba(255,255,255,.85); max-width: 30ch; }
/* brand + Get Involved share one column: as a fifth sibling the CTA wrapped to a
   second grid row and left a column-high void beside it */
.footer__brandcol { display: flex; flex-direction: column; gap: 30px; }
.footer__social { display: flex; gap: 10px; margin-top: 16px; }
.footer__social a {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; padding: 0; border-radius: 999px;
  background: rgba(255,255,255,.1); border: 1px solid rgba(148,197,248,.28); color: var(--white);
}
.footer__social a:hover { background: var(--sky); color: var(--deep); border-color: var(--sky); }
.footer__cta .footer__tag { margin-bottom: 14px; }
/* .footer a resets every link to a full-width block, which flattened the two CTA
   buttons: no padding, label jammed against the left edge. Every theme restates
   .footer a as well, so these have to outrank a themed `[data-theme] .footer a`
   — hence the extra class in the selector rather than a bare .footer .btn. */
.footer .footer__cta a.btn {
  display: inline-flex; width: 100%; max-width: 280px; padding: 12px 24px;
  margin-bottom: 10px; font-size: 15.5px;
}
.footer .footer__cta a.btn--cta { color: var(--white); }
.footer .footer__cta a.btn--light { background: var(--white); color: var(--navy); }
.footer .footer__cta a.btn--light:hover { background: var(--sky-100); color: var(--navy); }
.footer__bar { border-top: 1px solid rgba(148,197,248,.2); padding-block: 18px; font-size: 14.5px; display: flex; flex-wrap: wrap; gap: 10px 24px; justify-content: space-between; color: rgba(255,255,255,.8); }

/* ---------- hero slider ---------- */
.slider { position: relative; overflow: clip; background: linear-gradient(180deg, var(--white), var(--sky-50)); border-bottom: 1px solid rgba(2,58,113,.08); }
.slider__slide {
  position: absolute; inset: 0;
  opacity: 0; transition: opacity 500ms var(--ease); pointer-events: none;
}
.slider__slide.is-active { opacity: 1; pointer-events: auto; position: relative; }
.slider__grid {
  display: grid; grid-template-columns: 1.05fr .95fr; gap: clamp(24px, 4vw, 56px);
  align-items: center; padding-block: clamp(40px, 5vw, 72px) clamp(84px, 7vw, 110px);
}
.slider__photo img {
  width: 100%; height: clamp(360px, 44vw, 620px); object-fit: cover; object-position: center 58%; --framed: 1;
  border-radius: var(--r-xl); box-shadow: var(--sh-lg); background: var(--sky-100);
}
.slider__banner img { width: 100%; height: auto; object-fit: contain; border-radius: var(--r-lg); box-shadow: var(--sh-md); }
@media (max-width: 900px) { .slider__grid { grid-template-columns: 1fr; } .slider__photo img { height: min(52vw, 340px); } }
.slider__title { font-size: clamp(30px, 4.2vw, 54px); font-weight: 700; color: var(--navy); }
.slider__nav {
  position: absolute; left: 50%; transform: translateX(-50%); bottom: 26px; z-index: 5;
  display: flex; align-items: center; gap: 14px;
}
.slider__arrow {
  width: 48px; height: 48px; border-radius: 999px; cursor: pointer;
  /* white disc on the slider's white→sky-50 band: the border is the only thing
     separating the control from the surface, so it has to clear 3:1 on its own */
  background: var(--white); border: 1.5px solid rgba(2,58,113,.55); color: var(--navy);
  font-size: 18px; transition: background-color var(--t) var(--ease), border-color var(--t) var(--ease);
}
.slider__arrow:hover { background: var(--sky-100); border-color: var(--navy); }
.slider__dots { display: flex; gap: 8px; }
.slider__dot { width: 26px; height: 6px; border-radius: 999px; border: 0; cursor: pointer; background: rgba(2,58,113,.25); transition: background-color var(--t) var(--ease), width var(--t) var(--ease); padding: 0; }
.slider__dot.is-active { background: var(--crimson); width: 40px; }
.slider__count { font-family: var(--font-head); font-size: 15px; color: var(--slate); margin-left: 6px; }
.slider__count b { color: var(--navy); }
@media (max-width: 700px) { .slider__nav { bottom: 14px; } }

/* misc */
.backlink { font-family: var(--font-head); font-weight: 600; font-size: 14.5px; color: var(--navy); text-decoration: none; display: inline-flex; gap: 8px; align-items: center; margin-bottom: 20px; }
.backlink:hover { color: var(--crimson); }
.center { text-align: center; }
.mt-0 { margin-top: 0; } .mb-lg { margin-bottom: var(--flow-sm); }
::-webkit-scrollbar { width: 12px; }
::-webkit-scrollbar-track { background: var(--paper); }
::-webkit-scrollbar-thumb { background: #C6D4E8; border-radius: 8px; border: 3px solid var(--paper); }

/* ---------- sponsor banner slots (Adzerk/MultiView, as on the original) ---------- */
.adslot { display: flex; justify-content: center; padding: 14px 16px; }
.adslot > div { min-height: 0; }
.adslot img, .adslot iframe { max-width: 100%; }
.adslot--framed { background: var(--white); border-block: 1px solid rgba(2,58,113,.08); }

/* ---------- re-housed original structures: band rhythm ---------- */
/* A re-housed Webflow band arrives at padding:0 — the stylesheet that carried the
   page's vertical rhythm isn't part of the mirror — so its first heading prints on
   the boundary of whatever band sits above it. Which bands qualify is decided in
   render.mjs (see tagRehousedBands): a hand-built widget that already states its
   own spacing is never tagged, and only the outermost band of a stack is, so
   nothing compounds. */
.prose [data-band] { padding-block: var(--flow-sm); }

/* the booking link that replaces the dead Calendly loader — see repairCalendlySlot */
.prose .bookcta { display: flex; justify-content: center; margin-top: 26px; }

/* Webflow's two-up band — `_2-col_wrapper`, one picture beside one block of copy —
   ships `grid-template-columns: 1fr 1fr` in wf-layout.css and none of the
   breakpoint overrides that made it stack, because those lived in the per-page
   stylesheet the mirror doesn't carry. On a phone that leaves a 149px thumbnail
   next to a 149px column of text setting two words to the line. The generic
   stacking rule below can't reach it: this wrapper is neither a .w-layout-grid nor
   a `grid_*`. Stack it at the same breakpoint the rest of the page stacks at.
   (Only visible now that the picture is back in the band at all — until the hero
   stopped hoisting it, the cell it sits in was empty. See tierB's image picker.) */
@media (max-width: 720px) {
  .prose [class*="_2-col_wrapper"] { grid-template-columns: 1fr !important; }
}

/* ---------- re-housed original structures: grids & cards ---------- */
.prose .w-layout-grid, .prose [class*="grid_"] {
  display: grid; gap: 22px; align-items: stretch;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  margin: 1.6em 0;
}
.prose [class*="grid_"][class*="2-col"] { grid-template-columns: repeat(2, 1fr); }
.prose [class*="grid_"][class*="3-col"] { grid-template-columns: repeat(3, 1fr); }
.prose [class*="grid_"][class*="4-col"] { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 991px) {
  .prose [class*="grid_"][class*="3-col"], .prose [class*="grid_"][class*="4-col"] { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 640px) {
  .prose .w-layout-grid, .prose [class*="grid_"] { grid-template-columns: 1fr !important; }
}
/* :not([class*="whs2"]) throughout this generic-card family: the Women's
   Health Symposium page ships its own fully-styled, self-contained "whs2-*"
   BEM component (see the inline <style> in that page's content) whose class
   names happen to contain the plain English word "card" (whs2-awards-card,
   whs2-awards-card-img, whs2-awards-card-name). [class*="card"] matched them
   too and — at higher specificity than the widget's own rules — stamped a
   22px padding + white/bordered box onto an 80x80 avatar (shrinking the
   visible photo to ~36px) and onto the name text (an unwanted bordered pill
   around it). Generic Webflow-import styling must never leak into a
   hand-built embed's own namespace.

   Same story for the /events/nda-events page: it ships a self-contained hand-built
   homepage design rooted at .ndahome, whose event/news/district/CTA cards are
   full-bleed photo tiles (district-card, event-card-large, news-card-featured, …).
   The 22px padding + white box inset every photo away from its own card edge and
   left the caption gradients floating over bare card background. Excluding the
   whole .ndahome subtree — rather than adding a class name to the :not() list per
   card variant — keeps the embed's namespace sealed as new cards are added.

   And again for the /resources/2026-nda-awards embed rooted at #nda-awards: its
   honoree tile nests card-photo / card-body / card-award / card-name / card-detail
   inside .card, so [class*="card"] hit all five and drew a white bordered pill
   around every single line of text — eyebrow, name and role each in its own box,
   inside a bordered card-body box, inside the card. The embed resets margin/padding
   on its own descendants but not background/border/radius/shadow, so only the boxes
   leaked through. Sealed as a subtree for the same reason as .ndahome.

   ONE BOX PER CARD — the last two exclusions generalise all of the above.
   Naming a namespace per incident stopped scaling: a sweep of the built site found
   190 nested boxes across 48 of the 120 pages, and 30+ hand-built widgets style
   their own "…card…" classes. So the invariant is stated structurally instead:

     [data-selfstyled] *                        an embed that styles its own cards
                                                paints itself — render.mjs marks
                                                those embeds at build time, see
                                                sealSelfStyledEmbeds()
     [class*="card"]:not([class*="cards"]) *    a card box never sits inside another
     [class*="flex-block"] *                    card box (the outermost one wins)

   Stated as exclusions on this rule rather than as a later `!important` reset on
   purpose: a reset outranks the widgets' own declarations too. The first attempt
   did exactly that and erased the gradient scrim on #nda .img-small-card-overlay,
   dropping white caption text onto a photo. Excluded here, nothing is overridden —
   the embed's own CSS is simply the only thing painting inside it.

   The eight theme sheets carry the same exclusion list (they load after this file
   and repeat the rule at higher specificity); keep them in sync. */
.prose [class*="card"]:not([class*="cards"], [class*="whs2"], .ndahome *, #nda-awards *,
                       [data-selfstyled] *,
                       [class*="card"]:not([class*="cards"]) *, [class*="flex-block"] *) {
  background: var(--white); border: 1px solid rgba(2,58,113,.12);
  border-radius: var(--r-lg); box-shadow: var(--sh-sm); padding: 22px;
}
.prose [class*="card"]:not([class*="whs2"], .ndahome *, #nda-awards *, [data-selfstyled] *) img { border-radius: var(--r-md); margin: 0 0 14px; box-shadow: none; }
.prose [class*="card"]:not([class*="whs2"], .ndahome *, #nda-awards *, [data-selfstyled] *) h3, .prose [class*="card"]:not([class*="whs2"], .ndahome *, #nda-awards *, [data-selfstyled] *) h4 { color: var(--navy); }
.prose a[class*="card"]:not(.ndahome *, #nda-awards *) { text-decoration: none; transition: transform var(--t) var(--ease), box-shadow var(--t) var(--ease); display: block; }
.prose a[class*="card"]:not(.ndahome *, #nda-awards *):hover { transform: translateY(-3px); box-shadow: var(--sh-md); }
.prose [class*="flex_"] { display: flex; flex-wrap: wrap; gap: 20px; align-items: flex-start; }
.prose [class*="flex_"] > * { flex: 1 1 260px; }
/* In a COLUMN flex box that same 260px basis is a 260px-tall block, not a
   260px-wide one: the stat numerals and their captions each claimed 260px and
   the imported space-between shoved them to opposite ends of a 552px cell. */
.prose [class*="flex_vertical"] {
  flex-direction: column; flex-wrap: nowrap; gap: 12px;
  align-items: center; justify-content: center !important;
}
.prose [class*="flex_vertical"] > * { flex: 0 0 auto; max-width: 100%; }

/* grid photo cells tile edge-to-edge like the original galleries */
.prose [class*="grid_"] > img, .prose .w-layout-grid > img,
.prose [class*="grid_"] a > img, .prose .w-layout-grid a > img {
  margin: 0; width: 100%; height: 100%; object-fit: cover; object-position: center top;
  border-radius: var(--r-md);
}
/* …and the link that IS a cell fills it. Direct children only: unscoped, this
   reached every anchor anywhere inside a grid, so the inline "Email" link in a
   committee card became a block as tall as its own paragraph — a 130px hole between
   the chair's name and the description, in 13 cards at once. */
.prose [class*="grid_"] > a, .prose .w-layout-grid > a { display: block; height: 100%; }
/* prose flow text stays left-aligned unless the source centers it */
.prose--flow { text-align: left; }

/* photo-collage columns: compact tiles, not photo towers */
.prose .w-layout-grid[class*="grid_1-col"] { gap: 16px; align-content: start; }
.prose .w-layout-grid[class*="grid_1-col"] > img {
  height: clamp(240px, 26vw, 380px) !important;
  object-fit: cover; object-position: center top;
  border-radius: var(--r-md); margin: 0;
}
/* two-column feature rows: keep the text vertically centered next to media */
.prose [class*="grid_2-col"] { align-items: center; }

/* ---------- embedded-widget legibility guards (2026-07-25 contrast sweep) ----------
   career-center widget: original text colors assume the old dark backdrop, but the
   cards render light in v2 — force readable ink/slate inside the light cards */
.nda-career-widget .feature-description,
.nda-career-widget .job-title,
.nda-career-widget .job-description,
.nda-career-widget .featured-job-details { color: var(--ink) !important; }
.nda-career-widget .job-employer,
.nda-career-widget .job-location { color: var(--slate) !important; }
/* instagram embed pre-hydration placeholder: readable slate instead of faint gray
   (class is stripped at extraction — target the data attribute instead) */
[data-instgrm-permalink], [data-instgrm-permalink] p, [data-instgrm-permalink] a,
[data-instgrm-permalink] div { color: var(--slate) !important; }

/* ---------- natural-large photos + compact link grids (2026-07-25 user pass) ----------
   image-only cards render as full-bleed covers — the original ran a Webflow
   width/background interaction on these (ix_card-change-width-background) */
.prose [class*="ix_card"] { padding: 0 !important; overflow: hidden; }
.prose [class*="ix_card"] {
  display: flex; align-items: center; justify-content: center;
  background: transparent; border: 0 !important; box-shadow: none !important; padding: 0 !important;
  align-self: center;
}
.prose [class*="ix_card"] img, .prose [class*="ix_card"] a > img {
  width: 100%; height: auto !important; max-height: clamp(320px, 40vw, 620px);
  object-fit: contain; margin: 0; border-radius: var(--r-lg);
  box-shadow: var(--sh-md);
}
/* "A card whose only child is a photo IS the photo" — but `[class*="card"]` also
   matches Webflow utility classes that only sound like cards. `radius_card` is a
   corner-radius utility, and on the two overlay bands that use it the single child
   is not the card's picture at all: it is an `.overlay_opacity-*` image, which
   wf-layout.css takes out of flow (`position:absolute; inset:0`) to sit BEHIND the
   heading and copy laid over it.

   Treating that as an image-only card broke both bands the same way. The wrapper
   took `align-self:center`, so instead of stretching to the row the copy had
   already sized it collapsed to its content — and an absolute child contributes no
   height. The image then took `height:auto`, which for an out-of-flow replaced
   element resolves to its intrinsic 1872px, capped by the `max-height` clamp to
   620px, and `overflow:hidden` on the collapsed wrapper sliced that down to a
   ~50px band floating in the middle of the paragraph. That is the bar cutting
   through the text on /nda-programs/eddie-g-smith-leadership-institute.

   An out-of-flow overlay image is never the "just the photo" case, so exclude it
   by the class that puts it out of flow. Genuine image-only cards — card-photo (64)
   and card_body_small-5 (22) — are untouched; this changes 2 elements site-wide. */
.prose [class*="card"]:not([class*="cards"], [class*="whs2"], .ndahome *, #nda-awards *,
                       [data-selfstyled] *,
                       [class*="card"]:not([class*="cards"]) *, [class*="flex-block"] *):has(> img:only-child):not(:has(> img[class*="overlay_"])) { padding: 0; overflow: hidden; }
.prose [class*="card"]:not([class*="cards"], [class*="whs2"], .ndahome *, #nda-awards *,
                       [data-selfstyled] *,
                       [class*="card"]:not([class*="cards"]) *, [class*="flex-block"] *) > img:only-child:not([class*="overlay_"]) {
  width: 100%; height: auto; max-height: clamp(320px, 40vw, 620px);
  object-fit: contain; margin: 0; border-radius: var(--r-md);
}
/* a photo card is just the photo: centred beside its text, no empty box around it */
.prose [class*="grid_2-col"] > [class*="ix_card"],
.prose [class*="grid_2-col"] > [class*="card"]:has(> img:only-child):not(:has(> img[class*="overlay_"])) { align-self: center; }
.prose [class*="card"]:not([class*="cards"], [class*="whs2"], .ndahome *, #nda-awards *,
                       [data-selfstyled] *,
                       [class*="card"]:not([class*="cards"]) *, [class*="flex-block"] *):has(> img:only-child):not(:has(> img[class*="overlay_"])) {
  background: transparent; border: 0; box-shadow: none; padding: 0; align-self: center;
}
.prose [class*="card"]:not([class*="cards"], [class*="whs2"], .ndahome *, #nda-awards *,
                       [data-selfstyled] *,
                       [class*="card"]:not([class*="cards"]) *, [class*="flex-block"] *) > img:only-child:not([class*="overlay_"]) { border-radius: var(--r-lg); box-shadow: var(--sh-md); }
/* …and the same seal for the base .prose img chrome. The embed frames its own photos
   (the tile carries the radius + overflow:hidden), so prose's 1.4em auto margin,
   corner radius and drop shadow only fought it — that margin is what floated each
   district/event/news photo off its tile even once the card padding was excluded. */
/* `[data-selfstyled]` belongs on that list for the same reason the two named
   embeds do, and its absence was visible: the sponsor logos on
   /news/nda-on-the-hill sit in white cards the embed draws itself (16px radius,
   1.5px sky border, its own shadow) and prose then drew a second 14px radius and
   drop shadow around the logo inside each one — a box inside a box, in a band
   whose whole job is to present two marks cleanly. */
.prose .ndahome img, .prose #nda-awards img,
.prose [data-selfstyled] img { margin: 0; border-radius: 0; box-shadow: none; }
/* nested link grids pack to the top instead of stretching rows apart */
.prose .w-layout-grid .w-layout-grid { align-content: start; row-gap: 18px; }
/* in-flow content h1s (mid-page section headings) render at the original's scale —
   hero h1s live outside .prose and keep the large clamp */
.prose h1 { font-size: clamp(30px, 3.6vw, 44px); }
/* career widget "View All Jobs" link carries inline white — force readable navy on the light card.
   Scoped away from the pill buttons in the same widget: they sit on the dark
   maroon→navy panel, where navy lettering disappears. */
.nda-career-widget a[href*="careerwebsite"]:not(:where(.cta-btn, [class*="btn"])) { color: var(--navy) !important; }

/* ---------- Architects of Change campaign goal meter ---------- */
.goalmeter { margin: 22px 0 6px; max-width: 560px; }
.goalmeter__head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 10px; font-family: var(--font-head); }
.goalmeter__head b { font-size: 22px; color: var(--navy); font-weight: 700; }
.goalmeter__head span { font-size: 14.5px; color: var(--slate); font-weight: 500; }
.goalmeter__track {
  height: 18px; border-radius: 999px; background: var(--sky-100);
  border: 1px solid rgba(2,58,113,.14); overflow: hidden;
  box-shadow: inset 0 1px 3px rgba(11,36,71,.08);
}
.goalmeter__fill {
  height: 100%; width: 0; border-radius: 999px;
  background: linear-gradient(90deg, var(--maroon), var(--crimson));
  position: relative; overflow: hidden;
  transition: width 1600ms cubic-bezier(.22,.8,.32,1);
}
.goalmeter.is-inview .goalmeter__fill { width: var(--goal, 0%); }
.goalmeter__fill::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(115deg, transparent 30%, rgba(255,255,255,.35) 50%, transparent 70%);
  background-size: 220% 100%; animation: goalshimmer 2.6s linear infinite;
}
@keyframes goalshimmer { from { background-position: 130% 0; } to { background-position: -90% 0; } }
@media (prefers-reduced-motion: reduce) {
  .goalmeter__fill { transition: none; width: var(--goal, 0%); }
  .goalmeter__fill::after { animation: none; }
}

/* ---------- button micro-animations (every button family, all themes inherit) ---------- */
.btn, .w-button, .ex-btn, .ex-btn-p, .nc-btn, .cta-btn, .nda-wwd__button,
.nda-modal-button, .job-apply-btn, .follow-button, .slider__arrow, .backlink {
  transition: transform 200ms var(--ease), box-shadow 200ms var(--ease),
              background-color 200ms var(--ease), color 200ms var(--ease),
              border-color 200ms var(--ease), filter 200ms var(--ease);
  will-change: transform;
}
.w-button:hover, .ex-btn:hover, .ex-btn-p:hover, .nc-btn:hover, .cta-btn:hover,
.nda-wwd__button:hover, .nda-modal-button:hover, .job-apply-btn:hover, .follow-button:hover {
  transform: translateY(-2px); box-shadow: 0 8px 22px rgba(11,36,71,.18);
}
.btn:active, .w-button:active, .ex-btn:active, .ex-btn-p:active, .nc-btn:active,
.cta-btn:active, .nda-wwd__button:active, .nda-modal-button:active, .job-apply-btn:active,
.follow-button:active { transform: translateY(0) scale(.975); box-shadow: 0 2px 8px rgba(11,36,71,.14); }
.btn--cta, .cta-btn { position: relative; overflow: hidden; }
.btn--cta::after, .cta-btn::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(115deg, transparent 35%, rgba(255,255,255,.28) 50%, transparent 65%);
  background-size: 240% 100%; background-position: 130% 0;
  transition: background-position 600ms var(--ease);
}
.btn--cta:hover::after, .cta-btn:hover::after { background-position: -110% 0; }
@media (prefers-reduced-motion: reduce) {
  .btn--cta::after, .cta-btn::after { display: none; }
  .btn:hover, .w-button:hover, .ex-btn:hover, .nc-btn:hover, .cta-btn:hover { transform: none; }
}

/* ============================================================
   Semantic classes carried over from the original markup.
   These elements (stat numerals, section eyebrows, inline buttons,
   small print) arrive with no other styling hook — without these
   rules they render as plain body text.
   ============================================================ */

/* big statistic numerals ("3,000+", "31", "112") */
.prose [class*="heading_huge"] {
  font-family: var(--font-head); font-size: clamp(52px, 6.4vw, 96px); font-weight: 600;
  line-height: 1.02; letter-spacing: -.03em; color: var(--deep); margin: 0 0 8px;
}
/* in-content heading levels */
.prose [class*="heading_h1"] { font-family: var(--font-head); font-size: clamp(30px, 3.6vw, 44px); font-weight: 700; line-height: 1.15; color: var(--navy); margin: 0 0 .4em; }
.prose [class*="heading_h2"] { font-family: var(--font-head); font-size: clamp(26px, 3.2vw, 38px); font-weight: 700; line-height: 1.18; color: var(--navy); margin: 0 0 .4em; }
.prose [class*="heading_h3"] { font-family: var(--font-head); font-size: clamp(20px, 2.2vw, 26px); font-weight: 600; line-height: 1.25; color: var(--navy); margin: 0 0 .4em; }
.prose [class*="heading_h4"] { font-family: var(--font-head); font-size: clamp(18px, 1.7vw, 21px); font-weight: 600; line-height: 1.3; color: var(--navy); margin: 0 0 .4em; }
.prose [class*="heading_h6"] { font-family: var(--font-head); font-size: 16px; font-weight: 600; color: var(--navy); margin: 0 0 .4em; }

/* section eyebrows / kickers */
.prose [class^="eyebrow"], .prose [class*=" eyebrow"] {
  font-family: var(--font-head); font-weight: 600; font-size: 13px;
  letter-spacing: .14em; text-transform: uppercase; color: var(--crimson);
  display: inline-flex; align-items: center; gap: 10px; margin-bottom: 12px;
}
.prose [class^="eyebrow"]::before, .prose [class*=" eyebrow"]::before {
  content: ""; width: 26px; height: 2px; background: var(--crimson); border-radius: 2px;
}
/* sub-headline under a section title */
.prose [class*="subheading"] { font-size: clamp(17px, 1.5vw, 20px); color: var(--slate); max-width: 62ch; }
.prose [class*="paragraph_small"] { font-size: 15.5px; line-height: 1.65; color: var(--slate); }

/* inline buttons from the original ("See all", "Learn more" …) — the
   button-group-* wrappers are containers, not buttons */
.prose a[class*="button"]:not([class*="button-group"]):not([class*="button_icon"]) {
  font-family: var(--font-head); font-weight: 600; font-size: 15.5px;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 48px; padding: 12px 26px; border-radius: 999px;
  background: var(--navy); color: var(--white); text-decoration: none;
  border: 1.5px solid transparent; cursor: pointer;
  transition: transform 200ms var(--ease), box-shadow 200ms var(--ease), background-color 200ms var(--ease);
}
.prose a[class*="button"]:not([class*="button-group"]):not([class*="button_icon"]):hover {
  background: var(--navy-700); transform: translateY(-2px); box-shadow: 0 8px 22px rgba(11,36,71,.18);
}
.prose [class*="button-group"] { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }
.prose [class*="button_label"] { font: inherit; color: inherit; }
.prose [class*="text-button"] {
  font-family: var(--font-head); font-weight: 600; color: var(--navy);
  text-decoration: underline; text-underline-offset: 4px;
}

/* stat trio: give the numeral + caption pairs real card presence */
.prose [class*="grid_3-col"] > [class*="flex_vertical"] { padding-right: 18px; }
.prose [class*="flex_vertical"] > [class*="heading_huge"] + p { margin-top: 0; }
@media (max-width: 600px) {
  .prose [class*="heading_huge"] { font-size: clamp(44px, 13vw, 60px); }
}

/* ---------- original interactive components in the redesign language ---------- */
/* tabbed switchers (membership plan billing, category filters) */
.w-tab-menu {
  display: inline-flex; flex-wrap: wrap; gap: 6px; padding: 6px;
  background: var(--sky-100); border-radius: 999px; border: 1px solid rgba(2,58,113,.12);
}
.w-tab-link {
  font-family: var(--font-head); font-weight: 600; font-size: 14.5px;
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; padding: 10px 22px; border-radius: 999px;
  color: var(--navy); background: transparent; text-decoration: none; cursor: pointer;
  transition: background-color 200ms var(--ease), color 200ms var(--ease), box-shadow 200ms var(--ease);
}
.w-tab-link:hover { background: rgba(255,255,255,.7); }
.w-tab-link.w--current, .w-tab-link.w--current * { color: var(--white) !important; }
.w-tab-link.w--current { background: var(--navy); box-shadow: var(--sh-sm); }
/* `.prose a { text-decoration: underline }` outranks the bare .w-tab-link rule
   above, so every pill in a tab switcher rendered underlined. */
.prose a.w-tab-link, .prose a.w-tab-link:hover { text-decoration: none; }
.w-tab-link div { text-decoration: none; }
.w-tab-content { width: 100%; }
.w-tab-pane { display: none; }
.w-tab-pane.w--tab-active { display: block; }

/* plan / feature cards inside those panes — outermost only, never card-in-card.
   `.tiertile` opts out: the membership tiers carry their own surface, padding and
   hover further down this file, and this rule's `:not()` list ends in
   `#nda-awards *`, which lends the whole selector ID-level specificity (1,4,0) —
   more than any plain class selector written after it can answer. Excluding the
   tile here is the only way a later rule gets to paint it.

   (That specificity is also why these tiles are `.tiertile` and not `.tiercard`:
   `[class*="card"]` would have matched, and the generic card family's h3 rule —
   `.prose [class*="card"]:not(…, #nda-awards *, …) h3` — repainted every tier
   header navy-on-navy. v2.js's contrast sweep then found the failing pair and
   flattened the header's gradient to a pale blue to rescue it, so the cards
   arrived washed out with no way to tell from the stylesheet why.) */
.w-tab-pane [class*="flex-block"]:not([class*="flex-block"] *, [data-selfstyled] *, [class*="card"]:not([class*="cards"]) *, .tiertile),
.prose [class*="flex-block"]:not([class*="flex-block"] *, [data-selfstyled] *, [class*="card"]:not([class*="cards"]) *, .tiertile) {
  background: var(--white); border: 1px solid rgba(2,58,113,.10);
  border-radius: var(--r-lg); box-shadow: var(--sh-sm); padding: 26px 22px;
  transition: transform 200ms var(--ease), box-shadow 200ms var(--ease);
}
.w-tab-pane [class*="flex-block"]:not([class*="flex-block"] *, [data-selfstyled] *, [class*="card"]:not([class*="cards"]) *, .tiertile):hover,
.prose [class*="flex-block"]:not([class*="flex-block"] *, [data-selfstyled] *, [class*="card"]:not([class*="cards"]) *, .tiertile):hover {
  transform: translateY(-3px); box-shadow: var(--sh-md);
}
.w-tab-pane [class*="flex-block"] h3, .prose [class*="flex-block"] h3 { color: var(--navy); }

/* ---------- roster cards: leadership, office staff (Webflow `.team4_*`) ----------
   Three faults, all visible at once on /about/leadership:

   1. Every portrait was stretched. `.team4_image` forces `aspect-ratio: 2/3` with
      `object-fit: fill`, and not one of the 29 files is 2:3 — they run 0.69–0.75
      (3:4 camera frames). Filling that box squeezes each face ~7–12% narrower than
      the person is. `cover` at the ratio the files actually are ends the distortion
      and crops nothing worth keeping.
   2. There was no card. The photo, the name and the button sat as three loose
      blocks on white paper, so the button read as belonging to the page rather than
      to the person above it. A padded surface puts the action inside the card.
   3. The button landed wherever the name happened to end. In a stretched grid row
      that put four buttons at four different heights — and the one card carrying a
      second button (Executive Director → Calendly) pushed its whole row 48px taller
      while its neighbours kept their buttons floating mid-card. Pinning the button
      block to the bottom of the card lines the row up whatever each card holds. */
.prose .team4_item {
  height: 100%;
  background: var(--white); border: 1px solid rgba(2,58,113,.10);
  border-radius: var(--r-lg); padding: 14px 14px 16px; box-shadow: var(--sh-sm);
  align-items: stretch;
  transition: transform 200ms var(--ease), box-shadow 200ms var(--ease);
}
.prose .team4_item:hover { transform: translateY(-3px); box-shadow: var(--sh-md); }
.prose .team4_image-wrapper { border-radius: 14px; overflow: hidden; }
.prose .team4_image {
  aspect-ratio: 3 / 4; width: 100%; height: auto; display: block;
  object-fit: cover; object-position: center 20%; --framed: 1;   /* headroom, never chins */
  border-radius: 14px;
}
/* the action block sits on the card floor; a second link stacks under the first */
.prose .team4_item > a { margin-top: auto; width: 100%; }
.prose .team4_item > a + a { margin-top: 8px; }
/* …and the second one is not a second primary. Two identical navy pills gave
   "View Bio" and "Schedule A Call" equal weight, so the card asked its reader to
   choose between two identical-looking buttons. The secondary is the same shape in
   outline — one obvious primary, one clearly optional companion. Specificity has to
   clear `.prose a[class*="button"]…` (0,4,1), hence the doubled attribute match. */
.prose .team4_item > a[class*="button"] + a[class*="button"] {
  background: var(--white); color: var(--navy); border-color: rgba(2,58,113,.30);
}
.prose .team4_item > a[class*="button"] + a[class*="button"]:hover {
  background: var(--sky-100); color: var(--navy); border-color: var(--navy);
}

/* ---------- membership tier grid (/membership/membership, /membership/join-us) ----------
   The original is a three-track grid (wf-layout `.grid-2`); the generic auto-fit
   rule above re-flowed it to four ~305px tracks, narrower than the tier cards'
   own content. At that width the Annual / N-Payments switcher wrapped onto two
   rows, every CTA label broke across two lines, and "Affiliate/International"
   split mid-word. The cards also inherit justify-content:center from
   `.flex-block`, so each one centred its content independently and nothing lined
   up across a row — prices, feature lists and buttons all sat at different
   heights, and the tallest card (Life Membership, ~1,000 characters of
   eligibility requirements) stretched its row to 1,300px, leaving its three
   neighbours mostly empty.

   `.tiergrid`/`.tiertile` are stamped on in render.mjs (tagTierCards) off the
   same test this used to re-derive per selector — a grid holding a price
   switcher — so the partner and benefit grids in the sibling panes keep the
   generic grid treatment. Flex rather than grid so a short final row centres
   instead of hanging off the left edge, and so the Life Membership panel can
   take a full row of its own.

   The cards themselves were eight identical sheets of white paper: a centred
   name, a price, a centred column of grey feature text and a button. Nothing on
   them said which tier the page wants to sell, the "Non Member" card was two
   words and a button over ~250px of blank paper, and Life Membership — the only
   tier you apply for rather than buy — read exactly like the seven you can buy
   with a card. Each of those three now states itself: a painted header cap and a
   display-size price for the priced tiers, the word Free at display size for the
   ones whose whole offer is that word, a ribboned emphasis on General Member,
   and a dark gold-ruled panel for Life Membership. */
.prose .tiergrid {
  display: flex !important;
  flex-wrap: wrap;
  justify-content: center;
  align-items: stretch;
  gap: 26px;
}
/* `[class*="flex-block"]` on the selector, and on every rule below that states a
   max-width: the blanket overflow guard near the end of this file,
   `.prose *:not(.photowall):not(.photowall *)`, weighs (0,3,0) and sets
   max-width:100%. A three-class selector ties it and loses on source order, so a
   plain `.prose .tiergrid > .tiertile { max-width: 420px }` never landed and the
   last card of a row stretched to the full 1,324px container. Same trap the
   pubitem and progress-meter caps below already document. */
.prose .tiergrid > .tiertile[class*="flex-block"] {
  position: relative; isolation: isolate; overflow: hidden;
  flex: 1 1 340px;          /* 340px is the narrowest a tier card fits its own CTA label at */
  max-width: 420px;
  width: auto;              /* beats the generic `.prose .w-layout-grid > * { width: 100% }` */
  justify-content: flex-start;
  align-items: stretch;
  text-align: center;
  gap: 12px;
  padding: 0 26px 28px;     /* 0 at the top: the header cap runs edge to edge */
  background: linear-gradient(180deg, var(--white) 0%, var(--sky-50) 100%);
  border: 1px solid rgba(2,58,113,.10);
  border-radius: var(--r-xl);
  box-shadow: var(--sh-sm);
}

/* ---- the header cap: the tier's name, painted, full-bleed across the card top */
.prose .tiergrid > .tiertile > h2,
.prose .tiergrid > .tiertile > h3 {
  display: flex; align-items: center; justify-content: center;
  position: relative; z-index: 1;
  min-height: 3.15em; margin: 0 -26px 6px; padding: 20px 20px 18px;
  /* the cap is the card's two side paddings wider than the content box it sits
     in; stated rather than left to `align-items: stretch`, because the same
     blanket `max-width: 100%` guard would otherwise clamp it back to the content
     width and the painted band would stop 52px short of the card's right edge */
  width: calc(100% + 52px); max-width: none;
  font-size: clamp(20px, 1.8vw, 24px); font-weight: 700; line-height: 1.2;
  color: var(--white);
  background: linear-gradient(135deg, var(--deep) 0%, var(--navy) 58%, #0C5395 100%);
  border-radius: var(--r-xl) var(--r-xl) 0 0;
}
/* a soft light source in the top-left corner of the cap, so eight caps in a row
   read as moulded surfaces rather than eight flat swatches of the same blue */
.prose .tiergrid > .tiertile > h2::after,
.prose .tiergrid > .tiertile > h3::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: radial-gradient(120% 140% at 12% 0%, rgba(148,197,248,.34), transparent 62%);
  transition: opacity 420ms var(--ease); opacity: .9;
}

/* ---- the price block */
.prose .tiergrid [class*="text-block-37"] { padding-top: 0; color: var(--slate); font-size: 15.5px; }
.prose .tiergrid [class*="div-block-108"] { display: block; }
.prose .tiergrid [class*="div-block-108"] > h2 {
  margin: 0; line-height: .95; letter-spacing: -.035em;
  font-size: clamp(42px, 4.2vw, 56px); font-weight: 700; color: var(--deep);
  transition: transform 420ms var(--spring);
}
.prose .tiergrid [class*="div-block-108"] > [class*="text-block-38"] {
  margin-top: 6px; font-family: var(--font-head); font-weight: 600; font-size: 12.5px;
  letter-spacing: .12em; text-transform: uppercase; color: var(--slate);
}
/* the Annual / N-Payments switcher, on a track so the inactive pill reads as the
   other half of one control rather than as a second button */
.prose .tiergrid [class*="tabs-menu"] {
  flex-wrap: nowrap; justify-content: center; gap: 4px;
  padding: 4px; border-radius: 999px; background: rgba(2,58,113,.06);
}
/* "3 Payments" broke after "3" on a phone, so the two halves of the switcher sat
   at different heights and the track read as two mismatched buttons */
.prose .tiergrid [class*="tabs-menu"] .w-tab-link { white-space: nowrap; }
@media (max-width: 420px) {
  .prose .tiergrid [class*="tabs-menu"] .w-tab-link { padding-inline: 16px; font-size: 14.5px; }
}
.prose .tiergrid [class*="flex-block-4"] { margin-top: 4px; }
.prose .tiergrid .list:empty { display: none; }
/* the instalment breakdown reads as a small statement, not as body copy */
.prose .tiergrid [class*="flex-block-2"] {
  margin-top: 14px; padding-top: 12px; border-top: 1px dashed rgba(2,58,113,.18);
  font-size: 14.5px;
}
.prose .tiergrid [class*="flex-block-3"] { justify-content: space-between; }
.prose .tiergrid .text-block-38-total { font-weight: 700; color: var(--deep); }

/* ---- feature list: ticks down a left-aligned column. Centred grey lines with no
   markers were four to eight rows of ragged text that no eye could scan across
   cards; a tick and a common left edge make the rows comparable tier to tier. */
.prose .tiergrid .list { list-style: none; margin: 0; padding: 0; text-align: left; }
.prose .tiergrid .list li { margin: 0; padding: 0; }
.prose .tiergrid .list li > [class*="text-block-38"] {
  position: relative; padding-left: 27px; margin: 0 0 9px;
  font-size: 15px; line-height: 1.45; color: var(--slate); text-align: left;
}
.prose .tiergrid .list li > [class*="text-block-38"]::before {
  content: ""; position: absolute; left: 0; top: .18em;
  width: 17px; height: 17px; border-radius: 50%;
  background: var(--sky-100) center / 10px 10px no-repeat
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M1.5 6.4l3 3 6-6.6' fill='none' stroke='%23023A71' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
/* every CTA lands on the card's baseline, whatever sits above it. `order` because
   the Non-Member card lists its "Free" caption *after* the button in the source. */
.prose .tiergrid > .tiertile > a[class*="button"] {
  order: 1; margin-top: auto; width: 100%;
  padding: 13px 18px; white-space: normal;
  box-shadow: 0 6px 18px rgba(2,58,113,.16);
}

/* ---- the tier the page exists to sell. A ribbon plus a deeper card: an emphasis
   a reader can find without reading all eight prices first. */
.prose .tiergrid > .tiertile[data-featured] {
  border-color: rgba(139,21,56,.30);
  box-shadow: 0 10px 34px rgba(11,36,71,.14);
}
.prose .tiergrid > .tiertile[data-featured] > h2,
.prose .tiergrid > .tiertile[data-featured] > h3 {
  background: linear-gradient(135deg, var(--maroon) 0%, var(--crimson) 62%, #A11B45 100%);
}
.prose .tiergrid > .tiertile[data-featured] > h2::after,
.prose .tiergrid > .tiertile[data-featured] > h3::after {
  background: radial-gradient(120% 140% at 12% 0%, rgba(255,255,255,.26), transparent 62%);
}
.prose .tiergrid > .tiertile[data-featured]::before {
  /* 45° with the band's midpoint over the corner, so both ends run off the card
     and the overflow:hidden clip reads as the ribbon passing behind it. Any
     other angle leaves one end visibly sheared off mid-letter. */
  content: "Most popular"; position: absolute; z-index: 2; top: 20px; right: -52px;
  width: 182px; padding: 5px 0; transform: rotate(45deg);
  font-family: var(--font-head); font-weight: 700; font-size: 10.5px;
  letter-spacing: .11em; text-transform: uppercase; text-align: center;
  color: var(--deep); background: linear-gradient(135deg, #FFD469, #E9A93B);
  box-shadow: 0 4px 12px rgba(11,36,71,.28);
}
.prose .tiergrid > .tiertile[data-featured] [class*="div-block-108"] > h2 { color: var(--crimson); }
.prose .tiergrid > .tiertile[data-featured] > a[class*="button"] {
  background: linear-gradient(135deg, var(--maroon), var(--crimson));
  box-shadow: 0 8px 22px rgba(113,29,58,.30);
}
.prose .tiergrid > .tiertile[data-featured] > a[class*="button"]:hover {
  background: linear-gradient(135deg, #5F1830, var(--maroon));
}

/* ---- the free tiers. Non-Member and the graduate years have no price, no
   payment plan and (Non-Member) not one feature line, so the card was a name and
   a button with a column of blank paper between them while its neighbours were
   full. The word is the offer: give it the empty space at display size. */
.prose .tiergrid > .tiertile[data-card="free"] [class*="div-block-106"] {
  display: flex; flex: 1 1 auto; align-items: center; justify-content: center; padding: 0;
}
.prose .tiergrid > .tiertile[data-card="free"] [class*="div-block-108"] { padding: 18px 0 22px; }
.prose .tiergrid > .tiertile[data-card="free"] [class*="div-block-108"] > h2 {
  font-size: clamp(64px, 8.4vw, 108px); line-height: .84; letter-spacing: -.05em;
  background: linear-gradient(135deg, var(--deep) 6%, var(--navy) 48%, #3B87D6 100%);
  /* `-webkit-text-fill-color`, not `color: transparent`: the painted result is
     identical, but `color` stays a real navy, so the contrast sweeps (the build's
     and v2.js's runtime one) measure the word they can see instead of reading
     transparent as black, calling 1:1 and repainting it flat. Anything without
     text-fill support gets solid navy, which is the fallback you want anyway.
     #3B87D6 is where the gradient ends: 3.6:1 on paper, clear of the 3:1 large
     text needs, so the palest corner of the word still holds. */
  -webkit-background-clip: text; background-clip: text;
  color: var(--navy); -webkit-text-fill-color: transparent;
}
.prose .tiergrid > .tiertile[data-card="free"] [class*="div-block-108"] > [class*="text-block-38"] {
  margin-top: 12px; font-size: 13px; letter-spacing: .18em;
}
/* the switcher on a free card is a single dead pill ("Free Forever") that now
   reads under the price instead — it would only repeat it */
.prose .tiergrid > .tiertile[data-card="free"] [class*="tabs-menu"] { display: none; }

/* ---- Life Membership is an application, not a price column: 30 years of
   standing, three documents and two letters. It takes the whole row as a dark
   panel — the requirements beside the invitation rather than under it, which is
   what turned it into a 1,000-character column of run-on text. */
.prose .tiergrid > .tiertile[data-card="life"] {
  flex: 1 1 100%; max-width: none;
  display: grid !important;
  grid-template-columns: minmax(280px, 5fr) minmax(320px, 6fr);
  grid-template-areas: "head reqs" "intro reqs" "cta1 reqs" "cta2 reqs";
  grid-template-rows: auto auto auto 1fr;
  align-content: start; column-gap: 48px; row-gap: 16px;
  padding: 0 0 0 0; text-align: left;
  background: linear-gradient(135deg, var(--deep) 0%, #072E58 46%, var(--navy) 100%);
  border-color: rgba(201,162,39,.34);
  color: rgba(255,255,255,.86);
}
/* a thin gold rule across the top — the panel's only ornament, and the one
   colour on this page reserved for the tier you cannot simply buy */
.prose .tiergrid > .tiertile[data-card="life"]::before {
  content: ""; position: absolute; inset: 0 0 auto; height: 4px;
  background: linear-gradient(90deg, transparent, #C9A227 22%, #F0D584 50%, #C9A227 78%, transparent);
}
.prose .tiergrid > .tiertile[data-card="life"] > [class*="div-block-106"] {
  grid-area: head; padding: 40px 0 0 44px;
}
.prose .tiergrid > .tiertile[data-card="life"] > [class*="div-block-106"] h2 {
  min-height: 0; margin: 0; padding: 0; background: none; border-radius: 0;
  display: block; text-align: left; color: var(--white);
  font-size: clamp(30px, 3.2vw, 42px); letter-spacing: -.02em;
}
.prose .tiergrid > .tiertile[data-card="life"] > [class*="div-block-106"] h2::after { content: none; }
.prose .tiergrid > .tiertile[data-card="life"] > [class*="text-block-37"] {
  grid-area: intro; padding: 0 0 0 44px; max-width: 46ch; text-align: left;
  color: rgba(255,255,255,.80); font-size: 16.5px; line-height: 1.62;
}
.prose .tiergrid > .tiertile[data-card="life"] > [class*="text-block-37"] strong { font-weight: 500; }
.prose .tiergrid > .tiertile[data-card="life"] > [class*="flex-block-4"] {
  grid-area: reqs; margin: 0; padding: 40px 44px 40px 0;
}
.prose .tiergrid > .tiertile[data-card="life"] .list { margin: 0; }
.prose .tiergrid > .tiertile[data-card="life"] .list li > [class*="text-block-38"] { padding-left: 0; }
.prose .tiergrid > .tiertile[data-card="life"] .list li > [class*="text-block-38"]::before { content: none; }
/* "Requirements:" is the panel's only label — set it as one */
.prose .tiergrid > .tiertile[data-card="life"] .text-block-38-copy:not(.text-block-38-1-copy) {
  margin: 0 0 12px; font-family: var(--font-head); font-size: 12px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: #E7C868;
}
.prose .tiergrid > .tiertile[data-card="life"] [class*="text-block-38-1-copy"] {
  max-width: none; margin: 0; padding: 22px 24px; text-align: left;
  font-size: 15px; line-height: 1.72; color: rgba(255,255,255,.80);
  background: rgba(255,255,255,.055); border: 1px solid rgba(255,255,255,.12);
  border-radius: var(--r-lg);
}
.prose .tiergrid > .tiertile[data-card="life"] [class*="text-block-38-1-copy"] strong { color: var(--white); font-weight: 600; }
/* areas rather than source order: the application is the primary action, and it
   ships after the form download in the mirror's markup */
/* `align-self: start` is what keeps these buttons buttons: the requirements panel
   is the tallest thing on the row, so the CTA column's last track is a 1fr
   remainder ~280px tall and a stretched button became a pill that tall — a
   250x283 lozenge reading "Download Form" */
.prose .tiergrid > .tiertile[data-card="life"] > a[class*="button"] {
  order: 0; margin: 0 0 0 44px; width: auto; min-width: 250px;
  justify-self: start; align-self: start;
  grid-area: cta1;
}
.prose .tiergrid > .tiertile[data-card="life"] > a[class*="button-12-copy"] {
  grid-area: cta2; margin-bottom: 40px;
  background: transparent; color: #F0D584; border-color: rgba(240,213,132,.55);
  box-shadow: none;
}
.prose .tiergrid > .tiertile[data-card="life"] > a[class*="button-12-copy"]:hover {
  background: rgba(240,213,132,.12); color: #F7E6B4; border-color: #F0D584;
}
@media (max-width: 900px) {
  .prose .tiergrid > .tiertile[data-card="life"] {
    grid-template-columns: 1fr;
    grid-template-areas: "head" "intro" "reqs" "cta1" "cta2";
    grid-template-rows: none; row-gap: 18px;
  }
  .prose .tiergrid > .tiertile[data-card="life"] > [class*="div-block-106"],
  .prose .tiergrid > .tiertile[data-card="life"] > [class*="text-block-37"] { padding-inline: 26px; }
  .prose .tiergrid > .tiertile[data-card="life"] > [class*="flex-block-4"] { padding: 4px 26px 0; }
  .prose .tiergrid > .tiertile[data-card="life"] > a[class*="button"] { margin-inline: 26px; }
  .prose .tiergrid > .tiertile[data-card="life"] > a[class*="button-12-copy"] { margin-bottom: 32px; }
}

/* ---- hover: the cards are the page's only interactive surface, so they should
   answer the pointer. A short spring lift with the shadow deepening under it, the
   price easing up a fraction, and a light sweep crossing the card once — enough
   motion to feel live, all of it transform/opacity so it stays on the compositor.
   @media(hover) keeps a touch tap from parking a card in its hover state; the
   reduced-motion block at the top of this file zeroes the durations. */
.prose .tiergrid > .tiertile {
  transition: transform 460ms var(--spring), box-shadow 380ms var(--ease),
              border-color 380ms var(--ease);
  will-change: transform;
}
.prose .tiergrid > .tiertile::after {
  content: ""; position: absolute; inset: -40% -60%; z-index: 0; pointer-events: none;
  background: linear-gradient(72deg, transparent 38%, rgba(148,197,248,.30) 48%, rgba(255,255,255,.55) 52%, transparent 62%);
  transform: translateX(-92%); opacity: 0;
  transition: transform 900ms var(--ease), opacity 300ms var(--ease);
}
.prose .tiergrid > .tiertile > * { position: relative; z-index: 1; }
@media (hover: hover) {
  .prose .tiergrid > .tiertile:hover {
    transform: translateY(-10px) scale(1.017);
    box-shadow: 0 26px 58px rgba(11,36,71,.20);
    border-color: rgba(2,58,113,.30);
  }
  .prose .tiergrid > .tiertile:hover::after { transform: translateX(92%); opacity: 1; }
  .prose .tiergrid > .tiertile:hover [class*="div-block-108"] > h2 { transform: translateY(-3px) scale(1.045); }
  .prose .tiergrid > .tiertile:hover > h2::after,
  .prose .tiergrid > .tiertile:hover > h3::after { opacity: 1; }
  .prose .tiergrid > .tiertile[data-featured]:hover { border-color: rgba(139,21,56,.48); }
  /* the full-width panel is 1,100px of surface — lifting it that far reads as the
     page moving, not a card. It answers with light instead. */
  .prose .tiergrid > .tiertile[data-card="life"]:hover {
    transform: translateY(-4px); border-color: rgba(201,162,39,.62);
    box-shadow: 0 26px 58px rgba(11,36,71,.28);
  }
  .prose .tiergrid > .tiertile[data-card="life"]:hover::after { opacity: .35; }
}
/* the card sits on its own compositor layer while hovered and drops back off it
   afterwards — `will-change` left on permanently would pin one layer per card */
@media (hover: none) {
  .prose .tiergrid > .tiertile { will-change: auto; }
  .prose .tiergrid > .tiertile::after { content: none; }
}

@media (max-width: 700px) {
  /* same weight as the blanket `max-width: 100%` guard needs answering here too */
  .prose .tiergrid > .tiertile[class*="flex-block"] { flex: 1 1 100%; max-width: none; }
  /* a corner ribbon needs a corner to spare. On a one-up phone column the card is
     as wide as the screen and the diagonal cut straight through "General
     Member"; unpinned, the same ::before becomes the card's first flex item — a
     gold strip above the header cap, which the cap then meets square. */
  .prose .tiergrid > .tiertile[data-featured]::before {
    position: static; transform: none; width: calc(100% + 52px); margin: 0 -26px;
    padding: 7px 0; border-radius: var(--r-xl) var(--r-xl) 0 0; box-shadow: none;
  }
  .prose .tiergrid > .tiertile[data-featured] > h2,
  .prose .tiergrid > .tiertile[data-featured] > h3 { border-radius: 0; }
}

/* ---------- panes the original left unreachable (no tab link) ----------
   Freed in extract.mjs and rendered as an ordinary band. The tier grid was
   authored as a fixed 4-track row holding 5 cells, so the intro was squeezed
   into a quarter column and the last tier wrapped onto a row of its own.

   Both rules below are scoped to a pane whose cells are `flex-block` tier cards,
   because "freed pane" is a structural label, not a layout: the committee roster
   on /national-convention/committe-page is one too, and unscoped these rules read
   its first committee (Awards) as an intro — stretching that one card across all
   four columns, stripping its card chrome, and leaving the rest of the row empty. */
.freed-pane { display: block; margin-top: var(--flow-sm); }
.freed-pane [class*="grid"]:has(> [class*="flex-block"]) {
  display: grid !important;
  grid-template-columns: repeat(4, minmax(0, 1fr)) !important;
  gap: 22px !important; align-items: stretch !important; width: 100%;
}
.freed-pane [class*="grid"]:has(> [class*="flex-block"]) > :first-child {
  grid-column: 1 / -1; align-items: flex-start; text-align: left;
  padding: 0 0 4px; background: none; border: 0; box-shadow: none;
}
.freed-pane [class*="grid"]:has(> [class*="flex-block"]) > :first-child:hover { transform: none; box-shadow: none; }
.freed-pane [class*="flex-block"]:not([class*="flex-block"] *, [data-selfstyled] *, [class*="card"]:not([class*="cards"]) *) {
  background: var(--white); border: 1px solid rgba(2,58,113,.10);
  border-radius: var(--r-lg); box-shadow: var(--sh-sm); padding: 26px 22px;
  display: flex; flex-direction: column; gap: 10px;
}
.freed-pane [class*="flex-block"] h2, .freed-pane [class*="flex-block"] h2 strong {
  color: var(--deep); font-size: clamp(30px, 3vw, 40px); margin: 0;
}
.freed-pane [class*="flex-block"] ul { margin: 4px 0 0; padding-left: 18px; }
.freed-pane [class*="flex-block"] li { margin-bottom: 6px; }
.freed-pane [class*="flex-block"] a[class*="button"] { margin-top: auto; align-self: stretch; text-align: center; }
/* responsive columns for this band live at the end of the file, after the
   site-wide "collapse imported grids on small screens" rules */

/* Instagram feed: the embed script swaps the blockquote for an iframe carrying
   the live profile header + latest posts, so the panel is framed rather than
   height-capped — a cap cropped the bottom row of the grid. */
/* !important because the embed ships its own `.instagram-container { width:100% }`
   in a page-local <style> that would otherwise win on source order. The width is
   capped near 1,000px: Instagram sizes the frame for a 3-up grid, and past that
   the reserved height ran ~500px beyond where the posts actually end. */
.instagram-container {
  max-width: 1000px !important; margin-inline: auto; background: var(--white);
  border: 1px solid rgba(2,58,113,.10); border-radius: var(--r-lg);
  box-shadow: var(--sh-md); overflow: hidden;
}
.instagram-media, iframe.instagram-media, [data-instgrm-permalink] {
  width: 100% !important; min-width: 0 !important; max-width: 100% !important;
  margin: 0 !important; border: 0 !important; border-radius: 0 !important; display: block !important;
}
/* the height Instagram reserves lands a little short of its own 3-up grid, so the
   bottom row of posts was cut in half — the tiles are a third of the width each,
   so two rows plus the profile header need roughly 0.67w + 160 */
iframe.instagram-media { min-height: calc(62vw + 140px); }
@media (max-width: 600px) { iframe.instagram-media { min-height: 370px; } }
@media (min-width: 1000px) { iframe.instagram-media { min-height: 830px; } }
.instagram-container .follow-section { border-radius: 0; }
/* "Follow us for updates…" is white on Instagram's brand ramp
   (#f09433→#bc1888). That ramp is only readable at its magenta end: white on the
   orange start measures 2.3:1, and averaged across the band 4.26:1 — under 4.5
   either way. Recolouring the stops would cost the brand identity the band exists
   to carry, so lay a 35% black scrim over the ramp instead: same hues in the same
   order, every stop dark enough to hold white lettering.
   `background-image` only, so the embed's own gradient stays the thing being
   tinted rather than being replaced. */
.instagram-container .follow-section {
  background-image:
    linear-gradient(rgba(0,0,0,.35), rgba(0,0,0,.35)),
    linear-gradient(45deg, #f09433 0%, #e6683c 25%, #dc2743 50%, #cc2366 75%, #bc1888 100%);
}

/* ============================================================
   "Building Healthy Communities" photo window — two vertical
   columns scrolling opposite directions inside a frame exactly two
   photos tall. Four photos are visible at once, so the section
   stays compact instead of the 2,800px tower the collage produced.
   ============================================================ */
.photowall {
  position: relative;
  display: grid; grid-template-columns: 1fr 1fr; gap: 14px;
  width: 100%; max-width: 100%;
  height: calc(var(--pw-ph, 240px) * 2 + 14px);
  overflow: hidden; border-radius: var(--r-lg);
}
/* soft top/bottom fade so photos enter and leave rather than pop */
.photowall::before, .photowall::after {
  content: ""; position: absolute; left: 0; right: 0; height: 54px; z-index: 2; pointer-events: none;
}
.photowall::before { top: 0; background: linear-gradient(180deg, var(--paper), transparent); }
.photowall::after { bottom: 0; background: linear-gradient(0deg, var(--paper), transparent); }
.photowall__col { position: relative; overflow: hidden; min-width: 0; }
.photowall__track {
  display: flex; flex-direction: column; gap: 14px;
  animation: photowall-up var(--pw-dur, 34s) linear infinite;
  will-change: transform;
}
.photowall__col--down .photowall__track { animation-name: photowall-down; }
.photowall:hover .photowall__track,
.photowall:focus-within .photowall__track { animation-play-state: paused; }
.photowall .photowall__track img[src] {
  flex: 0 0 auto;
  width: 100% !important;
  height: var(--pw-ph, 240px) !important;
  aspect-ratio: auto !important;
  /* the wall is built and cloned by script before the framing pass runs, so this
     static value has to be head-safe on its own: 16% keeps a portrait source's
     trim inside the same 8%-of-frame budget the runtime framing enforces */
  object-fit: cover; object-position: center top;
  border-radius: var(--r-md); box-shadow: var(--sh-sm); margin: 0; display: block;
}
@keyframes photowall-up { from { transform: translate3d(0,0,0); } to { transform: translate3d(0,-50%,0); } }
@keyframes photowall-down { from { transform: translate3d(0,-50%,0); } to { transform: translate3d(0,0,0); } }
@media (max-width: 900px) {
  .photowall::before, .photowall::after { height: 34px; }
}
/* motion-sensitive visitors get a static, wrapped gallery — nothing hidden */
@media (prefers-reduced-motion: reduce) {
  .photowall { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); height: auto; overflow: visible; }
  .photowall::before, .photowall::after { display: none; }
  .photowall__col { display: contents; }
  .photowall__track { display: contents; animation: none; }
  .photowall .photowall__track img[src] { height: 180px !important; }
  /* the loop clones exist only to make motion seamless */
  .photowall__track > [aria-hidden="true"] { display: none; }
}

/* ---------- partner / sponsor logos: bigger, legible, evenly set ----------
   The originals sat in 144px circles that cropped wide wordmarks down to a
   sliver. Rounded tiles give every logo the same optical size and breathing room. */
.logos { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 20px; }
.logos img {
  max-height: 82px; max-width: 220px; width: auto; height: auto;
  object-fit: contain; filter: none; opacity: 1;
}
.logos img:hover { filter: none; opacity: 1; transform: translateY(-2px); }

/* the original circular logo chips */
[class*="div-block-111"],
a[class*="link-block-mob"],
[class*="logo-tile"] {
  display: flex !important; align-items: center; justify-content: center;
  width: auto !important; height: auto !important;
  min-height: 158px; padding: 24px 30px !important;
  background: var(--white); border: 1px solid rgba(2,58,113,.10);
  border-radius: var(--r-lg) !important; box-shadow: var(--sh-sm);
  transition: transform 220ms var(--ease), box-shadow 220ms var(--ease);
}
[class*="div-block-111"]:hover,
a[class*="link-block-mob"]:hover { transform: translateY(-3px); box-shadow: var(--sh-md); }
[class*="div-block-111"] img,
a[class*="link-block-mob"] img,
[class*="logo-tile"] img {
  width: auto !important; height: auto !important;
  max-width: 100%; max-height: 104px; min-height: 56px;
  object-fit: contain !important; filter: none !important; opacity: 1 !important; margin: 0;
}
/* Partner / sponsor logo cells: the logo alone, no box.
   The original nests a.card > div.card_body > img and BOTH layers matched the
   card skin, so every wordmark sat inside two stacked white boxes. */
a[class*="card"]:has(> [class*="card_body"] > img:only-child),
[class*="card_body"]:has(> img:only-child) {
  display: flex !important; align-items: center; justify-content: center;
  background: none !important; border: 0 !important; box-shadow: none !important;
  border-radius: 0 !important; padding: 0 !important; min-height: 0 !important;
  overflow: visible !important;
}
a[class*="card"]:has(> [class*="card_body"] > img:only-child) {
  padding: 18px 14px !important;
  transition: transform 220ms var(--ease);
}
a[class*="card"]:has(> [class*="card_body"] > img:only-child):hover { transform: translateY(-3px); }
[class*="card_body"]:has(> img:only-child) > img {
  width: auto !important; height: auto !important;
  max-width: 100% !important; max-height: 74px !important;
  object-fit: contain !important; margin: 0; box-shadow: none !important; border-radius: 0 !important;
}
@media (max-width: 600px) {
  [class*="card_body"]:has(> img:only-child) > img { max-height: 52px !important; }
}

/* ---------- the opacity these overlays are named for ----------
   Same story as the object-fit note further down: Webflow names the class for the
   treatment it is supposed to have — overlay_opacity-middle-3, -middle-5 — and
   wf-layout.css carries only `position:absolute; inset:0`. The opacity itself lived
   in the stylesheet the mirror does not have, so once the band lays out correctly
   the photograph sits at FULL strength behind copy that is still navy on white, and
   the heading is unreadable wherever the picture is dark.

   0.35 is not a guess. Over the white section behind it, that is the strongest wash
   at which this page's navy (#023A71) still clears WCAG AA for body text against the
   photograph's darkest pixel — pure black — at 4.67:1. Half opacity, the reading
   "middle" invites, comes to 2.88:1 and fails. Two images site-wide. */
[class*="overlay_opacity"] { opacity: .35; }

/* an image being upscaled past its own resolution is shown whole rather than
   cropped — see the object-fit guard in v2.js */
img.is-contained {
  background: var(--white);
  padding: clamp(16px, 2.4vw, 34px);
  box-sizing: border-box;
}

/* logo rows lay out as an even, generous grid */
[class*="grid_"]:has(> a > [class*="div-block-111"]),
[class*="grid_"]:has(> [class*="div-block-111"]) {
  display: grid !important;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)) !important;
  gap: 20px !important; align-items: stretch !important;
}
@media (max-width: 600px) {
  [class*="div-block-111"], a[class*="link-block-mob"] { min-height: 124px; padding: 18px 20px !important; }
  [class*="div-block-111"] img, a[class*="link-block-mob"] img { max-height: 78px; }
}

/* embedded widgets ship fixed pixel column widths that exceed a phone screen
   (the news cards hardcode a 407px track) — let them collapse to one column */
@media (max-width: 900px) {
  [class*="nc-wrap"], [class*="cards-wrap"], .nda-wwd__grid, .w-embed [class*="grid"] {
    grid-template-columns: minmax(0, 1fr) !important;
  }
  .w-embed, .w-embed * { max-width: 100% !important; }
}

/* phones: original fixed-ratio media and multi-column tracks must reflow.
   (photo-wall imagery keeps its own sizing) */
@media (max-width: 900px) {
  [class*="image_cover"]:not(.photowall *), [class*="ratio_"]:not(.photowall *) {
    width: 100% !important; max-width: 100% !important;
    height: auto !important; aspect-ratio: auto !important;
  }
  .prose .w-layout-grid:not(.photowall *), .prose [class*="grid_"]:not(.photowall *) {
    grid-template-columns: minmax(0, 1fr) !important;
  }
}

/* a min-width beats any max-width, so embeds with hardcoded pixel minimums
   stretched the page on phones and clipped the layout */
@media (max-width: 900px) {
  .prose *, .w-embed *, [class*="nc-"], [class*="ex-"], [class*="nda-"] { min-width: 0 !important; }
}

/* phones: the Architects band stacks — its pillar pair was overflowing the screen */
@media (max-width: 900px) {
  .hero__grid { grid-template-columns: minmax(0, 1fr) !important; }
  .pillars { grid-template-columns: minmax(0, 1fr) !important; }
  .hero__grid > *, .pillars > * { min-width: 0 !important; max-width: 100% !important; }
}

/* icons stay icons: without their original sizing rules, inline arrow/chevron
   SVGs stretch to fill whatever cell they land in (they rendered page-wide once).
   Scoped to imported content so v2's own chrome keeps its deliberate sizes. */
.prose a svg, .prose button svg, .prose [class*="button"] svg, .prose [class*="icon"] svg,
.w-embed a svg, .w-embed [class*="button"] svg, .w-embed [class*="icon"] svg {
  width: 1.15em; height: 1.15em; max-width: 28px; max-height: 28px; flex: 0 0 auto;
}
.prose [class*="button_icon"] svg, .w-embed [class*="button_icon"] svg { width: 1em; height: 1em; }
.prose img[src*="arrow"], .prose img[src*="chevron"], .prose img[src*="caret"] {
  max-width: 40px !important; max-height: 40px !important; width: auto !important; height: auto !important;
}

/* grid children default to min-width:auto, so wide media pushes tracks past the
   viewport at in-between widths — the classic blowout, fixed here once.
   A child that's ALSO display:flex (team/staff card grids) shrink-wraps its
   content instead of stretching to its column — team photos collapsed to 0
   width (and so never loaded) inside a card sized to nothing. Force the fill. */
.prose .w-layout-grid > *, .prose [class*="grid_"] > *,
.w-embed [class*="grid"] > *, [class*="ix_marquee"] > * { min-width: 0; width: 100%; }
/* team-photo cards (align-items:flex-start on a column flex card, from the
   original) leave their own width:100% photo wrapper unresolved — nested
   percentage widths under a non-stretch cross-axis don't reliably resolve.
   Stretch the card's children directly instead of relying on the percentage. */
.prose [class*="team"][class*="_item"] { align-items: stretch !important; }
[class*="ix_marquee"], .photowall, [class*="position_relative"][class*="overflow_hidden"] {
  max-width: 100% !important;
}

/* narrow phones: logo tiles shrink their track instead of forcing one */
@media (max-width: 600px) {
  [class*="grid_"]:has(> a > [class*="div-block-111"]),
  [class*="grid_"]:has(> [class*="div-block-111"]) {
    grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)) !important;
  }
  [class*="div-block-111"], a[class*="link-block-mob"] {
    min-width: 0 !important; padding: 14px 12px !important; min-height: 96px;
  }
  [class*="div-block-111"] img, a[class*="link-block-mob"] img { max-height: 58px; }
}
/* fixed-ratio media never exceeds its column at any width */
[class*="image_cover"]:not(.photowall *), [class*="ratio_"]:not(.photowall *) {
  max-width: 100%; min-width: 0;
}
@media (max-width: 1200px) {
  [class*="ratio_"]:not(.photowall *) { aspect-ratio: auto !important; height: auto !important; }
}

/* smallest phones (320-375): long unbroken strings and the career widget's
   header padding were the last things pushing past the screen edge */
@media (max-width: 380px) {
  .prose, .w-embed, .prose *, .w-embed * { overflow-wrap: anywhere; }
  [class*="widget-header"], [class*="search-"] { padding-left: 12px !important; padding-right: 12px !important; }
}

/* last-mile: full-bleed banner sections and the goal-meter caption on tiny screens */
@media (max-width: 400px) {
  [class*="pricing-banner"], [class*="padding-global"], [class*="section-4-full-width"] {
    width: 100% !important; max-width: 100% !important; padding-left: 14px !important; padding-right: 14px !important;
  }
  .goalmeter__head { flex-wrap: wrap; gap: 4px; }
  .goalmeter__head span { flex: 1 1 100%; }
}

/* phones: any imported block still wider than the screen is contained rather
   than allowed to clip (tables and wide media scroll inside their own box) */
@media (max-width: 767px) {
  .prose > *, .prose section, .prose [class*="section"], .w-embed > * { max-width: 100% !important; }
  .prose table, .prose [class*="table"] { display: block; overflow-x: auto; max-width: 100%; }
  .prose [class*="banner"], .prose [class*="full-width"] { padding-left: 12px !important; padding-right: 12px !important; }
}

/* Global containment for imported content. Individual fixes kept reopening
   elsewhere, so every element inside a content region is capped to its column;
   the photo wall manages its own sizing. */
.prose *:not(.photowall):not(.photowall *), .w-embed *:not(.photowall *) {
  max-width: 100%;
}
.prose, .w-embed { min-width: 0; }

/* …with one exception, and it has to be stated here rather than up with the
   other .prose rules: the containment cap above weighs (0,3,0), so a rule of
   equal weight written earlier in the file loses the tie and the band stayed
   pinned to the reading column while its negative margins still pulled it left —
   content hard against the window edge with 700px of blank paper beside it.

   A hand-built embed is not body copy and should not be measured like it. The
   `nda-hd-*` component on /news/nda-on-the-hill is a run of full-bleed bands — a
   congressional roster, a video, a sponsor wall, a photo editorial — each with
   its own inner container and its own max width. Squeezed into prose's 76ch
   column those rendered 833px wide down the middle of a 1,600px screen, so the
   four-up roster stacked and the photo editorial ran as a column of postcards.
   Break the band out to the viewport and let the component's own container do
   the centring it was written to do; the prose around it keeps its measure, so
   an article that mixes real paragraphs with an embed still reads at 76ch.

   `.prose--bleed`, set by T.newsArticle, rather than every .prose on the site: an
   article IS its embed, so the band is the page. Elsewhere an embed is one
   component among many that a page has already placed, and unpinning it there
   moved bands that were positioned deliberately — /leadership/our-president
   pushed 120px past the window edge on the first attempt.

   Direct children only — a nested band would tear its own parent's layout apart —
   and `overflow-x: clip` on <body> absorbs the scrollbar's width, which is the
   usual reason a 100vw full-bleed leaves a horizontal scroll. */
.prose--bleed > [data-selfstyled]:not(.photowall),
.prose--bleed > :not([data-selfstyled]):has(> [data-selfstyled]) {
  width: 100vw; max-width: 100vw; margin-inline: calc(50% - 50vw);
}

/* the imported stylesheet turned v2's own .container into a flex row, which
   squeezed section headings into narrow columns ("More from the NDA" wrapped
   onto four lines). v2's layout wrappers own their display mode. */
.container:not(.nav__in):not(.footer__in):not(.slider__grid):not(.hero__grid):not(.slider__nav):not(.gal-jump__in):not(.gal-faq__in) {
  display: block;
}
/* closing gallery reads as a tidy row of photos at any count */
.masonry {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 16px; columns: auto;
}
.masonry img {
  width: 100%; height: clamp(170px, 17vw, 220px); object-fit: cover; object-position: center top;
  margin: 0; border-radius: var(--r-md); box-shadow: var(--sh-sm);
}
@media (max-width: 600px) { .masonry { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); } }

/* ---------- freed tier band: responsive columns + gutters ----------
   Placed last so it wins over the site-wide "collapse every imported grid to one
   column below 900px" rule — four price tiers read fine two-up on a tablet. The
   nested containers each carried 32px of their own padding, which on a phone left
   the cards 162px wide and clipped "$30,000" mid-word. */
@media (max-width: 1040px) {
  .prose .freed-pane [class*="grid"] { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
}
@media (max-width: 620px) {
  .prose .freed-pane [class*="grid"] { grid-template-columns: minmax(0, 1fr) !important; }
}
@media (max-width: 760px) {
  .freed-pane, .freed-pane > [class*="div-block"], .freed-pane [class*="grid"] {
    padding-left: 0 !important; padding-right: 0 !important;
  }
  .prose [class*="container-11"] { padding-left: 10px !important; padding-right: 10px !important; }
  .freed-pane [class*="flex-block"] h2, .freed-pane [class*="flex-block"] h2 strong { font-size: 30px; }
}

/* ============================================================
   Corporate Partnership Tiers (CRT schedule)
   Authored in render.mjs. The original squeezed this into a
   quarter-column of a 4-track grid; here each tier is a full
   card with a readable benefit schedule.
   ============================================================ */
.crt-band { background: linear-gradient(180deg, var(--sky-50), var(--paper)); }
.crt-band__head { max-width: 760px; margin: 0 auto 34px; text-align: center; }
.crt-band__head h2 { font-size: clamp(30px, 3.6vw, 46px); color: var(--deep); margin: 0 0 12px; }
.crt-band__head p { font-size: clamp(17px, 1.5vw, 20px); color: var(--slate); margin: 0; }
.crt-grid {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 24px; align-items: stretch;
}
.crt-tier {
  display: flex; flex-direction: column;
  background: var(--white); border: 1px solid rgba(2,58,113,.10);
  border-radius: var(--r-xl); box-shadow: var(--sh-md);
  padding: 30px 26px 26px; position: relative; overflow: hidden;
  transition: transform 220ms var(--ease), box-shadow 220ms var(--ease);
}
.crt-tier:hover { transform: translateY(-4px); box-shadow: var(--sh-lg); }
/* a rank stripe so the tiers read in order at a glance */
.crt-tier::before { content: ""; position: absolute; inset: 0 0 auto 0; height: 5px; background: var(--sky); }
.crt-tier--platinum::before { background: linear-gradient(90deg, var(--deep), var(--navy)); }
.crt-tier--gold::before { background: linear-gradient(90deg, #B8862B, #E3B457); }
.crt-tier--silver::before { background: linear-gradient(90deg, #7D8794, #B9C2CC); }
.crt-tier--bronze::before { background: linear-gradient(90deg, #8A5A2B, #C08A57); }
.crt-tier__name {
  font-family: var(--font-head); font-weight: 700; font-size: clamp(20px, 1.9vw, 24px);
  color: var(--navy); margin: 0 0 6px; letter-spacing: -.01em;
}
.crt-tier__price {
  font-family: var(--font-head); font-weight: 800; font-size: clamp(34px, 3.4vw, 44px);
  color: var(--deep); margin: 0 0 20px; line-height: 1.05; font-variant-numeric: tabular-nums;
}
.crt-tier__rows { margin: 0 0 22px; padding: 0; border-top: 1px solid rgba(2,58,113,.10); }
.crt-row {
  display: flex; align-items: baseline; justify-content: space-between; gap: 14px;
  padding: 11px 0; border-bottom: 1px solid rgba(2,58,113,.08);
}
.crt-row dt { font-size: 15.5px; color: var(--slate); margin: 0; }
.crt-row dd {
  margin: 0; font-family: var(--font-head); font-weight: 700; font-size: 17px;
  color: var(--navy); white-space: nowrap; font-variant-numeric: tabular-nums;
}
.crt-tier__actions { margin-top: auto; display: grid; gap: 10px; }
.crt-tier__actions .btn { width: 100%; }
@media (max-width: 1100px) {
  .crt-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  .crt-grid { grid-template-columns: minmax(0, 1fr); gap: 18px; }
  .crt-tier { padding: 26px 22px 22px; }
  .crt-row dt { font-size: 15px; }
}

/* Membership pages (join-us / membership) only ever get a light teaser for
   CRT — the full tier schedule (.crt-band above) belongs on its own program
   page. Clicking through opens the compact modal summary defined alongside. */
.crt-teaser {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 20px; background: var(--sky-50); border: 1px solid rgba(2,58,113,.10);
  border-radius: var(--r-xl); padding: 26px 30px; margin: 1.6em 0;
}
.crt-teaser__text h3 { font-size: 19px; color: var(--navy); margin: 0 0 4px; }
.crt-teaser__text p { font-size: 15px; color: var(--slate); margin: 0; }
.crt-teaser .btn { white-space: nowrap; }
@media (max-width: 560px) { .crt-teaser { padding: 22px; } }

.crt-modal__tiers { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; margin: 0 0 24px; }
.crt-modal__tier {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  background: var(--paper); border: 1px solid rgba(2,58,113,.08); border-radius: var(--r-md);
  padding: 12px 14px;
}
.crt-modal__tier b { color: var(--navy); font-size: 15px; }
.crt-modal__tier span { font-family: var(--font-head); font-weight: 700; color: var(--deep); font-variant-numeric: tabular-nums; }
.crt-modal__actions { display: flex; gap: 12px; flex-wrap: wrap; }
.crt-modal__actions .btn { flex: 1 1 200px; text-align: center; }
@media (max-width: 480px) { .crt-modal__tiers { grid-template-columns: 1fr; } }

/* ============================================================
   Content lifted out of third-party iframes (see nativizeEmbeds
   in render.mjs). Frames cost layout control and break silently;
   these are the same contents as native sections.
   ============================================================ */

/* --- video: poster only; the player is created on click --- */
.ytlite {
  position: relative; display: block; width: 100%; aspect-ratio: 16 / 9;
  border-radius: var(--r-lg); overflow: hidden; background: var(--deep);
  box-shadow: var(--sh-md); cursor: pointer; margin: 0 0 8px;
}
.ytlite__poster { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform 400ms var(--ease), opacity 300ms var(--ease); }
.ytlite:hover .ytlite__poster { transform: scale(1.03); opacity: .92; }
.ytlite__play {
  position: absolute; inset: 0; margin: auto; width: 78px; height: 54px;
  border: 0; border-radius: 14px; background: rgba(11,36,71,.82); cursor: pointer;
  transition: background-color 200ms var(--ease), transform 200ms var(--ease);
}
.ytlite__play::before {
  content: ""; position: absolute; inset: 0; margin: auto; width: 0; height: 0;
  border-left: 18px solid #fff; border-top: 11px solid transparent; border-bottom: 11px solid transparent;
  transform: translateX(2px);
}
.ytlite:hover .ytlite__play { background: var(--crimson); transform: scale(1.06); }
.ytlite__play:focus-visible { box-shadow: var(--ring); }
.ytlite__title {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 26px 18px 14px;
  font-family: var(--font-head); font-weight: 600; font-size: 15px; color: #fff;
  background: linear-gradient(0deg, rgba(11,36,71,.86), transparent);
  display: block; text-align: left;
}
.ytlite iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

/* An aspect-ratio box carries no intrinsic width. `.prose [class*="flex_vertical"]`
   centres its column, so a wrapper whose only content is such a box shrink-wraps
   to nothing and the media inside it disappears — About Us opened on a 0×0 header
   where its overview video should be. Let a wrapper that holds media take the row,
   and let the video's own 16/9 decide the height (the Webflow ratio box around it
   is 3/2, which would leave a band of empty slot under the player). */
.prose [class*="flex_vertical"] > *:has([class*="image-ratio_"], .ytlite) {
  align-self: stretch; width: 100%;
}
[class*="image-ratio_"]:has(.ytlite) { width: 100%; aspect-ratio: auto; }

/* --- publications (Issuu readers) --- */
.pubitem {
  display: flex; flex-direction: column; background: var(--white);
  border: 1px solid rgba(2,58,113,.10); border-radius: var(--r-lg);
  box-shadow: var(--sh-sm); overflow: hidden; margin: 0 0 20px;
  transition: transform 220ms var(--ease), box-shadow 220ms var(--ease);
}
.pubitem:hover { transform: translateY(-3px); box-shadow: var(--sh-md); }
.pubitem__cover { display: block; background: var(--sky-50); }
.pubitem__cover img { width: 100%; height: auto; display: block; }
.pubitem__body { padding: 18px 20px 22px; display: flex; flex-direction: column; gap: 14px; }
.pubitem__body h3 { margin: 0; font-size: 19px; color: var(--navy); }
.pubitem__body .btn { align-self: flex-start; }

/* --- documents (PDF / Drive) --- */
.docitem {
  display: flex; align-items: center; gap: 20px; padding: 22px 24px; margin: 0 0 20px;
  background: var(--white); border: 1px solid rgba(2,58,113,.10);
  border-radius: var(--r-lg); box-shadow: var(--sh-sm);
}
.docitem__icon {
  flex: 0 0 auto; width: 58px; height: 58px; display: grid; place-items: center;
  border-radius: var(--r-md); background: var(--crimson); color: #fff;
  font-family: var(--font-head); font-weight: 700; font-size: 14px; letter-spacing: .04em;
}
.docitem__body { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.docitem__body h3 { margin: 0; font-size: 19px; color: var(--navy); }
.docitem__body .btn { align-self: flex-start; }

/* --- a framed PDF that is a drawing, shown rather than offered (docFigure) --- */
.docfig { margin: 0 0 24px; }
.docfig__frame {
  display: block; background: var(--white); border: 1px solid rgba(2,58,113,.12);
  border-radius: var(--r-lg); box-shadow: var(--sh-sm); overflow: hidden;
  /* the plan is a wide sheet of fine line-work: on a phone it is unreadable
     scaled to fit, so it scrolls at a legible size instead of shrinking away */
  overflow-x: auto; -webkit-overflow-scrolling: touch;
}
.docfig__frame img { display: block; width: 100%; min-width: 720px; height: auto; }
.docfig__cap {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 12px; padding: 14px 4px 0; font-size: 15px; color: var(--slate);
}
@media (max-width: 700px) { .docfig__cap { flex-direction: column; align-items: flex-start; } }

/* --- portal-hosted tools (donations, live calendar) --- */
.portalitem {
  background: linear-gradient(180deg, var(--sky-50), var(--white));
  border: 1px solid rgba(2,58,113,.12); border-radius: var(--r-xl);
  padding: 32px 30px; margin: 0 0 20px; box-shadow: var(--sh-sm);
}
.portalitem h3 { margin: 0 0 10px; font-size: clamp(22px, 2.4vw, 28px); color: var(--deep); }
.portalitem p { margin: 0 0 18px; color: var(--slate); max-width: 60ch; }
.portalitem__note { font-size: 15px; }

/* --- past presidents --- */
.pastpres__intro { max-width: 780px; margin: 0 0 34px; }
.pastpres__intro h2 { font-size: clamp(28px, 3.2vw, 40px); color: var(--deep); margin: 0 0 14px; }
.pastpres__intro h3 { font-size: clamp(20px, 2vw, 25px); color: var(--navy); margin: 26px 0 10px; }
.pastpres__timeline h3 { font-size: clamp(22px, 2.4vw, 30px); color: var(--deep); margin: 0 0 6px; }
.pastpres__sub { color: var(--slate); margin: 0 0 24px; }
.ptl { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }
.ptl__item {
  display: flex; align-items: baseline; gap: 14px; padding: 12px 16px;
  background: var(--white); border: 1px solid rgba(2,58,113,.09);
  border-left: 3px solid var(--sky); border-radius: var(--r-md);
  transition: border-left-color 200ms var(--ease), transform 200ms var(--ease);
}
.ptl__item:hover { border-left-color: var(--crimson); transform: translateX(2px); }
.ptl__years {
  flex: 0 0 auto; font-family: var(--font-head); font-weight: 700; font-size: 14px;
  color: var(--navy); font-variant-numeric: tabular-nums; min-width: 82px;
}
.ptl__name { font-size: 16px; color: var(--ink); }

/* --- forms directory --- */
.formsdir__head { max-width: 720px; margin: 0 0 30px; }
.formsdir__head h2 { font-size: clamp(28px, 3.2vw, 40px); color: var(--deep); margin: 0 0 12px; }
.formsdir__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(290px, 1fr)); gap: 20px; }
.formitem {
  display: flex; flex-direction: column; gap: 12px; padding: 24px 22px;
  background: var(--white); border: 1px solid rgba(2,58,113,.10);
  border-radius: var(--r-lg); box-shadow: var(--sh-sm);
  transition: transform 200ms var(--ease), box-shadow 200ms var(--ease);
}
.formitem:hover { transform: translateY(-3px); box-shadow: var(--sh-md); }
.formitem h3 { margin: 0; font-size: 18px; color: var(--navy); line-height: 1.3; }
.formitem p { margin: 0; color: var(--slate); font-size: 15.5px; flex: 1; }
.formitem .btn { align-self: flex-start; }

/* --- districts legend --- */
.districtlegend h2 { font-size: clamp(26px, 3vw, 36px); color: var(--deep); margin: 0 0 10px; }
.districtlegend__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 16px; margin-top: 24px; }
.dcard {
  display: flex; flex-direction: column; gap: 6px; padding: 22px 20px; text-decoration: none;
  background: var(--white); border: 1px solid rgba(2,58,113,.10); border-radius: var(--r-lg);
  box-shadow: var(--sh-sm); transition: transform 200ms var(--ease), box-shadow 200ms var(--ease);
}
.dcard:hover { transform: translateY(-3px); box-shadow: var(--sh-md); }
.dcard__name { font-family: var(--font-head); font-weight: 700; font-size: 19px; color: var(--navy); }
.dcard__count { font-size: 15px; color: var(--slate); }
@media (max-width: 600px) {
  .docitem { flex-direction: column; align-items: flex-start; }
  .ptl { grid-template-columns: minmax(0, 1fr); }
}

/* --- House of Delegates (lifted from the app frame) --- */
.hod__head { max-width: 780px; margin: 0 0 30px; }
.hod__head h2 { font-size: clamp(28px, 3.2vw, 42px); color: var(--deep); margin: 0 0 12px; }
.hod__about { max-width: 860px; margin: 0 0 34px; }
.hod__about h3 { font-size: clamp(21px, 2.1vw, 26px); color: var(--navy); margin: 0 0 14px; }
.hod__about p { color: var(--slate); margin: 0 0 14px; }
.hod__pillars { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 18px; margin: 0 0 34px; }
.hod__pillar {
  padding: 22px 20px; background: var(--white); border: 1px solid rgba(2,58,113,.10);
  border-top: 3px solid var(--sky); border-radius: var(--r-lg); box-shadow: var(--sh-sm);
}
.hod__pillar h4 { margin: 0 0 8px; font-family: var(--font-head); font-size: 17px; color: var(--navy); }
.hod__pillar p { margin: 0; font-size: 15.5px; color: var(--slate); }
.hod__split { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 20px; }
.hod__card {
  padding: 28px 26px; background: var(--white); border: 1px solid rgba(2,58,113,.10);
  border-radius: var(--r-xl); box-shadow: var(--sh-sm);
}
.hod__card h3 { margin: 0 0 12px; font-size: clamp(20px, 2vw, 25px); color: var(--deep); }
.hod__card p { color: var(--slate); margin: 0 0 14px; }
.hod__card--portal { background: linear-gradient(180deg, var(--sky-50), var(--white)); }

/* A wrapper that used to hold an iframe was sized and breakpoint-scoped for one:
   height:0 with padding-bottom for aspect ratio, or .webflow-embed-desktop set to
   display:none on phones. With native content inside, those rules hide real
   content — this marker (added in render.mjs) undoes them. */
.has-native {
  display: block !important;
  height: auto !important; min-height: 0 !important; max-height: none !important;
  padding-bottom: 0 !important; padding-top: 0 !important;
  position: static !important; overflow: visible !important;
}

/* --- upcoming events (calendar pages) --- */
.events-band h2 { font-size: clamp(28px, 3.2vw, 40px); color: var(--deep); margin: 0 0 26px; }
.evgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 20px; }
.evitem {
  display: flex; flex-direction: column; gap: 8px; padding: 26px 22px;
  background: var(--white); border: 1px solid rgba(2,58,113,.10);
  border-left: 4px solid var(--crimson); border-radius: var(--r-lg); box-shadow: var(--sh-sm);
  transition: transform 200ms var(--ease), box-shadow 200ms var(--ease);
}
.evitem:hover { transform: translateY(-3px); box-shadow: var(--sh-md); }
.evitem__date {
  font-family: var(--font-head); font-weight: 700; font-size: 13.5px; letter-spacing: .08em;
  text-transform: uppercase; color: var(--crimson);
}
.evitem__title { margin: 0; font-size: 20px; color: var(--navy); line-height: 1.25; }
.evitem__loc { font-size: 15.5px; color: var(--slate); }

/* --- partner / member offer cards: the partner's mark owns the card's top half ---
   The logos arrived at their natural sizes (93px next to 48px next to 134px), so
   the cards read as ragged. A fixed media block, contained not cropped, gives every
   partner the same optical weight. No tint/border behind the mark — many logos
   are flat JPGs with their own white canvas baked in, and a colored panel behind
   a white logo just reads as a mismatched white box floating on the card. */
.prose [class*="flex-block"]:not([class*="flex-block"] *, [data-selfstyled] *, [class*="card"]:not([class*="cards"]) *) > img:first-child,
.w-tab-pane [class*="flex-block"]:not([class*="flex-block"] *, [data-selfstyled] *, [class*="card"]:not([class*="cards"]) *) > img:first-child {
  display: block; box-sizing: border-box;
  width: calc(100% + 44px); margin: 0 -22px 18px;
  height: clamp(180px, 20vw, 250px); padding: 26px 24px;
  object-fit: contain; object-position: center;
  background: none;
  border-radius: var(--r-lg) var(--r-lg) 0 0;
}
@media (max-width: 600px) {
  .prose [class*="flex-block"]:not([class*="flex-block"] *, [data-selfstyled] *, [class*="card"]:not([class*="cards"]) *) > img:first-child,
  .w-tab-pane [class*="flex-block"]:not([class*="flex-block"] *, [data-selfstyled] *, [class*="card"]:not([class*="cards"]) *) > img:first-child {
    height: 160px; padding: 20px;
    width: calc(100% + 44px); margin: 0 -22px 16px;
  }
}

.prose [class*="flex-block"]:not([class*="flex-block"] *, [data-selfstyled] *, [class*="card"]:not([class*="cards"]) *):has(> img:first-child),
.w-tab-pane [class*="flex-block"]:not([class*="flex-block"] *, [data-selfstyled] *, [class*="card"]:not([class*="cards"]) *):has(> img:first-child) {
  padding-top: 0 !important; overflow: hidden;
}
/* keep every offer card's mark on the same baseline: content packs from the top
   instead of centring, so logos do not float at different heights card to card.
   min-height + a clamped description keep every card the same footprint whether
   its copy is one line or five, so the grid reads as uniform tiles, not a ragged
   masonry — and the button sits on the same baseline in every card. */
.prose [class*="flex-block"]:not([class*="flex-block"] *, [data-selfstyled] *, [class*="card"]:not([class*="cards"]) *):has(> img:first-child),
.w-tab-pane [class*="flex-block"]:not([class*="flex-block"] *, [data-selfstyled] *, [class*="card"]:not([class*="cards"]) *):has(> img:first-child) {
  justify-content: flex-start !important; align-items: stretch !important;
  min-height: 460px;
}
.prose [class*="flex-block"]:not([class*="flex-block"] *, [data-selfstyled] *, [class*="card"]:not([class*="cards"]) *) > img:first-child,
.w-tab-pane [class*="flex-block"]:not([class*="flex-block"] *, [data-selfstyled] *, [class*="card"]:not([class*="cards"]) *) > img:first-child {
  margin: 0 -22px 18px !important; align-self: stretch !important; max-width: none !important;
}
.prose [class*="flex-block"]:not([class*="flex-block"] *, [data-selfstyled] *, [class*="card"]:not([class*="cards"]) *):has(> img:first-child) > .text-block-37,
.w-tab-pane [class*="flex-block"]:not([class*="flex-block"] *, [data-selfstyled] *, [class*="card"]:not([class*="cards"]) *):has(> img:first-child) > .text-block-37 {
  display: -webkit-box; -webkit-line-clamp: 5; -webkit-box-orient: vertical;
  overflow: hidden; flex: 1 1 auto; margin: 0 0 18px;
}
.prose [class*="flex-block"]:not([class*="flex-block"] *, [data-selfstyled] *, [class*="card"]:not([class*="cards"]) *):has(> img:first-child) > a[class*="button"],
.w-tab-pane [class*="flex-block"]:not([class*="flex-block"] *, [data-selfstyled] *, [class*="card"]:not([class*="cards"]) *):has(> img:first-child) > a[class*="button"] {
  margin-top: auto;
}
@media (max-width: 600px) {
  .prose [class*="flex-block"]:not([class*="flex-block"] *, [data-selfstyled] *, [class*="card"]:not([class*="cards"]) *):has(> img:first-child),
  .w-tab-pane [class*="flex-block"]:not([class*="flex-block"] *, [data-selfstyled] *, [class*="card"]:not([class*="cards"]) *):has(> img:first-child) {
    min-height: 0;
  }
}

/* ---- Member Exclusive Offers, as a fixed four-up grid ----
   The generic auto-fit track (minmax(250px,1fr)) re-flowed this to four columns
   at 1440px and five at 1600px, which is fine for a wall of logos and wrong for
   a list someone curates: "second row" then names a different set of partners at
   every window width, and the logo plate shrinks by a fifth on the wider screen
   where there is more room for it, not less. Four tracks, stated. */
.prose .offergrid {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 24px;
}
@media (max-width: 1100px) { .prose .offergrid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 860px)  { .prose .offergrid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px)  { .prose .offergrid { grid-template-columns: 1fr; } }

/* Four of the 27 offers ship no <h3> and one shipped no logo either (its file had
   been hoisted into the page hero), so those cards rendered as an unattributed
   paragraph over a button — and, missing the `:has(> img:first-child)` test every
   rule above is scoped by, without the card treatment either: centred, short, and
   visibly a hole in the row. render.mjs (repairOfferCards) now names and
   illustrates them from the partner page each already links to, so they meet
   those rules on their own; this pins the parts that are the card's, not the
   image's — one baseline for the mark, one for the name, one for the button. */
.prose .offertile { min-height: 460px; justify-content: flex-start; text-align: center; }
.prose .offertile > img:first-child { border-bottom: 1px solid rgba(2,58,113,.08); }
.prose .offertile > h3 {
  margin: 0 0 12px; font-size: clamp(17px, 1.35vw, 20px); font-weight: 600;
  line-height: 1.3; color: var(--navy); text-wrap: balance;
}
.prose .offertile > a[class*="button"] { width: 100%; }

/* the same spring lift the tier cards answer with, at a smaller amplitude: these
   sit 20+ to a screen, and a 10px lift across a wall of them reads as the grid
   breathing rather than as one card responding */
.prose .offertile {
  transition: transform 420ms var(--spring), box-shadow 340ms var(--ease), border-color 340ms var(--ease);
}
@media (hover: hover) {
  .prose .offertile:hover {
    transform: translateY(-6px) scale(1.012);
    box-shadow: 0 18px 40px rgba(11,36,71,.16);
    border-color: rgba(2,58,113,.26);
  }
  .prose .offertile:hover > img:first-child { transform: scale(1.045); }
  .prose .offertile > img:first-child { transition: transform 520ms var(--ease); }
}

/* once a video is playing, the poster and its button must leave the tab order —
   they were sitting behind the player, still focusable and still announced */
.ytlite.is-playing .ytlite__poster,
.ytlite.is-playing .ytlite__play,
.ytlite.is-playing .ytlite__title { display: none !important; }

/* --- past conventions archive --- */
.pastconv h2 { font-size: clamp(28px, 3.2vw, 42px); color: var(--deep); margin: 0 0 26px; }
.pcgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(270px, 1fr)); gap: 22px; }
.convitem {
  display: flex; flex-direction: column; gap: 8px; padding: 28px 24px; position: relative; overflow: hidden;
  background: var(--white); border: 1px solid rgba(2,58,113,.10);
  border-radius: var(--r-xl); box-shadow: var(--sh-sm);
  transition: transform 220ms var(--ease), box-shadow 220ms var(--ease);
}
.convitem:hover { transform: translateY(-4px); box-shadow: var(--sh-md); }
.convitem::before { content: ""; position: absolute; inset: 0 0 auto 0; height: 4px; background: linear-gradient(90deg, var(--maroon), var(--crimson)); }
.convitem__year {
  font-family: var(--font-head); font-weight: 800; font-size: clamp(34px, 3.4vw, 46px);
  color: var(--deep); line-height: 1; font-variant-numeric: tabular-nums; margin-bottom: 4px;
}
.convitem__edition { margin: 0; font-size: 18px; color: var(--navy); }
.convitem__where { font-weight: 600; color: var(--ink); }
.convitem__venue, .convitem__dates { font-size: 15.5px; color: var(--slate); }
.convitem .btn { align-self: flex-start; margin-top: 14px; }

/* --- newsroom band (homepage close) --- */
.newsband__head { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; flex-wrap: wrap; margin: 0 0 28px; }
.newsband__head h2 { font-size: clamp(28px, 3.2vw, 42px); color: var(--deep); margin: 0; }
.newsgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(290px, 1fr)); gap: 24px; }
.newsitem {
  display: flex; flex-direction: column; text-decoration: none; overflow: hidden;
  background: var(--white); border: 1px solid rgba(2,58,113,.10);
  border-radius: var(--r-xl); box-shadow: var(--sh-sm);
  transition: transform 220ms var(--ease), box-shadow 220ms var(--ease);
}
.newsitem:hover { transform: translateY(-4px); box-shadow: var(--sh-md); }
.newsitem__media { aspect-ratio: 16 / 10; background: var(--sky-50); overflow: hidden; }
.newsitem__media img { width: 100%; height: 100%; object-fit: cover; object-position: center top; display: block; transition: transform 500ms var(--ease); }
.newsitem:hover .newsitem__media img { transform: scale(1.05); }
.newsitem__body { padding: 22px 22px 24px; display: flex; flex-direction: column; gap: 10px; flex: 1; }
.newsitem__body h3 { margin: 0; font-size: 19px; line-height: 1.3; color: var(--navy); }
.newsitem__body p { margin: 0; font-size: 15.5px; color: var(--slate); flex: 1; }
.newsitem__more { font-family: var(--font-head); font-weight: 600; font-size: 14.5px; color: var(--crimson); }
@media (max-width: 600px) { .newsgrid { grid-template-columns: minmax(0, 1fr); } }

/* the donate page's progress meter sits on its own light band */
.goalband { background: linear-gradient(180deg, var(--sky-50), var(--paper)); }

/* Webflow's "change width on scroll" interaction starts these cards as a 144px
   sliver and animates them open. v2 runs no Webflow interactions, so they stayed
   slivers — which is why the photo beside "One of America's Most Unmet Health
   Needs" rendered at 144x81 next to an empty white box. */
.prose [class*="ix_card-change-width"],
.prose [class*="ix_card-change-width"] > [class*="grid_1-col"],
.prose [class*="change-width"] {
  width: 100% !important; max-width: 100% !important; min-width: 0 !important;
  flex: 1 1 auto !important;
}
.prose [class*="ix_card-change-width"] img {
  width: 100% !important; height: auto !important;
  max-height: clamp(280px, 34vw, 520px) !important; object-fit: contain;
}
/* the text card and its photo sit side by side, evenly, instead of staggering */
.prose [class*="flex_horizontal"]:has(> [class*="ix_card-change-width"]) {
  display: grid !important; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)) !important;
  gap: clamp(20px, 3vw, 40px) !important; align-items: center !important;
}
/* that row also stretched the photo card to the tallest column, leaving the small
   source photo (345px wide) floating in an empty 789px box */
.prose [class*="flex_horizontal"]:has([class*="ix_card-change-width"]) { align-items: start !important; }
.prose [class*="ix_card-change-width"] { height: auto !important; align-self: start !important; }
.prose [class*="ix_card-change-width"] > [class*="grid_1-col"] { height: auto !important; }
.prose [class*="ix_card-change-width"] img { margin-inline: auto; }
/* and the side column was a 207px ribbon — give every column room to read */
.prose [class*="width_33percent"] { width: auto !important; min-width: 0 !important; flex: 1 1 320px !important; }

/* ---- partner logos: the logo, nothing else ----
   These were being drawn twice over: my own tile treatment on .div-block-111 (white
   card, border, shadow) plus a rounded, shadowed pill on the image itself. A partner
   mark needs neither — it should sit on the page as artwork. */
[class*="div-block-111"],
a[class*="link-block-mob"],
[class*="logo-tile"],
[class*="div-block-111"]:hover,
a[class*="link-block-mob"]:hover {
  background: none !important; border: 0 !important; box-shadow: none !important;
  border-radius: 0 !important; padding: 10px 14px !important; min-height: 0 !important;
  transform: none !important;
}
[class*="div-block-111"] img,
a[class*="link-block-mob"] img,
[class*="logo-tile"] img {
  border-radius: 0 !important; box-shadow: none !important; background: none !important;
  padding: 0 !important; max-height: 74px !important; width: auto !important; height: auto !important;
  max-width: 100% !important; object-fit: contain !important;
  transition: transform 220ms var(--ease), opacity 220ms var(--ease);
}
[class*="div-block-111"]:hover img, a[class*="link-block-mob"]:hover img { transform: translateY(-2px); }
/* the row itself keeps generous, even spacing without any framing */
[class*="grid_"]:has(> a > [class*="div-block-111"]),
[class*="grid_"]:has(> [class*="div-block-111"]) {
  gap: clamp(22px, 3vw, 44px) !important; align-items: center !important;
}
@media (max-width: 600px) {
  [class*="div-block-111"] img, a[class*="link-block-mob"] img { max-height: 52px !important; }
}
/* the meter sits inside the page's own Campaign Progress block, so it needs no
   heading of its own — just the track under the figures already stated there */
.goalmeter--inline { margin-top: 18px; max-width: 720px; margin-inline: auto; }

/* ---- homepage "Most Unmet Health Needs" band ----
   The original animates a sliver card open and slides side content in. With no
   Webflow interactions this rendered as a 626px text block, a 144px photo stranded
   in ~640px of white, and a 428px column of two cards. Flatten the interaction
   wrappers so every piece becomes a tile in one honest grid. */
.prose [class*="flex_horizontal"]:has(> [class*="ix_card-change-width"]) {
  display: grid !important;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)) !important;
  gap: clamp(18px, 2vw, 26px) !important;
  align-items: start !important;
}
.prose [class*="flex_horizontal"]:has(> [class*="ix_card-change-width"]) > [class*="ix_card-change-width"] { display: contents !important; }
.prose [class*="flex_horizontal"]:has(> [class*="ix_card-change-width"]) > [class*="ix_card-change-width"] > [class*="grid_1-col"] { display: contents !important; }
.prose [class*="flex_horizontal"]:has(> [class*="ix_card-change-width"]) > [class*="width_33percent"] { display: contents !important; }
.prose [class*="flex_horizontal"]:has(> [class*="ix_card-change-width"]) > [class*="width_33percent"] > [class*="ix_card-change-side-content"] { display: contents !important; }
.prose [class*="flex_horizontal"]:has(> [class*="ix_card-change-width"]) > [class*="width_33percent"] > * > [class*="div-block"] { display: contents !important; }
/* the stranded photo becomes a real tile, sized so the small source stays sharp */
.prose [class*="ix_card-change-width-background"] {
  display: block !important; width: auto !important; min-width: 0 !important;
  height: 220px !important; align-self: start !important;
  border-radius: var(--r-lg); overflow: hidden; box-shadow: var(--sh-sm); background: var(--sky-50);
}
.prose [class*="ix_card-change-width-background"] img {
  width: 100% !important; height: 100% !important;
  object-fit: cover !important; object-position: center top !important;
  max-height: none !important; max-width: none !important; border-radius: 0 !important; margin: 0 !important;
}
/* the photo is now its own grid item — give it the card treatment the others have,
   at a height its 345px source can fill without being blown up */
.prose [class*="flex_horizontal"]:has(> [class*="ix_card-change-width"]) [class*="ix_card-change-width-background"] {
  display: block !important; height: 240px !important; min-height: 240px !important;
  align-self: start !important; width: 100% !important;
  border-radius: var(--r-lg) !important; overflow: hidden !important;
  box-shadow: var(--sh-sm) !important; background: var(--sky-50) !important; padding: 0 !important;
}
.prose [class*="flex_horizontal"]:has(> [class*="ix_card-change-width"]) [class*="ix_card-change-width-background"] > img {
  width: 100% !important; height: 240px !important; min-height: 240px !important;
  object-fit: cover !important; object-position: center top !important;
  max-width: none !important; max-height: none !important; border-radius: 0 !important; margin: 0 !important;
}

/* ---- footer: aligned columns, a visible mark ----
   Everything was inheriting the centred text-align of the section above, so the
   columns read as scattered lines, and the navy logo was all but invisible against
   the navy panel. */
.footer, .footer * { text-align: left !important; }
.footer__in { align-items: start !important; }
.footer__brand { display: flex; flex-direction: column; align-items: flex-start; }
.footer__brand img {
  width: 104px; margin-bottom: 16px;
  filter: brightness(0) invert(1);       /* the mark is navy artwork on a navy panel */
  opacity: .95;
}
.footer h4 { margin-top: 0; }
.footer a { padding: 5px 0; }
.footer__bar { justify-content: space-between !important; align-items: center; }
.footer__bar a { display: inline !important; padding: 0 !important; text-decoration: underline; text-underline-offset: 3px; }
@media (max-width: 900px) {
  .footer__in { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; gap: 26px 24px; }
}
@media (max-width: 560px) {
  .footer__in { grid-template-columns: minmax(0, 1fr) !important; }
  .footer__bar { flex-direction: column; align-items: flex-start; gap: 8px; }
}

/* ============================================================
   Logos, everywhere: the mark only.
   No card, no border, no shadow, no white plate — and one common
   size per row so a wordmark and a roundel read as equals. Many
   source files carry a baked-in white background, which no CSS can
   erase; multiply blends that white into the light panel behind it.
   ============================================================ */
/* `[class*="logo"] > a` / `> div` used to close this list. It reached far past the
   partner rows it was written for: across the site its only unique target was the
   family-org logo bar, while it also stripped the white plate off every card in
   the style guide's logo-download grid (.sg-logos-grid > .sg-logo-card >
   .sg-logo-preview). Those cards sit on a near-black navy band, so five of the six
   NDA marks — the navy and black variants — were being drawn dark on dark and
   simply could not be seen. Named the logo bar instead of matching on "logo". */
[class*="div-block-111"], a[class*="link-block-mob"], [class*="logo-tile"],
[class*="family-org"] a, [class*="family-org"] > div,
[class*="partner"] [class*="card_body"], [class*="logo-bar"] > a, [class*="logo-bar"] > div {
  background: none !important; background-color: transparent !important;
  border: 0 !important; box-shadow: none !important; border-radius: 0 !important;
  padding: 8px 12px !important; min-height: 0 !important;
}
[class*="div-block-111"] img, a[class*="link-block-mob"] img, [class*="logo-tile"] img,
[class*="family-org"] img, [class*="card_body"] > img:only-child {
  width: auto !important; height: auto !important;
  max-height: 72px !important; max-width: 100% !important;
  object-fit: contain !important;
  background: transparent !important; box-shadow: none !important;
  border-radius: 0 !important; padding: 0 !important; margin: 0 auto !important;
  mix-blend-mode: multiply;                /* neutralises baked-in white plates */
}
/* on dark panels multiply would erase the mark, so keep those as-is */
.section--dark [class*="link-block-mob"] img, .footer img,
[class*="is-inverse"] img, [class*="on-overlay"] img { mix-blend-mode: normal; }
@media (max-width: 600px) {
  [class*="div-block-111"] img, a[class*="link-block-mob"] img,
  [class*="logo-tile"] img, [class*="family-org"] img,
  [class*="card_body"] > img:only-child { max-height: 52px !important; }
}
/* every logo occupies the same box, so a tall roundel and a wide wordmark read as
   equals rather than one dwarfing the next */
[class*="div-block-111"], a[class*="link-block-mob"], [class*="logo-tile"],
[class*="family-org"] a {
  display: flex !important; align-items: center !important; justify-content: center !important;
  min-height: 96px !important;
}
[class*="div-block-111"] img, a[class*="link-block-mob"] img, [class*="logo-tile"] img,
[class*="family-org"] img {
  height: 72px !important; width: auto !important; max-width: 100% !important;
  object-fit: contain !important;
}
@media (max-width: 600px) {
  [class*="div-block-111"], a[class*="link-block-mob"], [class*="logo-tile"], [class*="family-org"] a { min-height: 72px !important; }
  [class*="div-block-111"] img, a[class*="link-block-mob"] img, [class*="logo-tile"] img, [class*="family-org"] img { height: 52px !important; }
}
/* some marks in the same row are bare <img> children of the grid rather than
   wrapped in a link, so they missed the sizing above — match the whole row */
[class*="grid_"]:has(a[class*="link-block-mob"]) > img,
[class*="grid_"]:has(a[class*="link-block-mob"]) > a > img,
[class*="grid_"]:has([class*="div-block-111"]) > img {
  height: 72px !important; width: auto !important; max-width: 100% !important;
  object-fit: contain !important; margin: 0 auto !important;
  background: transparent !important; box-shadow: none !important; border-radius: 0 !important;
  mix-blend-mode: multiply;
}
@media (max-width: 600px) {
  [class*="grid_"]:has(a[class*="link-block-mob"]) > img,
  [class*="grid_"]:has(a[class*="link-block-mob"]) > a > img,
  [class*="grid_"]:has([class*="div-block-111"]) > img { height: 52px !important; }
}

/* ---------- Family Orgs logo row: bigger marks, tighter spacing (2026-07-26 user pass) ----------
   overrides the 72px sizing above for this specific row — it read as small
   marks lost in a lot of surrounding gap */
.prose .familylogos { gap: 14px !important; align-items: center; }
.prose .familylogos > img, .prose .familylogos a > img, .prose .familylogos a {
  height: 116px !important;
}
@media (max-width: 600px) {
  .prose .familylogos > img, .prose .familylogos a > img, .prose .familylogos a { height: 76px !important; }
}

/* ---------- stat row (3,000+ / 31 / 112): proper tile treatment ----------
   shipped as three bare numbers directly on the section's own flat grey
   background (#f3f4f6 from the original stylesheet) with no card, divider or
   spacing treatment at all */
.prose section.statband {
  background: var(--sky-50) !important; padding-block: var(--flow-sm) !important;
}
.prose .statband [class*="grid_"] {
  display: grid !important; grid-template-columns: repeat(3, 1fr) !important; gap: 0 !important;
  background: var(--white); border: 1px solid rgba(2, 58, 113, .1); border-radius: var(--r-xl);
  box-shadow: var(--sh-md); padding: 44px 20px; margin: 0 auto; max-width: 1100px;
}
.prose .statband [class*="grid_"] > div { padding: 0 28px; position: relative; }
.prose .statband [class*="grid_"] > div + div::before {
  content: ""; position: absolute; left: 0; top: 6px; bottom: 6px; width: 1px;
  background: rgba(2, 58, 113, .14);
}
.prose .statband .heading_huge {
  font-family: var(--font-head); font-weight: 800; color: var(--navy);
  font-size: clamp(42px, 4.6vw, 60px); line-height: 1; margin-bottom: 14px;
}
.prose .statband p { font-size: 15.5px; color: var(--slate); margin: 0; }
@media (max-width: 768px) {
  .prose .statband [class*="grid_"] { grid-template-columns: 1fr !important; gap: 30px !important; padding: 34px 26px; }
  .prose .statband [class*="grid_"] > div + div::before { left: 12px; right: 12px; top: -15px; bottom: auto; width: auto; height: 1px; }
}

/* ---------- "cover" images that were never told to cover ----------
   Webflow names these classes for the fit they are supposed to have —
   image_cover, image_cover-13, image-ratio_16x9 — and wf-layout.css duly gives them
   `width:100%; height:100%` inside a fixed-ratio box. What it never gives them is
   `object-fit`: the property lived in the stylesheet the mirror doesn't carry, and
   the file declares it exactly zero times across all 71 of these images on 8 pages.
   The CSS default is `fill`, so every one of them is squashed to whatever ratio its
   slot happens to be rather than cropped to it. On /resources/nda-new-dentist-hub
   three portrait frames (2:3) are poured into a 2:1 card and render 125% too wide —
   the people in them are more than twice as broad as they are — and the society
   banner (4:3) into 2:1 at 50% too wide.

   Stating the fit their own name promises also hands them back to the framing pass
   in v2.js, which only ever touches a `cover` image: the crop then lands on the
   people in the frame instead of its geometric middle, and a logo that would be
   upscaled past its own resolution is contained rather than blown up.

   It is not only the classes with "cover" in the name. wf-layout.css pins an
   aspect-ratio in 34 different rules — image-ratio_3x2, image-ratio_1x1,
   gallery19_image, bio-hero_image-2, ratio_3x2 — and sets object-fit in none of
   them, so every one of those slots distorts whatever it is given. (The roster
   grid's .team4_image was the same fault, found and fixed on its own earlier;
   this is the rest of the family.) /about/contact runs 20 portrait headshots
   through `.gallery19_image { aspect-ratio: 1 }` and squashes every face by half. */
img[class*="image_cover"],
img[class*="ratio_"],
img[class*="gallery19_image"],
img[class*="bio-hero_image"],
[class*="ratio_"] img { object-fit: cover; }

/* ---------- New Dentist Hub: the three layouts that left holes (/resources/nda-new-dentist-hub) ----------

   1. THE NDSN CARD MOSAIC. Five cards in three tracks, with per-node grid-area rules
   (`#w-node-…{grid-area:span 1/span 2}`) making the 2nd and 3rd span two tracks each.
   Row 1 is 1+2, row 2 is 2+1, and row 3 is the "Join Now!" card alone beside 927px
   of nothing — the section's call to action reading as an accident. The same rules
   size the cards so unevenly that one photograph is 706px wide and the next 395px,
   and each card floats its picture mid-body with dead space underneath.
   Six tracks instead, every card two of them wide: three across the top, and the
   remaining two centred beneath (tracks 2–3 and 4–5). Every card is now the same
   width as every other, and the short last row reads as a deliberate pair rather
   than one card stranded beside a hole. */
.prose [class*="grid_"]:has(> [class*="card-6"]) {
  grid-template-columns: repeat(6, minmax(0, 1fr)) !important;
  align-items: stretch !important;
}
.prose [class*="grid_"]:has(> [class*="card-6"]) > * { grid-area: auto !important; grid-column: span 2 !important; }
.prose [class*="grid_"]:has(> [class*="card-6"]) > :nth-child(4) { grid-column: 2 / span 2 !important; }
.prose [class*="grid_"]:has(> [class*="card-6"]) > :nth-child(5) { grid-column: 4 / span 2 !important; }

/* Inside the card: title, copy, then the picture on the floor at one shape
   throughout, so the titles line up across a row instead of each starting wherever
   the card above it happened to end. Three different structures ship here for the
   same thing — a bare <img>, an .image-ratio wrapper, and a `flex-child_expand`
   wrapper that grows to eat the whole card (that one gave two cards a 627x523
   near-square where their neighbours had a 16:9 strip). Normalise all three. */
.prose [class*="card-6"] > [class*="flex_vertical"] { height: 100%; }
/* the inner column two of the cards wrap their picture in is a passthrough, not a
   second full-height column: left as a flex item it held the picture 155px clear of
   the copy above it. Dissolving it hands the picture straight to the card's column. */
.prose [class*="card-6"] [class*="flex_vertical"] [class*="flex_vertical"] { display: contents; }
.prose [class*="card-6"] [class*="image-ratio"],
.prose [class*="card-6"] > [class*="flex_vertical"] > img {
  flex: 0 0 auto;
  width: 100%; height: auto !important; aspect-ratio: 16 / 9;
  border-radius: var(--r-md); overflow: hidden;
}
.prose [class*="card-6"] [class*="image-ratio"] > img {
  width: 100%; height: 100% !important; aspect-ratio: auto; margin: 0; border-radius: inherit;
}
/* the standfirsts run one line in two cards and two in the other three. Pushing the
   picture to the card floor instead would line the pictures up, but only in a row
   where no card carries a button — and it opens ~95px of blank card under the short
   copy to do it. Holding two lines of space for every standfirst lines the pictures
   up by making the thing above them the same height, with no gap to look at. */
.prose [class*="card-6"] > [class*="flex_vertical"] > p { min-height: 3.4em; margin-bottom: 0; }
/* a card that also carries a button keeps it on the card floor, below the picture */
.prose [class*="card-6"] [class*="button-group"] { margin-top: auto; padding-top: 16px; flex: 0 0 auto; justify-content: center; }
@media (max-width: 900px) {
  .prose [class*="grid_"]:has(> [class*="card-6"]) { grid-template-columns: minmax(0, 1fr) !important; }
  .prose [class*="grid_"]:has(> [class*="card-6"]) > *,
  .prose [class*="grid_"]:has(> [class*="card-6"]) > :nth-child(4),
  .prose [class*="grid_"]:has(> [class*="card-6"]) > :nth-child(5) { grid-column: auto !important; }
}

/* 2. "YOUR FIRST 90 DAYS WITH THE NDA". A two-column grid holding three children —
   heading, the 90-day list, and the CE button — so the first row is heading beside
   list and the second is the button alone under the heading, with the whole
   bottom-right quarter of the band empty. The button belongs to both columns, not
   to the heading: give it the full width and centre it, which closes the hole and
   turns a stray link into the band's call to action. */
.prose .header-25 { align-items: center !important; row-gap: clamp(18px, 2vw, 26px) !important; }
.prose .header-25 > :last-child {
  grid-column: 1 / -1 !important; justify-content: center !important; margin-top: 0 !important;
}
/* the 90-day plan is a list — "Week 1:", "Weeks 2–4:", "Month 2:" — and centring it
   set every wrapped item as a ragged pyramid with its label floating mid-line.
   Flush left, the four milestones read down the column as the sequence they are. */
.prose .header-25 > p { text-align: left !important; margin-bottom: 0 !important; }
@media (max-width: 900px) {
  /* two 143px columns on a phone set the heading three words to the line beside a
     list doing the same — this band is one of the `is-2-col` grids the mirror never
     shipped a breakpoint rule for */
  .prose .header-25 { grid-template-columns: minmax(0, 1fr) !important; }
}

/* 4. THE WELCOME CARD'S GRID. It holds a single card, and the mirror kept the track
   list but not the rule that spanned the card across it — worse, the track list
   itself came through damaged: `grid-10` resolves to `0px 0px 441px 441px 441px`,
   five tracks two of which are nothing. On a phone that squeezes the welcome copy
   into 46px of a 318px screen. A grid with one child needs exactly one track, and
   that is true of every such grid, not just this one.
   The track list alone isn't enough: the card carries `grid-area: 1/3/2/6` of its
   own, which conjures the five implicit tracks back whatever the template says. The
   placement has to go with it. */
.prose .w-layout-grid:has(> :only-child),
.prose [class*="grid_"]:has(> :only-child) { grid-template-columns: minmax(0, 1fr) !important; }
.prose .w-layout-grid:has(> :only-child) > *,
.prose [class*="grid_"]:has(> :only-child) > * { grid-area: auto !important; grid-column: 1 / -1 !important; }

/* 3. THE FAQ. Its eyebrow is a full-width flex row, so "FAQ: NEW DENTIST ESSENTIALS"
   sat hard against the left margin while the heading and every answer under it were
   centred — and centring the answers themselves set two-line replies as ragged
   pyramids across a 673px measure. Centre the eyebrow with the heading it belongs
   to, then set the questions and answers flush left where they read as a list. */
.prose .header-26 [class*="eyebrow"] { justify-content: center !important; }
.prose [class*="grid_2-col"]:has(> * > [class*="heading_h4"]) { align-items: start !important; }
.prose [class*="grid_2-col"]:has(> * > [class*="heading_h4"]) > * { text-align: left !important; }

/* ---------- Member Benefits (join-us/membership/membership-offers, 2026-07-26) ----------
   5 benefits shipped as a flat stack of bold heading + paragraph + a 1px bottom
   divider — no card, icon or grid treatment at all. Proper icon-card grid instead. */
.prose .benefitgrid {
  display: grid !important; grid-template-columns: repeat(2, 1fr) !important; gap: 20px !important;
  margin: 1.4em 0 !important;
}
.prose .benefitgrid .divider-5 {
  border-bottom: 0 !important; border: 1px solid rgba(2, 58, 113, .1); border-radius: var(--r-lg);
  background: var(--white); box-shadow: var(--sh-sm); padding: 24px 24px 22px 66px !important;
  position: relative; transition: transform 200ms var(--ease), box-shadow 200ms var(--ease);
}
.prose .benefitgrid .divider-5:hover { transform: translateY(-3px); box-shadow: var(--sh-md); }
.prose .benefitgrid .divider-5::before {
  content: "\2713"; position: absolute; top: 22px; left: 22px; width: 30px; height: 30px;
  border-radius: 50%; background: linear-gradient(135deg, var(--maroon), var(--crimson));
  color: #fff; font-size: 14px; font-weight: 700; line-height: 30px; text-align: center;
}
.prose .benefitgrid .heading_h4-12 { color: var(--navy); font-size: 18px; margin: 0 0 8px; }
.prose .benefitgrid .rich-text-9 p { color: var(--slate); font-size: 15px; line-height: 1.6; margin: 0; }
@media (max-width: 760px) { .prose .benefitgrid { grid-template-columns: 1fr !important; } }

/* "See Our Endorsed Programs → View Offers" (membership-offers only): a bare
   line of text plus a button floating with no visual container at all */
.prose .div-block-117 {
  display: flex !important; align-items: center; justify-content: center; gap: 22px;
  flex-wrap: wrap; background: var(--sky-50); border: 1px solid rgba(2, 58, 113, .1);
  border-radius: var(--r-xl); padding: 22px 32px; margin: 1.6em 0;
}
.prose .div-block-117 .scroll_text {
  margin: 0; font-family: var(--font-head); font-weight: 600; font-size: 17px; color: var(--navy);
}

/* ============================================================
   Gallery (/about/gallery)
   Six event albums, each a full-width band with its own header, a
   flush photo mosaic and the outbound pic-time link stated twice
   (header + footer) so the link is never more than a screen away.
   ============================================================ */

.gal-hero .hero__grid { align-items: center; }
.gal-hero__media { display: grid; gap: 18px; grid-template-columns: 1fr 1fr; }
.gal-hero__shot { margin: 0; border-radius: var(--r-xl); overflow: hidden; box-shadow: var(--sh-lg); }
.gal-hero__shot img { width: 100%; height: 100%; object-fit: cover; object-position: center top; display: block; }
.gal-hero__shot--1 { aspect-ratio: 3/4; transform: translateY(-14px); }
.gal-hero__shot--2 { aspect-ratio: 3/4; transform: translateY(14px); }
@media (max-width: 900px) {
  .gal-hero__shot--1, .gal-hero__shot--2 { transform: none; aspect-ratio: 1/1; }
}

/* the marquee the original ran under the hero, rebuilt without its runtime JS */
.gal-strip { overflow: hidden; padding: 22px 0; background: linear-gradient(120deg, var(--deep), var(--navy)); }
.gal-strip__track { display: flex; gap: 22px; width: max-content; animation: galStrip 90s linear infinite; }
.gal-strip:hover .gal-strip__track { animation-play-state: paused; }
.gal-strip__item { flex: 0 0 auto; width: clamp(200px, 22vw, 320px); aspect-ratio: 4/3; border-radius: var(--r-md); overflow: hidden; box-shadow: 0 10px 26px rgba(0,0,0,.32); }
.gal-strip__item img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 0%; }
@keyframes galStrip { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) {
  .gal-strip__track { animation: none; overflow-x: auto; }
}

.gal-jump { position: sticky; top: 72px; z-index: 30; background: rgba(255,255,255,.92); -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); border-bottom: 1px solid var(--nav-rule); }
.gal-jump__in { display: flex; align-items: center; gap: 18px; padding-block: 12px; }
.gal-jump__label { font-family: var(--font-head); font-weight: 700; font-size: 12px; letter-spacing: .12em; text-transform: uppercase; color: var(--maroon); flex: 0 0 auto; }
/* the rail scrolls when six album names outrun the viewport — fade the cut edge
   so the overflow reads as "more this way" rather than a chip sliced in half */
.gal-jump__links {
  display: flex; gap: 8px; overflow-x: auto; scrollbar-width: none; padding-block: 2px;
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 44px), transparent);
  mask-image: linear-gradient(90deg, #000 calc(100% - 44px), transparent);
}
.gal-jump__links::-webkit-scrollbar { display: none; }
.chip--link { flex: 0 0 auto; text-decoration: none; white-space: nowrap; transition: background var(--t) var(--ease), color var(--t) var(--ease); }
.chip--link:hover { background: var(--navy); color: #fff; border-color: var(--navy); }
/* the mobile header is a two-row grid of its own — a second sticky bar under it
   eats half the screen, so the album rail scrolls away with the page there */
@media (max-width: 991px) { .gal-jump { position: static; } }
@media (max-width: 700px) { .gal-jump__label { display: none; } }

.gal-album { padding-block: clamp(56px, 6.4vw, 104px); scroll-margin-top: 132px; }
.gal-album--dark { background: linear-gradient(170deg, var(--deep) 0%, var(--navy) 100%); color: #fff; }
.gal-album--dark h2 { color: #fff; }
.gal-album--dark .lead { color: rgba(234,243,254,.82); }
.gal-album--dark .eyebrow { color: var(--sky); }
.gal-album--dark .gal-album__foot { border-top-color: rgba(255,255,255,.16); }
.gal-album--dark .gal-album__foot p { color: rgba(234,243,254,.72); }
.gal-album:not(.gal-album--dark) { background: var(--sky-50); }

.gal-album__head { display: flex; align-items: flex-end; justify-content: space-between; gap: 28px; flex-wrap: wrap; margin: 0 0 clamp(26px, 3vw, 40px); }
.gal-album__head h2 { font-size: clamp(30px, 3.8vw, 50px); margin: 0 0 10px; max-width: 20ch; }
.gal-album__head .lead { margin: 0; max-width: 56ch; }
.gal-album__cta { flex: 0 0 auto; }

.gal-rows { display: flex; flex-direction: column; gap: 16px; }
.gal-row { display: flex; gap: 16px; height: clamp(200px, 25vw, 380px); }
.gal-row--1 { height: clamp(240px, 32vw, 500px); }
.gal-shot { margin: 0; min-width: 0; border-radius: var(--r-lg); overflow: hidden; background: rgba(11,36,71,.08); box-shadow: var(--sh-md); }
.gal-shot img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 0%; cursor: zoom-in; transition: transform 420ms var(--ease); }
.gal-shot:hover img { transform: scale(1.045); }
@media (max-width: 900px) {
  .gal-row, .gal-row--1 { display: grid; grid-template-columns: 1fr 1fr; height: auto; }
  .gal-shot { aspect-ratio: 4/3; }
  .gal-shot[style] { flex: none !important; }
}
/* stay 2-up on phones (what the original did too): one photo per row turned a
   6-album page into a 19,000px scroll */
@media (max-width: 520px) { .gal-row { gap: 10px; } .gal-rows { gap: 10px; } .gal-row--1 { grid-template-columns: 1fr; } }

.gal-album__foot { display: flex; align-items: center; justify-content: space-between; gap: 20px; flex-wrap: wrap; margin-top: clamp(24px, 2.6vw, 36px); padding-top: 22px; border-top: 1px solid rgba(2,58,113,.14); }
.gal-album__foot p { margin: 0; font-size: 15px; color: var(--slate); }

.gal-faq__in { display: grid; grid-template-columns: .85fr 1.15fr; gap: clamp(28px, 4vw, 64px); align-items: start; }
.gal-faq__head h2 { font-size: clamp(28px, 3.2vw, 42px); color: var(--deep); }
.gal-faq__head .lead { margin: 0; }
.gal-faq__list { display: flex; flex-direction: column; gap: 12px; }
.gal-faq__item { background: var(--white); border: 1px solid rgba(2,58,113,.12); border-radius: var(--r-lg); box-shadow: var(--sh-sm); padding: 20px 24px; }
.gal-faq__item summary { cursor: pointer; list-style: none; font-family: var(--font-head); font-weight: 600; font-size: 18px; color: var(--navy); display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.gal-faq__item summary::-webkit-details-marker { display: none; }
.gal-faq__item summary::after { content: "+"; font-size: 24px; font-weight: 400; line-height: 1; color: var(--crimson); flex: 0 0 auto; transition: transform var(--t) var(--ease); }
.gal-faq__item[open] summary::after { content: "–"; }
.gal-faq__item p { margin: 12px 0 0; color: var(--slate); font-size: 16px; }
@media (max-width: 860px) { .gal-faq__in { grid-template-columns: 1fr; } }

/* ============================================================
   Events calendar (/events/calendar-view, /events/new-events-page)
   Month · Week · Day · Agenda · Year over the portal's calendar_feed
   ============================================================ */

.u-sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.btn--sm { min-height: 40px; padding: 8px 18px; font-size: 14.5px; }

.ndacal {
  --cal-line: rgba(2,58,113,.13);
  --cal-line-soft: rgba(2,58,113,.07);
  /* source colours ride the theme tokens so the design-proposal themes recolour
     the calendar with the rest of the page */
  --cal-national: var(--navy); --cal-site: var(--crimson);
  --cal-society: #1D6FB8; --cal-district: var(--slate);
  margin-top: clamp(24px, 3vw, 38px);
  background: var(--white); border: 1px solid var(--cal-line);
  border-radius: var(--r-xl); box-shadow: var(--sh-md); overflow: hidden;
}
.ndacal *, .ndacal *::before, .ndacal *::after { box-sizing: border-box; }

/* ---------- toolbar ---------- */
.ndacal__bar {
  display: flex; align-items: center; justify-content: space-between; gap: 18px; flex-wrap: wrap;
  padding: 18px clamp(16px, 2vw, 26px); border-bottom: 1px solid var(--cal-line);
  background: linear-gradient(180deg, var(--sky-50), var(--white));
}
.ndacal__nav { display: flex; align-items: center; gap: 8px; min-width: 0; }
.ndacal__ib {
  width: 40px; height: 40px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%; border: 1px solid var(--cal-line); background: var(--white); color: var(--navy);
  cursor: pointer; transition: background-color var(--t) var(--ease), color var(--t) var(--ease), border-color var(--t) var(--ease);
}
.ndacal__ib svg { width: 20px; height: 20px; }
.ndacal__ib:hover { background: var(--navy); border-color: var(--navy); color: #fff; }
.ndacal__today { margin-left: 4px; }
.ndacal__title {
  margin: 0 0 0 10px; font-size: clamp(19px, 2vw, 26px); font-weight: 700; color: var(--deep);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ndacal__views { display: flex; gap: 2px; padding: 4px; background: var(--sky-100); border-radius: 999px; flex-wrap: wrap; }
.ndacal__view {
  font-family: var(--font-head); font-weight: 600; font-size: 14px; letter-spacing: .01em;
  padding: 9px 17px; border-radius: 999px; border: 0; background: transparent; color: var(--navy);
  cursor: pointer; transition: background-color var(--t) var(--ease), color var(--t) var(--ease);
}
.ndacal__view:hover { background: rgba(255,255,255,.7); }
.ndacal__view[aria-selected="true"] { background: var(--navy); color: #fff; box-shadow: var(--sh-sm); }

/* ---------- filters ---------- */
.ndacal__filters {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 14px clamp(16px, 2vw, 26px); border-bottom: 1px solid var(--cal-line); background: var(--white);
}
.ndacal__search { position: relative; display: flex; align-items: center; flex: 1 1 220px; max-width: 320px; }
.ndacal__search svg { position: absolute; left: 13px; width: 18px; height: 18px; color: var(--slate); pointer-events: none; }
.ndacal__search input {
  width: 100%; font-family: var(--font-body); font-size: 15px; color: var(--ink);
  padding: 10px 14px 10px 40px; border: 1px solid var(--cal-line); border-radius: 999px; background: var(--paper);
}
.ndacal__search input::-webkit-search-cancel-button { cursor: pointer; }
.ndacal__sel select {
  font-family: var(--font-body); font-size: 15px; color: var(--ink); cursor: pointer;
  padding: 10px 34px 10px 15px; border: 1px solid var(--cal-line); border-radius: 999px; background: var(--paper);
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%233B475A' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center; background-size: 15px;
}
.ndacal__count { margin-left: auto; font-size: 14px; color: var(--slate); font-weight: 500; }

/* ---------- stage ---------- */
.ndacal__stage { padding: clamp(14px, 1.8vw, 22px); min-height: 320px; overflow-x: auto; }
.ndacal-empty {
  margin: 0; padding: 56px 20px; text-align: center; color: var(--slate); font-size: 16.5px;
  display: flex; flex-direction: column; align-items: center; gap: 16px;
}
.ndacal-empty strong { display: block; font-family: var(--font-head); font-size: 19px; color: var(--deep); }

/* ---------- month ---------- */
.ndacal-month { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 1px; background: var(--cal-line-soft); border: 1px solid var(--cal-line); border-radius: var(--r-md); overflow: hidden; }
.ndacal-month__wd { background: var(--sky-50); padding: 10px 8px; text-align: center; font-family: var(--font-head); font-weight: 600; font-size: 12.5px; letter-spacing: .1em; text-transform: uppercase; color: var(--navy); }
.ndacal-cell { background: var(--white); min-height: 122px; padding: 7px 8px 9px; display: flex; flex-direction: column; gap: 4px; text-align: left; border: 0; font: inherit; cursor: pointer; transition: background-color 160ms var(--ease); }
.ndacal-cell:hover { background: var(--sky-50); }
.ndacal-cell.is-out { background: #FBFCFE; }
.ndacal-cell.is-out .ndacal-cell__n { color: #9AA7B8; }
.ndacal-cell__n { font-family: var(--font-head); font-weight: 600; font-size: 14.5px; color: var(--slate); width: 27px; height: 27px; display: inline-flex; align-items: center; justify-content: center; border-radius: 50%; flex: 0 0 auto; }
.ndacal-cell.is-today .ndacal-cell__n { background: var(--crimson); color: #fff; }
.ndacal-cell.is-weekend { background: #FCFDFF; }
.ndacal-chip {
  display: block; width: 100%; text-align: left; border: 0; font: inherit; cursor: pointer;
  font-size: 12.4px; line-height: 1.35; font-weight: 600; color: #fff;
  padding: 4px 7px; border-radius: 6px; background: var(--cal-national);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  transition: filter var(--t) var(--ease), transform var(--t) var(--ease);
}
.ndacal-chip:hover { filter: brightness(1.15); transform: translateX(1px); }
.ndacal-chip time { font-weight: 500; opacity: .85; margin-right: 4px; }
.ndacal-chip--site { background: var(--cal-site); }
.ndacal-chip--society { background: var(--cal-society); }
.ndacal-chip--district { background: var(--cal-district); }
.ndacal-chip.is-mid { background-image: linear-gradient(90deg, rgba(255,255,255,.22), rgba(255,255,255,0) 60%); }
.ndacal-more { border: 0; background: none; font: inherit; font-size: 12px; font-weight: 600; color: var(--navy); cursor: pointer; text-align: left; padding: 1px 7px; }
.ndacal-more:hover { text-decoration: underline; }

/* ---------- week / day time grid ---------- */
.ndacal-tg { border: 1px solid var(--cal-line); border-radius: var(--r-md); overflow: hidden; }
.ndacal-tg__head { display: grid; background: var(--sky-50); border-bottom: 1px solid var(--cal-line); }
.ndacal-tg__gut { width: 66px; flex: 0 0 66px; }
.ndacal-tg__dh { padding: 9px 6px; text-align: center; border-left: 1px solid var(--cal-line-soft); }
.ndacal-tg__dh span { display: block; font-family: var(--font-head); font-size: 11.5px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase; color: var(--slate); }
.ndacal-tg__dh b { font-family: var(--font-head); font-size: 20px; font-weight: 700; color: var(--deep); display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px; border-radius: 50%; margin-top: 2px; }
.ndacal-tg__dh.is-today b { background: var(--crimson); color: #fff; }
.ndacal-tg__allday { display: grid; border-bottom: 1px solid var(--cal-line); background: #FCFDFF; min-height: 40px; }
.ndacal-tg__allday-lbl { font-size: 11.5px; font-weight: 600; color: var(--slate); padding: 8px 8px; text-align: right; text-transform: uppercase; letter-spacing: .06em; }
.ndacal-tg__allday-col { border-left: 1px solid var(--cal-line-soft); padding: 5px 4px; display: flex; flex-direction: column; gap: 3px; }
.ndacal-tg__body { display: grid; position: relative; max-height: 640px; overflow-y: auto; }
.ndacal-tg__hours { border-right: 1px solid var(--cal-line-soft); }
.ndacal-tg__hr { height: 52px; position: relative; }
.ndacal-tg__hr span { position: absolute; top: 3px; right: 8px; font-size: 11.5px; color: var(--slate); }
.ndacal-tg__col { position: relative; border-left: 1px solid var(--cal-line-soft); }
.ndacal-tg__col.is-weekend { background: #FCFDFF; }
.ndacal-tg__slot { height: 52px; border-bottom: 1px solid var(--cal-line-soft); }
.ndacal-ev {
  position: absolute; border: 0; font: inherit; cursor: pointer; text-align: left; overflow: hidden;
  display: flex; flex-direction: column; align-items: flex-start; justify-content: flex-start;
  border-radius: 7px; padding: 5px 7px; color: #fff; background: var(--cal-national);
  box-shadow: 0 1px 3px rgba(11,36,71,.2); min-height: 22px;
  transition: filter var(--t) var(--ease);
}
.ndacal-ev:hover { filter: brightness(1.12); z-index: 3; }
.ndacal-ev--site { background: var(--cal-site); }
.ndacal-ev--society { background: var(--cal-society); }
.ndacal-ev--district { background: var(--cal-district); }
.ndacal-ev b { display: block; font-size: 12.6px; font-weight: 700; line-height: 1.25; }
.ndacal-ev time { font-size: 11.5px; opacity: .9; }
.ndacal-now { position: absolute; left: 0; right: 0; height: 2px; background: var(--crimson); z-index: 4; pointer-events: none; }
.ndacal-now::before { content: ""; position: absolute; left: -5px; top: -4px; width: 10px; height: 10px; border-radius: 50%; background: var(--crimson); }

/* ---------- agenda ---------- */
.ndacal-agenda { display: flex; flex-direction: column; }
.ndacal-agenda__month {
  margin: 26px 0 12px; font-family: var(--font-head); font-size: 15px; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--crimson);
  padding-bottom: 8px; border-bottom: 1px solid var(--cal-line);
}
.ndacal-agenda__month:first-child { margin-top: 4px; }
.ndacal-row { display: grid; grid-template-columns: 78px 1fr; gap: 18px; padding: 16px 6px; border-bottom: 1px solid var(--cal-line-soft); align-items: start; }
.ndacal-row:hover { background: var(--sky-50); }
.ndacal-row.is-past { opacity: .62; }
.ndacal-row__date { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 10px 4px; background: var(--sky-100); border-radius: var(--r-md); }
.ndacal-row__wd { font-size: 11.5px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--slate); }
.ndacal-row__d { font-family: var(--font-head); font-size: 27px; font-weight: 700; line-height: 1.05; color: var(--navy); }
.ndacal-row__mo { font-size: 12px; font-weight: 600; color: var(--slate); text-transform: uppercase; letter-spacing: .06em; }
.ndacal-row__tags { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 7px; }
.ndacal-row__title { margin: 0 0 6px; font-family: var(--font-head); font-size: clamp(17px, 1.7vw, 20px); font-weight: 700; color: var(--deep); line-height: 1.25; }
.ndacal-row__meta { font-size: 14.5px; color: var(--slate); }
.ndacal-row__desc { margin: 9px 0 0; font-size: 15px; color: var(--slate); max-width: 74ch; }
.ndacal-row__acts { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 13px; }
.ndacal-tag {
  display: inline-flex; align-items: center; font-family: var(--font-head); font-size: 11.5px; font-weight: 600;
  letter-spacing: .07em; text-transform: uppercase; padding: 4px 10px; border-radius: 999px;
  background: var(--sky-100); color: var(--navy);
}
.ndacal-tag--national { background: rgba(2,58,113,.12); color: var(--cal-national); }
.ndacal-tag--site { background: rgba(139,21,56,.12); color: var(--cal-site); }
.ndacal-tag--society { background: rgba(29,111,184,.14); color: var(--cal-society); }
.ndacal-tag--district { background: rgba(59,71,90,.13); color: var(--cal-district); }
.ndacal-tag--virtual { background: rgba(2,58,113,.08); color: var(--slate); }

/* ---------- year ---------- */
.ndacal-year { display: grid; grid-template-columns: repeat(auto-fit, minmax(212px, 1fr)); gap: clamp(14px, 1.6vw, 22px); }
.ndacal-mini { border: 1px solid var(--cal-line); border-radius: var(--r-md); padding: 12px 12px 14px; background: var(--white); }
.ndacal-mini.is-empty { opacity: .55; }
.ndacal-mini__h { border: 0; background: none; font: inherit; cursor: pointer; width: 100%; text-align: left; font-family: var(--font-head); font-size: 15px; font-weight: 700; color: var(--deep); margin-bottom: 8px; }
.ndacal-mini__h:hover { color: var(--crimson); }
.ndacal-mini__g { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.ndacal-mini__wd { font-size: 10px; font-weight: 600; color: var(--slate); text-align: center; padding-bottom: 3px; }
.ndacal-mini__d { aspect-ratio: 1; border: 0; background: none; font: inherit; font-size: 11.5px; color: var(--slate); border-radius: 50%; display: flex; align-items: center; justify-content: center; position: relative; }
.ndacal-mini__d.is-out { color: transparent; pointer-events: none; }
.ndacal-mini__d.is-today { outline: 1.5px solid var(--crimson); }
.ndacal-mini__d.has-ev { background: var(--navy); color: #fff; font-weight: 700; cursor: pointer; }
.ndacal-mini__d.has-ev:hover { background: var(--crimson); }
.ndacal-mini__d.has-ev--site { background: var(--cal-site); }
.ndacal-mini__d.has-ev--society { background: var(--cal-society); }
.ndacal-mini__d.has-ev--district { background: var(--cal-district); }

/* ---------- footer / legend ---------- */
.ndacal__foot { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; padding: 15px clamp(16px, 2vw, 26px); border-top: 1px solid var(--cal-line); background: var(--sky-50); }
.ndacal__legend { display: flex; flex-wrap: wrap; gap: 16px; }
.ndacal-key { display: inline-flex; align-items: center; gap: 7px; font-size: 13.5px; font-weight: 600; color: var(--slate); }
.ndacal-key::before { content: ""; width: 11px; height: 11px; border-radius: 3px; background: var(--cal-national); }
.ndacal-key--site::before { background: var(--cal-site); }
.ndacal-key--society::before { background: var(--cal-society); }
.ndacal-key--district::before { background: var(--cal-district); }
.ndacal__footacts { display: flex; gap: 10px; flex-wrap: wrap; }

/* ---------- detail modal ---------- */
.ndacal-modal { position: fixed; inset: 0; z-index: 1200; display: flex; align-items: center; justify-content: center; padding: 20px; background: rgba(11,36,71,.55); backdrop-filter: blur(3px); }
.ndacal-modal[hidden] { display: none; }
.ndacal-modal__panel { position: relative; width: min(640px, 100%); max-height: 88vh; overflow-y: auto; background: var(--white); border-radius: var(--r-xl); box-shadow: var(--sh-lg); padding: clamp(24px, 3vw, 36px); }
.ndacal-modal__x { position: absolute; top: 12px; right: 14px; width: 38px; height: 38px; border-radius: 50%; border: 0; background: var(--sky-100); color: var(--navy); font-size: 26px; line-height: 1; cursor: pointer; }
.ndacal-modal__x:hover { background: var(--navy); color: #fff; }
.ndacal-modal h4 { margin: 10px 0 14px; font-family: var(--font-head); font-size: clamp(21px, 2.4vw, 28px); font-weight: 700; color: var(--deep); padding-right: 34px; }
.ndacal-modal__tags { display: flex; flex-wrap: wrap; gap: 6px; }
.ndacal-modal__facts { display: grid; gap: 12px; margin: 0 0 18px; }
.ndacal-modal__fact { display: grid; grid-template-columns: 22px 1fr; gap: 11px; align-items: start; font-size: 15.5px; color: var(--ink); }
.ndacal-modal__fact svg { width: 20px; height: 20px; color: var(--crimson); margin-top: 1px; }
.ndacal-modal__desc { font-size: 15.5px; color: var(--slate); margin: 0 0 20px; }
.ndacal-modal__acts { display: flex; flex-wrap: wrap; gap: 10px; padding-top: 16px; border-top: 1px solid var(--cal-line); }

/* ---------- responsive ---------- */
@media (max-width: 900px) {
  .ndacal__bar { padding: 14px 14px; }
  .ndacal__title { margin-left: 6px; font-size: 18px; }
  .ndacal__views { width: 100%; justify-content: space-between; }
  .ndacal__view { flex: 1 1 auto; padding: 9px 8px; text-align: center; font-size: 13px; }
  .ndacal__count { margin-left: 0; width: 100%; }
}
@media (max-width: 700px) {
  .ndacal-cell { min-height: 74px; padding: 5px 4px; gap: 2px; align-items: center; }
  .ndacal-cell__n { width: 24px; height: 24px; font-size: 13px; }
  .ndacal-month__wd { font-size: 10.5px; letter-spacing: .04em; padding: 8px 2px; }
  .ndacal-chip { font-size: 0; padding: 0; height: 7px; border-radius: 4px; }
  .ndacal-chip time { display: none; }
  .ndacal-more { font-size: 10.5px; padding: 0; }
  .ndacal-row { grid-template-columns: 62px 1fr; gap: 12px; }
  .ndacal-row__d { font-size: 22px; }
  .ndacal-tg__gut { width: 48px; flex-basis: 48px; }
  /* a 7px bar is not a tap target — on phones the whole cell opens that day */
  .ndacal-chip { pointer-events: none; height: 8px; }
  .ndacal-tg__allday-col .ndacal-chip { pointer-events: auto; }
  /* !important because the site's mobile-overflow guard sets `min-width: 0
     !important` on every descendant of .prose/.w-embed, which is exactly where
     the calendar is mounted. Scroll the week rather than crush it. */
  .ndacal-tg--week { min-width: 620px !important; }
  .ndacal-year { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
  .ndacal__foot { flex-direction: column; align-items: flex-start; }
}

/* ============================================================
   History timeline (/about/about-us)
   The original is a Webflow IX2 component v2 does not run, so it
   froze into a 411px date column beside a 180px text column. This
   is the same content as a scroll-driven chronology: a sticky year
   that tracks position, a spine with a dot per event, cards that
   carry each date + story + photo, and a band colour that changes
   as each event takes the viewport.
   ============================================================ */
.tl {
  --tl-bg: #F2F8FE; --tl-ink: var(--ink); --tl-accent: var(--navy);
  --tl-card: #FFFFFF; --tl-line: rgba(2,58,113,.16); --tl-muted: var(--slate);
  position: relative; isolation: isolate;
  color: var(--tl-ink);
  margin-inline: calc(50% - 50vw);
  padding-inline: max(20px, calc(50vw - 680px));
  padding-block: clamp(44px, 6vw, 84px);
  margin-block: clamp(30px, 5vw, 56px);
  transition: color 620ms var(--ease);
}
/* the wash is painted by a pseudo-element pinned to the viewport width rather
   than by .tl itself: negative-margin full-bleed depends on the ancestor's own
   width, and inside the prose column it left ~140px of the right edge unpainted */
.tl::before {
  content: ""; position: absolute; top: 0; bottom: 0;
  left: var(--wash-l, 50%); width: var(--wash-w, 100vw); transform: translateX(var(--wash-t, -50%));
  background: var(--tl-bg); z-index: -1;
  transition: background-color 620ms var(--ease);
}
/* one wash per event; the closing two go deep navy */
.tl[data-tone="0"] { --tl-bg: #F2F8FE; --tl-accent: #023A71; --tl-line: rgba(2,58,113,.16); }
.tl[data-tone="1"] { --tl-bg: #FBF4F6; --tl-accent: #8B1538; --tl-line: rgba(113,29,58,.18); }
.tl[data-tone="2"] { --tl-bg: #EEF3F9; --tl-accent: #0B2447; --tl-line: rgba(11,36,71,.18); }
.tl[data-tone="3"] { --tl-bg: #E7F1FD; --tl-accent: #023A71; --tl-line: rgba(2,58,113,.22); }
.tl[data-tone="4"] {
  --tl-bg: #0B2447; --tl-ink: #FEFEFE; --tl-accent: #94C5F8;
  --tl-card: rgba(255,255,255,.06); --tl-line: rgba(148,197,248,.34); --tl-muted: rgba(255,255,255,.82);
}
.tl__in { display: grid; grid-template-columns: 208px minmax(0, 1fr); gap: clamp(22px, 3vw, 52px); align-items: start; }

/* sticky rail: the current year, how far through, and a jump list */
.tl__rail { position: sticky; top: calc(var(--navH, 84px) + 16px); }
.tl__badge { display: flex; flex-direction: column; gap: 10px; }
.tl__count { font-family: var(--font-head); font-weight: 600; font-size: 13px; letter-spacing: .14em; color: var(--tl-muted); }
.tl__count i { font-style: normal; opacity: .5; margin: 0 2px; }
.tl__year {
  font-family: var(--font-head); font-weight: 700; line-height: 1.1;
  font-size: clamp(26px, 2.9vw, 40px); color: var(--tl-accent); text-wrap: balance;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
/* a few entries are titles rather than years ("Family Organizations and the NDA
   Network") and at year size they filled the rail — they step down instead */
.tl__year.is-long { font-size: clamp(17px, 1.55vw, 21px); line-height: 1.25; -webkit-line-clamp: 3; }
.tl__track { display: block; height: 4px; border-radius: 999px; background: var(--tl-line); overflow: hidden; }
.tl__fill { display: block; height: 100%; width: 8%; background: var(--tl-accent); border-radius: 999px; transition: width 420ms var(--ease); }
.tl__marks { display: flex; flex-direction: column; gap: 1px; margin-top: 20px; max-height: 46vh; overflow: auto; }
.tl__mark {
  appearance: none; background: none; border: 0; cursor: pointer; text-align: left;
  font-family: var(--font-head); font-size: 13.5px; line-height: 1.3; color: var(--tl-muted);
  padding: 7px 10px; border-radius: 8px; border-left: 2px solid transparent;
  transition: color var(--t) var(--ease), background-color var(--t) var(--ease), border-color var(--t) var(--ease);
}
.tl__mark span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tl__mark:hover { color: var(--tl-accent); background: rgba(255,255,255,.5); }
.tl[data-tone="4"] .tl__mark:hover { background: rgba(255,255,255,.1); }
.tl__mark.is-active { color: var(--tl-accent); font-weight: 700; border-left-color: var(--tl-accent); }

/* the spine and its events */
.tl__items { list-style: none; margin: 0; padding: 0 0 0 36px; position: relative; }
.tl__items::before { content: ""; position: absolute; left: 9px; top: 14px; bottom: 14px; width: 2px; background: var(--tl-line); }
.tl__item { position: relative; padding-bottom: clamp(26px, 3.4vw, 46px); scroll-margin-top: calc(var(--navH, 90px) + 28px); }
.tl__item:last-child { padding-bottom: 0; }
.tl__pin {
  position: absolute; left: -36px; top: 30px; width: 20px; height: 20px; border-radius: 999px;
  background: var(--tl-bg); border: 3px solid var(--tl-line);
  transition: border-color 380ms var(--ease), box-shadow 380ms var(--ease), transform 380ms var(--ease);
}
.tl__item.is-active .tl__pin { border-color: var(--tl-accent); transform: scale(1.15); box-shadow: 0 0 0 6px rgba(148,197,248,.28); }
.tl__panel {
  background: var(--tl-card); border: 1px solid var(--tl-line); border-radius: var(--r-lg);
  padding: clamp(20px, 2.3vw, 32px); box-shadow: var(--sh-sm);
  transition: box-shadow 380ms var(--ease), transform 380ms var(--ease), border-color 380ms var(--ease);
}
.tl__item.is-active .tl__panel { box-shadow: var(--sh-md); border-color: var(--tl-accent); }
.tl__date {
  font-family: var(--font-head); font-weight: 700; font-size: 13.5px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--tl-accent); margin: 0 0 6px;
}
.tl__title { font-size: clamp(20px, 2.1vw, 27px); line-height: 1.2; margin: 0 0 12px; }
/* every theme restates heading colour (`[data-theme] h3` beats a lone class), so
   the tone-aware colour needs the extra class to win — on the deep navy band the
   title was rendering navy-on-navy at 1.26:1 */
.tl .tl__items .tl__title, .tl .tl__items h1, .tl .tl__items h2,
.tl .tl__items h3, .tl .tl__items h4 { color: var(--tl-ink); }
.tl__text { font-size: 17px; line-height: 1.75; color: var(--tl-muted); max-width: 68ch; }
.tl__text strong { color: var(--tl-ink); }
.tl__text a { color: var(--tl-accent); text-underline-offset: 3px; }

/* the NDA family of organizations, as marks rather than a typed dash list. Each
   tile carries its own paper chip so the logos hold up on the deep navy band as
   well as the light one, and links where /national-convention/family-org links. */
.tl__orgs {
  list-style: none; margin: 20px 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px;
}
.tl__org-link {
  display: flex; flex-direction: column; align-items: center; gap: 10px; height: 100%;
  padding: 16px 12px 14px; text-align: center; text-decoration: none;
  background: #FFFFFF; border: 1px solid var(--tl-line); border-radius: var(--r-md);
  transition: transform var(--t) var(--ease), box-shadow var(--t) var(--ease), border-color var(--t) var(--ease);
}
.tl__org-link:hover { transform: translateY(-3px); box-shadow: var(--sh-md); border-color: var(--tl-accent); }
/* the cap is stated in pixels, not as 100% of the slot: an auto-sized grid row is
   an indefinite height, so a percentage max-height resolves to none and a 600px
   mark paints straight over the name beneath it */
.tl__org-mark { display: flex; align-items: center; justify-content: center; width: 100%; height: 72px; }
.tl__org-mark img { max-width: 100%; max-height: 72px; width: auto; height: auto; object-fit: contain; }
.tl__org-name {
  font-family: var(--font-head); font-weight: 600; font-size: 12.5px; line-height: 1.35;
  color: var(--navy); display: block;
}
.tl__org-name b { display: block; font-size: 11.5px; letter-spacing: .1em; color: var(--slate); margin-top: 3px; }
.tl__media { margin-top: 20px; display: grid; gap: 14px; justify-items: center; }
/* No cropping: a cover box cut the people out of the Present Day photograph (a
   1000x1500 portrait squeezed into a 460px-tall slot). Both maxima applied to an
   auto-sized image scale the whole frame down instead — landscape photos fill the
   card width, tall ones stop at a readable height with nothing cut off. */
.tl__media img {
  width: auto; height: auto; max-width: 100%; max-height: min(70vh, 620px);
  border-radius: var(--r-md); box-shadow: var(--sh-sm); display: block; margin-inline: auto;
}
.tl__media .ytlite, .tl__media [class*="youtubevideo"] { border-radius: var(--r-md); overflow: hidden; }
.tl__actions { margin-top: 18px; display: flex; flex-wrap: wrap; gap: 12px; }
.tl[data-tone="4"] .tl__actions .btn--ghost { border-color: rgba(148,197,248,.6); color: #FEFEFE; }
.tl[data-tone="4"] .tl__actions .btn--ghost:hover { background: rgba(148,197,248,.18); }

/* arrive rather than appear */
.tl__item { opacity: 0; transform: translateY(14px); transition: opacity 520ms var(--ease), transform 520ms var(--ease); }
.tl__item.is-inview { opacity: 1; transform: none; }

@media (max-width: 900px) {
  .tl { padding-inline: 20px; }
  .tl__in { grid-template-columns: 1fr; gap: 16px; }
  .tl__rail {
    position: sticky; top: var(--navH, 72px); z-index: 3;
    background: var(--tl-bg); padding-block: 12px 10px; border-bottom: 1px solid var(--tl-line);
    transition: background-color 620ms var(--ease);
  }
  .tl__badge { flex-direction: row; align-items: center; gap: 12px; }
  .tl__year { font-size: 20px; flex: 0 0 auto; max-width: 55%; }
  .tl__count { order: 3; flex: 0 0 auto; }
  .tl__track { flex: 1 1 auto; }
  .tl__marks { display: none; }
  .tl__orgs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tl__items { padding-left: 26px; }
  .tl__pin { left: -26px; width: 16px; height: 16px; top: 26px; }
  .tl__items::before { left: 7px; }
  .tl__text { font-size: 16.5px; }
}

@media (prefers-reduced-motion: reduce) {
  .tl, .tl__rail, .tl__item, .tl__panel, .tl__pin, .tl__fill { transition: none !important; }
  .tl__item { opacity: 1; transform: none; }
}

.ndacal-when { display: inline-flex; gap: 3px; padding: 4px; margin: 2px 0 6px; background: var(--sky-100); border-radius: 999px; }
.ndacal-when__b { font-family: var(--font-head); font-weight: 600; font-size: 13.5px; color: var(--navy); border: 0; background: none; padding: 8px 16px; border-radius: 999px; cursor: pointer; }
.ndacal-when__b span { opacity: .65; font-weight: 500; }
.ndacal-when__b:hover { background: rgba(255,255,255,.75); }
.ndacal-when__b[aria-pressed="true"] { background: var(--white); color: var(--deep); box-shadow: var(--sh-sm); }

/* The calendar is injected where the portal iframe used to sit, which on these
   pages is inside .prose — and `.prose a` (0,1,1) outranks `.btn--primary`
   (0,1,0), which painted navy text on the navy Register button. Re-assert the
   button colours from inside the calendar's own scope. */
.ndacal .btn--primary, .ndacal-modal .btn--primary { color: var(--white); }
.ndacal .btn--ghost, .ndacal-modal .btn--ghost { color: var(--navy); }
.ndacal .btn--primary:hover, .ndacal-modal .btn--primary:hover { color: var(--white); }
.ndacal .btn--ghost:hover, .ndacal-modal .btn--ghost:hover { color: var(--white); }
.ndacal a, .ndacal-modal a { text-decoration: none; }
.ndacal-section > .container { width: 100%; padding: 0; }

.ndacal__footnote { width: 100%; margin: 4px 0 0; font-size: 13.5px; line-height: 1.6; color: var(--slate); }
.ndacal__footnote a { color: var(--navy); font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }
.ndacal__footnote a:hover { color: var(--crimson); }

.ndacal-soon { display: inline-flex; align-items: center; font-family: var(--font-head); font-weight: 600; font-size: 13px; letter-spacing: .04em; color: var(--slate); background: var(--sky-100); border-radius: 999px; padding: 8px 16px; }

/* ---- HECTA task force: un-stack the intro ----
   Webflow laid this section out as a 5-column grid with the copy card placed to
   deliberately overlap the photo (grid-area 2/1/4/4 sitting under 1/3/5/6). At the
   original's ~560px container the two barely touched; in v2's 1368px container a
   quarter of the paragraph runs under the photograph and is unreadable. Straighten
   it into two honest columns — copy left, photo right, as it reads on the original. */
.prose .grid_5-col-4 {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) !important;
  align-items: center !important;
}
.prose .grid_5-col-4 > * { grid-area: auto !important; }
.prose .grid_5-col-4 > .header-37 { order: 1; }
.prose .grid_5-col-4 > .image-ratio_1x1-9 { order: 2; aspect-ratio: 3/2 !important; }
@media (max-width: 860px) {
  .prose .grid_5-col-4 { grid-template-columns: minmax(0, 1fr) !important; }
}

/* ---- gallery bands survive every theme ----
   The eight alternate themes load AFTER v2.css and restyle .section, h2, .lead and
   .eyebrow globally — they were written before the gallery had dark bands, so a
   themed visit painted navy headings onto the navy band (coastal measured 1.0:1)
   and bloom flattened the band to paper while the copy stayed white. These bands
   own their own paint so no theme can wash them out. The runtime guard in v2.js
   can still override with an inline !important if a future theme breaks them. */
.gal-album.gal-album--dark {
  background: linear-gradient(170deg, var(--deep) 0%, var(--navy) 100%) !important;
  color: #fff !important;
}
.gal-album.gal-album--dark h2 { color: #fff !important; }
.gal-album.gal-album--dark .lead { color: rgba(234, 243, 254, .86) !important; }
.gal-album.gal-album--dark .eyebrow {
  color: var(--sky) !important; background: none !important; border: 0 !important; padding-left: 0 !important;
}
.gal-album.gal-album--dark .eyebrow::before { background: var(--sky) !important; }
.gal-album.gal-album--dark .gal-album__foot { border-top-color: rgba(255, 255, 255, .18) !important; }
.gal-album.gal-album--dark .gal-album__foot p { color: rgba(234, 243, 254, .78) !important; }
.gal-album.gal-album--dark .btn--light { background: #fff !important; color: var(--deep) !important; border-color: #fff !important; }
.gal-album.gal-album--dark .btn--cta { color: #fff !important; }
/* the light bands take whatever surface the active theme gives .section; only the
   tint needs stating, and their copy is dark on light in every theme */
.gal-album:not(.gal-album--dark) .gal-album__foot p { color: var(--slate); }

/* ---- logos are marks, not photographs ----
   .prose img hands every image a 14px radius + drop shadow, which is right for a
   photo and wrong for a logo: partner and sponsor art is almost all JPG/PNG on a
   white plate, so the shadow traces a box around the mark and the radius rounds the
   plate's corners. 141 logos across the site were rendering inside a phantom box —
   most visibly the membership offer cards, where the boxed logo sat above a divider
   line inside the card that already framed it. */
.prose img[src*="logo" i], .prose img[alt*="logo" i], .prose img[class*="logo" i],
.prose [class*="logo"] img, .prose [class*="Logo"] img {
  border-radius: 0 !important;
  box-shadow: none !important;
  background: transparent !important;
}

/* ============================================================
   Control boundaries (2026-07-27 button contrast sweep)
   A button has to be findable, not just readable. WCAG 1.4.11 asks for 3:1
   between a control's boundary and the surface behind it; several brand fills
   pass their own label test and still vanish into the panel they sit on:
     · maroon .btn--cta on the deep-navy footer band  — 1.46:1
     · maroon .btn--cta on the dark gallery album head — 1.33:1
   The fills stay exactly as branded; a sky-tinted ring supplies the missing
   edge. .btn:hover replaces box-shadow wholesale, so the hover state has to
   restate the ring or the button loses its outline mid-interaction.
   ============================================================ */
.footer .footer__cta a.btn--cta,
.gal-album--dark .btn--cta,
.gal-album--dark .btn--primary {
  box-shadow: 0 0 0 1.5px rgba(148,197,248,.8);
}
.footer .footer__cta a.btn--cta:hover,
.gal-album--dark .btn--cta:hover,
.gal-album--dark .btn--primary:hover {
  box-shadow: 0 0 0 1.5px var(--sky), var(--sh-md);
}
/* the light footer button is white on navy and needs no ring — but .btn:hover's
   shadow is invisible on a dark band, so give it the same treatment for parity */
.footer .footer__cta a.btn--light:hover { box-shadow: 0 0 0 1.5px rgba(148,197,248,.55); }

/* Instagram follow button: the embed paints it over the gradient avatar band.
   White fill reads at 5:1 against that red where the navy repair sat at 2.7:1. */
.follow-section .follow-button {
  background: var(--white); color: var(--navy); border: 1.5px solid rgba(255,255,255,.9);
}
.follow-section .follow-button:hover { background: var(--sky-100); color: var(--navy); }

/* ---- site chrome outranks imported page CSS ----
   Extracted pages keep their own <style> blocks, and several of them use
   unscoped generic names: /about/webinars ships a bare `.btn { border: none }`.
   That selector weighs the same (0,1,0) as v2's own `.btn` and loads later, so
   it silently erased the outline on the header's Log In button — the control
   then had no fill, no border and nothing separating it from the header.
   Restate the contract from a chrome ancestor, which no page embed can reach. */
.nav .btn, .footer .btn { border-width: 1.5px; border-style: solid; }
.nav .btn--ghost, .footer .btn--ghost { border-color: rgba(2,58,113,.55); background: transparent; }
.nav .btn--primary, .footer .btn--primary { background: var(--navy); color: var(--white); border-color: transparent; }
.nav .btn--cta { background: linear-gradient(135deg, var(--maroon), var(--crimson)); color: var(--white); border-color: transparent; }

/* ============================================================
   Emptied embed slots + native publication cards (2026-07-28)
   ============================================================ */

/* A "responsive embed" reserves its frame's height with percentage padding on a
   wrapper — `.sg-embed-frame { padding-bottom: 66% }` on the publications page.
   nativizeEmbeds() replaces the iframe with a native card but cannot edit the
   page's stylesheet, so the reserved box survived as ~900px of nothing under a
   small card. render.mjs marks each slot it emptied; collapse them to content. */
/* Only the box that DIRECTLY holds the replacement collapses — render.mjs marks
   the whole ancestor chain up to .w-embed, and zeroing padding that far up would
   strip spacing from sections that never reserved anything for a frame. */
.is-native-slot:has(> .pubitem, > .docitem, > .ytlite, > .portalitem) {
  padding-bottom: 0 !important; padding-top: 0 !important;
  height: auto !important; min-height: 0 !important;
}
/* the frame it replaced was absolutely positioned inside that padding box; the
   card has to return to normal flow or it stacks on top of the copy above */
.is-native-slot > .pubitem, .is-native-slot > .docitem, .is-native-slot > .portalitem { position: relative; }

/* Publications: the Issuu reader became a cover card, and the column beside it
   already carries the title, "View Online" and "Download PDF". Show the cover as
   artwork at the scale the slot was designed for and drop the duplicate caption
   rather than printing the same title and CTA twice in one card. */
.journal-preview { display: grid; place-items: center; min-height: 0; padding: 34px 30px; }
.journal-preview .pubitem {
  background: none; border: 0; box-shadow: none; margin: 0; width: 100%;
}
.journal-preview .pubitem:hover { transform: none; box-shadow: none; }
.journal-preview .pubitem__body { display: none; }
.journal-preview .pubitem__cover { background: none; display: grid; place-items: center; }
.journal-preview .pubitem__cover img {
  width: auto; max-width: 100%; max-height: 460px; height: auto;
  border-radius: 4px; box-shadow: 0 18px 44px rgba(11,36,71,.30);
  transition: transform 260ms var(--ease), box-shadow 260ms var(--ease);
}
.journal-preview .pubitem__cover:hover img { transform: translateY(-4px); box-shadow: 0 24px 56px rgba(11,36,71,.36); }

/* the style-guide cover sits on the section's near-black band, so it keeps its
   own caption + "Read publication" — that CTA opens Issuu, which the "Download
   Style Guide PDF" button beneath the card does not do */
.sg-embed-wrap .pubitem { background: none; border: 0; box-shadow: none; margin: 0; }
.sg-embed-wrap .pubitem:hover { transform: none; box-shadow: none; }
.sg-embed-wrap .pubitem__cover { background: none; display: grid; place-items: center; padding: 40px 30px 8px; }
.sg-embed-wrap .pubitem__cover img {
  width: auto; max-width: 100%; max-height: 420px; height: auto;
  border-radius: 4px; box-shadow: 0 18px 44px rgba(0,0,0,.45);
}
.sg-embed-wrap .pubitem__body { align-items: center; text-align: center; padding: 6px 20px 30px; }
.sg-embed-wrap .pubitem__body h3 { color: #FEFEFE; }
.sg-embed-wrap .pubitem__body .btn { align-self: center; }

/* The publications hero splits `45% 55%` and then adds a 60px gap, so the track
   total is 100% + 60px and the right column hangs 60px past the section's
   `overflow: hidden` edge — the card was visibly sliced off. Percentages ignore
   the gap; fr units account for it. The extra 20px translate on the card pushed
   it further still. Only reachable on this page (.hero-content + .hero-card). */
.hero-section .hero-content { grid-template-columns: minmax(0, 45fr) minmax(0, 55fr); }
.hero-section .hero-card { transform: none; }
.hero-section .hero-image { padding-left: 0; }

/* A publication card standing on its own in body copy is a tile, not a poster.
   This never mattered while the covers were 116px thumbnails; with real 800px
   artwork a bare .pubitem filled the whole column and out-shouted the copy
   around it. Cap the tile and the cover; the two slots that deliberately want a
   large cover (.journal-preview, .sg-embed-wrap, above) opt back out. */
/* The blanket overflow guard `.prose :not(.photowall):not(.photowall *)` weighs
   (0,3,0) — `:not()` inherits its argument's specificity — so the cap has to
   match that weight or it never lands. */
.pubitem, .prose .pubitem, .prose .w-embed .pubitem, .w-embed .pubitem { max-width: 440px; }
.pubitem__cover { display: grid; place-items: center; padding: 18px 18px 2px; }
.pubitem__cover img {
  width: auto; max-width: 100%; max-height: 380px; height: auto;
  border-radius: 4px; box-shadow: 0 10px 26px rgba(11,36,71,.20);
}
.prose .journal-preview .pubitem, .prose .sg-embed-wrap .pubitem,
.journal-preview .pubitem, .sg-embed-wrap .pubitem { max-width: none; }

/* An embed's own `a { color: inherit }` weighs (0,1,1) and outranks
   `.btn--primary` (0,1,0), so v2's filled buttons sitting inside imported copy
   inherited that page's body colour — #111 on navy in the Flossline block, which
   the runtime guard then "repaired" by washing the navy out to a pale blue.
   State the label from .prose, which no page-level selector can reach. The eight
   themes restate these at (0,3,0) and still win, as they should. */
.prose .btn--primary, .prose .btn--cta { color: var(--white); }

/* ============================================================
   Architects of Change campaign meter (2026-07-28)
   The campaign's headline number leads the donate page now, so the bar has to
   carry that weight: a taller track, the brand gradient, a live shimmer, and a
   fill that counts up from zero when it scrolls into view rather than arriving
   already finished. Styles the page's OWN bar (.nda-progress-bar-*) — the
   injected .goalmeter is only a fallback for a section that ships none.
   ============================================================ */
/* `.prose :not(.photowall):not(.photowall *)` weighs (0,3,0) and sets
   max-width:100%, so the meter's own 800px cap never landed and the raised and
   goal figures sat at opposite ends of a 1360px row. Match that weight. */
.prose .nda-progress-section .nda-progress-content,
.nda-progress-section .nda-progress-content { max-width: 1100px; }
.nda-progress-raised span { margin-left: .35em; }
.nda-progress-bar-track {
  height: 34px !important;
  background: linear-gradient(180deg, #E4EBF3, #EFF4F9) !important;
  border: 1px solid rgba(2,58,113,.10);
  border-radius: 999px !important;
  box-shadow: inset 0 2px 6px rgba(11,36,71,.12) !important;
  overflow: hidden; position: relative;
}
.nda-progress-bar-fill {
  height: 100% !important; border-radius: 999px !important;
  background: linear-gradient(90deg, var(--navy) 0%, var(--crimson) 100%) !important;
  position: relative; overflow: hidden;
  box-shadow: 0 2px 10px rgba(113,29,58,.35);
  /* the authored width is the target; hold at 0 until the meter is seen */
  transition: width 1800ms cubic-bezier(.22,.8,.32,1) !important;
}
.nda-progress-section.is-armed .nda-progress-bar-fill { width: 0 !important; }
.nda-progress-section.is-armed.is-inview .nda-progress-bar-fill { width: var(--goal) !important; }
/* travelling highlight — the same sweep the .goalmeter uses, so the two read as
   one component if a page ever shows both */
.nda-progress-bar-fill::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(115deg, transparent 30%, rgba(255,255,255,.38) 50%, transparent 70%);
  background-size: 220% 100%; animation: goalshimmer 2.6s linear infinite;
}
/* soft leading edge so the bar reads as filling rather than as a hard block */
.nda-progress-bar-fill::before {
  content: ""; position: absolute; top: 0; right: 0; bottom: 0; width: 34px;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.30));
  border-radius: 999px;
}
.nda-progress-raised { font-size: clamp(2rem, 3.6vw, 3rem) !important; letter-spacing: -.02em; }
.nda-progress-goal { font-size: clamp(1rem, 1.3vw, 1.2rem) !important; }
.nda-progress-percent-label { margin-top: 16px !important; font-size: 1.05rem !important; }
@media (prefers-reduced-motion: reduce) {
  .nda-progress-bar-fill { transition: none !important; }
  .nda-progress-bar-fill::after { animation: none; }
  .nda-progress-section.is-armed .nda-progress-bar-fill { width: var(--goal) !important; }
}
@media (max-width: 700px) {
  .nda-progress-bar-track { height: 26px !important; }
  .nda-progress-bar-fill::before { width: 22px; }
}

/* ---- photo cards: chips sized by their label, copy that survives the photo ----
   `.w-embed [class*="grid"] > *` forces width:100% so a card fills its grid
   track — across the site it is right 90 times out of 97. The exceptions are
   wrappers whose class merely CONTAINS "grid" while being ordinary blocks:
   `.nda-featured-grid-content` is a caption stack, so the rule stretched the
   little category pill inside it into a full-width bar spanning the card. A chip
   is sized by its label; none of the 90 genuine grid children is a chip. */
.w-embed [class*="grid"] > [class*="tag"],
.w-embed [class*="grid"] > [class*="badge"],
.w-embed [class*="grid"] > [class*="chip"],
.w-embed [class*="grid"] > [class*="pill"] { width: auto; }

/* These cards set white copy over a photograph and rely on a ::before scrim for
   contrast. The scrim was tuned for a dark image: at the top of the copy block
   it is only ~0.2–0.45 opaque, and over the S.M.I.L.E. photograph — a row of
   white lab coats — the headline measured near 1.5:1. Deepen the ramp so it is
   still carrying weight where the copy actually starts (63% up the story card,
   42% up the grid cards), and keep it transparent at the very top so the
   photograph still reads as a photograph. The runtime guard deliberately does
   not touch text over photos: the scrim is the author's tool, so it is the
   thing to fix. */
.nda-featured-story-card::before {
  background: linear-gradient(to top,
    rgba(2,10,22,.92) 0%, rgba(2,10,22,.82) 45%,
    rgba(2,10,22,.62) 68%, rgba(2,10,22,.25) 88%, transparent 100%) !important;
}
.nda-featured-grid-item::before {
  background: linear-gradient(to top,
    rgba(2,10,22,.92) 0%, rgba(2,10,22,.80) 38%,
    rgba(2,10,22,.55) 60%, rgba(2,10,22,.20) 84%, transparent 100%) !important;
}

/* A control that sits over slider imagery cannot rely on a hairline: its backdrop
   changes with every slide, and the pixel sweep measured the arrows at 1.95:1 and
   the ghost CTA at 2.95:1 against the photos actually behind them. Give both a
   full-strength navy edge — plus a soft shadow on the arrows, which overlap the
   photograph itself — so they separate on a pale slide and a dark one alike. */
.slider__arrow { border-color: var(--navy); box-shadow: 0 2px 10px rgba(11,36,71,.28); }
.slider .btn--ghost { border-color: var(--navy); }

/* ---------- event page components (2026 Inauguration & Scholarship Gala) ----------
   This page used to be a self-styled Webflow embed; T.gala in render.mjs now
   composes it from the design system instead (see the note there). Four small
   components carry what the system didn't already have: a fact tile, a checklist,
   a media-beside-copy feature card, and a sponsor wall. All token-driven, so the
   theme layers re-tune them along with everything else. */

/* --- fact tile: one event fact — icon, label, value --- */
.fact { display: grid; gap: 10px; align-content: start; }
.fact__icon {
  width: 46px; height: 46px; border-radius: var(--r-md);
  background: var(--sky-100); color: var(--navy);
  display: grid; place-items: center; box-shadow: inset 0 0 0 1px rgba(2,58,113,.1);
}
.fact__icon svg { width: 23px; height: 23px; }
.fact__label {
  font-family: var(--font-head); font-weight: 600; font-size: 12.5px;
  letter-spacing: .12em; text-transform: uppercase; color: var(--crimson);
}
.fact__value {
  font-family: var(--font-head); font-weight: 600; font-size: 17px;
  line-height: 1.45; color: var(--navy);
}

/* --- checklist: the embed drew these rows with a bare ✓ character --- */
.checks { list-style: none; margin: 0 0 22px; padding: 0; display: grid; gap: 14px; }
.check { display: grid; grid-template-columns: 24px 1fr; gap: 13px; align-items: start; font-size: 16px; color: var(--slate); }
.check__mark {
  width: 24px; height: 24px; border-radius: 999px; margin-top: 2px;
  background: var(--sky-100); color: var(--navy); display: grid; place-items: center;
}
.check__mark svg { width: 14px; height: 14px; }
.check strong { color: var(--navy); }

/* --- feature card: picture beside copy, both halves full-bleed to the card ---
   .card is a column, and .card__media is a 16:10 box inside it; as a two-column
   card the media has to fill its own column at whatever height the copy sets. */
.gala-feature {
  display: grid; grid-template-columns: minmax(0, .85fr) minmax(0, 1.15fr);
  margin: 34px 0 0; border-radius: var(--r-xl);
}
/* the picture fills its column at whatever height the copy beside it sets, so it
   is taken out of flow: left in flow, a 1728×2397 portrait made the card 826px
   tall and stranded three lines of copy in the middle of an empty white half */
/* width and height are stated rather than left auto because every theme layer
   loads after this file and several re-tune `.card__media` with an aspect-ratio
   (bloom/coastal 16/11, clay 16/12). In a two-column card the row height is
   already definite, so an aspect ratio there resolves the other way round — it
   sized the media box off its own height and grew it 75px past its grid track,
   over the top of the copy beside it. A definite width leaves nothing for the
   ratio to solve for. */
.gala-feature .card__media {
  position: relative; aspect-ratio: auto;
  width: 100%; height: 100%; min-height: clamp(320px, 32vw, 460px);
}
.gala-feature .card__media img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  /* a studio portrait is shot with headroom: anchoring the crop at centre put the
     frame's ceiling in the card and cut the subject off at the chin */
  object-fit: cover; object-position: center 22%; --framed: 1;
}
.gala-feature .card__body { padding: clamp(26px, 3vw, 42px); justify-content: center; gap: 12px; }
.gala-feature .card__body h3 { font-size: clamp(22px, 2.4vw, 30px); color: var(--navy); margin: 0; }
.gala-feature .card__body p { color: var(--slate); margin: 0; }
.gala-feature--lodge .card__media img { object-position: center 55%; --framed: 1; }
/* the sponsorship packet is a cover, not a photograph — .journal-preview already
   sets a cover as artwork on its plate; give it the tint the media column had */
.gala-feature--packet { grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr); }
.gala-feature--packet .journal-preview {
  background: linear-gradient(160deg, var(--sky-100), var(--sky-50) 60%, rgba(2,58,113,.06));
  padding: clamp(28px, 3vw, 44px);
}
.gala-contact {
  margin-top: 6px !important; padding-top: 16px; font-size: 15.5px;
  border-top: 1px solid rgba(2,58,113,.12);
}
.gala-subhead { margin: 46px 0 20px; color: var(--navy); }
@media (max-width: 860px) {
  .gala-feature, .gala-feature--packet { grid-template-columns: 1fr; }
  .gala-feature .card__media { min-height: 0; aspect-ratio: 16/10; }
  /* a portrait subject in a landscape crop loses their head at phone widths */
  .gala-feature--portrait .card__media { aspect-ratio: 4/5; }
  .gala-feature--portrait .card__media img { object-position: center 12%; --framed: 1; }
}

/* --- sponsor wall: marks shown in colour on their own tile, evenly sized --- */
.sponsorwall .tile { display: grid; place-items: center; padding: 26px 22px; min-height: 132px; }
.sponsorwall img { max-height: 62px; width: auto; max-width: 100%; object-fit: contain; }
/* four marks stacked one per screen is a scroll, not a sponsor wall */
@media (max-width: 640px) { .sponsorwall { grid-template-columns: repeat(2, 1fr); } }

/* ============================================================
   /national-convention/family-org — the NDA family of organizations
   One hero, one index. The mirror's own version introduced the six
   organisations twice in a row (text pills in a gradient hero, then the same
   six as logos in the bar directly beneath it); here the marks ARE the index —
   each jumps to that organisation's row — so the logos do a job instead of
   repeating the names. Every surface below is a declared v2 surface, so no text
   on this page depends on the runtime guard inferring a backdrop.
   ============================================================ */
.hero--family .hero__in { text-align: center; }
.hero--family .eyebrow { justify-content: center; }
.hero--family .lead { margin-inline: auto; max-width: 74ch; }
.hero--family .hero__actions { justify-content: center; }

.famindex {
  list-style: none; margin: clamp(34px, 4.4vw, 56px) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: clamp(10px, 1.2vw, 18px);
}
.famindex__link {
  display: flex; flex-direction: column; align-items: center; gap: 10px; height: 100%;
  padding: 18px 12px 16px; border-radius: var(--r-lg); text-decoration: none;
  background: var(--white); border: 1px solid rgba(2,58,113,.14); box-shadow: var(--sh-sm);
  transition: transform var(--t) var(--ease), box-shadow var(--t) var(--ease), border-color var(--t) var(--ease);
}
.famindex__link:hover { transform: translateY(-4px); border-color: var(--sky); box-shadow: var(--sh-md); }
/* Every one of the six marks is supplied with generous whitespace baked into the
   file — NDAF and NDHA are 600×600 squares whose artwork sits in a narrow central
   band, USNDA is a wordmark adrift in 1536×1024 — so a box sized to the type reads
   as a row of tiny logos. Size the box for the padded file, not for the mark. */
.famindex__mark { display: flex; align-items: center; justify-content: center; width: 100%; height: 88px; }
.famindex__mark img { max-width: 100%; max-height: 88px; width: auto; height: auto; object-fit: contain; }
.famindex__abbr {
  font-family: var(--font-head); font-weight: 700; font-size: 13.5px;
  letter-spacing: .1em; color: var(--navy);
}
.famindex__name {
  font-family: var(--font-head); font-weight: 600; font-size: 10.5px; letter-spacing: .09em;
  text-transform: uppercase; color: var(--slate); text-align: center; line-height: 1.35;
}
/* the intro sits centred under a centred eyebrow, so its 62ch measure has to be
   centred too or the paragraph hangs off the left of its own heading */
.famcenter { justify-content: center; }
.famlead { margin-inline: auto; }

/* ---- one row per organisation ---- */
.famorg--tint { background: linear-gradient(180deg, var(--sky-50), var(--sky-100)); }
.famorg__row {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(28px, 4vw, 60px); align-items: center;
}
.famorg--flip .famorg__media { order: 2; }
.famorg__media {
  margin: 0; border-radius: var(--r-xl); overflow: hidden;
  box-shadow: var(--sh-lg); background: var(--sky-100); aspect-ratio: 4 / 3;
}
.famorg__media img { width: 100%; height: 100%; object-fit: cover; object-position: center top; }
.famorg__body { display: flex; flex-direction: column; align-items: flex-start; gap: 14px; min-width: 0; }
.famorg__body h2 { margin: 0; color: var(--navy); }
.famorg__body p { margin: 0; color: var(--slate); font-size: 17px; }
.famorg__actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 8px; }

/* ---- closing band ----
   The one dark surface on the page, and it declares every colour it uses: the
   band, the heading, the body copy and the secondary button. Nothing here is
   inherited from a parent the guard would have to go looking for. */
.famcta { padding-block: clamp(58px, 6.4vw, 96px); }
.famcta h2 { margin: 0 0 14px; }
.famcta p { font-size: clamp(17px, 1.5vw, 20px); max-width: 66ch; margin: 0 auto; }
.famcta__actions { display: flex; flex-wrap: wrap; gap: 14px; justify-content: center; margin-top: 30px; }
/* Six of the eight themes restate a bare `html[data-theme=x] h2 { color: ... }`.
   That weighs (0,1,2) — the attribute counts as a class, and `html` + `h2` are two
   types — so it reaches straight past `.famcta h2` at (0,1,1), and this band's
   heading came out slate-grey on navy in bloom, clay, coastal, editorial,
   sanctuary and civic: 3.25:1, the exact failure this page was rebuilt to end.
   A dark band cannot leave its own colours at class weight. Restate them where no
   generic theme heading rule can outrank them, and give the band its background
   at the same weight so a theme cannot lighten the surface out from under white
   type either. Any new dark band on this site needs this treatment. */
.famcta, html[data-theme] .famcta {
  background:
    radial-gradient(900px 420px at 82% -20%, rgba(139,21,56,.55), transparent 62%),
    linear-gradient(135deg, var(--deep) 0%, var(--navy) 52%, var(--maroon) 100%);
  color: var(--white);
}
.famcta h2, html[data-theme] .famcta h2 { color: var(--white); }
.famcta p, html[data-theme] .famcta p { color: rgba(255,255,255,.88); }
/* .btn--light is redefined further up as navy-on-navy, which is unreadable here —
   this band needs a genuinely light control, declared outright */
/* Crimson on a navy-to-maroon band clears its label easily but not its own edge —
   at the maroon end the fill and the surface are the same family, so the control
   has no boundary (WCAG 1.4.11). v2.js's edge pass will draw a ring here, but a
   band that declares everything else about itself should declare this too. */
.famcta .btn--cta, html[data-theme] .famcta .btn--cta { border-color: rgba(255,255,255,.62); }
.famcta__btn, html[data-theme] .famcta__btn { background: var(--white); color: var(--navy); border-color: var(--white); }
.famcta__btn:hover, html[data-theme] .famcta__btn:hover { background: var(--sky-50); color: var(--navy); }

@media (max-width: 1100px) {
  .famindex { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 900px) {
  .famorg__row { grid-template-columns: 1fr; }
  .famorg--flip .famorg__media { order: 0; }
  .famorg__media { aspect-ratio: 16 / 10; }
}
@media (max-width: 560px) {
  .famindex { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .famindex__mark, .famindex__mark img { height: 68px; max-height: 68px; }
}

/* =========================================================================
   FULL-PAGE EMBEDS  (T.fullPage → .pagebleed)
   A few pages are a whole design in one embed rather than a hero plus prose:
   the convention sponsorship and exhibitor pages. They bring their own hero,
   their own section rhythm and their own edge-to-edge colour bands, and they
   render here without .container, .section or .prose around them so those
   bands actually reach the edges instead of stopping 20px short of them.

   The rule set is deliberately tiny. Everything these pages need is in their
   own <style> block; the job here is only to stop the shell's defaults from
   reaching in, and to hold the line on the two things a self-authored embed
   is most likely to get wrong at full width — a horizontal scrollbar, and
   text clipped by a fixed-height box.
   ========================================================================= */
.pagebleed { width: 100%; }
/* the embed's own sections are the page's sections; nothing wraps them */
.pagebleed > .w-embed, .pagebleed > .w-embed > #nda-wrapper { display: block; width: 100%; }
/* a self-styled band is free to be any width it likes, but never wider than
   the page — one overflowing marquee otherwise scrolls the whole document */
.pagebleed { overflow-x: clip; }
.pagebleed img, .pagebleed table { max-width: 100%; }
/* Cards in these embeds are sized by content, not by a fixed height. Several
   were authored against a narrower column and clip their own last line once
   the band goes full width (".. digital program placements, e-"). Let a card
   grow rather than cut its copy; the grids they sit in are all auto-rows. */
.pagebleed [class*="-card"], .pagebleed [class*="card-"] { overflow: visible; }
/* An embed that calls a section "hero" or a link "btn" is not asking for the
   shell's hero or the shell's button — but those are v2's class names too, and
   outside .prose the shell's rules reach in. The embed's own #nda-scoped CSS
   outranks v2 on every property it declares, so all that actually leaks is what
   the embed never mentions: the sponsors hero inherited the shell hero's
   animated ::before aura (96px of it outside the band, clipped away, animating
   forever) and its hairline bottom border. Take back exactly those. */
.pagebleed .hero { border-bottom: 0; }
.pagebleed .hero::before, .pagebleed .hero::after { content: none; animation: none; }

/* ---------- imported layouts: cards that never got card treatment, columns
   stranded by centre alignment, and photographs sized by their own pixels ----------
   Four pages carried the same three faults into the redesign (committe-page,
   hecta-taskforce, corporate-roundtable-crt, womens-health-symposium). Each rule
   below is written against the shape of the fault, not against a page, because
   the shapes recur wherever a Webflow page was assembled the same way. */

/* 1. Committee roster (/national-convention/committe-page): 13 committees, each a
   bare stack of tag + heading + paragraph with an optional photo above it. No
   surface, no padding, no consistent photo box — so a card with a photo and a card
   without read as two different components, and the grid looked like text spilled
   onto the page rather than a roster. Give every cell the same card. */
/* Both selectors, because this roster mixes wrappers: Webflow built some committee
   cells as <div class="w-layout-blockcontainer content-block-link-2"> and the ones
   that link out as <a class="content-block-link-2 w-inline-block">. `.prose
   [class*="grid_"] > a` (line 820) is (0,2,1) and this rule was (0,2,0), so the
   anchors lost the flex card layout to it and stayed display:block — which is what
   made their photos a different size from their neighbours'. Naming `a` here ties
   the specificity, and this rule is later, so the card wins for both shapes. */
.prose .content-block-link-2,
.prose a.content-block-link-2 {
  display: flex; flex-direction: column; align-items: stretch; gap: 10px;
  /* stretch, never `height: 100%`: a percentage height on a grid item that holds
     an aspect-ratio image box resolves against a row the box is itself sizing, and
     the row settles ~50px short — the last line of the longest card printed
     outside its own border */
  max-width: none;                        /* .w-layout-blockcontainer caps at 940px */
  text-align: left;                       /* the band centres its text; a card's doesn't */
  background: var(--white); border: 1px solid rgba(2,58,113,.10);
  border-radius: var(--r-lg); box-shadow: var(--sh-sm); padding: 16px 16px 20px;
  transition: transform 200ms var(--ease), box-shadow 200ms var(--ease);
}
.prose .content-block-link-2:hover { transform: translateY(-3px); box-shadow: var(--sh-md); }
/* the photo is the card's lid: one height for every card that has one, so a row of
   cards lines its headings up whatever each photograph happens to be. A height, not
   an aspect-ratio: a ratio box inside a grid item is sized from the item's
   max-content width rather than its final track, and the row it produced landed
   ~50px short — the longest card printed its last line below its own border. */
.prose .content-block-link-2 [class*="image-ratio"] {
  /* `width` is stated, not left auto. These boxes carry Webflow's aspect-ratio:3/2,
     and a block-level box with a ratio AND a definite height DERIVES its width from
     them — 200px tall became 300px wide, inside a 419px card, while the flex-parent
     cards next to it stretched theirs to the full 419. Stating the width
     over-constrains the ratio so the height above wins and every lid is identical. */
  width: 100%;
  height: clamp(150px, 14vw, 200px); border-radius: 12px; overflow: hidden; margin: 0 0 4px;
}
.prose .content-block-link-2 [class*="image-ratio"] > img {
  width: 100%; height: 100%; object-fit: cover; display: block; border-radius: 12px;
}
.prose .content-block-link-2 h3 { margin: 0; font-size: 18.5px; line-height: 1.3; color: var(--navy); }
.prose .content-block-link-2 p { margin: 0; font-size: 14.5px; line-height: 1.6; color: var(--slate); }
.prose .content-block-link-2 [class*="tag_group"] { margin: 0; }
.prose .content-block-link-2 [class*="tag-"] {
  display: inline-block; font-family: var(--font-head); font-weight: 700;
  font-size: 10.5px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--crimson); background: var(--sky-100); border-radius: 999px;
  padding: 4px 10px;
}

/* 2. A photograph dropped straight into a layout container — no card, no grid, no
   ratio box — renders at its own pixel size. The CRT page ships two 940×1410
   portraits that took 1,410px of page each, and HECTA stacks a 1440×2160 portrait
   in a column beside its FAQ, 1,019px tall on a 666px track. Cap the height,
   centre what's left, and give it the same rounded plate every other photo has. */
.prose .w-layout-blockcontainer > img,
.prose [class*="container-"] > img,
.prose [class*="header-"] > img,
.prose [class*="flex_vertical"] > img {
  display: block; margin-inline: auto; width: auto; max-width: 100%;
  /* 500px was too shy: a 2:3 portrait came out 333px wide in a 1,440px band and
     read as a thumbnail stranded in a hole. 760 puts the same picture at ~507px
     and a flyer at a size you can actually read, while landscape photographs and
     the partner screenshots hit `max-width: 100%` long before this and are
     unaffected. Still capped, so nothing runs a whole screen tall. */
  max-height: clamp(420px, 52vw, 760px);
  border-radius: var(--r-lg); box-shadow: var(--sh-md);
}

/* ---- a lone portrait paired with the copy that introduces it (pairLonePortraits) ----
   Two sections, one grid: copy left, picture right. Inside its own column the
   picture FILLS — width:100% and a stated height, cropped to fit — rather than
   sitting on the centred plate it needs when it is alone in a full-width band. That
   plate exists to make a hole look like a frame; in a column there is no hole, so it
   is switched off here and the photograph simply occupies the space.

   Cropping is safe because the crop is not blind: the image carries data-focus, so
   v2.js frames the cut on the people in it (2:3 down to roughly 1:1 here).

   `.prose` is on the front of each selector only to out-specify the plate rules
   above, which are (0,3,1) and would otherwise win the tie on source order. */
.prose .prosepair { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr); align-items: center; gap: clamp(20px, 3vw, 52px); }
.prose .prosepair > section { padding-block: 0; }
.prose .prosepair > section + section [class*="container-"] { width: 100%; max-width: none; padding-inline: 0; }
.prose .prosepair > section + section .w-layout-blockcontainer {
  width: 100%; padding: 0; background: none; box-shadow: none; display: block;
}
.prose .prosepair > section + section img {
  width: 100%; height: clamp(360px, 42vw, 600px); max-height: none; max-width: none;
  object-fit: cover; border-radius: var(--r-lg); box-shadow: var(--sh-md);
}
/* stacked, the column is the whole page — a wide crop of a portrait would throw away
   most of the picture, so give it back its natural shape and let it run tall */
@media (max-width: 900px) {
  .prose .prosepair { grid-template-columns: minmax(0, 1fr); gap: 18px; }
  .prose .prosepair > section + section img {
    width: auto; height: auto; max-height: 70vh; max-width: 100%; margin-inline: auto; object-fit: contain;
  }
}
/* a lone portrait in a 1,400px column leaves more paper than picture either side
   of it; the same soft plate the hero uses for uncropped artwork turns that from a
   gap into a frame (see .hero__media--fit) */
.prose .w-layout-blockcontainer:has(> img:only-child) {
  display: grid; place-items: center; padding: clamp(18px, 2.2vw, 30px);
  /* the plate frames the photograph; it does not become a 1,360px panel with a
     picture lost in the middle of it */
  width: fit-content; max-width: 100%; margin-inline: auto;
  border-radius: var(--r-xl);
  background: linear-gradient(155deg, rgba(148,197,248,.30), rgba(255,255,255,.62) 58%, rgba(2,58,113,.06));
  box-shadow: inset 0 0 0 1px rgba(2,58,113,.08);
}
/* logos and wordmarks are not photographs — they live in their own tiles */
.prose [class*="card_body"] > img, .prose [class*="div-block-111"] > img,
.prose [class*="logo"] > img, .prose img[class*="logo"] {
  max-height: none; border-radius: 0; box-shadow: none;
}

/* 3. Two-column bands: `align-items: center` is right for a photo beside a
   paragraph and wrong for a heading beside a long column. HECTA pairs a 321px
   heading block with 1,613px of FAQ, and centring hung the heading in the middle
   of 640px of white. Centre only when one side is actually media. */
.prose [class*="grid_2-col"]:not(:has(> img, > a > img, > [class*="image"], > [class*="ratio"])) {
  align-items: start;
}

/* 4. Logo strips: a fixed 3-track grid holding 4 logos leaves the fourth alone on
   a row of its own under three-quarters of empty space (HECTA's sponsors). Let the
   track count follow the logo count. */
.prose [class*="grid_3-col"]:has(> img):not(:has(> :not(img))) {
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)) !important;
  align-items: center;
}

/* --- newsroom card meta + article byline (category · date, from the CMS) --- */
.card__meta {
  font-family: var(--font-head); font-weight: 600; font-size: 13px;
  letter-spacing: .06em; text-transform: uppercase; color: var(--crimson);
  margin: -2px 0 2px;
}
.prose .byline {
  margin: 0 0 26px; padding-bottom: 16px; font-size: 15.5px; color: var(--slate);
  border-bottom: 1px solid rgba(2,58,113,.12);
}
.prose .byline b { color: var(--navy); }

/* --- newsroom lead story: picture beside the headline ---
   Same shape (and same fix) as .gala-feature: the media is taken out of flow so
   the card's height comes from the copy, not from whatever aspect the lead
   photograph happens to have. The featured President's Reflection leads with a
   4:5 quote card, which in flow made the lead story 955px tall with 600px of
   empty white beside three lines of blurb. `width`/`height` are stated because
   several theme layers re-tune .card__media with an aspect-ratio of their own. */
.newslead { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); margin-bottom: 36px; }
.newslead .card__media {
  position: relative; aspect-ratio: auto;
  width: 100%; height: 100%; min-height: clamp(280px, 30vw, 420px);
}
.newslead .card__media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.newslead .card__body { justify-content: center; padding: clamp(24px, 2.6vw, 38px); }
@media (max-width: 800px) {
  .newslead { grid-template-columns: 1fr; }
  .newslead .card__media { min-height: 0; aspect-ratio: 16/10; }
}

/* a portrait cover shown whole (see portraitCover in render.mjs) — the plate
   fills what `contain` leaves over, so the card still reads edge to edge */
.card__media--fit {
  background: linear-gradient(155deg, rgba(148,197,248,.34), rgba(255,255,255,.62) 58%, rgba(2,58,113,.07));
}
.card__media--fit img { object-fit: contain; }
/* the lead card states object-fit on `.newslead .card__media img`, which outweighs
   the line above — restate it at that weight rather than reaching for !important */
.newslead .card__media--fit img { object-fit: contain; inset: 14px; }
/* a contained 4:5 cover only fills ~400px of the media column, so the column
   narrows to fit it rather than framing it in half a metre of plate */
.newslead:has(.card__media--fit) { grid-template-columns: minmax(0, .62fr) minmax(0, 1.38fr); }
/* `.card__foot { margin-top: auto }` pins the link to the bottom of the card,
   which is right in a grid tile of equal-height cards and wrong here: it left a
   200px hole between a three-line blurb and "Read article →" */
.newslead .card__foot { margin-top: 16px; }

/* ============================================================
   T17 · Contact / visit (/about/contact)
   The mirror shipped every fact on this page inside ONE paragraph —
   address, phone and four staff emails separated by <br>, with each
   department run into its own address ("Membership: Mike Johnson,
   mjohnson@…"). Below it sat a Webflow slider and an Instagram
   blockquote, neither of which runs in v2: they rendered as a single
   photo in a full-width empty frame and a blank embed box. Facts,
   desks, a visit band and packed photo rows replace all of it, so
   nothing on the page is a line of text pretending to be a control.
   ============================================================ */
.ct-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(232px, 1fr)); gap: 20px; }
.ct-facts .fact { gap: 11px; }
.ct-facts .fact__value { font-size: 16.5px; }
.ct-facts .fact__value a { color: var(--navy); text-decoration: none; border-bottom: 1px solid rgba(2,58,113,.26); }
.ct-facts .fact__value a:hover { color: var(--crimson); border-bottom-color: var(--crimson); }
.ct-note { font-family: var(--font-body); font-weight: 400; font-size: 14.5px; line-height: 1.5; color: var(--slate); }

/* one card per desk, so an address is a button rather than a run of text a
   reader has to select out of a paragraph and paste into their mail client */
.ct-desks { display: grid; grid-template-columns: repeat(auto-fit, minmax(258px, 1fr)); gap: 20px; }
.ct-desk { transition: transform var(--t) var(--spring), box-shadow var(--t) var(--ease); }
.ct-desk:hover { transform: translateY(-3px); box-shadow: var(--sh-md); }
.ct-desk .card__body { gap: 9px; padding: 26px; }
.ct-desk .fact__icon { margin-bottom: 3px; }
.ct-desk h3 { font-size: 20px; color: var(--navy); }
/* not a <p>: the themes restate `.card__body p { color }` at a weight this file
   cannot outrank from before them in the cascade, and the name is a label rather
   than body copy anyway — so it never enters that rule's scope */
.ct-desk__who { font-family: var(--font-head); font-weight: 600; font-size: 15px; color: var(--crimson); margin-top: -6px; }
.ct-desk__mail {
  margin-top: auto; padding-top: 15px; display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-head); font-weight: 600; font-size: 15px;
  color: var(--navy); text-decoration: none; overflow-wrap: anywhere;
}
.ct-desk__mail svg { width: 16px; height: 16px; flex: 0 0 auto; }
.ct-desk__mail:hover { color: var(--crimson); }

.ct-visit { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.04fr); gap: clamp(26px, 4vw, 56px); align-items: center; }
.ct-visit p { color: var(--slate); }
.ct-addr { font-family: var(--font-head); font-weight: 600; font-size: 18.5px; line-height: 1.5; color: var(--navy); margin: 0 0 18px; }
.ct-map { position: relative; border-radius: var(--r-xl); overflow: hidden; box-shadow: var(--sh-lg); background: var(--sky-100); aspect-ratio: 4 / 3.15; }
.ct-map iframe { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 1; }
.ct-map__fallback {
  position: absolute; inset: 0; z-index: 0;
  display: grid; align-content: center; justify-items: center; gap: 12px; padding: 26px;
  text-align: center; text-decoration: none; color: var(--navy);
  font-family: var(--font-head); font-weight: 600; font-size: 18px; line-height: 1.5;
}
.ct-map__fallback .ct-note { color: var(--crimson); font-weight: 600; font-family: var(--font-head); }

/* the Instagram blockquote never loaded, and its script is a third-party render
   this page cannot wait on — the follow band states the same thing itself */
.ct-follow { grid-template-columns: auto minmax(0, 1.4fr) auto; }
.ct-follow__mark {
  width: 62px; height: 62px; border-radius: 19px; display: grid; place-items: center; color: #fff;
  background: linear-gradient(135deg, #F9CE34, #EE2A7B 52%, #6228D7); box-shadow: var(--sh-md);
}
.ct-follow__mark svg { width: 31px; height: 31px; }

@media (max-width: 900px) {
  .ct-visit { grid-template-columns: 1fr; }
  .ct-map { aspect-ratio: 16 / 10; }
}
@media (max-width: 700px) {
  .ct-follow { grid-template-columns: 1fr; }
  .ct-follow__mark { width: 54px; height: 54px; }
}

/* ---------------- site search ----------------
   /search runs entirely in the browser against /search-index.json, so this styles
   three states from one block: idle (popular links), results, and no-match. */
.srch__form {
  display: flex; gap: 12px; flex-wrap: wrap;
  margin: 22px 0 8px; max-width: 720px;
}
.srch__input {
  flex: 1 1 320px; min-width: 0;
  font-family: var(--font-body); font-size: 1.05rem;
  padding: 14px 18px; color: var(--ink); background: var(--white);
  border: 1px solid rgba(2,58,113,.18); border-radius: var(--r-md);
  box-shadow: var(--sh-sm); transition: border-color var(--t) var(--ease), box-shadow var(--t) var(--ease);
}
.srch__input:focus-visible { outline: none; border-color: var(--navy); box-shadow: 0 0 0 3px rgba(148,197,248,.55); }
.srch__status { min-height: 1.4em; margin: 6px 0 18px; color: var(--muted, #55637a); font-size: .95rem; }

.srch__results { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; max-width: 820px; }
.srch__hit a {
  display: grid; gap: 5px; text-decoration: none; color: inherit;
  background: var(--white); border: 1px solid rgba(2,58,113,.08);
  border-radius: var(--r-lg); box-shadow: var(--sh-sm); padding: 18px 20px;
  transition: transform var(--t) var(--ease), box-shadow var(--t) var(--ease), border-color var(--t) var(--ease);
}
.srch__hit a:hover, .srch__hit a:focus-visible { transform: translateY(-2px); box-shadow: var(--sh-md); border-color: rgba(2,58,113,.22); }
.srch__sec {
  font-family: var(--font-head); font-size: .72rem; font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase; color: var(--maroon);
}
.srch__title { font-family: var(--font-head); font-size: 1.16rem; font-weight: 600; color: var(--navy); line-height: 1.3; }
.srch__snip { color: var(--ink); opacity: .82; font-size: .96rem; line-height: 1.55; }
.srch__url { font-size: .82rem; color: var(--muted, #55637a); opacity: .75; }
.srch__hit mark { background: rgba(148,197,248,.45); color: inherit; padding: 0 2px; border-radius: 3px; }

.srch__empty { margin-top: 8px; }
.srch__links { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 12px; }

@media (max-width: 700px) {
  .srch__form { gap: 10px; }
  .srch__input { flex-basis: 100%; }
  .srch__hit a { padding: 15px 16px; }
}

/* ============================================================
   Leadership intro (/about/leadership)
   The imported block is one centred text run at the full 1,400px measure —
   1,300px lines, a stray leading <br>, and the "Contact Us" button jammed
   against the "2026 Executive Committee" heading below it. Same Webflow class
   numbers appear on seven other pages, so everything here hangs off the route
   handle the shell now stamps on <body data-page>.
   ============================================================ */
[data-page="about-leadership"] .section-40 { padding-block: clamp(6px, 1.4vw, 18px) clamp(30px, 3.6vw, 54px); }

[data-page="about-leadership"] .section-40 .div-block-113 {
  max-width: 900px; margin-inline: auto;
  background: linear-gradient(180deg, var(--white), var(--sky-50));
  border: 1px solid rgba(2,58,113,.09); border-radius: var(--r-xl);
  box-shadow: var(--sh-sm); padding: clamp(30px, 3.4vw, 48px) clamp(22px, 3vw, 44px);
  position: relative; overflow: hidden;
}
/* the same short crimson rule .eyebrow carries, centred as the panel's opening
   mark — a full-width bar reads as a clipped arc against a 26px corner radius */
[data-page="about-leadership"] .section-40 .div-block-113::before {
  content: ""; display: block; width: 44px; height: 3px; margin: 0 auto clamp(20px, 2.2vw, 30px);
  background: var(--crimson); border-radius: 2px;
}

[data-page="about-leadership"] .section-40 .text-block-66 {
  max-width: 68ch; margin-inline: auto; padding: 0 0 clamp(22px, 2.4vw, 30px);
  font-size: clamp(16.5px, 1.28vw, 18.5px); line-height: 1.74; color: var(--slate);
  text-wrap: pretty;
}
/* the block opens on a hard break that reads as a hole above the first line */
[data-page="about-leadership"] .section-40 .text-block-66 > strong:first-child > br:first-child { display: none; }
/* Webflow wrapped the whole passage in <strong> purely to reach .bold-text-10;
   the opening sentence is the one that should actually carry weight */
[data-page="about-leadership"] .section-40 .text-block-66 > strong:first-of-type {
  color: var(--ink); font-size: 1.06em; font-weight: 500;
}
[data-page="about-leadership"] .section-40 .text-block-66 a {
  color: var(--crimson); font-weight: 600; text-decoration: underline;
  text-decoration-thickness: 1.5px; text-underline-offset: 3px;
  text-decoration-color: rgba(139,21,56,.38);
  transition: text-decoration-color var(--t) var(--ease), color var(--t) var(--ease);
}
[data-page="about-leadership"] .section-40 .text-block-66 a:hover { text-decoration-color: var(--crimson); }

[data-page="about-leadership"] .section-40 .container-82 { padding: 0; }
[data-page="about-leadership"] .section-40 .button-11-copy {
  font-family: var(--font-head); font-weight: 600; letter-spacing: .01em;
  /* Webflow stretches .w-button to the column on phones; a 300px-wide pill for
     two words reads as a form submit, not a quiet secondary action */
  width: fit-content; margin-inline: auto;
  border-radius: 999px; padding: .95em 2em;
  box-shadow: 0 6px 16px rgba(2,58,113,.22);
  transition: transform var(--t) var(--ease), box-shadow var(--t) var(--ease), background-color var(--t) var(--ease);
}
[data-page="about-leadership"] .section-40 .button-11-copy:hover {
  transform: translateY(-2px); box-shadow: 0 10px 24px rgba(2,58,113,.28);
  background-color: var(--deep-2);
}

/* the committee grid started immediately under the button */
[data-page="about-leadership"] .section_team4 { padding-top: clamp(20px, 2.6vw, 40px); }
