/* Zoe Dao-Kroeker — structural + component CSS.
   .container / .eyebrow / .btn-pill / .btn-outline / .btn-ghost / .card are
   copied class-for-class from larakroekerinteractive.com/design-guidelines/
   (structure and behaviour, not colour) per Lara's instruction to set this
   site up exactly the same as LKI's. Everything reads colors_and_type.css's
   role variables (--bg, --fg, --cta, etc.) — never a --zoe-* primitive
   directly, and never a hardcoded hex. */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-sans);
  font-size: var(--type-body);
  line-height: var(--type-body-lh);
  /* Was --fw-regular (300) — read too light for reading copy at body/small
     sizes (Lara, August 27, 2026). --fw-regular stays 300 and is still
     used explicitly by lead/intro-sized text, which she wants to keep
     light. */
  font-weight: var(--fw-body);
}

h1, h2, h3, h4 {
  margin: 0;
  font-family: var(--font-sans);
  font-weight: var(--fw-black);
  letter-spacing: var(--track-heading);
}
/* Display font on h1 only (hero headings, page titles). h2 reverted to the
   sans the same day it was added — Fontdiner Swanky is a one-tier accent,
   not the whole heading system — so h2/h3/h4 all stay on the base rule
   above. Fontdiner Swanky ships one weight, so reset weight/tracking rather
   than inherit the sans's black weight and tight negative tracking, which
   would fight a hand-lettered face. */
h1 {
  font-family: var(--font-display);
  font-weight: 400;
  letter-spacing: normal;
}
p { margin: 0; }
a { color: inherit; }
img { max-width: 100%; display: block; }
ul, ol { list-style: none; margin: 0; padding: 0; }

/* Real typography for raw post content (portfolio project write-ups,
   single-post.php) — the global reset zeroes p/ul/ol margins site-wide
   (see the top of this file), which left every paragraph, list item,
   and embedded <img> in this content running straight into the next
   with no breathing room. Not just list-style was missing. */
.body-copy ul, .post-content ul, .page-content ul { list-style: disc; padding-left: 1.25em; }
.body-copy ol, .post-content ol, .page-content ol { list-style: decimal; padding-left: 1.25em; }
.body-copy p, .post-content p, .page-content p { margin: 0 0 var(--sp-20); }
.body-copy p:last-child, .post-content p:last-child, .page-content p:last-child { margin-bottom: 0; }
.body-copy h2, .post-content h2, .page-content h2 { font-size: var(--type-h3); font-weight: var(--fw-black); margin: var(--sp-32) 0 var(--sp-12); }
.body-copy h3, .post-content h3, .page-content h3 { font-size: var(--type-h4); font-weight: var(--fw-black); margin: var(--sp-24) 0 var(--sp-8); }
.body-copy ul, .post-content ul, .page-content ul,
.body-copy ol, .post-content ol, .page-content ol { margin: 0 0 var(--sp-20); }
.body-copy li, .post-content li, .page-content li { margin-bottom: var(--sp-8); }
.body-copy li p, .post-content li p, .page-content li p { margin-bottom: 0; }
.body-copy img, .post-content img, .page-content img { max-width: 100%; height: auto; display: block; border-radius: var(--radius-lg); margin: var(--sp-32) 0; }
/* --fw-bold (700), not --fw-black (800) — pairs with the 400 base body
   weight the way Open Sans's real Bold/Regular pair is meant to; Black is
   reserved for headings and labels. */
.body-copy strong, .post-content strong, .page-content strong { font-weight: var(--fw-bold); }
.body-copy a, .post-content a, .page-content a { color: var(--accent-deep); text-decoration: underline; }

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--bg-inverse);
  color: var(--fg-on-dark);
  padding: var(--sp-8) var(--sp-16);
  z-index: 1000;
}
.skip-link:focus { left: var(--sp-12); top: var(--sp-12); }

.container { max-width: var(--wrap-max); margin: 0 auto; padding: 0 var(--sp-80); }

@media (max-width: 760px) {
  /* Was --sp-20 — too tight against the screen edge (Lara, August 27,
     2026: "the margins don't have enough right/left space"). */
  .container { padding: 0 var(--sp-32); }
}

/* ── Eyebrow ──────────────────────────────────────────────────────────── */

.eyebrow {
  display: block;
  font-size: var(--type-micro);
  line-height: var(--type-micro-lh);
  font-weight: var(--fw-black);
  letter-spacing: var(--track-micro);
  text-transform: uppercase;
  color: var(--accent-deep);
  margin-bottom: var(--sp-20);
}

/* Per-page eyebrow colour (Lara, August 27, 2026: "on research make the
   eyebrows blue... on about make the eyebrows green... except in the
   hero"). Scoped to page templates via a body-of-main class rather than
   overriding --accent-deep itself, which every other page still reads for
   Coral eyebrows/links/hover states. "Except in the hero" is any eyebrow
   inside .zoe-bg-block (the one colour block each of these pages has) —
   those already get forced to --fg-on-dark for contrast against the
   coloured background and must keep winning, hence the second, more
   specific rule below each. */
