/*
Theme Name: wit[h]nessing
Theme URI: https://withnessing.org
Author: wit[h]nessing
Description: The wit[h]nessing platform design — an artistic research platform working across art, design, architecture, photography, participatory design, speculative storytelling, curation, archival research and publishing. Ported from the Astro build; every colour, type size and spacing step is a custom property defined once in the DESIGN TOKENS section below.
Version: 1.0.0
Requires at least: 6.0
Tested up to: 6.7
Requires PHP: 7.4
License: All rights reserved
Text Domain: withnessing
*/

/* ═══════════════════════════════════════════════════════════════════════════
   HOW THIS FILE IS ORGANISED

   1. DESIGN TOKENS + BASE     — every colour, size and space, defined once.
                                 This is the part you edit to change the look.
   2. WORDPRESS ADJUSTMENTS    — the small set of rules that exist only because
                                 this runs inside WordPress (admin bar, editor).
   3. COMPONENTS               — header, footer, cards, filters. Shared by
                                 every page.
   4. PAGE TEMPLATES           — each one isolated behind a body class, so the
                                 project page's `.metastrip` and the activation
                                 page's `.metastrip` cannot overwrite one
                                 another.

   Edit this file directly. Almost every change you will want to make is a
   number or a colour in section 1 — you should not need to touch sections 3 or
   4 to change how the site looks, only to change how it is arranged.

   Section 4 is isolated by a class on <body>: the project page's `.metastrip`
   and the activation page's `.metastrip` are different rules and cannot
   overwrite one another. Keep new rules inside the section they belong to.
   ═══════════════════════════════════════════════════════════════════════════ */


/* ═══ 1. DESIGN TOKENS + BASE ═══ */

/* ═══════════════════════════════════════════════════════════════════════════
   wit[h]nessing — design tokens and base styles

   EVERY colour, font size, spacing step and timing value on the site is
   defined once, here, at the top of this file. Nothing is hardcoded in a
   component. If you want to change how the site looks, change a number here
   and it changes everywhere.

   The names are meant to be readable. `--color-text` is the colour of text.
   `--space-4` is a medium gap. You should not need to know CSS to change a
   colour.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  /* ─────────────────────────────────────────────────────────────────────────
     TYPEFACES

     Two families, both supplied by the client and served from this site's own
     domain — nothing is fetched from Google, Adobe or any other company.

     Minion  — the reading face. A classical oldstyle serif, used for every
               argument, essay and description on the site.
     Source Code — the interface face. A monospace, used small and tracked for
               dates, formats, labels, filters and captions. Setting the whole
               interface layer in monospace is what gives the site its voice,
               and it suits a name with a bracket in it.

     ⚠ LICENSING — READ BEFORE THE SITE GOES LIVE.
     Source Code is under the SIL Open Font License: free to embed and serve.
     Minion is NOT. The file says "© 1990–2018 Adobe. All rights reserved."
     and carries no licence permitting web use. An Adobe/Creative Cloud licence
     normally covers desktop use only; serving the font from a website is a
     separate licence, bought through Adobe Fonts.

     So before launch, either confirm a web licence for Minion, or change the
     ONE line below to an open face. Crimson Pro is the closest open substitute;
     Source Serif 4 is by Minion's own designer. Nothing else needs to change.
     ───────────────────────────────────────────────────────────────────────── */

  /* Long-form reading: project bodies, essays, activation texts. */
  --font-text: 'Minion Variable', 'Crimson Pro', Georgia, 'Times New Roman', serif;

  /* Interface and metadata: navigation, dates, labels, filters, captions. */
  --font-ui: 'Source Code Variable', ui-monospace, 'SF Mono', Menlo, monospace;

  /* ─────────────────────────────────────────────────────────────────────────
     COLOUR

     The platform's five colours, exactly as supplied:

       --brand-blue   #2266ff   --brand-amber  #ec9907
       --brand-paper  #f0f5eb   --brand-sky    #b3c7ea
       --brand-brown  #4c3815

     Everything below is built from those five. The role tokens
     (--color-text, --color-accent …) are what components actually use, so a
     colour can be re-pointed in one line without hunting through the site.

     Every text colour here has been measured against its background and meets
     WCAG AA. Two things to know before changing any of them:

     · The brand blue on paper measures 4.30:1 — just under the 4.5 minimum for
       normal-size text. Links therefore use --color-accent, which is the same
       blue darkened by four percent to 4.59:1. The difference is invisible;
       the compliance is not. The untouched brand blue is still used wherever
       it is a fill or large type, where it passes.

     · Amber on paper measures 2.08:1 and sky measures 1.55:1. Neither may ever
       be used for text on the light background. They are fills, rules and
       markers. Amber as a *fill* with brown text on it measures 4.84:1 and is
       fine.
     ───────────────────────────────────────────────────────────────────────── */

  /* One appearance only — see the note where the dark palette used to be. */
  color-scheme: light;

  /* The five brand colours. Do not change these — they are the identity. */
  --brand-blue: #2266ff;
  --brand-paper: #f0f5eb;
  --brand-brown: #4c3815;
  --brand-amber: #ec9907;
  --brand-sky: #b3c7ea;

  /* Roles — light */
  --color-bg: var(--brand-paper);
  --color-bg-sunken: #dbe5eb;      /* sky, mixed most of the way to paper */
  --color-text: var(--brand-brown);        /* 10.07:1  AAA */
  --color-text-muted: #75674a;             /*  5.00:1  AA  */
  --color-accent: #2162f5;                 /*  4.59:1  AA  — links */
  --color-accent-hover: #1a4fc4;
  --color-accent-fill: var(--brand-blue);  /* fills and large type only */
  --color-on-accent: #ffffff;              /*  4.76:1  AA on the blue fill */
  --color-highlight: var(--brand-amber);   /* fills and markers only */
  --color-on-highlight: var(--brand-brown);/*  4.84:1  AA on the amber fill */
  --color-rule: #dbe5eb;                   /* hairlines. Decorative. */
  --color-rule-strong: var(--brand-sky);   /* rules meant to be seen. */
  --color-focus: #2162f5;

  /* ── COLOUR FIELDS ──────────────────────────────────────────────────────
     A field is a band of solid colour that runs the full width of the page
     and holds type directly on it — the header, and the block a page title
     sits in. The header band and the page-title field are the same blue, so
     they read as one mass at the top of the page before the content drops
     onto paper.

     Only white may sit on the blue field (4.76:1). Paper is 4.30:1 — large
     type only — and amber (2.07:1) and sky (2.78:1) both fail on it, so no
     marker or underline may use them there.
     ────────────────────────────────────────────────────────────────────── */

  --field-bg: var(--brand-blue);
  --field-text: #ffffff;                   /* 4.76:1  AA on the blue field */
  --field-muted: #ffffff;                  /* no dimmed text on a field — it
                                              would drop below AA. Use opacity
                                              on a rule instead, never on type. */

  /* ─────────────────────────────────────────────────────────────────────────
     TYPE SCALE

     Seven steps. They grow and shrink with the width of the window, so a
     heading is large on a laptop and sensible on a phone without any extra
     rules. --fs-3 is normal body text.
     ───────────────────────────────────────────────────────────────────────── */

  --fs-1: 0.75rem;                              /* 12px — smallest labels */
  --fs-2: 0.875rem;                             /* 14px — metadata, captions */
  --fs-3: clamp(1.0625rem, 0.99rem + 0.3vw, 1.1875rem);  /* 17–19px — body text */
  --fs-4: clamp(1.25rem, 1.14rem + 0.5vw, 1.5rem);       /* 20–24px — lead paragraphs */
  --fs-5: clamp(1.5rem, 1.28rem + 1.1vw, 2.125rem);      /* 24–34px — section headings */
  --fs-6: clamp(2.25rem, 1.6rem + 3.2vw, 4rem);          /* 36–64px — page titles */
  --fs-7: clamp(2.75rem, 1.6rem + 6vw, 6.5rem);          /* 44–104px — display */

  --lh-display: 1;    /* Display type. Set solid — the references do. */
  --lh-tight: 1.1;    /* Large headings. */
  --lh-snug: 1.3;     /* Small headings, card titles. */
  --lh-normal: 1.65;  /* Body text. Generous — this is a reading site. */

  --tracking-wide: 0.08em;  /* For the small uppercase interface labels. */

  /* ─────────────────────────────────────────────────────────────────────────
     SPACING — a consistent set of gaps. Larger number, larger gap.
     ───────────────────────────────────────────────────────────────────────── */

  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: 4.5rem;
  --space-9: 7rem;    /* Between major sections of a page. */

  /* ─────────────────────────────────────────────────────────────────────────
     LAYOUT
     ───────────────────────────────────────────────────────────────────────── */

  --layout-max: 1440px;         /* The widest the page ever gets. */
  --layout-gutter: clamp(1.25rem, 4vw, 3.5rem);  /* Space at the left and right edges. */
  --grid-columns: 12;
  --grid-gap: clamp(1rem, 2vw, 2rem);

  /* How wide a column of text may get. Long lines are tiring to read; these
     keep a paragraph at a comfortable 65–75 characters. Set separately from
     the page width on purpose.

     Note: `ch` is the width of the digit "0", which in most serif faces is
     wider than the average letter — so these numbers are lower than the
     character counts they produce. 60ch measures out at roughly 70 characters
     in the current text face. If you change --font-text, re-check a paragraph
     and adjust. */
  --measure: 60ch;
  --measure-narrow: 46ch;

  /* ─────────────────────────────────────────────────────────────────────────
     MOTION — small and quick, or nothing at all.
     No scroll effects, no page transitions, no parallax.
     ───────────────────────────────────────────────────────────────────────── */

  --motion-fast: 150ms;
  --motion-base: 200ms;
  --motion-slow: 250ms;
  --ease: cubic-bezier(0.2, 0, 0.2, 1);
}

