/* =====================================================================
   Tech Ready Nevada — design system

   Visual language:
   - Warm, approachable nonprofit style. DM Sans throughout — Bold for
     headings, Regular for body — per the Tech Ready Nevada brand sheet.
   - Small uppercase teal eyebrows with a short trailing rule.
   - Curves are used ONLY where the page meets the header and the footer.
     Every section boundary in between is a flat horizontal edge.
   - Four background fields: cream for reading sections, brand teal for
     mid-page bands, pale mist blue for quiet closing notes, and navy for
     the hero and footer that frame the page.
   - Photos sit in organic "blob" masks with a pale backdrop shape.
   - White rounded cards with soft shadows sit on the teal bands.
   - Amber is the primary action colour and the accent on key words.

   Image/logo placeholders are marked "swap-out" — replace the element
   with a real <img>; no other markup changes needed.
   ===================================================================== */

/* --- Tokens ------------------------------------------------------------ */
/*
  EVERY COLOUR ON THIS SITE COMES FROM THE BRAND SHEET.
  There are no ad-hoc tints. If you need a new shade, add it to the brand
  sheet first, then add it here — don't invent one inline.
*/
:root {
  /* Core palette — official hex values, do not edit without sign-off */
  --navy: #1B3F73;
  --teal: #138A9E;
  --amber: #E6A21A;       /* was named --gold; same hex, brand-sheet name */
  --white: #FFFFFF;
  --warm-white: #FAFAF7;
  --light-gray: #E8ECEF;
  --charcoal: #2B3442;

  /* Illustration accents (brand sheet marks these optional).
     --sand is in use behind the numbered card chips. --sage is reserved:
     it's on the sheet and available, but nothing calls for it yet. */
  --sage: #8CA37A;
  --sand: #E9DDC7;
  --mist: #C9DCE3;

  /* Aliases kept so older rules keep working */
  --gold: var(--amber);
  --grey: var(--light-gray);

  /* Semantic roles — all of these resolve to palette colours above.
     Two rules of thumb this site follows:
       * amber is a FILL, never small text (amber on white is 2.2:1)
       * teal is for headings/labels, not body copy (teal on white is 4.07:1) */
  --ink: var(--charcoal);          /* body text on light  — 12.0:1 on cream */
  --body-muted: var(--charcoal);   /* secondary copy; same ink, brand has one */
  --ink-on-dark: var(--white);     /* body text on navy   — 10.5:1 */
  --ink-on-dark-muted: var(--mist);/* secondary on navy   — 7.4:1 */
  --link: var(--navy);             /* links are navy + underlined (10.5:1).
                                      Teal reads nicer but is 4.07:1 — under
                                      the AA floor for body-size text. */

  --rule-dark: rgba(255, 255, 255, 0.22);
  --rule-light: var(--light-gray);

  /* Type — DM Sans throughout: Bold (700) for headings, Regular for body.
     One variable family, weights 300-700 loaded. Both tokens point at the
     same face; they stay separate so a display face could be swapped in
     later without touching every rule. */
  --font-display: "DM Sans", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  --font-body: "DM Sans", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;

  /* Layout */
  --shell: 1200px;
  --shell-pad: clamp(1.25rem, 4vw, 3rem);
  --section-y: clamp(3.5rem, 7vw, 6.5rem);
  --measure: 60ch;

  --radius-card: 14px;
  --radius-btn: 6px;
  --shadow-card: 0 6px 26px rgba(27, 63, 115, 0.10);
  --shadow-card-hover: 0 14px 36px rgba(27, 63, 115, 0.16);
}

/* --- Reset ------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
img { max-width: 100%; display: block; }
h1, h2, h3, h4, p, ul, ol, figure { margin: 0; }
ul, ol { padding: 0; list-style: none; }

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

/* --- Base -------------------------------------------------------------- */
/* Sticky footer: body is a full-height flex column and <main> grows, so
   the footer always sits at the bottom of the window on short pages. */
body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  font-family: var(--font-body);
  background: var(--warm-white);
  color: var(--ink);
  font-size: clamp(1rem, 0.97rem + 0.15vw, 1.0625rem);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}
main { flex: 1 0 auto; }

/* Headings are DM Sans Bold (700), as specified on the brand sheet.
   If the webfont hasn't loaded the stack falls through to the platform UI
   sans, which is metrically close enough that the layout doesn't jump. */
h1, h2, h3, .display {
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--navy);
  line-height: 1.12;
  letter-spacing: -0.015em;
  text-wrap: balance;
}