.zoe-main--research .eyebrow { color: var(--zoe-blue); }
.zoe-main--research .zoe-bg-block .eyebrow { color: var(--fg-on-dark); }
.zoe-main--about .eyebrow { color: var(--zoe-green); }
.zoe-main--about .zoe-bg-block .eyebrow { color: var(--fg-on-dark); }

/* ── Buttons — one filled pill, one flash of CTA colour ──────────────── */

.btn-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-8);
  padding: var(--sp-8) var(--sp-8) var(--sp-8) var(--sp-24);
  border-radius: var(--radius-pill);
  background: var(--bg-inverse);
  color: var(--fg-on-dark);
  font-family: var(--font-sans);
  font-size: var(--type-small);
  font-weight: var(--fw-black);
  letter-spacing: 0.01em;
  border: none;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: background var(--dur-fast) var(--ease-standard), color var(--dur-fast) var(--ease-standard);
}
.btn-pill .arr {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--cta);
  color: var(--fg);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: transform var(--dur-std) var(--ease-standard);
}
.btn-pill:hover { background: var(--cta); color: var(--fg); }
.btn-pill:active { background: var(--cta-hover); color: var(--fg); }
.btn-pill:hover .arr { background: var(--bg-inverse); color: var(--fg-on-dark); transform: rotate(45deg); }

.btn-outline {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-8);
  padding: var(--sp-12) var(--sp-24);
  border-radius: var(--radius-pill);
  border: 1.5px solid var(--fg);
  background: transparent;
  color: var(--fg);
  font-family: var(--font-sans);
  font-size: var(--type-small);
  font-weight: var(--fw-black);
  cursor: pointer;
  text-decoration: none;
  transition: background var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast);
}
.btn-outline:hover { background: var(--cta); border-color: var(--cta); color: var(--fg); }
.btn-outline:active { background: var(--cta-hover); border-color: var(--cta-hover); color: var(--fg); }

.btn-ghost {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-8);
  background: none;
  border: none;
  cursor: pointer;
  text-decoration: none;
  font-family: var(--font-sans);
  font-size: var(--type-small);
  font-weight: var(--fw-black);
  color: var(--fg-on-dark-muted);
  transition: color var(--dur-fast);
}
.btn-ghost:hover { color: var(--cta); }
.btn-ghost--dark { color: var(--fg-muted); }
.btn-ghost--dark:hover {
  color: var(--fg);
  text-decoration: underline;
  /* --cta-hover, not --cta: the base amber only clears WCAG's 3:1
     non-text-contrast minimum with dark text sitting ON it (buttons, the
     arrow circle) — as a thin line on a light background it undershoots
     3:1. The darker pressed-state tone reads clearly here instead. */
  text-decoration-color: var(--cta-hover);
  text-underline-offset: 5px;
  text-decoration-thickness: 2px;
}

/* ── Card ─────────────────────────────────────────────────────────────── */

.card {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--sp-32) var(--sp-24);
  display: flex;
  flex-direction: column;
  background: var(--bg-raised);
  transition: transform var(--dur-std) var(--ease-standard), box-shadow var(--dur-std) var(--ease-standard);
}
.card:hover { transform: translateY(-4px); box-shadow: var(--shadow-xs); }

/* ── Nav ──────────────────────────────────────────────────────────────── */

.zoe-nav {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--bg-raised);
  border-bottom: 1px solid var(--border);
}
.zoe-nav__inner {
  max-width: var(--wrap-max);
  margin: 0 auto;
  padding: var(--sp-12) var(--sp-80);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-24);
}
.zoe-nav__logo-link { text-decoration: none; display: flex; align-items: center; }
.zoe-nav__logo-link img { max-height: 84px; width: auto; }
.zoe-nav__logo-text { font-weight: var(--fw-black); font-size: var(--type-lead); color: var(--fg); }

.zoe-nav__links { display: flex; align-items: center; gap: var(--sp-32); flex-wrap: wrap; }
.zoe-nav__links a {
  text-decoration: none;
  font-size: var(--type-small);
  font-weight: var(--fw-black);
  color: var(--fg-muted);
  transition: color var(--dur-fast);
}
.zoe-nav__links a:hover { color: var(--accent-deep); }