/* ─────────────────────────────────────────────────────────────────────────────
   COLOUR — dark

   The page turns to the brand brown and the text to the brand paper. Only the
   role tokens are redefined; everything else above still applies.

   Note the two swaps. The blue is lightened, because the brand blue on brown
   measures 2.34:1 and is unreadable. Amber, which may never be text in light
   mode, measures 4.84:1 on brown and so is allowed to be text here.
   ───────────────────────────────────────────────────────────────────────────── */

/* No dark palette. The page is paper at every hour and on every machine: the
   site used to redefine the role tokens under prefers-color-scheme: dark, which
   turned the ground brown for anyone whose system was set that way, and the
   client wants one background. `color-scheme: light` above stops the browser
   darkening scrollbars and form controls to compensate. */

/* ═══════════════════════════════════════════════════════════════════════════
   BASE STYLES
   ═══════════════════════════════════════════════════════════════════════════ */

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

html {
  -webkit-text-size-adjust: 100%;
  /* Anchored sections on /about should not land under the sticky header. */
  scroll-padding-top: var(--space-8);
}

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-text);
  font-size: var(--fs-3);
  line-height: var(--lh-normal);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* Keep the footer at the bottom of short pages. */
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}

/* Every heading is set in the interface face, not the reading face. The serif
   carries the argument; the monospace carries everything the site says in its
   own voice — headings included. */
h1,
h2,
h3,
h4 {
  font-family: var(--font-ui);
  font-weight: 500;
  line-height: var(--lh-snug);
  text-wrap: balance;
  margin: 0 0 var(--space-4);

  /* Capitals, applied in CSS rather than typed into the content. Two reasons:
     the Markdown keeps its real casing, so a title can be changed back without
     re-typing it; and a screen reader still receives ordinary words, where
     text typed in capitals is often read out letter by letter. */
  text-transform: uppercase;

  /* Capitals in a monospace need air, not tightening — every glyph already
     occupies the same width, so the usual display-type negative tracking makes
     capitals look cramped. `ch` is exactly one character in this face, so a
     max-width set in ch on a heading means literally that many characters. */
  letter-spacing: 0.01em;
}

h1 {
  font-size: var(--fs-6);
  line-height: var(--lh-tight);
}
h2 {
  font-size: var(--fs-5);
}
h3 {
  font-size: var(--fs-4);
}

p,
ul,
ol {
  margin: 0 0 var(--space-5);
}

a {
  color: var(--color-accent);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
  transition: color var(--motion-fast) var(--ease);
}

a:hover {
  color: var(--color-accent-hover);
}

img,
picture,
video {
  max-width: 100%;
  height: auto;
  display: block;
}

hr {
  border: 0;
  border-top: 1px solid var(--color-rule);
  margin: var(--space-7) 0;
}

/* ─── Keyboard focus ──────────────────────────────────────────────────────────
   The whole site must be usable with a keyboard alone, which means it must
   always be visible which thing the keyboard is currently on. Do not remove.
   ─────────────────────────────────────────────────────────────────────────── */

:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 3px;
  border-radius: 1px;
}

/* ─── Reusable pieces ─────────────────────────────────────────────────────── */

/* Text that only a screen reader should encounter. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* The page's horizontal container. */
.wrap {
  width: 100%;
  max-width: var(--layout-max);
  margin-inline: auto;
  padding-inline: var(--layout-gutter);
}

/* A column of readable text. Narrower than the page, on purpose. */
.measure {
  max-width: var(--measure);
}

/* Small, wide-tracked, uppercase — the interface voice.
   Dates, formats, status pills, filter chips, captions. */
.label {
  font-family: var(--font-ui);
  font-size: var(--fs-1);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-text-muted);
  line-height: 1.4;
}

/* A full-width band of solid colour with type sitting directly on it.
   Bleeds to both edges of the window regardless of where it sits in the
   layout, so it does not need to be lifted out of its container. */
.field {
  background: var(--field-bg);
  color: var(--field-text);
}

.field a {
  color: var(--field-text);
}

/* The site's one structural motif: a fine horizontal rule.
   Used under the header, above the footer, and between list rows. */
.rule {
  border: 0;
  border-top: 1px solid var(--color-rule);
  margin: 0;
}

/* The first thing a keyboard user reaches. Invisible until focused. */
.skip-link {
  position: absolute;
  left: var(--space-4);
  top: var(--space-4);
  z-index: 100;
  padding: var(--space-3) var(--space-4);
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-ui);
  font-size: var(--fs-2);
  border: 1px solid var(--color-rule-strong);
  text-decoration: none;
  transform: translateY(-200%);
}

.skip-link:focus-visible {
  transform: translateY(0);
}