h1 { font-size: clamp(2.35rem, 1.6rem + 3.4vw, 4rem); line-height: 1.06; }
h2 { font-size: clamp(1.8rem, 1.35rem + 2vw, 2.75rem); }
h3 { font-size: clamp(1.1rem, 1.02rem + 0.4vw, 1.3rem); line-height: 1.25; }

p { max-width: var(--measure); }
p + p { margin-top: 1.05em; }

a { color: var(--link); text-underline-offset: 0.2em; }
a:hover { color: var(--navy); }
strong { font-weight: 700; }

/* Gold accent on a key phrase inside a headline */
.accent { color: var(--gold); }

/*
  Eyebrow: small uppercase label with a short rule trailing after it
  ("OUR MISSION ———").

  ACCESSIBILITY NOTE. These labels use brand teal by request. On cream that
  measures 3.89:1 — under the WCAG AA 4.5:1 floor for small text — so some
  visitors will find them faint. Changing `color` below to var(--navy)
  fixes it (10.0:1) at the cost of the teal. Teal is unreadable on navy
  (2.6:1), which is why .eyebrow--on-dark uses amber and the teal bands
  use white.
*/
.eyebrow {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--teal);
  margin-bottom: 1.1rem;
}
.eyebrow::after {
  content: "";
  height: 1px;
  width: 42px;
  background: currentColor;
  opacity: 0.75;
  flex-shrink: 0;
}
/* On navy/charcoal the raw brand gold is readable (4.8:1) */
.eyebrow--on-dark { color: var(--gold); }

.lede {
  font-size: clamp(1.02rem, 1rem + 0.3vw, 1.15rem);
  color: var(--body-muted);
}
:is(.section--navy, .section--charcoal, .section--teal) .lede {
  color: var(--ink-on-dark);
}

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

/* Spacing utilities, so page markup never needs inline style=""
   attributes (which a strict Content-Security-Policy blocks). */
.u-mt-sm { margin-top: 0.85rem; }
.u-mt { margin-top: 1.35rem; }
.u-mt-lg { margin-top: 2rem; }
.u-muted { color: var(--body-muted); }
/* Lets one paragraph run the full width of its section instead of stopping
   at the 60ch reading measure. Use it on short closing lines only — a full
   column of body text at this width is genuinely harder to read. */
.u-wide { max-width: none; }
:is(.section--navy, .section--charcoal, .section--teal) .u-muted {
  color: var(--ink-on-dark-muted);
}

.section {
  position: relative;
  padding-block: var(--section-y);
  /*
    The decorative starburst and the blob's backdrop shape deliberately sit
    outside their column, which otherwise pushes the page wider than the
    viewport and creates a horizontal scrollbar on phones and tablets.
    `clip` trims that overhang WITHOUT turning the section into a scroll
    container the way `overflow: hidden` would — which matters, because
    hidden on one axis forces the other axis to `auto` and would clip the
    curve sitting at the section's bottom edge.
  */
  overflow-x: clip;
}
/* Older browsers without overflow:clip fall back to hidden. The curve is
   given a 1px allowance below so the fallback doesn't shave it. */
@supports not (overflow: clip) {
  .section { overflow-x: hidden; }
}
/* Reduced vertical padding — for short interjections like the pull quote,
   which would look marooned inside a full-height section. */
.section--tight { padding-block: clamp(2rem, 4vw, 3.25rem); }
/* Trims only the TOP padding, for a band that should sit close under the
   section above it rather than floating a full gap away. */
.section--tight-top { padding-top: clamp(1.75rem, 3.5vw, 3rem); }

.section--navy {
  background: var(--navy);
  color: var(--ink-on-dark);
}
.section--charcoal {
  background: var(--charcoal);
  color: var(--ink-on-dark);
}
/*
  Teal band — the mid-page counterpart to the navy top and bottom.

  READ THIS BEFORE REUSING THE TEAL BAND FOR LONG COPY.
  This is the exact brand teal (#138A9E), by request. White text on it is
  4.07:1 — fine for headings and buttons (large text needs only 3:1) but
  just under the 4.5:1 AA floor for body-size paragraphs. Keep paragraphs
  on this band short. If a band ever needs to carry a lot of reading copy,
  use .section--navy instead (white on navy is 10.5:1).
*/