.zoe-nav__hamburger {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  width: 36px;
  height: 36px;
  background: none;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.zoe-nav__hamburger span { display: block; height: 2px; background: var(--fg); }

/* ── Layout shell ─────────────────────────────────────────────────────── */

.zoe-main { max-width: var(--wrap-max); margin: 0 auto; padding: 0 var(--sp-80); }
@media (max-width: 760px) { .zoe-main { padding: 0 var(--sp-32); } }

/* ── Hero ─────────────────────────────────────────────────────────────── */

.zoe-hero {
  display: grid;
  grid-template-columns: 1.25fr 0.75fr;
  gap: var(--sp-56);
  padding: var(--sp-96) 0;
  border-bottom: 1px solid var(--border);
  align-items: center;
}
.zoe-hero__heading {
  font-size: var(--type-h1);
  line-height: var(--type-h1-lh);
  letter-spacing: var(--track-display);
  max-width: 20ch;
}

/* No hero image on this page — full-width text instead of a blank second
   column. Research/About/Work all currently render this way. */
.zoe-hero--full { grid-template-columns: 1fr; }
.zoe-hero--full .zoe-hero__heading,
.zoe-hero--full .zoe-hero__intro { max-width: none; }

/* ── Page-specific hero/intro background blocks ──────────────────────────
   One shared box treatment (padding, radius, margin — replaces the plain
   .zoe-hero/.zoe-section border-bottom with a self-contained panel), three
   colour variants. Applied to .zoe-hero (Research, About) or
   .zoe-section--intro (Work) as an additional class.
   Research = Blue, About = Green, Work = Coral — Primary colours only
   (August 27, 2026: Lara asked that Additional stay documentation-only,
   never used on an actual page — these were briefly Blush/Deep Teal/Coral).
   All three primaries land in a similar mid-luminance band (none is dark
   enough for comfortable light-text the way Deep Teal briefly was, none
   light enough for the default sitewide colours to just work), so all
   three get the same override below rather than three different
   treatments. */
.zoe-bg-block {
  padding: var(--sp-56);
  border-radius: var(--radius-lg);
  margin: var(--sp-40) 0;
  border-bottom: none;
  /* All three variants read the same height regardless of how much their
     own copy wraps to (Lara: "make them all the same height") — generous
     enough for the longest current content (a 2-line heading + 3-4 line
     intro) with room to spare; .zoe-hero's own align-items:center keeps
     shorter content vertically centred rather than pinned to the top. */
  min-height: 26rem;
}
.zoe-bg-block--coral { background: var(--zoe-coral); }
.zoe-bg-block--blue { background: var(--zoe-blue); }
.zoe-bg-block--green { background: var(--zoe-green); }
/* Magenta — the Design Guidelines page's own hero (August 27, 2026, Lara:
   "add a BG to the hero area like on work/about/research"). Magenta was the
   one Primary colour with no page-level identity yet (Work/About/Research
   already claim Coral/Green/Blue) — giving it one here instead of picking
   a colour that's already spoken for. */
.zoe-bg-block--magenta { background: var(--zoe-magenta); }
/* Neutral (off-white) text on all three — Lara's call, August 27, 2026 —
   in place of the dark text these previously forced. This is a harder
   contrast trade than dark text was: dark cleared 4.5:1+ against all
   three, neutral only reaches ~3.4-3.5:1 (large-text AA, not small-text
   AA) against Blue/Green and ~2.6:1 against Coral. Implemented as asked;
   flagged, not fixed. The heading needed an explicit override here (it
   previously inherited --fg by default, which no longer applies). */
.zoe-bg-block--coral .eyebrow, .zoe-bg-block--coral .zoe-hero__heading,
.zoe-bg-block--blue .eyebrow, .zoe-bg-block--blue .zoe-hero__heading,
.zoe-bg-block--green .eyebrow, .zoe-bg-block--green .zoe-hero__heading,
.zoe-bg-block--magenta .eyebrow, .zoe-bg-block--magenta .zoe-hero__heading {
  color: var(--fg-on-dark);
}
.zoe-bg-block--coral .zoe-hero__intro,
.zoe-bg-block--blue .zoe-hero__intro,
.zoe-bg-block--green .zoe-hero__intro,
.zoe-bg-block--magenta .zoe-hero__intro {
  color: var(--fg-on-dark-muted);
}

/* Design Guidelines header isn't a .zoe-hero (its own eyebrow/h1/lede/
   tagline/meta shape, not the two-column hero grid), so it needs its own
   on-dark overrides rather than inheriting the .zoe-hero__* ones above. */
.dg-header.zoe-bg-block {
  padding: var(--sp-56);
  border-bottom: none;
}
.dg-header.zoe-bg-block .eyebrow,
.dg-header.zoe-bg-block .dg-h1 { color: var(--fg-on-dark); }
.dg-header.zoe-bg-block .dg-lede { color: var(--fg-on-dark-muted); }
.dg-header.zoe-bg-block .dg-meta {
  color: var(--fg-on-dark-subtle);
  border-top-color: var(--border-on-dark);
}
.dg-header.zoe-bg-block .dg-meta a { color: var(--fg-on-dark); }
.zoe-hero__intro {
  color: var(--fg-muted);
  max-width: 60ch;
  margin-top: var(--sp-20);
  font-size: var(--type-lead);
  line-height: var(--type-lead-lh);
  font-weight: var(--fw-regular);
}
.zoe-hero__media img { border-radius: var(--radius-lg); }

/* ── CTAs ─────────────────────────────────────────────────────────────── */

.zoe-ctas { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-16); margin-top: var(--sp-32); }
.zoe-ctas--center { justify-content: center; }

/* ── Stat bar ─────────────────────────────────────────────────────────── */

/* Four circles, one Primary colour each (Coral/Magenta/Green/Blue, in
   that fixed order — matches the Design Guidelines Primary row) — Lara's
   call, was a plain 4-column bordered strip with no colour. Text is
   --fg (dark) throughout: same reasoning as the page-hero blocks, none
   of the four primaries is dark enough for comfortable light text. */