/* ─── Reduced motion ──────────────────────────────────────────────────────────
   Some people get motion sickness or migraines from movement on screen. If
   they have asked their device for less of it, we give them none.
   ─────────────────────────────────────────────────────────────────────────── */

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

/* ═══════════════════════════════════════════════════════════════════════════
   THE FONT FILES

   Both are variable fonts, so one file covers every weight. They are served
   from /fonts/ on this site's own domain. `font-display: swap` means the text
   is readable in a fallback face immediately and re-renders when the real one
   arrives — nobody ever stares at a blank page waiting for a font.
   ═══════════════════════════════════════════════════════════════════════════ */

@font-face {
  font-family: 'Minion Variable';
  src: url('assets/fonts/minion-variable-roman.woff2') format('woff2-variations');
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Minion Variable';
  src: url('assets/fonts/minion-variable-italic.woff2') format('woff2-variations');
  font-weight: 400 700;
  font-style: italic;
  font-display: swap;
}

@font-face {
  font-family: 'Source Code Variable';
  src: url('assets/fonts/source-code-variable-roman.woff2') format('woff2-variations');
  font-weight: 200 900;
  font-style: normal;
  font-display: swap;
}

/* Minion carries an optical-size axis: it thickens slightly at small sizes and
   refines at large ones. Browsers do this automatically, but say so explicitly. */
body {
  font-optical-sizing: auto;
}


/* ═══════════════════════════════════════════════════════════════════════════
   2. WORDPRESS ADJUSTMENTS

   Rules that exist only because the design now runs inside WordPress. Nothing
   here is part of the original design; it is the glue that stops WordPress's
   own furniture from disturbing it.
   ═══════════════════════════════════════════════════════════════════════════ */

/* The admin bar is a fixed 32px band that WordPress adds for logged-in users,
   pushing the whole document down. The site's own layout assumes it starts at
   the top of the window, so the offset is absorbed here rather than left to
   disturb the header band. */
body.admin-bar {
  min-height: calc(100dvh - 32px);
}

@media screen and (max-width: 782px) {
  body.admin-bar {
    min-height: calc(100dvh - 46px);
  }
}

/* WordPress wraps aligned and sized images in its own classes. Map them onto
   the site's measure so an image dropped into the editor still sits inside the
   text column rather than breaking out of it. */
.prose .alignwide,
.prose .alignfull {
  max-width: 100%;
}

.prose .aligncenter {
  margin-inline: auto;
}

.prose figure {
  margin: var(--space-6) 0;
}

.prose figcaption {
  font-family: var(--font-ui);
  font-size: var(--fs-1);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-text-muted);
  line-height: 1.4;
  margin-top: var(--space-3);
}

/* The editor emits <b>/<i> alongside <strong>/<em>; keep them identical. */
.prose b {
  font-weight: 600;
}

.prose i {
  font-style: italic;
}

/* The run of credit lines that closes some activation pages. Prose otherwise
   keeps one flat rhythm, so without this the first credit reads as another
   paragraph of the essay rather than the start of a different kind of list.
   Add it in the editor with Advanced → Additional CSS class: credits. */
.prose .credits {
  margin-top: var(--space-7);
}

/* WordPress block quotes, mapped to the site's voice. */
.prose blockquote {
  margin: var(--space-6) 0;
  padding-left: var(--space-5);
  border-left: 2px solid var(--color-rule-strong);
  color: var(--color-text-muted);
}

/* ── Search ───────────────────────────────────────────────────────────────
   The Astro site used Pagefind, a static index with its own markup and its
   own stylesheet. WordPress searches the database instead, so the results are
   ordinary markup and are dressed here, in the same voice as an index row.
   ─────────────────────────────────────────────────────────────────────── */

.searchform {
  display: flex;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin-bottom: var(--space-7);
  max-width: var(--measure);
}

.searchform__input {
  flex: 1 1 14rem;
  font-family: var(--font-ui);
  font-size: var(--fs-2);
  color: var(--color-text);
  background: var(--color-bg);
  border: 1px solid var(--color-rule-strong);
  border-radius: 0;
  padding: var(--space-3) var(--space-4);
}

.searchform__submit {
  font-family: var(--font-ui);
  font-size: var(--fs-1);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  cursor: pointer;
  color: var(--color-on-accent);
  background: var(--color-accent-fill);
  border: 0;
  padding: var(--space-3) var(--space-5);
}

.searchform__submit:hover {
  background: var(--color-accent-hover);
}

.results {
  list-style: none;
  margin: 0;
  padding: 0;
}

.results__item {
  padding-bottom: var(--space-6);
}

.results__item .rule {
  margin-bottom: var(--space-5);
}

.results__title {
  font-size: var(--fs-4);
  margin: 0 0 var(--space-3);
}

.results__title a {
  text-decoration: none;
}

.results__title a:hover {
  text-decoration: underline;
}

.results__summary {
  max-width: var(--measure);
  margin: 0;
}

.results__empty {
  color: var(--color-text-muted);
}

/* WordPress's own pagination markup, in the interface face. */
.pagination .nav-links {
  display: flex;
  gap: var(--space-4);
  flex-wrap: wrap;
  font-family: var(--font-ui);
  font-size: var(--fs-2);
}



/* ═══ 3. COMPONENTS ═══ */

/* ── BYLINE — the "By A and B" line, and the context note under it ── */
.byline {
    font-family: var(--font-ui);
    font-size: var(--fs-2);
    color: var(--color-text-muted);
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
  }

  .byline__names {
    color: var(--color-text);
  }

  .byline__context {
    font-style: italic;
  }

/* ── COVER IMAGE — every picture on the site, and the empty panel when there is none ── */
.cover {
    display: block;
    width: 100%;
    height: auto;
    object-fit: cover;
    background: var(--color-bg-sunken);
  }

  .cover--pending {
    border: 1px solid var(--color-rule);
  }

/* ── FILTER CHIPS — the format and field buttons on the three index pages ── */
.filters {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    margin-bottom: var(--space-6);
  }

  .filters__group {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
  }

  .filters__legend {
    margin-right: var(--space-2);
    color: var(--color-text-muted);
  }

  .chip {
    border: 1px solid var(--color-rule-strong);
    border-radius: 999px;
    background: none;
    padding: 0.3em 0.9em;
    color: var(--color-text-muted);
    cursor: pointer;
    font-family: var(--font-ui);
    transition:
      color var(--motion-fast) var(--ease),
      border-color var(--motion-fast) var(--ease),
      background var(--motion-fast) var(--ease);
  }

  .chip:hover {
    color: var(--color-text);
    border-color: var(--color-text);
  }

  .chip[aria-pressed='true'] {
    background: var(--color-text);
    border-color: var(--color-text);
    color: var(--color-bg);
  }

  .filters__status {
    margin: 0;
    min-height: 1.4em;
  }