/* --- Background texture --------------------------------------------------
   Applied to three of the four background fields, never to cream — cream is
   where the reading happens and it stays flat. Everything here is a CSS
   gradient (no image requests) held at 4-7% opacity: enough to stop a large
   flat band looking like dead space, too faint to read as a pattern.

   All three tints are drawn in NAVY or WHITE, both palette colours, and all
   three are dark-on-light or light-on-dark in the direction that nudges
   text contrast UP rather than down. The teal band in particular gains a
   hair of contrast for its white type rather than losing any.
   -------------------------------------------------------------------- */
.section--teal {
  background-color: var(--teal);
  background-image: repeating-linear-gradient(
    135deg,
    rgba(27, 63, 115, 0.055) 0 1px,
    rgba(27, 63, 115, 0) 1px 10px);
  color: var(--ink-on-dark);
}
/*
  Mist-blue band — a pale closing note. Light field, so it opts out of all
  the dark-section rules below and just uses the normal ink colours.
*/
.section--mist {
  background-color: var(--mist);
  background-image: radial-gradient(rgba(27, 63, 115, 0.07) 1px, transparent 1px);
  background-size: 15px 15px;
}
.section--mist :is(h1, h2, h3) { color: var(--navy); }        /* 7.4:1  */
.section--mist :is(p, .lede, .u-muted) { color: var(--charcoal); } /* 8.9:1 */
.section--mist .eyebrow { color: var(--navy); }

/* :is() keeps these lists readable; add any new dark section variant here
   once and every rule below picks it up. */
:is(.section--navy, .section--charcoal, .section--teal) :is(h1, h2, h3) {
  color: var(--white);
}
:is(.section--navy, .section--charcoal, .section--teal) p {
  color: var(--ink-on-dark);
}

/*
  IMPORTANT: the two rules above turn text white for anything inside a dark
  section — including the WHITE cards that sit on top of one, which would
  render white-on-white and vanish. Every light surface used inside a dark
  section must reset its own text colour here.
*/
:is(.section--navy, .section--charcoal, .section--teal)
  :is(.card h3, .statement h3, .event--light .event__when, .partners__slot) {
  color: var(--navy);
}
:is(.section--navy, .section--charcoal, .section--teal)
  :is(.card p, .statement p) {
  color: var(--body-muted);
}
:is(.section--navy, .section--charcoal, .section--teal) .statement__text {
  color: var(--navy);
}
:is(.section--navy, .section--charcoal, .section--teal)
  :is(.card, .statement) .eyebrow {
  color: var(--teal);
}
/*
  The teal band is much lighter than navy, so tones that pass on navy fail
  on teal and are lifted to white here:
    amber      1.85:1 on teal -> white (4.07:1)
    mist blue  2.88:1 on teal -> white (4.07:1)
  Amber stays on navy, where it measures 4.76:1 — hence the teal-only scope.
*/
.section--teal .eyebrow { color: var(--white); }
/*
  Mist-blue eyebrow used for the Workshops "Catalog" label by request.
  On the teal band it measures 2.88:1, under the AA 4.5:1 floor for small
  text — it is a short signpost label rather than content the page depends
  on, but if it ever needs to pass, deleting this one rule returns it to
  white. Must stay after the rule above to win.
*/
.section--teal .eyebrow--pale { color: var(--mist); }
.section--teal .u-muted { color: var(--white); }
.section--teal .arrow-link--light { color: var(--white); }
.section--teal .arrow-link--light:hover {
  color: var(--white);
  text-decoration: underline;
}

/* Asymmetric two-column grid */
.duo {
  display: grid;
  gap: clamp(2.75rem, 7vw, 6.5rem);
  align-items: center;
}
@media (min-width: 900px) {
  .duo { grid-template-columns: 1fr 1fr; }
  .duo--text-narrow { grid-template-columns: 5fr 7fr; }
  .duo--text-wide { grid-template-columns: 7fr 5fr; }
}

/* --- Curved section dividers --------------------------------------------
   A soft SVG wave sits at the bottom of a section and is filled with the
   NEXT section's background colour, so the two fields meet on a curve
   instead of a straight edge. Set the colour with .curve--<name>; the
   path uses fill="currentColor".
   Purely decorative — the wrapper is aria-hidden in the markup. */
.curve {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;      /* -1px hides sub-pixel seams between the two fields */
  line-height: 0;
  pointer-events: none;
  z-index: 2;
}
.curve svg {
  display: block;
  width: 100%;
  height: clamp(38px, 5.5vw, 82px);
}
.curve--cream { color: var(--warm-white); }
.curve--navy { color: var(--navy); }
.curve--charcoal { color: var(--charcoal); }
.curve--teal { color: var(--teal); }
.curve--white { color: var(--white); }