.zoe-statbar { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--sp-24); padding: var(--sp-32) 0; }
.zoe-stat {
  aspect-ratio: 1;
  max-width: 220px;
  margin: 0 auto;
  border-radius: 50%;
  padding: var(--sp-24);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
}
.zoe-stat:nth-child(4n+1) { background: var(--zoe-coral); }
.zoe-stat:nth-child(4n+2) { background: var(--zoe-magenta); }
.zoe-stat:nth-child(4n+3) { background: var(--zoe-green); }
.zoe-stat:nth-child(4n+4) { background: var(--zoe-blue); }
.zoe-stat b { display: block; font-size: var(--type-h3); font-weight: var(--fw-black); color: var(--fg-on-dark); }
.zoe-stat span {
  font-family: var(--font-sans);
  font-size: var(--type-micro);
  /* Bumped to black weight — unset, this was inheriting the body's
     regular/300 weight, which was a big part of why it read as washed
     out even before white-on-colour contrast came into it. */
  font-weight: var(--fw-black);
  color: var(--fg-on-dark);
  letter-spacing: var(--track-tight);
  margin-top: var(--sp-4);
}
@media (max-width: 760px) {
  .zoe-statbar { grid-template-columns: repeat(2, 1fr); }
}

/* ── Sections ─────────────────────────────────────────────────────────── */

.zoe-section { padding: var(--sp-96) 0; border-bottom: 1px solid var(--border); }
.zoe-section--intro { padding-top: var(--sp-120); }
.zoe-section--center { text-align: center; }
/* A dark full-tone panel for one section on its own (not a page-hero
   block) — currently just Research's "The framework". Text needs
   explicit overrides here since --fg/--fg-muted (the sitewide default
   for headings/body) are dark and would be invisible on this background;
   the eyebrow and process-step kicker (--accent-deep, Coral) already
   read fine on dark (~6:1) and need no override. */
.zoe-section--dark {
  background: var(--bg-inverse);
  color: var(--fg-on-dark);
  border-radius: var(--radius-lg);
  border-bottom: none;
  padding: var(--sp-56);
  margin: var(--sp-40) 0;
}
.zoe-section--dark .zoe-section__heading { color: var(--fg-on-dark); }
.zoe-section--dark .zoe-section__intro { color: var(--fg-on-dark-muted); }
.zoe-section__heading {
  font-size: var(--type-h2);
  line-height: var(--type-h2-lh);
  letter-spacing: var(--track-heading);
  margin-bottom: var(--sp-16);
}
/* font-weight pinned explicitly — without it this would silently pick up
   body's new 400 default; lead-sized intro copy stays --fw-regular (300)
   on purpose (Lara, August 27, 2026). */
.zoe-section__intro { color: var(--fg-muted); max-width: 65ch; font-size: var(--type-lead); line-height: var(--type-lead-lh); font-weight: var(--fw-regular); }
.zoe-section--center .zoe-section__intro { margin: 0 auto; }

/* single-portfolio.php — the project itself on the left, a "browse other
   projects" sidebar on the right, grouped by category, image + title
   only (no excerpt — this is navigation, not another zoe-card grid). */
.zoe-portfolio-layout { display: grid; grid-template-columns: 2fr 1fr; gap: var(--sp-56); align-items: start; }
.zoe-portfolio-sidebar h3 {
  font-family: var(--font-sans);
  font-size: var(--type-micro);
  font-weight: var(--fw-black);
  text-transform: uppercase;
  letter-spacing: var(--track-micro);
  color: var(--fg-muted);
  margin: var(--sp-32) 0 var(--sp-16);
}
.zoe-portfolio-sidebar h3:first-child { margin-top: 0; }
.zoe-portfolio-sidebar ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--sp-16); }
.zoe-portfolio-sidebar li a { display: flex; align-items: center; gap: var(--sp-12); text-decoration: none; color: var(--fg); }
.zoe-portfolio-sidebar li img { width: 64px; height: 64px; object-fit: cover; border-radius: var(--radius-sm); flex-shrink: 0; }
.zoe-portfolio-sidebar li span { font-size: var(--type-small); font-weight: var(--fw-black); line-height: var(--type-small-lh); }
.zoe-portfolio-sidebar li a:hover span { color: var(--accent-deep); }
@media (max-width: 760px) {
  .zoe-portfolio-layout { grid-template-columns: 1fr; }
}

/* Two columns — copy left, a decorative illustration right — for a plain
   .zoe-section that wants an image without becoming a full bg-block
   hero. Currently just Home's research teaser (the airship). */
.zoe-section--split { display: grid; grid-template-columns: 1.25fr 0.75fr; gap: var(--sp-56); align-items: center; }
.zoe-section--split .zoe-section__media svg { width: 100%; height: auto; display: block; }
/* A third child (e.g. a card grid) that should span both columns below
   the copy/media row instead of squeezing into one of them. */
.zoe-section--split .zoe-section__full { grid-column: 1 / -1; margin-top: var(--sp-16); }
@media (max-width: 760px) {
  .zoe-section--split { grid-template-columns: 1fr; }
}

/* Research's "Demo" section — a real photo of students using the tool
   plus its own GIFs, side by side, image + no caption (the surrounding
   section copy carries the context). */
.zoe-demo-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--sp-24); margin-top: var(--sp-32); }
.zoe-demo-grid img { width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; border-radius: var(--radius-lg); display: block; }