/* ── FOOTER — two columns of links, the wordmark line ── */
.footer {
    margin-top: var(--space-9);
    font-family: var(--font-ui);
  }

  .footer--flush {
    margin-top: 0;
  }

  .footer__inner {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    gap: var(--space-7) var(--grid-gap);
    padding-block: var(--space-7);
  }

  .footer__heading {
    margin: 0 0 var(--space-4);
    font-weight: 400;
  }

  .footer__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
  }

  .footer__list a {
    font-size: var(--fs-2);
    color: var(--color-text);
    text-decoration: none;
  }

  .footer__list a:hover {
    color: var(--color-accent);
    text-decoration: underline;
    text-underline-offset: 0.18em;
  }

  .footer__base {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    /* The copyright sits at the right, and stays there. This line used to hold
       the wordmark as well and pushed the two apart with space-between; with
       one item left, space-between would have parked it at the left instead,
       so the edge is now named outright rather than left to fall out of the
       spacing. Anything added back beside it wants space-between again. */
    justify-content: flex-end;
    gap: var(--space-3);
    padding-block: var(--space-4) var(--space-7);
    margin: 0;
    text-transform: none;
    letter-spacing: 0;
  }

/* ── HEADER — the blue band, the navigation, the mobile menu ── */
.header {
    /* The band, not the page, is what the wordmark sits on. */
    --wordmark-colour: var(--field-text);
  }

  .header__inner {
    display: flex;
    align-items: center;
    gap: var(--space-4) var(--space-5);
    padding-block: var(--space-4);
    flex-wrap: wrap;
  }

  @media (min-width: 48em) {
    .header__inner {
      /* One line, always. The tagline is what gives way if space is tight. */
      flex-wrap: nowrap;
    }

    .nav__list {
      flex-wrap: nowrap;
    }
  }

  .header__home {
    display: flex;
    align-items: baseline;
    gap: var(--space-4);
    text-decoration: none;
    margin-right: auto;
    color: var(--field-text);
  }

  /* The short descriptor beside the wordmark, as in the KoozArch lockup. */
  .header__tagline {
    font-family: var(--font-ui);
    font-size: var(--fs-1);
    line-height: 1.25;
    max-width: 12ch;
    color: var(--field-text);
  }

  .nav {
    display: contents;
  }

  .nav__list {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-5);
    list-style: none;
    margin: 0;
    padding: 0;
  }

  .nav__list a {
    font-family: var(--font-ui);
    font-size: var(--fs-2);
    color: var(--field-text);
    text-decoration: none;
    padding-block: var(--space-1);
    border-bottom: 2px solid transparent;
  }

  /* White, because nothing else clears AA on this blue. */
  .nav__list a:hover,
  .nav__list a[aria-current='page'] {
    border-bottom-color: var(--field-text);
  }

  .header__search {
    color: var(--field-text);
    display: inline-flex;
    padding: var(--space-1);
  }

  .header__search svg {
    width: 1.15rem;
    height: 1.15rem;
  }

  .nav__toggle {
    display: none;
    align-items: center;
    gap: var(--space-2);
    background: none;
    border: 0;
    padding: var(--space-2);
    margin: 0;
    color: var(--field-text);
    font: inherit;
    cursor: pointer;
  }

  .nav__toggle-icon {
    width: 1.25rem;
    height: 1.25rem;
  }

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

  /* The focus ring has to be visible against the blue, not the page. */
  .header :focus-visible {
    outline-color: var(--field-text);
  }

  /* Narrow screens. Only takes effect once the script has marked the nav as
     collapsible — without JavaScript the links stay visible and wrap. */
  /* The lockup needs real room. Below this the tagline goes rather than
     letting the header wrap onto a second line. */
  @media (max-width: 63.99em) {
    .header__tagline {
      display: none;
    }
  }

  @media (max-width: 47.99em) {
    .nav[data-collapsible] {
      display: contents;
    }

    .nav[data-collapsible] .nav__toggle {
      display: inline-flex;
      order: 1;
    }

    .nav[data-collapsible] .nav__list {
      order: 3;
      flex-basis: 100%;
      flex-direction: column;
      gap: var(--space-4);
      padding-block: var(--space-4) var(--space-2);
    }

    .nav[data-collapsible] .nav__list[hidden] {
      display: none;
    }

    .header__search {
      order: 2;
    }
  }

/* ── STATUS PILL — In development / Ongoing / Completed ── */
.pill {
    display: inline-block;
    border: 1px solid var(--color-rule-strong);
    border-radius: 999px;
    padding: 0.15em 0.75em;
    color: var(--color-text-muted);
    white-space: nowrap;
  }

  .pill[data-status='in-development'] {
    border-color: var(--color-accent);
    color: var(--color-accent);
  }

  .pill[data-status='ongoing'] {
    border-color: var(--color-rule-strong);
    color: var(--color-text);
  }

  /* On a colour field, white is the only value that clears AA — so every
     status reads the same there, and the wording carries the difference. */
  .pill[data-on-field],
  .pill[data-on-field][data-status='in-development'],
  .pill[data-on-field][data-status='ongoing'] {
    color: var(--field-text);
    border-color: var(--field-text);
  }

/* ── WORDMARK — the logo, drawn as a mask so it takes the text colour ── */
.wordmark {
    display: inline-block;
    margin: 0;
    line-height: 0;
  }

  .wordmark__mark {
    display: block;
    width: var(--wordmark-width);
    /* The artwork is 1500 × 328, so the box matches its proportions exactly
       and the header never shifts as the page loads. */
    aspect-ratio: 1500 / 328;

    /* Falls back to the page text colour, but a colour field (the header band)
       overrides --wordmark-colour so the mark switches to white on the blue. */
    background-color: var(--wordmark-colour, var(--color-text));
    -webkit-mask-image: url('assets/brand/wordmark.png');
    mask-image: url('assets/brand/wordmark.png');
    -webkit-mask-size: contain;
    mask-size: contain;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: left center;
    mask-position: left center;

    transition: background-color var(--motion-fast) var(--ease);
  }

  a:hover .wordmark__mark {
    background-color: var(--wordmark-colour, var(--color-accent));
    opacity: 0.75;
  }

/* ── PAGE FRAME — pushes the footer to the bottom of a short page ── */
/* Pushes the footer to the bottom of a short page. */
  .main {
    flex: 1 0 auto;
  }

  /* …except where the content is meant to end where it ends. */
  .main--flush {
    flex: 0 0 auto;
  }

/* ═══ 4. PAGE TEMPLATES ═══ */

/* ── NOT FOUND PAGE
      Styled through body.wn-404 ── */
body.wn-404 .notfound {
    padding-block: var(--space-9);
    min-height: 60vh;
  }

  body.wn-404 .notfound__title {
    font-size: var(--fs-7);
    line-height: var(--lh-display);
    letter-spacing: 0.01em;
    margin: 0 0 var(--space-5);
    color: var(--field-text);
  }

  body.wn-404 .notfound__body {
    font-size: var(--fs-4);
    color: var(--field-text);
    margin: 0 0 var(--space-7);
    max-width: 40ch;
  }

  body.wn-404 .notfound__links {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3) var(--space-5);
    list-style: none;
    margin: 0;
    padding: 0;
    font-family: var(--font-ui);
    font-size: var(--fs-2);
  }

  body.wn-404 .notfound__links a {
    color: var(--field-text);
    text-decoration: none;
    border-bottom: 1px solid currentColor;
    padding-bottom: 2px;
  }

/* ── STANDING PAGES — Press, Support, and anything added later
      Styled through body.wn-standard ── */
body.wn-standard .head {
    padding-block: var(--space-7) var(--space-8);
  }

  body.wn-standard .head__title {
    font-size: var(--fs-7);
    line-height: var(--lh-display);
    letter-spacing: 0.01em;
    margin: 0;
    color: var(--field-text);
  }

  body.wn-standard .head__intro {
    font-size: var(--fs-4);
    color: var(--field-text);
    margin: var(--space-5) 0 0;
    max-width: 44ch;
  }

  body.wn-standard .body {
    padding-block: var(--space-8) var(--space-9);
  }