/* Any section carrying a .curve needs extra bottom padding, otherwise the
   wave overlaps the last line of content. */
.has-curve {
  padding-bottom: calc(var(--section-y) * 0.7 + clamp(38px, 5.5vw, 82px));
}

/* --- Masthead ---------------------------------------------------------- */
.masthead {
  position: sticky;
  top: 0;
  z-index: 30;
  background: var(--warm-white);
  border-bottom: 1px solid var(--rule-light);
}
.masthead__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-block: 0.9rem;
  flex-wrap: wrap;
}

/*
  Logo lockup.

  Two files, not one file recoloured:
    images/logo.svg        navy + teal, for the cream header
    images/logo-light.svg  white knockout, for the navy footer

  A CSS filter can't produce the footer version. The mark is a raster with
  its detail drawn in white ON navy, so `brightness(0) invert(1)` flattens
  it to a solid white blob. logo-light.svg instead paints the silhouette
  white and repaints the detail in the footer's own navy, so it reads as
  genuinely punched out.

  Sizing is by height only; width follows the 974.88 x 262.5 viewBox.
*/
.wordmark {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
}
.wordmark__logo {
  display: block;
  height: clamp(38px, 4.6vw, 52px);
  width: auto;
}
.colophon .wordmark__logo { height: clamp(40px, 5vw, 56px); }

#nav-toggle {
  display: none;
  background: none;
  border: 1px solid var(--rule-light);
  border-radius: var(--radius-btn);
  padding: 0.55rem 0.9rem;
  font: inherit;
  font-weight: 600;
  color: var(--navy);
  cursor: pointer;
}

.nav {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2.2vw, 2rem);
}
.nav a {
  text-decoration: none;
  color: var(--charcoal);
  font-weight: 500;
  padding-block: 0.3rem;
  border-bottom: 2px solid transparent;
}
.nav a:hover { color: var(--link); }
.nav a[aria-current="page"] {
  color: var(--navy);
  border-bottom-color: var(--teal);
}
/* Amber pill CTA sitting at the end of the nav */
.nav .nav__cta {
  border-bottom: none;
  padding: 0;
}

@media (max-width: 920px) {
  #nav-toggle { display: block; }
  .nav {
    display: none;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.2rem;
    width: 100%;
    padding-block: 0.5rem 0.25rem;
  }
  .nav.is-open { display: flex; }
  .nav li { width: 100%; }
  .nav a {
    display: block;
    width: 100%;
    padding-block: 0.65rem;
    border-bottom: 1px solid var(--rule-light);
  }
  .nav .nav__cta { padding-block: 0.75rem; border-bottom: none; }
}

/* --- Hero -------------------------------------------------------------- */
.hero {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: center;
  min-height: clamp(28rem, 74vh, 42rem);
  padding-block: clamp(3.5rem, 8vw, 6rem) clamp(5rem, 9vw, 7.5rem);
  overflow: hidden;
  background: var(--navy);
  color: var(--ink-on-dark);
}
.hero h1 { color: var(--white); max-width: 15ch; }

/*
  Background photo layer. The faint hatching is a fallback: it only shows
  if images/hero.jpg is missing, so a not-yet-added photo reads as "nothing
  here yet" instead of looking broken. Once the real image loads it covers
  the hatching completely — nothing to delete.
*/
.hero__media {
  position: absolute;
  inset: 0;
  z-index: -2;
  background-color: var(--charcoal);
  background-image: repeating-linear-gradient(
    45deg,
    rgba(255, 255, 255, 0.10) 0 14px,
    rgba(255, 255, 255, 0) 14px 28px
  );
}
/* object-fit: cover crops the photo to fill the hero without distorting it,
   so any aspect ratio works. object-position picks which part survives the
   crop — change it to e.g. "center 30%" to favour the top of the image. */