.zoe-note {
  margin-top: var(--sp-24);
  padding: var(--sp-16) var(--sp-24);
  border-left: 3px solid var(--accent-deep);
  /* Was --bg-accent (Blush) — an "Additional" colour Lara asked to keep
     documentation-only, never on an actual page (August 27, 2026). It had
     landed here anyway; caught in the August 27 colour/type audit and
     swapped for --bg-raised, the same white every other card/callout on
     the site already uses. */
  background: var(--bg-raised);
  font-size: var(--type-small);
  border-radius: var(--radius-sm);
}

/* ── Card grids ───────────────────────────────────────────────────────── */

.zoe-card-grid, .zoe-feature {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--sp-24);
  margin-top: var(--sp-32);
}
.zoe-card {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--sp-32) var(--sp-24);
  background: var(--bg-raised);
  text-decoration: none;
  color: inherit;
  overflow: hidden;
  transition: transform var(--dur-std) var(--ease-standard), box-shadow var(--dur-std) var(--ease-standard);
}
.zoe-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-xs); }
/* Bleeds a card's featured image to the card's own edges (undoing its
   padding), flush with the top border — used by zoe_portfolio_grid()'s
   real post thumbnails on the Work page. */
.zoe-card__image {
  width: calc(100% + var(--sp-24) * 2);
  max-width: none;
  margin: calc(-1 * var(--sp-32)) calc(-1 * var(--sp-24)) var(--sp-16);
  aspect-ratio: 16 / 10;
  object-fit: cover;
}
.zoe-card__tag {
  font-family: var(--font-sans);
  font-size: var(--type-micro);
  text-transform: uppercase;
  letter-spacing: var(--track-tight);
  color: var(--accent-deep);
  font-weight: var(--fw-black);
}
.zoe-card__title { font-size: var(--type-h4); line-height: var(--type-h4-lh); margin: var(--sp-8) 0; }
.zoe-card__description { color: var(--fg-muted); font-size: var(--type-small); line-height: var(--type-small-lh); }
/* A card called out from its siblings — About's one time-sensitive
   facilitation item so far, but usable anywhere zoe_acf_card_subfields()
   is used (its new optional "highlight" sub-field). */
.zoe-card--highlight { border-color: var(--accent-deep); }

/* Publications & awards cards (About page) — a small type icon (set by the
   card's Type field, publication or award), and an optional outside link.
   Rendered via <img src="....svg">, not inline, so it can't pick up
   currentColor from this stylesheet (a separate document context) — same
   plain-black treatment the Icon Library page already uses for the same
   files, kept deliberately muted here with opacity instead of a colour
   swap. */
.zoe-card__type-icon { opacity: 0.35; margin-bottom: var(--sp-8); }
.zoe-card__link {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-4);
  margin-top: var(--sp-16);
  font-size: var(--type-small);
  font-weight: var(--fw-black);
  color: var(--accent-deep);
  text-decoration: none;
}
.zoe-card__link:hover { text-decoration: underline; }

/* ── About: timeline (Background section) ────────────────────────────────
   A centred intro, then every background_blocks row except the last as
   an alternating photo/text pair, then the last row as a dark closing
   panel (reuses .zoe-section--dark's token overrides). Rows without a
   photo (none are uploaded yet) fall back to full-width text via :has(). */
.zoe-timeline-intro { text-align: center; max-width: 640px; margin: 0 auto var(--sp-56); }
.zoe-timeline { display: flex; flex-direction: column; }
.zoe-timeline__row {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: var(--sp-56);
  align-items: center;
  padding: var(--sp-48) 0;
  border-bottom: 1px solid var(--border);
}
.zoe-timeline__row:last-child { border-bottom: none; }
.zoe-timeline__row--reverse .zoe-timeline__copy { order: 2; }
.zoe-timeline__row--reverse .zoe-timeline__media { order: 1; }
.zoe-timeline__row:not(:has(.zoe-timeline__media)) .zoe-timeline__copy { grid-column: 1 / -1; max-width: 65ch; }
.zoe-timeline__title { font-size: var(--type-h4); margin: var(--sp-8) 0 var(--sp-12); }
.zoe-timeline__media img { width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; border-radius: var(--radius-lg); display: block; }
@media (max-width: 760px) {
  .zoe-timeline__row { grid-template-columns: 1fr; }
  .zoe-timeline__row--reverse .zoe-timeline__copy,
  .zoe-timeline__row--reverse .zoe-timeline__media { order: initial; }
}

.zoe-timeline__final { margin-top: var(--sp-40); text-align: center; }
/* The dark closing panel is always the last thing in its .zoe-section, but
   that outer section still carried its own 96px bottom padding + hairline
   border AFTER the panel's own 40px margin — on top of the NEXT section's
   96px top padding, the gap below the panel was ~230px vs ~40px above it
   (Lara, August 27, 2026: "the spacing top and bottom ... is different").
   Zeroing the outer section's own bottom edge here makes the panel's
   margin the only thing between it and its neighbours on both sides,
   matching the top, which was never touching that padding to begin with. */