/* ── ABOUT PAGE
      Styled through body.wn-about ── */
body.wn-about .about__field {
    padding-block: var(--space-7) var(--space-8);
  }

  body.wn-about .about__title {
    font-size: var(--fs-7);
    line-height: var(--lh-display);
    letter-spacing: 0.01em;
    margin: 0 0 var(--space-6);
    color: var(--field-text);
  }

  body.wn-about .contents__heading {
    color: var(--field-text);
    margin: 0 0 var(--space-4);
  }

  body.wn-about .contents__list {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3) var(--space-5);
    list-style: none;
    margin: 0;
    padding: 0;
    font-family: var(--font-ui);
    font-size: var(--fs-2);
  }

  body.wn-about .contents__list a {
    color: var(--field-text);
    text-decoration: none;
    border-bottom: 1px solid currentColor;
    padding-bottom: 2px;
  }

  /* No bottom padding: the footer already carries --space-9 above itself, and
     adding another here gave the About page twice the gap every other page
     type has between its last line and the footer. */
  body.wn-about .about__body {
    padding-block: var(--space-8) 0;
  }

  /* Each section gets air above it, and a rule to separate the strands. */
  body.wn-about .prose h2 {
    font-size: var(--fs-5);
    margin-top: var(--space-8);
    padding-top: var(--space-6);
    border-top: 1px solid var(--color-rule);
    /* So a jump from the contents list does not land under the header. */
    scroll-margin-top: var(--space-5);
  }

  body.wn-about .prose h2:first-child {
    margin-top: 0;
    padding-top: 0;
    border-top: 0;
  }

  body.wn-about .prose h3 {
    font-size: var(--fs-4);
    margin-top: var(--space-6);
  }

/* ── ACTIVATION PAGE — one workshop, exhibition, residency
      Styled through body.wn-activation ── */
/* ── The title field ────────────────────────────────────────────────── */

  body.wn-activation .activation__field {
    padding-block: var(--space-7) var(--space-8);
  }

  body.wn-activation .crumb {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3) var(--space-5);
    margin: 0 0 var(--space-6);
    color: var(--field-text);
  }

  body.wn-activation .crumb a {
    color: var(--field-text);
    text-decoration: none;
  }

  body.wn-activation .crumb > a {
    border-bottom: 1px solid currentColor;
    padding-bottom: 2px;
  }

  /* The parent project is the important link here — give it the underline
     weight. It cannot take a colour: nothing but white clears AA on the blue. */
  body.wn-activation .crumb__parent a {
    border-bottom: 2px solid currentColor;
    padding-bottom: 2px;
  }

  body.wn-activation .crumb__and {
    opacity: 0.8;
  }

  body.wn-activation .activation__title {
    font-size: var(--fs-6);
    line-height: var(--lh-display);
    letter-spacing: 0.01em; /* capitals need air, not tightening */
    max-width: 24ch;
    margin: 0 0 var(--space-5);
    color: var(--field-text);
    text-wrap: pretty;
  }

  body.wn-activation .activation__summary {
    font-size: var(--fs-4);
    color: var(--field-text);
    margin: 0 0 var(--space-5);
    max-width: 46ch;
  }

  body.wn-activation .activation__field .byline,
body.wn-activation .activation__field .byline__names {
    color: var(--field-text);
  }

  /* ── The facts ──────────────────────────────────────────────────────── */

  body.wn-activation .details {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-5) var(--space-7);
    margin: var(--space-6) 0 0;
  }

  body.wn-activation .details__row {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
  }

  body.wn-activation .details dt {
    margin: 0;
    color: var(--field-text);
  }

  body.wn-activation .details__value {
    margin: 0;
    font-family: var(--font-ui);
    font-size: var(--fs-2);
    color: var(--field-text);
  }

  /* A date we do not have yet is said out loud, not left blank. On the blue
     field the amber marker fails contrast, so it becomes a dotted underline. */
  body.wn-activation .details__value--pending {
    border-bottom: 2px dotted var(--field-text);
    padding-bottom: 1px;
    display: inline-block;
  }

  body.wn-activation .activation__external {
    margin: var(--space-5) 0 0;
    font-family: var(--font-ui);
    font-size: var(--fs-2);
  }

  body.wn-activation .activation__external a {
    color: var(--field-text);
  }

  /* ── Two-column article ─────────────────────────────────────────────── */

  body.wn-activation .article {
    padding-top: var(--space-8);
  }

  body.wn-activation .article__text {
    max-width: var(--measure);
  }

  @media (min-width: 60em) {
    body.wn-activation .article--paired {
      display: grid;
      grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
      gap: var(--grid-gap);
      align-items: start;
    }

    body.wn-activation .article--paired .article__figure {
      position: sticky;
      top: var(--space-5);
    }
  }

  @media (max-width: 59.99em) {
    body.wn-activation .article__figure {
      margin-bottom: var(--space-7);
    }
  }

  /* ── Body ───────────────────────────────────────────────────────────── */

  body.wn-activation .prose p:last-child {
    margin-bottom: 0;
  }

  body.wn-activation .pending {
    color: var(--color-text-muted);
    font-style: italic;
  }

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

  body.wn-activation .section {
    margin-top: var(--space-8);
  }

  body.wn-activation .section__heading {
    font-size: var(--fs-5);
    margin-block: var(--space-6) var(--space-4);
  }

  body.wn-activation .gallery {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
    gap: var(--grid-gap);
  }

  body.wn-activation .gallery__figure {
    margin: 0;
  }

  body.wn-activation .gallery__caption {
    margin-top: var(--space-2);
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    text-transform: none;
    letter-spacing: 0;
  }

  body.wn-activation .gallery__credit {
    color: var(--color-text-muted);
  }

  body.wn-activation .metastrip {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-6) var(--space-7);
  }

  body.wn-activation .metastrip__item {
    margin-top: var(--space-5);
  }

  body.wn-activation .metastrip__item h2 {
    margin: 0 0 var(--space-2);
  }

  body.wn-activation .metastrip__text {
    margin: 0;
    font-family: var(--font-ui);
    font-size: var(--fs-2);
  }

  body.wn-activation .plainlist {
    list-style: none;
    margin: 0;
    padding: 0;
    font-family: var(--font-ui);
    font-size: var(--fs-2);
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
  }

  body.wn-activation .plainlist__role {
    color: var(--color-text-muted);
  }

  /* ── Pager ──────────────────────────────────────────────────────────── */

  body.wn-activation .pager {
    margin-top: var(--space-8);
  }

  body.wn-activation .pager__inner {
    display: flex;
    justify-content: space-between;
    gap: var(--space-5);
    padding-block: var(--space-6);
  }

  body.wn-activation .pager__link {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    text-decoration: none;
    color: inherit;
    max-width: 22ch;
  }

  body.wn-activation .pager__link--next {
    text-align: right;
    margin-left: auto;
  }

  body.wn-activation .pager__title {
    font-size: var(--fs-4);
  }

  body.wn-activation .pager__link:hover .pager__title {
    color: var(--color-accent);
  }