.hero__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}
/*
  Scrim. Required, not decorative: white text over an arbitrary photo is
  unreadable without it. Measured against a pure-white photograph, the
  headline still holds ~7:1. If you swap in a very bright image and it
  looks washed out, raise these alpha values.
*/
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
    100deg,
    rgba(20, 45, 84, 0.93) 0%,
    rgba(20, 45, 84, 0.86) 38%,
    rgba(20, 45, 84, 0.50) 64%,
    rgba(20, 45, 84, 0.20) 100%
  );
}
/*
  The scrim is heaviest on the left, where the headline sits, and fades to
  nearly clear on the right so the photograph is actually visible. Measured
  against a worst case of a pure-white photo, white headline text still
  holds about 7:1 in the heavy zone — well past the WCAG AA minimum.
  If you swap in a very bright image and the text feels weak, raise the
  first two alpha values (0.93 / 0.86) rather than adding a text shadow.
*/
.hero__lede {
  margin-top: 1.5rem;
  max-width: 40ch;
  font-size: clamp(1.02rem, 1rem + 0.35vw, 1.18rem);
  color: var(--ink-on-dark);
}
.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.85rem;
  margin-top: 2.2rem;
}
/* Small caption marking the placeholder. Delete with the placeholder. */
.hero__note {
  position: absolute;
  right: var(--shell-pad);
  bottom: clamp(3.5rem, 6vw, 5.5rem);
  z-index: 3;
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.6);
}

/* --- Page hero (inner pages) ------------------------------------------- */
.page-hero {
  position: relative;
  background: var(--navy);
  color: var(--ink-on-dark);
  padding-block: clamp(3rem, 6vw, 5rem) clamp(4.5rem, 8vw, 7rem);
}
.page-hero h1 { color: var(--white); max-width: 17ch; }
.page-hero__lede {
  margin-top: 1.3rem;
  max-width: 52ch;
  font-size: clamp(1.02rem, 1rem + 0.3vw, 1.15rem);
  color: var(--ink-on-dark);
}

/* --- Blob photo treatment ------------------------------------------------
   An organic mask for photographs, with a pale tinted shape peeking out
   behind it — the mockup's signature image treatment. */
.blob-wrap {
  position: relative;
  isolation: isolate;
}
/* Pale backdrop shape, offset and rotated so it peeks out from behind the
   photo on two corners rather than ringing it evenly. */
.blob-wrap::before {
  content: "";
  position: absolute;
  inset: -9% -3% 2% -9%;
  z-index: -1;
  background: var(--mist);
  border-radius: 62% 38% 30% 70% / 55% 62% 38% 45%;
  transform: rotate(-6deg);
}
:is(.section--navy, .section--charcoal, .section--teal) .blob-wrap::before {
  background: rgba(255, 255, 255, 0.10);
}

/*
  The organic mask itself — shared by the real photo and the placeholder.
  swap-out: replace a placeholder <div class="blob"> with
      <img class="blob" src="..." alt="describe what is happening">
*/
.blob {
  border-radius: 46% 54% 62% 38% / 40% 45% 55% 60%;
  overflow: hidden;
  aspect-ratio: 4 / 3;
  width: 100%;
}
/* A real photograph: fills the mask edge to edge, no placeholder chrome. */
img.blob {
  height: 100%;
  object-fit: cover;
  object-position: center;
}
/* Placeholder chrome — only applies while the slot is still an empty <div>,
   so it disappears automatically the moment a photo is dropped in. */
div.blob {
  background: var(--grey);
  border: 1px dashed var(--teal);
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 1.5rem;
  color: var(--charcoal);
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}


/* --- Cards ---------------------------------------------------------------*/
.card-grid {
  display: grid;
  gap: clamp(1.1rem, 2vw, 1.6rem);
  grid-template-columns: repeat(auto-fit, minmax(255px, 1fr));
}
.card-grid--3 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
/* Force exactly three columns on desktop — with five items, auto-fit
   would give a lopsided 4 + 1 row. */
@media (min-width: 900px) {
  .card-grid--3up { grid-template-columns: repeat(3, 1fr); }
}

.card {
  display: flex;
  flex-direction: column;
  background: var(--white);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  overflow: hidden;
  transition: transform 0.22s ease, box-shadow 0.22s ease;
}
.card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-card-hover);
}
.card__body {
  /* min-height gives every card the same generous body even when the title
     is one short line, so a grid of them reads as a deliberate set rather
     than a row of mismatched boxes. */
  min-height: 190px;
  padding: clamp(1.5rem, 2.4vw, 2rem);
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  flex: 1 0 auto;
}
/* Cards carrying a description need less forced height — the copy fills it. */
.card-grid--3 .card__body { min-height: 150px; }
.card__body p { color: var(--body-muted); font-size: 0.95rem; }
.card__meta {
  margin-top: auto;
  padding-top: 0.85rem;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--link);
}