.zoe-section:has(> .zoe-timeline__final:last-child) {
  padding-bottom: 0;
  border-bottom: none;
}
.zoe-timeline__final .zoe-section__heading { max-width: none; }
.zoe-timeline__final-body { max-width: 65ch; margin: 0 auto; color: var(--fg-on-dark-muted); }
.zoe-tag-list { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--sp-12); margin-top: var(--sp-32); }
.zoe-tag { border: 1px solid var(--border-on-dark); border-radius: var(--radius-pill); padding: var(--sp-8) var(--sp-20); font-size: var(--type-small); color: var(--fg-on-dark); }

/* ── About: Facilitation & community — a fixed intro/photo column beside
   a plain stacked list of text (no boxes — Lara's call; was the same
   .zoe-card treatment as everywhere else). Divider between items instead
   of a border; the one time-dated item gets a left accent rule instead
   of the coloured box-border .zoe-card--highlight used elsewhere. */
.zoe-facilitation-split { display: grid; grid-template-columns: 0.8fr 1.2fr; gap: var(--sp-56); margin-top: var(--sp-32); align-items: start; }
.zoe-facilitation-split__photo { width: 100%; margin-top: var(--sp-24); aspect-ratio: 3 / 4; object-fit: cover; border-radius: var(--radius-lg); display: block; }
.zoe-facilitation-split__list { display: flex; flex-direction: column; }
.zoe-facilitation-split__item { padding: var(--sp-24) 0; border-bottom: 1px solid var(--border); }
.zoe-facilitation-split__list .zoe-facilitation-split__item:last-child { border-bottom: none; }
.zoe-facilitation-split__item--highlight { border-left: 3px solid var(--accent-deep); padding-left: var(--sp-16); }
@media (max-width: 760px) { .zoe-facilitation-split { grid-template-columns: 1fr; } }

/* ── About: closing CTA bar — one bordered strip, text left, buttons
   right, instead of the sitewide centred/stacked section treatment ──── */
.zoe-cta-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--sp-24);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--sp-32) var(--sp-40);
}
.zoe-cta-bar__heading { font-size: var(--type-h3); margin-bottom: var(--sp-8); }
.zoe-cta-bar__text { color: var(--fg-muted); max-width: 50ch; }
.zoe-cta-bar .zoe-ctas { margin-top: 0; }

/* Two labelled numbered lists side by side — Research's "Piloting the
   tool" section (what the trials showed / where else the framework
   applies). */
.zoe-piloting-cols { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-56); margin-top: var(--sp-32); }
.zoe-piloting-cols h3 { font-size: var(--type-h4); margin-bottom: var(--sp-16); }
.zoe-piloting-cols ol { list-style: decimal; padding-left: 1.25em; }
.zoe-piloting-cols li { margin-bottom: var(--sp-12); color: var(--fg-muted); font-size: var(--type-small); line-height: var(--type-small-lh); }
@media (max-width: 760px) {
  .zoe-piloting-cols { grid-template-columns: 1fr; gap: var(--sp-32); }
}

/* ── Process / step grids ─────────────────────────────────────────────── */

.zoe-process {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 1px;
  background: var(--border);
  margin-top: var(--sp-32);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.zoe-process__step { background: var(--bg-raised); padding: var(--sp-32) var(--sp-24); }
.zoe-process__step b {
  font-family: var(--font-sans);
  font-size: var(--type-micro);
  letter-spacing: var(--track-tight);
  color: var(--accent-deep);
  font-weight: var(--fw-black);
}
.zoe-process__step h4 { font-size: var(--type-h3); margin: var(--sp-8) 0; }
.zoe-process__step p { color: var(--fg-muted); font-size: var(--type-small); line-height: var(--type-small-lh); }
.zoe-section--dark .zoe-process__step h4 { color: var(--fg-on-dark); }
.zoe-section--dark .zoe-process__step p { color: var(--fg-on-dark-muted); }

/* Plain (no white step backgrounds, no divider grid, no border) —
   Home's process section, and now Research's framework_steps once its
   section went dark: white cards on a dark section would read as a
   separate block rather than one panel. */
.zoe-process--plain {
  background: none;
  border: none;
  border-radius: 0;
  gap: var(--sp-32);
}
.zoe-process--plain .zoe-process__step { background: none; padding: 0; }
/* Fixed 4 columns instead of auto-fit — Research's framework_steps, one
   row of Build/Scan/Discuss/Fly rather than whatever auto-fit wraps to
   at a given width. Was 2 columns (.zoe-process--cols2) briefly. */
.zoe-process--cols4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 900px) {
  .zoe-process--cols4 { grid-template-columns: repeat(2, 1fr); row-gap: var(--sp-32); }
}
@media (max-width: 500px) {
  .zoe-process--cols4 { grid-template-columns: 1fr; }
}

/* ── Closing CTA ──────────────────────────────────────────────────────────
   One dark banner, every page, right above the footer bar — structurally
   copied from larakroekerinteractive.com's own closing "Let's talk"
   section (same idea: a full-bleed dark strip, an eyebrow, one big
   statement, one button), repainted in Zoe's own tokens rather than
   LKI's navy/pink. --type-display was otherwise unused outside the
   guidelines page's own specimen row; this is its first real job. The
   button is its own colour treatment (amber fill, not the usual dark
   pill) since the surrounding section is already dark — .btn-pill's
   default dark-on-dark would have no separation here. */