/* ── ACTIVATIONS INDEX — the chronological list
      Styled through body.wn-activations-index ── */
body.wn-activations-index .head {
    padding-block: var(--space-7) var(--space-8);
  }

  body.wn-activations-index .head__title {
    font-size: var(--fs-7);
    line-height: var(--lh-display);
    letter-spacing: 0.01em;
    margin: 0 0 var(--space-5);
    color: var(--field-text);
  }

  body.wn-activations-index .head__intro {
    font-size: var(--fs-4);
    color: var(--field-text);
    margin: 0;
    max-width: 44ch;
  }

  body.wn-activations-index .band {
    padding-top: var(--space-8);
    margin-bottom: var(--space-9);
  }

  body.wn-activations-index .activations {
    list-style: none;
    margin: 0;
    padding: 0;
  }

  body.wn-activations-index .activation__row {
    display: grid;
    grid-template-columns: 180px minmax(0, 1fr);
    gap: var(--grid-gap);
    align-items: start;
    padding-block: var(--space-5);
  }

  body.wn-activations-index .activation__when,
body.wn-activations-index .activation__where {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin: 0;
  }

  body.wn-activations-index .activation__format {
    color: var(--color-text);
  }

  /* Not a link, so not the link colour — an amber rule instead. */
  body.wn-activations-index .activation__tbc {
    color: var(--color-text);
    border-bottom: 2px solid var(--color-highlight);
    padding-bottom: 1px;
  }

  body.wn-activations-index .activation__title {
    font-size: var(--fs-4);
    margin: var(--space-2) 0;
  }

  body.wn-activations-index .activation__title a {
    color: inherit;
    text-decoration: none;
  }

  body.wn-activations-index .activation__title a:hover {
    color: var(--color-accent);
  }

  body.wn-activations-index .activation__summary {
    margin: 0 0 var(--space-3);
    max-width: var(--measure);
    color: var(--color-text-muted);
    font-size: var(--fs-3);
    line-height: 1.5;
  }

  body.wn-activations-index .activation__parent a {
    color: var(--color-accent);
  }

  body.wn-activations-index .activation__and {
    color: var(--color-text-muted);
  }

  body.wn-activations-index .activations__empty p {
    padding-block: var(--space-6);
    color: var(--color-text-muted);
  }

  @media (max-width: 47.99em) {
    body.wn-activations-index .activation__row {
      grid-template-columns: 1fr;
      gap: var(--space-4);
    }

    body.wn-activations-index .activation__thumb {
      max-width: 220px;
    }
  }

/* ── LANDING PAGE — the statement on blue. Deliberately almost empty.
      Styled through body.wn-home ── */
body.wn-home .opening {
    padding-block: var(--space-9);
  }

  body.wn-home .opening__inner {
    display: flex;
    flex-direction: column;
  }

  /* The only thing on the page. A paragraph of argument rather than a short
     claim, so it takes a reading size and a real measure — set any larger and
     it becomes a wall instead of something anyone reads. */
  body.wn-home .opening__statement {
    font-size: var(--fs-5);
    line-height: 1.32;
    color: var(--field-text);
    max-width: 34ch;
    margin: 0;
    text-wrap: pretty;
  }

/* ── TEXT PAGE — one essay, chapter or contribution
      Styled through body.wn-reflection ── */
body.wn-reflection .text__field {
    padding-block: var(--space-7) var(--space-8);
  }

  body.wn-reflection .crumb {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3) var(--space-5);
    margin: 0 0 var(--space-6);
    color: var(--field-text);
  }

  body.wn-reflection .crumb a {
    color: var(--field-text);
    text-decoration: none;
  }

  body.wn-reflection .crumb > a {
    border-bottom: 1px solid currentColor;
    padding-bottom: 2px;
  }

  body.wn-reflection .crumb__parent a {
    border-bottom: 2px solid currentColor;
    padding-bottom: 2px;
  }

  body.wn-reflection .text__title {
    font-size: var(--fs-6);
    line-height: var(--lh-display);
    letter-spacing: 0.01em;
    max-width: 24ch;
    margin: 0 0 var(--space-5);
    color: var(--field-text);
  }

  body.wn-reflection .text__summary {
    font-size: var(--fs-4);
    color: var(--field-text);
    margin: 0 0 var(--space-5);
    max-width: 46ch;
  }

  body.wn-reflection .text__field .byline,
body.wn-reflection .text__field .byline__names {
    color: var(--field-text);
  }

  body.wn-reflection .details {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-5) var(--space-7);
    margin: var(--space-6) 0 0;
  }

  body.wn-reflection .details__row {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
  }

  body.wn-reflection .details dt {
    margin: 0;
    color: var(--field-text);
  }

  body.wn-reflection .details__value {
    margin: 0;
    font-family: var(--font-ui);
    font-size: var(--fs-2);
    color: var(--field-text);
  }

  body.wn-reflection .details__value--pending {
    border-bottom: 2px dotted var(--field-text);
    padding-bottom: 1px;
    display: inline-block;
  }

  /* ── The text ───────────────────────────────────────────────────────── */

  body.wn-reflection .article {
    padding-top: var(--space-8);
  }

  body.wn-reflection .article__text {
    max-width: var(--measure);
  }

  @media (min-width: 60em) {
    body.wn-reflection .article--paired {
      display: grid;
      grid-template-columns: minmax(0, 0.8fr) minmax(0, 1fr);
      gap: var(--grid-gap);
      align-items: start;
    }

    body.wn-reflection .article--paired .article__figure {
      position: sticky;
      top: var(--space-5);
    }
  }

  @media (max-width: 59.99em) {
    body.wn-reflection .article__figure {
      margin-bottom: var(--space-7);
      max-width: 22rem;
    }
  }

  /* The line that says why the text stops. Quiet, but it must be seen. */
  body.wn-reflection .policy-note {
    font-family: var(--font-ui);
    font-size: var(--fs-2);
    line-height: 1.55;
    color: var(--color-text-muted);
    border-top: 1px solid var(--color-rule-strong);
    padding-top: var(--space-4);
    margin: var(--space-7) 0 0;
    max-width: var(--measure);
  }

  body.wn-reflection .citation {
    border: 1px solid var(--color-rule-strong);
    padding: var(--space-5);
    margin-top: var(--space-6);
  }

  body.wn-reflection .citation h2 {
    margin: 0 0 var(--space-3);
  }

  body.wn-reflection .citation__line {
    margin: 0;
    font-family: var(--font-ui);
    font-size: var(--fs-2);
    line-height: 1.6;
  }

  body.wn-reflection .citation__licence {
    margin: var(--space-3) 0 0;
  }

  body.wn-reflection .citation__links {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-4);
    margin: var(--space-4) 0 0;
    font-family: var(--font-ui);
    font-size: var(--fs-2);
  }

  body.wn-reflection .citation__links:empty {
    display: none;
  }

/* ── REFLECTIONS INDEX
      Styled through body.wn-reflections-index ── */