/*
  Workshop catalog titles — exact brand teal (#138A9E) by request.

  READ THIS BEFORE CHANGING THE FONT-SIZE OR WEIGHT BELOW.
  Brand teal on a white card measures 4.07:1. That is under the WCAG AA
  minimum of 4.5:1 for normal-size text, but over the 3:1 minimum that
  applies to *large* text — defined as 14pt bold (18.66px at weight 700)
  or larger. So the 1.2rem floor (19.2px) and the 700 weight are
  load-bearing: they are what makes the exact brand colour pass here.
  If these titles are ever made smaller or lighter, switch the colour to
  var(--navy) (10.5:1) at the same time.

  Scoped to --catalog so the identical card grid on the Resources page
  keeps its navy titles.
*/
.card-grid--catalog .card h3,
:is(.section--navy, .section--charcoal, .section--teal)
  .card-grid--catalog .card h3 {
  color: var(--teal);
  font-size: clamp(1.2rem, 1.12rem + 0.4vw, 1.4rem);
  font-weight: 700;
}

/* swap-out: replace with <img src="..." alt=""> at the top of the card */
.card__media {
  aspect-ratio: 16 / 10;
  background: var(--grey);
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 1rem;
  color: var(--charcoal);
  font-size: 0.68rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

/* Small gold index chip on topic cards */
.card__chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  border-radius: 10px;
  background: var(--sand);   /* brand accent; navy on sand is 7.8:1 */
  color: var(--navy);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.05rem;
  margin-bottom: 0.35rem;
}

/* --- Statement cards (mission / vision) ---------------------------------- */
.statement {
  background: var(--white);
  border-radius: 18px;
  box-shadow: var(--shadow-card);
  padding: clamp(1.6rem, 3vw, 2.5rem);
}
.statement__text {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.2rem, 1.05rem + 0.7vw, 1.55rem);
  line-height: 1.35;
  color: var(--navy);
  letter-spacing: -0.01em;
  max-width: 34ch;
}
.statement-pair {
  display: grid;
  gap: clamp(1.25rem, 2.5vw, 1.75rem);
}
@media (min-width: 860px) {
  .statement-pair { grid-template-columns: 1fr 1fr; }
}

/* --- Pull quote -----------------------------------------------------------
   A single highlighted statement, set large with a teal rule down its left
   edge. Marked up as <blockquote> so it is a quotation semantically, not
   just big text. */
/*
  Pull quote — a centred white card with an oversized teal quotation mark,
  sitting on a mist-blue slab that is offset a few pixels down and right.
  That offset slab is the whole trick: it gives the card depth without a
  drop shadow and echoes the blob backdrops used behind the photographs.

  Replaces an earlier left-rule treatment, which pinned the quote to a
  narrow column on the left and left the right half of the band empty.
*/
.pull-quote {
  position: relative;
  margin: 0 auto;
  max-width: 60rem;
  padding: clamp(2.25rem, 4vw, 3.25rem) clamp(1.5rem, 5vw, 4rem)
           clamp(2rem, 3.5vw, 2.75rem);
  background: var(--white);
  border-radius: var(--radius-card);
  text-align: center;
  /*
    The offset slab is a hard-edged box-shadow, not a pseudo-element.
    A pseudo-element would need z-index: -1 to sit behind the card, and a
    negative z-index child paints above its parent's BACKGROUND — so the
    mist slab covered the white card instead of peeking out from under it.
    box-shadow paints outside the border box by definition and has no such
    problem. It also inherits the border-radius for free.
  */
  box-shadow: 16px 16px 0 var(--mist);
}
/*
  Decorative opening quote mark. The paired slash-empty-string gives it a
  null alt text in browsers that support it, so a screen reader announces
  the quotation itself and not a stray punctuation glyph.
*/
.pull-quote::before {
  content: "\201C" / "";
  display: block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(3.25rem, 7vw, 5rem);
  line-height: 0.68;
  color: var(--teal);
  margin-bottom: 0.5rem;
}
.pull-quote p {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.25rem, 0.95rem + 1.2vw, 1.85rem);
  line-height: 1.38;
  letter-spacing: -0.015em;
  color: var(--navy);
  max-width: 44ch;      /* keeps the LINES readable inside the wide card */
  margin-inline: auto;
}

/* --- Audience list --------------------------------------------------------- */
.audience-list li {
  position: relative;
  padding-left: 1.9rem;
  margin-bottom: 0.9rem;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.15rem, 1rem + 0.7vw, 1.5rem);
  line-height: 1.3;
  letter-spacing: -0.01em;
  color: var(--navy);
}
.audience-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.5em;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--teal);   /* teal bullets, per the Contact page brief */
}