.zoe-closing-cta {
  background: var(--bg-inverse);
  padding: var(--sp-96) var(--sp-80);
  text-align: center;
}
@media (max-width: 760px) {
  .zoe-closing-cta { padding: var(--sp-64) var(--sp-32); }
}
.zoe-closing-cta__inner { max-width: 760px; margin: 0 auto; }
.zoe-closing-cta .eyebrow { margin-bottom: var(--sp-24); }
.zoe-closing-cta__heading {
  font-family: var(--font-sans);
  font-weight: var(--fw-black);
  /* --type-h2 — Lara's call, after --type-display, --type-h1, and
     --type-h4 were each tried in turn. */
  font-size: var(--type-h2);
  line-height: var(--type-h2-lh);
  letter-spacing: var(--track-heading);
  color: var(--fg-on-dark);
}

.btn-pill--cta { background: var(--cta); color: var(--fg); }
.btn-pill--cta .arr { background: var(--bg-inverse); color: var(--fg-on-dark); }
.btn-pill--cta:hover { background: var(--cta-hover); color: var(--fg); }
.btn-pill--cta:hover .arr { transform: rotate(45deg); }

/* ── Footer ───────────────────────────────────────────────────────────── */

.zoe-footer { padding: var(--sp-48) 0; border-top: 1px solid var(--border); }
.zoe-footer__inner {
  max-width: var(--wrap-max);
  margin: 0 auto;
  padding: 0 var(--sp-80);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-24);
}
/* Sized to match .zoe-nav__links a (--type-small) — Lara's call; this is
   the footer's own nav (Email/LinkedIn/Instagram/...), so it reads as
   one size with the header nav rather than matching card titles. */
.zoe-footer__link { font-size: var(--type-small); font-weight: var(--fw-black); text-decoration: none; color: var(--fg-muted); }
.zoe-footer__link:hover { color: var(--accent-deep); }
.zoe-footer__copy { margin-left: auto; font-family: var(--font-sans); font-size: var(--type-small); color: var(--fg-muted); }

@media (max-width: 760px) {
  .zoe-footer__inner { padding: 0 var(--sp-32); }
  .zoe-footer__copy { margin-left: 0; }
}

/* ── Mobile nav ───────────────────────────────────────────────────────── */

@media (max-width: 760px) {
  /* Stacked to one column already; three more changes here, all Lara,
     August 27, 2026, from the same round of mobile feedback:
     - illustration first, above the text (order: -1 — grid order, not DOM
       order, so source/reading order for screen readers is unaffected)
     - the illustration capped and centred instead of running the full
       column width, which made it dominate the screen next to the text
     - the row gap (was --sp-56, meant for the desktop side-by-side gap)
       cut down, since stacked it was reading as dead space between the
       image and the copy ("less space between the writing") */
  .zoe-hero { grid-template-columns: 1fr; padding: var(--sp-56) 0; gap: var(--sp-24); }
  .zoe-hero__media { order: -1; max-width: 70%; margin: 0 auto; }
  .zoe-hero__intro { margin-top: var(--sp-16); }
  .zoe-nav__inner { padding: var(--sp-16) var(--sp-32); }
  .zoe-nav__hamburger { display: flex; }
  .zoe-nav__links {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--bg-raised);
    border-bottom: 1px solid var(--border);
    flex-direction: column;
    align-items: flex-start;
    padding: var(--sp-16) var(--sp-32);
    gap: var(--sp-16);
  }
  .zoe-nav__links.is-open { display: flex; }
}

/* ── Design Guidelines page ───────────────────────────────────────────── */

.dg-header { padding: var(--sp-80) 0 var(--sp-48); border-bottom: 1px solid var(--border); }
.dg-h1 { font-size: var(--type-h1); line-height: var(--type-h1-lh); max-width: 16ch; margin: var(--sp-16) 0; }
.dg-lede { color: var(--fg-muted); max-width: 60ch; font-size: var(--type-lead); line-height: var(--type-lead-lh); font-weight: var(--fw-regular); }
.dg-meta {
  display: flex; flex-wrap: wrap; gap: var(--sp-16);
  margin-top: var(--sp-32); padding-top: var(--sp-24); border-top: 1px solid var(--border);
  font-family: var(--font-sans); font-size: var(--type-micro); color: var(--fg-muted);
}
.dg-meta a { color: var(--accent-deep); }

/* Plain-text summary for AI tools that only read visible text (the full
   machine-readable export sits right after it in a JSON <script> block —
   see page-design-guidelines.php). Styled as a utility note, not page
   copy, so it doesn't read as part of the human-facing narrative. */
.dg-ai-summary {
  margin-top: var(--sp-24);
  padding: var(--sp-16) var(--sp-24);
  background: var(--fill-subtle);
  border-radius: var(--radius-sm);
  font-size: var(--type-small);
  line-height: var(--type-small-lh);
  color: var(--fg-muted);
  max-width: 70ch;
}

.dg-section { padding: var(--sp-80) 0; border-bottom: 1px solid var(--border); }

.dg-pvm { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: var(--sp-32); margin-top: var(--sp-24); }
/* Was a 3px solid Blue accent bar — changed to a hairline (August 27, 2026,
   Lara: "make the lines hairline borders"), matching --border's actual
   documented purpose ("hairline borders", per the Colour section's own
   Grey 5 swatch) instead of a bold accent colour. */