body.wn-reflections-index .head {
    padding-block: var(--space-7) var(--space-8);
  }

  body.wn-reflections-index .head__title {
    font-size: var(--fs-7);
    line-height: var(--lh-display);
    letter-spacing: 0.01em;
    margin: 0 0 var(--space-5);
    color: var(--field-text);
  }

  body.wn-reflections-index .head__intro {
    font-size: var(--fs-4);
    color: var(--field-text);
    margin: 0;
    max-width: 44ch;
  }

  body.wn-reflections-index .band {
    padding-top: var(--space-8);
    margin-bottom: var(--space-9);
  }

  body.wn-reflections-index .texts {
    list-style: none;
    margin: 0;
    padding: 0;
  }

  body.wn-reflections-index .text__row {
    display: grid;
    grid-template-columns: 180px minmax(0, 1fr);
    gap: var(--grid-gap);
    align-items: start;
    padding-block: var(--space-5);
  }

  body.wn-reflections-index .text__when,
body.wn-reflections-index .text__where {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin: 0;
  }

  body.wn-reflections-index .text__format {
    color: var(--color-text);
  }

  /* Not a link, so not the link colour. Same marker as an undated activation. */
  body.wn-reflections-index .text__tbc {
    color: var(--color-text);
    border-bottom: 2px solid var(--color-highlight);
    padding-bottom: 1px;
  }

  body.wn-reflections-index .text__title {
    font-size: var(--fs-4);
    margin: var(--space-2) 0;
  }

  body.wn-reflections-index .text__title a {
    color: inherit;
    text-decoration: none;
  }

  body.wn-reflections-index .text__title a:hover {
    color: var(--color-accent);
  }

  body.wn-reflections-index .text__summary {
    margin: var(--space-3) 0;
    max-width: var(--measure);
    color: var(--color-text-muted);
    font-size: var(--fs-3);
    line-height: 1.5;
  }

  body.wn-reflections-index .text__published {
    font-style: italic;
    text-transform: none;
    letter-spacing: 0;
  }

  body.wn-reflections-index .text__parent a {
    color: var(--color-accent);
  }

  body.wn-reflections-index .texts__empty p {
    padding-block: var(--space-6);
    color: var(--color-text-muted);
  }

  @media (max-width: 47.99em) {
    body.wn-reflections-index .text__row {
      grid-template-columns: 1fr;
      gap: var(--space-4);
    }

    body.wn-reflections-index .text__thumb {
      max-width: 190px;
    }
  }

/* ── PROJECT PAGE — the spine, the developments, the metastrip
      Styled through body.wn-project ── */
/* ── The title field ────────────────────────────────────────────────── */

  body.wn-project .project__field {
    /* Runs from the header band down; no rule between them. */
    padding-block: var(--space-7) var(--space-8);
  }

  body.wn-project .project__crumb {
    margin: 0 0 var(--space-6);
  }

  body.wn-project .project__crumb a {
    color: var(--field-text);
    text-decoration: none;
    border-bottom: 1px solid currentColor;
    padding-bottom: 2px;
  }

  body.wn-project .project__title {
    /* Display size, set solid, running close to the edge of the field. */
    font-size: var(--fs-7);
    line-height: var(--lh-display);
    letter-spacing: 0.01em; /* capitals need air, not tightening */
    max-width: 22ch;
    margin: 0 0 var(--space-4);
    color: var(--field-text);
    text-wrap: pretty;
  }

  body.wn-project .project__subtitle {
    font-size: var(--fs-4);
    color: var(--field-text);
    margin: 0 0 var(--space-6);
    max-width: 34ch;
  }

  body.wn-project .project__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-3);
    margin: 0 0 var(--space-4);
    color: var(--field-text);
  }

  body.wn-project .project__meta .label {
    color: var(--field-text);
  }

  body.wn-project .project__field .byline,
body.wn-project .project__field .byline__names {
    color: var(--field-text);
  }

  /* ── Two-column article ─────────────────────────────────────────────────
     The figure column is sticky on a wide screen so the image stays with the
     argument. `align-items: start` is what lets sticky work inside a grid.
     ─────────────────────────────────────────────────────────────────────── */

  body.wn-project .article {
    padding-top: var(--space-8);
  }

  body.wn-project .article__text {
    max-width: var(--measure);
  }

  @media (min-width: 60em) {
    body.wn-project .article--paired {
      display: grid;
      grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
      gap: var(--grid-gap);
      align-items: start;
    }

    body.wn-project .article--paired .article__figure {
      position: sticky;
      top: var(--space-5);
    }

    body.wn-project .article--paired .article__text {
      /* The measure still governs, whatever the column happens to be. */
      max-width: var(--measure);
    }
  }

  @media (max-width: 59.99em) {
    body.wn-project .article__figure {
      margin-bottom: var(--space-7);
    }
  }

  /* ── The argument ───────────────────────────────────────────────────── */

  body.wn-project .prose {
    font-size: var(--fs-3);
  }

  body.wn-project .prose h2 {
    font-size: var(--fs-4);
    margin-top: var(--space-7);
  }

  body.wn-project .prose p:last-child {
    margin-bottom: 0;
  }

  /* ── Support note ───────────────────────────────────────────────────── */

  body.wn-project .support {
    border: 1px solid var(--color-accent);
    padding: var(--space-5);
    margin-top: var(--space-7);
  }

  body.wn-project .support h2 {
    margin: 0 0 var(--space-3);
    color: var(--color-accent);
  }

  body.wn-project .support p:last-child {
    margin-bottom: 0;
  }

  /* ── Meta strip ─────────────────────────────────────────────────────── */

  body.wn-project .metastrip {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-6);
    margin-top: var(--space-8);
  }

  body.wn-project .metastrip__item h2 {
    margin: 0 0 var(--space-2);
  }

  body.wn-project .metastrip__item p {
    margin: 0;
    font-size: var(--fs-2);
    font-family: var(--font-ui);
  }

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

  body.wn-project .section,