/* --- Audience line -------------------------------------------------------- */
.audience-line {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.5rem, 1.15rem + 1.6vw, 2.4rem);
  line-height: 1.28;
  letter-spacing: -0.015em;
  color: var(--navy);
  max-width: 22ch;
}

/* --- Bullets -------------------------------------------------------------- */
.marks li {
  position: relative;
  padding-left: 1.7rem;
  margin-bottom: 0.65rem;
  max-width: var(--measure);
}
.marks li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--teal);   /* teal bullets, per the Contact page brief */
}

/* --- Buttons ------------------------------------------------------------ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  font-family: var(--font-body);
  font-size: 0.95rem;
  font-weight: 600;
  text-decoration: none;
  padding: 0.8rem 1.4rem;
  border: 1.5px solid var(--navy);
  background: var(--navy);
  color: var(--white);
  border-radius: var(--radius-btn);
  transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}
.btn:hover { background: var(--charcoal); border-color: var(--charcoal); color: var(--white); }

/* Primary action. Charcoal text on amber measures 5.71:1. */
.btn--gold {
  background: var(--amber);
  border-color: var(--amber);
  color: var(--charcoal);
}
/* Hover flips to a navy fill, so the label MUST flip to white with it —
   charcoal on navy is 1.65:1 and would be effectively invisible. */
.btn--gold:hover { background: var(--navy); border-color: var(--navy); color: var(--white); }

/*
  Teal button with a white label — the Home hero call to action.

  READ THIS BEFORE SHRINKING IT.
  White on brand teal is 4.07:1. That clears the 3:1 WCAG floor for LARGE
  text but not the 4.5:1 floor for normal text, so the 1.18rem (18.9px) /
  700 size below is load-bearing: it is what puts this label in the "large"
  category. Drop the size or the weight and the button quietly fails.
  It reads as a deliberately prominent hero CTA, which is what it is.
*/
.btn--teal {
  background: var(--teal);
  border-color: var(--teal);
  color: var(--white);
  font-size: 1.18rem;
  font-weight: 700;
  padding: 0.95rem 1.75rem;
}
.btn--teal:hover {
  background: var(--navy);
  border-color: var(--navy);
  color: var(--white);
}

/*
  Button for use ON the teal band.
  Amber is the primary action colour everywhere else, but amber on teal is
  only 1.85:1 — below the 3:1 that WCAG asks for so a control's edge can be
  made out at all. A white fill is 4.07:1 against teal and clears it.
*/
.btn--on-teal {
  background: var(--white);
  border-color: var(--white);
  color: var(--navy);       /* 10.5:1 on white */
}
.btn--on-teal:hover {
  background: var(--navy);
  border-color: var(--white);
  color: var(--white);
}

/* For use on navy/charcoal fields and over the hero photo */
.btn--ghost {
  background: transparent;
  border-color: rgba(255, 255, 255, 0.75);
  color: var(--white);
}
.btn--ghost:hover {
  background: var(--white);
  border-color: var(--white);
  color: var(--navy);
}

.btn--sm { padding: 0.6rem 1.1rem; font-size: 0.88rem; }

/* Text link with a trailing arrow that slides on hover */
.arrow-link {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-weight: 600;
  color: var(--link);
  text-decoration: none;
}
.arrow-link:hover { color: var(--navy); }
.arrow-link::after {
  content: "\2192";
  transition: transform 0.2s ease;
}
.arrow-link:hover::after { transform: translateX(4px); }
.arrow-link--light { color: var(--gold); }
.arrow-link--light:hover { color: var(--white); }

.link-list {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.9rem;
}

/* --- Event rows (workshop dates) ----------------------------------------- */
.events { display: grid; gap: 0.75rem; }
.event {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid var(--rule-dark);
  border-radius: var(--radius-card);
  padding: 1rem 1.15rem;
}
.event__when {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.1rem;
  color: var(--white);
}
.event__where {
  display: block;
  font-size: 0.85rem;
  color: var(--ink-on-dark-muted);
  margin-top: 0.2rem;
}
/* Variant for event rows sitting on a cream/white background */
.event--light {
  background: var(--white);
  border-color: transparent;
  box-shadow: var(--shadow-card);
}
.event--light .event__when { color: var(--navy); }
.event--light .event__where { color: var(--body-muted); }