.dg-pvm__item { border-left: 1px solid var(--border); padding-left: var(--sp-16); }
.dg-pvm__item h3 { font-size: var(--type-h4); margin-bottom: var(--sp-8); }
.dg-pvm__item p { color: var(--fg-muted); font-size: var(--type-small); line-height: var(--type-small-lh); }

.dg-tags { display: flex; flex-wrap: wrap; gap: var(--sp-8); margin-top: var(--sp-16); }
.dg-tag {
  border: 1px solid var(--border); border-radius: var(--radius-pill);
  padding: var(--sp-8) var(--sp-16); font-size: var(--type-small); color: var(--fg-muted);
}

.dg-logo-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: var(--sp-24); margin-top: var(--sp-24); }
.dg-logo-card {
  border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--bg-raised);
  padding: var(--sp-56); display: flex; flex-direction: column; align-items: center; gap: var(--sp-24);
}
/* The "dark" logo file is a near-white wordmark, meant FOR dark backgrounds
   -- shown on this site's own dark surface so it's actually visible, not
   invisible-white-on-white the way it would be on the default card. */
.dg-logo-card--dark { background: var(--bg-inverse); border-color: var(--border-on-dark); }

.dg-photo-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--sp-16); margin-top: var(--sp-24); }
.dg-photo-grid img { border-radius: var(--radius-md); aspect-ratio: 4/3; object-fit: cover; }

.dg-icon-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(90px, 1fr)); gap: var(--sp-24);
  margin-top: var(--sp-24); padding: var(--sp-32); border: 1px solid var(--border); border-radius: var(--radius-md);
}
.dg-icon-cell { display: flex; flex-direction: column; align-items: center; gap: var(--sp-8); text-align: center; }
.dg-icon-cell span { font-family: var(--font-sans); font-size: var(--type-micro); color: var(--fg-muted); word-break: break-word; }

.dg-swatch-group { margin-top: var(--sp-48); }
.dg-swatch-group h3 { font-size: var(--type-h4); margin-bottom: var(--sp-16); }
.dg-swatch-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: var(--sp-16); }
.dg-swatch-row--5 { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }

/* One swatch = one card: colour box on top, info block below, as a single
   grid cell. (The color box and its meta used to be separate siblings
   inside .dg-swatch-row, which split one swatch into two grid items —
   fixed by wrapping both in .dg-swatch-item.) */
.dg-swatch-item {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--bg-raised);
  display: flex;
  flex-direction: column;
}
.dg-swatch { height: 110px; }
.dg-swatch__meta {
  padding: var(--sp-16);
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.dg-swatch__meta b { font-size: var(--type-body); font-weight: var(--fw-black); }
.dg-swatch__meta code { font-family: var(--font-sans); font-size: var(--type-small); color: var(--fg-muted); }
.dg-swatch__token {
  font-family: var(--font-sans); font-size: var(--type-micro); color: var(--fg-subtle);
  margin-bottom: var(--sp-8);
}
.dg-swatch__note {
  margin-top: var(--sp-8); padding-top: var(--sp-8); border-top: 1px solid var(--border);
  font-size: var(--type-micro); font-weight: var(--fw-black); text-transform: uppercase;
  letter-spacing: var(--track-tight); color: var(--fg);
}

.dg-type-families { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: var(--sp-32); padding-bottom: var(--sp-32); border-bottom: 1px solid var(--border); }
.dg-type-label { font-family: var(--font-sans); font-size: var(--type-micro); text-transform: uppercase; letter-spacing: var(--track-tight); color: var(--fg-muted); }
.dg-type-glyph { font-size: 64px; margin: var(--sp-8) 0; }
.dg-type-sub { font-family: var(--font-sans); font-size: var(--type-micro); color: var(--fg-muted); }

.dg-type-scale { margin-top: var(--sp-32); }
.dg-type-row {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-24);
  padding: var(--sp-24) 0; border-bottom: 1px solid var(--border);
}
.dg-type-meta { font-family: var(--font-sans); font-size: var(--type-micro); color: var(--fg-muted); white-space: nowrap; }

.dg-sub { font-size: var(--type-h3); margin: var(--sp-48) 0 var(--sp-16); }

.dg-spacing-row { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--sp-24); }
.dg-sp-item { display: flex; flex-direction: column; align-items: center; gap: var(--sp-8); }
.dg-sp-bar { background: var(--bg-inverse); border-radius: var(--radius-sm); }
.dg-sp-item b { font-size: var(--type-small); }
.dg-sp-item span { font-size: var(--type-micro); color: var(--fg-muted); text-align: center; max-width: 90px; }

.dg-radius-row { display: flex; flex-wrap: wrap; gap: var(--sp-32); }
.dg-radius-item { display: flex; flex-direction: column; align-items: center; gap: var(--sp-8); }
.dg-radius-box { width: 64px; height: 64px; background: var(--fill); }
.dg-radius-item b { font-size: var(--type-small); }
.dg-radius-item span { font-size: var(--type-micro); color: var(--fg-muted); }

.dg-btn-demo__panel { padding: var(--sp-32); border: 1px solid var(--border); border-radius: var(--radius-md); margin-top: var(--sp-16); }