body.wn-project .spine-section {
    margin-top: var(--space-8);
  }

  body.wn-project .section__heading {
    font-size: var(--fs-5);
    margin-block: var(--space-6) var(--space-3);
  }

  body.wn-project .section__intro {
    color: var(--color-text-muted);
    margin-bottom: var(--space-6);
  }

  /* ── The spine ──────────────────────────────────────────────────────────
     A thin rule down the left with a marker at each node. Just a border and
     some positioned dots — it reflows to one column and never scrolls
     sideways.
     ─────────────────────────────────────────────────────────────────────── */

  body.wn-project .spine {
    list-style: none;
    margin: 0;
    padding: 0 0 0 var(--space-6);
    border-left: 1px solid var(--color-rule-strong);
  }

  body.wn-project .spine__node {
    position: relative;
    padding-block: var(--space-5);
  }

  body.wn-project .spine__node + .spine__node {
    border-top: 1px solid var(--color-rule);
  }

  /* The marker sitting on the rule. */
  body.wn-project .spine__node::before {
    content: '';
    position: absolute;
    left: calc(var(--space-6) * -1 - 4px);
    top: calc(var(--space-5) + 0.5em);
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--color-bg);
    border: 1px solid var(--color-rule-strong);
  }

  body.wn-project .spine__link {
    display: block;
    text-decoration: none;
    color: inherit;
  }

  body.wn-project .spine__link:hover .spine__title {
    color: var(--color-accent);
  }

  body.wn-project .spine__node:hover::before {
    background: var(--color-accent);
    border-color: var(--color-accent);
  }

  body.wn-project .spine__when {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin: 0 0 var(--space-2);
  }

  body.wn-project .spine__format {
    color: var(--color-text);
  }

  /* See the note on .activation__tbc — a marker, not a link. */
  body.wn-project .spine__tbc {
    color: var(--color-text);
    border-bottom: 2px solid var(--color-highlight);
    padding-bottom: 1px;
  }

  body.wn-project .spine__main {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 140px;
    gap: var(--grid-gap);
    align-items: start;
  }

  body.wn-project .spine__title {
    font-size: var(--fs-4);
    margin: 0 0 var(--space-2);
    transition: color var(--motion-fast) var(--ease);
  }

  body.wn-project .spine__where {
    margin: 0 0 var(--space-2);
  }

  body.wn-project .spine__summary {
    margin: 0;
    font-size: var(--fs-3);
    line-height: 1.5;
    color: var(--color-text-muted);
    max-width: var(--measure);
  }

  /* ── The Developments strand ────────────────────────────────────────────
     Set unlike the spine on purpose: no markers, no thumbnails, no rule down
     the side. A reader should be able to tell at a glance that these are not
     things the platform did.
     ─────────────────────────────────────────────────────────────────────── */

  body.wn-project .developments {
    margin: 0;
    max-width: var(--measure);
  }

  body.wn-project .developments__row {
    display: grid;
    grid-template-columns: 6rem minmax(0, 1fr);
    gap: var(--space-4);
    padding-block: var(--space-4);
    border-top: 1px solid var(--color-rule);
  }

  body.wn-project .developments__date {
    margin: 0;
    color: var(--color-text-muted);
  }

  body.wn-project .developments__text {
    margin: 0;
  }

  body.wn-project .reflections__where {
    color: var(--color-text-muted);
    text-transform: none;
    letter-spacing: 0;
  }

  @media (max-width: 39.99em) {
    body.wn-project .developments__row {
      grid-template-columns: 1fr;
      gap: var(--space-1);
    }
  }

  /* ── Output cards ───────────────────────────────────────────────────── */

  body.wn-project .cards {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
    gap: var(--grid-gap);
  }

  body.wn-project .cards a {
    text-decoration: none;
    color: inherit;
  }

  body.wn-project .card__title {
    font-size: var(--fs-3);
    margin: var(--space-3) 0 var(--space-1);
  }

  body.wn-project .cards a:hover .card__title {
    color: var(--color-accent);
  }

  body.wn-project .card__meta {
    margin: 0;
  }

  /* ── Reflections list ───────────────────────────────────────────────── */

  body.wn-project .reflections {
    list-style: none;
    margin: 0;
    padding: 0;
  }

  body.wn-project .reflections li {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--space-3);
    padding-block: var(--space-3);
    border-top: 1px solid var(--color-rule);
  }

  /* ── Pager ──────────────────────────────────────────────────────────── */

  body.wn-project .pager {
    margin-top: var(--space-8);
  }

  body.wn-project .pager__inner {
    display: flex;
    justify-content: space-between;
    gap: var(--space-5);
    padding-block: var(--space-6);
  }

  body.wn-project .pager__link {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    text-decoration: none;
    color: inherit;
    max-width: 20ch;
  }

  body.wn-project .pager__link--next {
    text-align: right;
    margin-left: auto;
  }

  body.wn-project .pager__title {
    font-size: var(--fs-4);
  }

  body.wn-project .pager__link:hover .pager__title {
    color: var(--color-accent);
  }

  @media (max-width: 47.99em) {
    body.wn-project .spine {
      padding-left: var(--space-5);
    }

    body.wn-project .spine__node::before {
      left: calc(var(--space-5) * -1 - 4px);
    }

    body.wn-project .spine__main {
      grid-template-columns: 1fr;
    }

    body.wn-project .spine__thumb {
      max-width: 160px;
    }
  }

/* ── RESEARCH INDEX — the two bands, Ongoing and Completed
      Styled through body.wn-research-index ── */
body.wn-research-index .head {
    padding-block: var(--space-7) var(--space-8);
  }

  body.wn-research-index .head__title {
    font-size: var(--fs-7);
    line-height: var(--lh-display);
    letter-spacing: 0.01em;
    margin: 0 0 var(--space-5);
    color: var(--field-text);
  }

  body.wn-research-index .head__intro {
    font-size: var(--fs-4);
    color: var(--field-text);
    margin: 0;
    max-width: 40ch;
  }

  /* No margin between the bands. They used to be separated because each one
     announced itself with a heading; without those the two groups are one
     continuous list, and a gap here would read as a hole rather than a
     division. The space before the footer is the footer's own margin-top. */
  body.wn-research-index .band:first-of-type {
    padding-top: var(--space-8);
  }

  body.wn-research-index .projects {
    list-style: none;
    margin: 0;
    padding: 0;
  }

  body.wn-research-index .project__link {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
    gap: var(--grid-gap);
    align-items: start;
    padding-block: var(--space-6);
    text-decoration: none;
    color: inherit;
  }

  body.wn-research-index .project__link:hover .project__title {
    color: var(--color-accent);
  }

  body.wn-research-index .project__title {
    font-size: var(--fs-5);
    margin: 0 0 var(--space-2);
    transition: color var(--motion-fast) var(--ease);
  }

  body.wn-research-index .project__subtitle {
    font-family: var(--font-ui);
    font-size: var(--fs-2);
    color: var(--color-text-muted);
    margin: 0 0 var(--space-4);
  }

  body.wn-research-index .project__summary {
    margin: 0 0 var(--space-5);
    max-width: var(--measure);
  }

  body.wn-research-index .project__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-3);
    margin: 0;
  }

  @media (max-width: 47.99em) {
    body.wn-research-index .project__link {
      grid-template-columns: 1fr;
      gap: var(--space-4);
    }
  }

/* ── SEARCH RESULTS
      Styled through body.wn-search ── */
body.wn-search .head {
    padding-block: var(--space-7) var(--space-8);
  }

  body.wn-search .head__title {
    font-size: var(--fs-7);
    line-height: var(--lh-display);
    letter-spacing: 0.01em;
    margin: 0 0 var(--space-5);
    color: var(--field-text);
  }

  body.wn-search .head__intro {
    font-size: var(--fs-4);
    color: var(--field-text);
    margin: 0;
    max-width: 44ch;
  }

  body.wn-search .body {
    padding-block: var(--space-8) var(--space-9);
    min-height: 40vh;
  }

  body.wn-search .note {
    font-family: var(--font-ui);
    font-size: var(--fs-2);
    color: var(--color-text-muted);
    max-width: var(--measure);
  }

  /* Pagefind ships its own styles; these bend them onto the site's tokens so
     the results do not look like a widget bolted on. */
  body.wn-search .body .pagefind-ui {
    --pagefind-ui-scale: 0.85;
    --pagefind-ui-primary: var(--color-text);
    --pagefind-ui-text: var(--color-text);
    --pagefind-ui-background: var(--color-bg);
    --pagefind-ui-border: var(--color-rule-strong);
    --pagefind-ui-tag: var(--color-bg-sunken);
    --pagefind-ui-border-width: 1px;
    --pagefind-ui-border-radius: 0;
    --pagefind-ui-font: var(--font-ui);
  }

  body.wn-search .body .pagefind-ui__result-title a {
    font-family: var(--font-ui);
    color: var(--color-text);
  }

  body.wn-search .body .pagefind-ui__result-excerpt {
    font-family: var(--font-text);
    font-size: var(--fs-3);
    line-height: 1.5;
  }