/*
  Stacked variant (Workshops → Upcoming Sessions).

  Two changes from the default side-by-side row:
  1. flex-direction: column puts the Register button underneath the date
     and venue instead of beside them.
  2. grid-auto-rows: 1fr forces every card in the list to the height of the
     tallest one, so adding a session with a long venue name later can't
     leave you with one card taller than its neighbours.

  The ul sizes to its own content (it is a plain block inside the grid
  column, not a grid item itself), so 1fr equalises the rows rather than
  stretching them to fill the column.
*/
.events--stacked { grid-auto-rows: 1fr; }
.events--stacked .event {
  flex-direction: column;
  flex-wrap: nowrap;
  align-items: flex-start;
  gap: 1.1rem;
}
.events--stacked .event .btn {
  /* auto margin pins the button to the bottom of its card, so the buttons
     line up with each other even when one card's text runs to an extra line */
  margin-top: auto;
  align-self: flex-start;
}

/* --- Partner logos ------------------------------------------------------ */
.partners {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  align-items: center;
  margin-top: 1.1rem;
}
/* swap-out: replace each with a partner logo <img> */
/* A white card behind each partner mark, so logos with their own colours
   and their own background assumptions all sit on a neutral field. */
.partners__slot {
  width: 196px;
  height: 124px;
  background: var(--white);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 0.85rem;
  color: var(--charcoal);
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
/* Real partner artwork: fit inside the card without cropping or distorting.
   object-fit: contain preserves each mark's own aspect ratio. */
.partners__slot img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
}

/* --- Contact display ----------------------------------------------------- */
.contact-email {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.4rem, 1rem + 2.2vw, 2.6rem);
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: var(--navy);
  text-decoration: none;
  display: inline-block;
  word-break: break-word;
  border-bottom: 3px solid var(--gold);
  padding-bottom: 0.15rem;
}
.contact-email:hover { color: var(--link); }

/* --- Footer -------------------------------------------------------------- */
/*
  The footer stays a FLAT field of brand navy — no texture.

  It used to carry a soft radial glow like the other bands. That glow lifted
  the top-left of the footer to about rgb(37,71,121) while the decorative
  wave immediately above it is a flat SVG fill of brand navy rgb(27,63,115),
  so the two blues visibly failed to meet along the seam. The wave takes its
  colour from `.curve--navy` and cannot carry a gradient, so anything applied
  here that changes the top edge will reopen that mismatch. Leave it flat.
*/
.colophon {
  background-color: var(--navy);
  color: var(--ink-on-dark-muted);
  padding-block: clamp(2.75rem, 5vw, 4rem) 1.75rem;
}
.colophon__grid {
  display: grid;
  gap: clamp(2rem, 4vw, 3rem);
}
@media (min-width: 800px) {
  .colophon__grid { grid-template-columns: 2.2fr 1fr 1fr 1.4fr; }
}
.colophon__blurb {
  margin-top: 1rem;
  font-size: 0.92rem;
  max-width: 30ch;
  color: var(--ink-on-dark-muted);
}

.colophon__heading {
  color: var(--white);
  font-size: 0.95rem;
  font-weight: 700;
  margin-bottom: 0.9rem;
}
.colophon__links li { margin-bottom: 0.5rem; }
.colophon__links a,
.colophon__contact a {
  color: var(--ink-on-dark-muted);
  text-decoration: none;
  font-size: 0.94rem;
}
.colophon__links a:hover,
.colophon__contact a:hover { color: var(--gold); }
.colophon__contact p { margin-bottom: 0.5rem; font-size: 0.94rem; }

/* "Ready for What's Next" — the tagline line under the footer blurb. */
.colophon__tagline {
  font-family: var(--font-display);
  font-style: italic;
  font-size: 1.05rem;
  color: var(--gold);
  margin-top: 0.45rem;
}

.colophon__badge {
  display: inline-block;
  border: 1px solid var(--rule-dark);
  border-radius: 6px;
  padding: 0.45rem 0.75rem;
  margin-top: 1.1rem;
  color: var(--ink-on-dark-muted);
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.colophon__base {
  margin-top: clamp(2rem, 4vw, 3rem);
  padding-top: 1.35rem;
  border-top: 1px solid var(--rule-dark);
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem 2rem;
  justify-content: space-between;
  /* var(--mist) measures 5.9:1 on --navy, clearing the AA 4.5:1 minimum for
     this small legal type. Do not darken further. */
  color: var(--mist);
  font-size: 0.82rem;
}
.colophon__base p { max-width: 62ch; }

/* --- Motion -------------------------------------------------------------- */
/* Sections fade up once on entry. The .reveal class is only added by JS,
   so with JS disabled everything renders visible as normal. */
.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.7s ease, transform 0.7s ease;
}
.reveal.is-visible { opacity: 1; transform: none; }

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