/* ==========================================================================
   HAIC @ NeurIPS 2026
   One stylesheet, no build step. Palette sampled from images/header.png.

   Sections declare their own surface by overriding the semantic tokens
   (--fg, --fg-dim, --rule, --surface, --heading) rather than by fighting
   specificity. Add .section--dark to a band and everything inside adapts.
   ========================================================================== */

/* ------------------------------------------------------------- fonts
   Self-hosted: no render-blocking cross-origin request, and no visitor IPs
   sent to a third party. Latin subsets from Google Fonts, whose own
   descriptors (weight ranges, unicode-range, display) are preserved verbatim.
   Bricolage is the variable font because h3/h4 use font-weight: 650.
   All three families are OFL-licensed. Regenerate with tools/get_fonts.py. */
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 400 800;
  font-stretch: 100%;
  font-display: swap;
  src: url('../fonts/bricolage-grotesque-var.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Source Serif 4';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/source-serif-4-400-italic.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Source Serif 4';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/source-serif-4-400.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Source Serif 4';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('../fonts/source-serif-4-600.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/ibm-plex-mono-400.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/ibm-plex-mono-500.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('../fonts/ibm-plex-mono-600.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /* palette, sampled from images/header.png */
  --ink:        #12242c;
  --ink-2:      #1a3340;
  --teal:       #25545c;
  --teal-deep:  #1c414a;
  --sea:        #569c9d;
  --cyan:       #62cacf;
  --amber:      #dba16f;
  --amber-lt:   #edc884;
  --violet:     #7c789c;

  --ground:     #eef2f1;
  --ground-sunk: #e3ebe9;   /* a step darker than --ground, for inset panels */
  --white:      #ffffff;
  --body-ink:   #22333a;
  --body-dim:   #4f6469;
  --hairline:   #d7e0de;

  /* semantic tokens: the light surface is the default */
  --fg:         var(--body-ink);
  --fg-dim:     var(--body-dim);
  --heading:    var(--ink);
  --rule:       var(--hairline);
  --surface:    var(--white);
  --link:       var(--teal);

  /* type */
  --display: "Bricolage Grotesque", "Segoe UI", system-ui, -apple-system, sans-serif;
  --serif:   "Source Serif 4", Georgia, "Times New Roman", serif;
  --mono:    "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* rhythm */
  --gutter:  clamp(20px, 5vw, 48px);
  --measure: 62ch;
  --radius:  12px;
  --band:    clamp(56px, 8vw, 104px);
}

/* --------------------------------------------------------------- reset */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { -webkit-text-size-adjust: 100%; }
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}
body {
  background: var(--ground);
  color: var(--fg);
  font-family: var(--serif);
  font-size: clamp(1rem, 0.97rem + 0.15vw, 1.0625rem);
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
}
img, svg { display: block; max-width: 100%; }
img { height: auto; }
a { color: var(--link); text-decoration-thickness: 1px; text-underline-offset: 0.18em; }
a:hover { text-decoration-thickness: 2px; }
ul, ol { padding-left: 1.15em; }
:focus-visible {
  outline: 2px solid var(--amber);
  outline-offset: 3px;
  border-radius: 3px;
}
::selection { background: var(--amber); color: var(--ink); }

/* --------------------------------------------------------- typography */
h1, h2, h3, h4 {
  font-family: var(--display);
  color: var(--heading);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.015em;
  text-wrap: balance;
}
h1 { font-size: clamp(2.15rem, 1.35rem + 3.6vw, 3.85rem); line-height: 1.02; letter-spacing: -0.025em; }
h2 { font-size: clamp(1.45rem, 1.2rem + 1.2vw, 2.05rem); }
h3 { font-size: clamp(1.06rem, 1rem + 0.3vw, 1.2rem); font-weight: 650; letter-spacing: -0.01em; }
h4 { font-size: 0.98rem; font-weight: 650; }

p + p, p + ul, p + ol, ul + p, h3 + p, .stack > * + * { margin-top: 0.9em; }
.prose > * + * { margin-top: 1.05em; }
.prose { max-width: var(--measure); }
.prose li + li { margin-top: 0.35em; }

.eyebrow {
  font-family: var(--mono);
  font-size: 0.715rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--fg-dim);
  display: block;
}
.lede {
  font-size: clamp(1.09rem, 1.02rem + 0.45vw, 1.28rem);
  line-height: 1.6;
  max-width: 58ch;
}
.note {
  font-family: var(--mono);
  font-size: 0.775rem;
  line-height: 1.6;
  color: var(--fg-dim);
  letter-spacing: 0.005em;
}
.mono { font-family: var(--mono); }
.nowrap { white-space: nowrap; }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

/* ------------------------------------------------------------- layout */
.wrap {
  width: min(1120px, 100% - (2 * var(--gutter)));
  margin-inline: auto;
}
.wrap--narrow { width: min(820px, 100% - (2 * var(--gutter))); }

.section { padding-block: var(--band); }
.section + .section { border-top: 1px solid var(--rule); }
.section--tight { padding-block: clamp(38px, 5vw, 64px); }

.section--dark {
  --fg: #d5e2e0;
  --fg-dim: #93aeae;
  --heading: #f2f7f6;
  --rule: rgba(255, 255, 255, 0.14);
  --surface: rgba(255, 255, 255, 0.045);
  --link: var(--cyan);
  background: var(--ink);
  color: var(--fg);
}
/* A change of surface is its own divider, so only draw a hairline between two
   sections that share one. Order matters here: the dark-to-dark rule is last. */
.section--dark + .section, .section + .section--dark { border-top: 0; }
.section--dark + .section--dark { border-top: 1px solid var(--rule); }

/* Heading rail: label column left, content right. Reads like a spec sheet. */
.band { display: grid; gap: clamp(20px, 3vw, 44px); }
/* Grid items default to min-width:auto, which lets unbreakable content (a LaTeX
   snippet, a wide table) widen the whole page instead of scrolling inside its
   own container. Zero lets them shrink so overflow-x on the child does its job. */
.band > * { min-width: 0; }
.band__head { display: grid; gap: 0.6rem; align-content: start; }
.band__head h2 { margin-top: 0.1rem; }
@media (min-width: 900px) {
  .band { grid-template-columns: 16.5rem minmax(0, 1fr); gap: clamp(32px, 4vw, 68px); }
  .band__head { position: sticky; top: 5.5rem; }
  .band__head h2 { font-size: clamp(1.45rem, 1.1rem + 0.85vw, 1.78rem); }
}

/* Full-width section head, for bands whose content needs the whole measure
   (the coevolution loop, the tier grid). */
.section__head {
  display: grid; gap: 0.6rem; max-width: 64ch;
  margin-bottom: clamp(28px, 4vw, 52px);
}
.section__head p { max-width: 54ch; }
@media (min-width: 900px) {
  .section__head--split {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
    gap: clamp(28px, 4vw, 64px); max-width: none; align-items: end;
  }
  .section__head--split > :first-child { display: grid; gap: 0.6rem; }
}

.rule-tick {
  width: 42px; height: 3px; background: var(--amber);
  border-radius: 2px; margin-top: 0.35rem;
}

/* ------------------------------------------------------- site header */
.masthead {
  position: sticky; top: 0; z-index: 50;
  background: rgba(18, 36, 44, 0.9);
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  color: #dbe6e4;
}
@supports (backdrop-filter: blur(10px)) {
  .masthead { background: rgba(18, 36, 44, 0.78); backdrop-filter: blur(12px) saturate(1.1); }
}
.masthead__bar {
  display: flex; align-items: center; flex-wrap: wrap; gap: 1rem;
  min-height: 60px; padding-block: 0.6rem;
}
.wordmark {
  display: flex; align-items: baseline; gap: 0.55rem;
  font-family: var(--display); font-weight: 700; font-size: 1.02rem;
  color: #f2f7f6; text-decoration: none; letter-spacing: -0.01em;
  margin-right: auto;
}
.wordmark:hover { text-decoration: none; }
.wordmark__mark { width: 26px; height: 26px; flex: none; align-self: center; }
.wordmark__year {
  font-family: var(--mono); font-size: 0.72rem; font-weight: 500;
  /* Not --sea: the masthead is 78% opaque, so over the brightest hero wave that
     lands at 2.97:1. This tone holds 5.25:1 in that worst case. */
  letter-spacing: 0.1em; color: #a8c8c7;
}

.nav { display: flex; align-items: center; gap: clamp(0.9rem, 1.6vw, 1.7rem); }
.nav a {
  font-family: var(--mono); font-size: 0.795rem; letter-spacing: 0.045em;
  color: #b9cdcb; text-decoration: none; padding-block: 0.35rem;
  border-bottom: 1.5px solid transparent;
}
.nav a:hover { color: #fff; border-bottom-color: var(--sea); text-decoration: none; }
/* [aria-current="page"] is set in the markup per page; the scrollspy in
   site.js sets [aria-current="true"] on same-page anchors. Both highlight. */
.nav a[aria-current] { color: #fff; border-bottom-color: var(--amber); }

.nav-toggle {
  display: none; align-items: center; gap: 0.5rem;
  font-family: var(--mono); font-size: 0.76rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: #cfe0de;
  background: transparent; border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 999px; padding: 0.42rem 0.8rem; cursor: pointer;
}
.nav-toggle__bars { display: grid; gap: 3px; }
.nav-toggle__bars i { display: block; width: 14px; height: 1.5px; background: currentColor; }

@media (max-width: 900px) {
  /* Without JavaScript the toggle would do nothing, so the nav stays in flow as
     a plain list on its own row and the button is not shown at all. */
  .js .nav-toggle { display: inline-flex; }
  .nav { display: grid; gap: 0; flex-basis: 100%; }
  .js .nav {
    position: absolute; left: 0; right: 0; top: 100%; flex-basis: auto;
    background: var(--ink); border-bottom: 1px solid rgba(255, 255, 255, 0.12);
    padding: 0.4rem var(--gutter) 1rem;
  }
  .nav[hidden] { display: none; }
  .nav a {
    padding-block: 0.7rem; border-bottom: 1px solid rgba(255, 255, 255, 0.08);
    font-size: 0.9rem;
  }
  .nav a:last-child { border-bottom: 0; }
}

/* keep the wordmark and the menu button on one row on the narrowest phones */
@media (max-width: 400px) {
  .masthead__bar { gap: 0.55rem; }
  .wordmark { font-size: 0.95rem; gap: 0.4rem; }
  .wordmark__mark { width: 22px; height: 22px; }
  .wordmark__year { font-size: 0.66rem; letter-spacing: 0.06em; }
  .nav-toggle { padding: 0.38rem 0.6rem; letter-spacing: 0.06em; gap: 0.4rem; }
  .nav a[aria-current] { border-bottom-color: rgba(255, 255, 255, 0.08); color: var(--amber-lt); }
}

/* --------------------------------------------------------------- hero */
.hero {
  position: relative; isolation: isolate; overflow: hidden;
  background:
    radial-gradient(120% 90% at 18% 6%, #235159 0%, #1a3a44 45%, var(--ink) 100%);
  color: #d8e6e4;
}
.hero::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  /* the plain url() is the fallback for browsers without image-set() */
  background-image: url("../../images/hero-waves.png");
  background-image: image-set(
    url("../../images/hero-waves.webp") type("image/webp"),
    url("../../images/hero-waves.png") type("image/png"));
  background-repeat: no-repeat;
  background-position: right -2rem top -1rem;
  background-size: auto 118%;
  opacity: 0.95;
}
.hero::after {
  /* keeps the type legible where the artwork is busiest */
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(96deg, rgba(15, 32, 39, 0.94) 0%, rgba(15, 32, 39, 0.72) 38%,
              rgba(15, 32, 39, 0.1) 72%, rgba(15, 32, 39, 0) 100%);
}
.hero__inner { padding-block: clamp(58px, 9vw, 132px) clamp(46px, 7vw, 96px); }
.hero .eyebrow { color: var(--cyan); }
.hero h1 { color: #fff; margin-top: 0.9rem; max-width: 20ch; }
.hero__sub {
  font-size: clamp(1.1rem, 1rem + 0.7vw, 1.42rem);
  line-height: 1.45; color: #bcd3d1; margin-top: 0.85rem; max-width: 34ch;
}
.hero__facts {
  display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 1.7rem;
  list-style: none; padding: 0;
}
.hero__facts li {
  font-family: var(--mono); font-size: 0.775rem; letter-spacing: 0.04em;
  color: #d3e4e2; background: rgba(255, 255, 255, 0.07);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 999px; padding: 0.4rem 0.85rem;
}
.hero__actions { display: flex; flex-wrap: wrap; gap: 0.7rem; margin-top: 1.9rem; }
.hero__deadline {
  margin-top: 2.4rem; padding-top: 1.1rem;
  border-top: 1px solid rgba(255, 255, 255, 0.16);
  display: flex; flex-wrap: wrap; gap: 0.4rem 1.4rem;
  font-family: var(--mono); font-size: 0.8rem; color: #a9c3c1;
}
.hero__deadline b { color: var(--amber-lt); font-weight: 500; }

/* subpage head: same artwork, quieter */
.pagehead {
  position: relative; isolation: isolate; overflow: hidden;
  background: linear-gradient(102deg, var(--ink) 0%, #1d414a 62%, #235159 100%);
  color: #d8e6e4;
}
.pagehead::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  /* the plain url() is the fallback for browsers without image-set() */
  background-image: url("../../images/hero-waves.png");
  background-image: image-set(
    url("../../images/hero-waves.webp") type("image/webp"),
    url("../../images/hero-waves.png") type("image/png"));
  background-repeat: no-repeat;
  background-position: right top -3rem;
  background-size: auto 150%;
  opacity: 0.42;
}
.pagehead::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(94deg, rgba(15, 32, 39, 0.92) 0%, rgba(15, 32, 39, 0.6) 46%, rgba(15, 32, 39, 0) 92%);
}
.pagehead__inner { padding-block: clamp(40px, 6vw, 76px) clamp(34px, 5vw, 62px); }
.pagehead .eyebrow { color: var(--cyan); }
.pagehead h1 { color: #fff; margin-top: 0.7rem; font-size: clamp(1.85rem, 1.3rem + 2.4vw, 2.9rem); }
.pagehead p { color: #b8d0ce; margin-top: 0.8rem; max-width: 56ch; font-size: 1.06rem; }

/* ------------------------------------------------------------ buttons */
.btn {
  display: inline-flex; align-items: center; gap: 0.5rem;
  font-family: var(--mono); font-size: 0.815rem; font-weight: 500;
  letter-spacing: 0.06em; text-transform: uppercase;
  padding: 0.72rem 1.25rem; border-radius: 999px;
  background: var(--amber); color: #14262d; border: 1px solid var(--amber);
  text-decoration: none; cursor: pointer;
  transition: transform 140ms ease, background-color 140ms ease, border-color 140ms ease;
}
.btn:hover { background: var(--amber-lt); border-color: var(--amber-lt); text-decoration: none; transform: translateY(-1px); }
.btn--ghost { background: transparent; color: #e6f1ef; border-color: rgba(255, 255, 255, 0.34); }
.btn--ghost:hover { background: rgba(255, 255, 255, 0.09); border-color: rgba(255, 255, 255, 0.55); color: #fff; }
.btn--onlight { background: var(--teal); border-color: var(--teal); color: #fff; }
.btn--onlight:hover { background: var(--teal-deep); border-color: var(--teal-deep); }
.btn--pending {
  background: transparent; color: #a7c1bf;
  border: 1px dashed rgba(255, 255, 255, 0.35); cursor: not-allowed;
}
.btn--pending:hover { background: transparent; border-color: rgba(255, 255, 255, 0.35); transform: none; }
.btn__arrow { width: 0.8em; height: 0.8em; flex: none; }

/* -------------------------------------------------------------- cards */
.grid { display: grid; gap: clamp(14px, 1.6vw, 20px); }
.grid--people { grid-template-columns: repeat(auto-fill, minmax(232px, 1fr)); }
.grid--org    { grid-template-columns: repeat(auto-fill, minmax(215px, 1fr)); }
/* The committee is five people, so give them one clean row on wide screens.
   Add a sixth organizer and this wants revisiting. */
@media (min-width: 1040px) {
  .grid--org { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .grid--org .person__focus { font-size: 0.875rem; }
}
.grid--tiers  { grid-template-columns: repeat(auto-fill, minmax(258px, 1fr)); }
.grid--two    { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }

.card {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 1.1rem 1.15rem 1.25rem;
}

.person { display: flex; flex-direction: column; }
.person__photo {
  aspect-ratio: 1; width: 100%; object-fit: cover;
  border-radius: 8px; background: var(--ink-2);
  border: 1px solid var(--rule);
}
.person__name { margin-top: 0.85rem; }
/* Names link to personal pages. Keep the heading colour and mark the link with
   the underline alone, so a grid of people does not read as a wall of links.
   color: inherit picks up --heading, so this works on light and dark surfaces. */
.person__name a {
  color: inherit;
  text-decoration-color: var(--sea);
  text-underline-offset: 0.16em;
}
.person__name a:hover { text-decoration-thickness: 2px; text-decoration-color: var(--amber); }
.person__aff {
  font-family: var(--mono); font-size: 0.755rem; letter-spacing: 0.02em;
  color: var(--fg-dim); margin-top: 0.3rem;
}
.person__focus { font-size: 0.925rem; line-height: 1.55; margin-top: 0.55rem; margin-bottom: 0.75rem; }
/* keeps the status chip on the baseline of the card, whatever the bio length */
.person .chip { margin-top: auto; }
.person__role {
  font-family: var(--mono); font-size: 0.735rem; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--teal); margin-top: 0.35rem;
}
.section--dark .person__role { color: var(--cyan); }

.chip {
  display: inline-flex; align-items: center; gap: 0.35rem;
  font-family: var(--mono); font-size: 0.665rem; font-weight: 500;
  letter-spacing: 0.1em; text-transform: uppercase;
  padding: 0.2rem 0.5rem; border-radius: 4px;
  border: 1px solid var(--rule); color: var(--fg-dim);
  margin-top: 0.7rem; align-self: flex-start;
}
.chip--confirmed { background: var(--teal); border-color: var(--teal); color: #fff; }
.chip--tba { border-style: dashed; }
.chip::before {
  content: ""; width: 5px; height: 5px; border-radius: 50%;
  background: currentColor; opacity: 0.85;
}

/* ------------------------------------------------- coevolution loop */
/* The three themes are one feedback loop, not a numbered list: each edge
   carries the causal claim from the proposal, and the return edge closes
   the cycle. Built from borders so it holds its shape at any width. */
.loop {
  position: relative; padding-left: var(--loop-gutter);
  /* Shared by the connectors so the return bracket can align itself to the
     centres of the outer theme cards rather than to their corners. */
  --loop-edge-w: clamp(8.5rem, 11vw, 12rem);
  --loop-gutter: 44px;
  --loop-line: 1.5px;
  --head-across: 9px;   /* base of the arrowhead */
  --head-long: 7px;     /* apex to base */
}
.loop__nodes { display: grid; gap: 0; }

/* Every arrowhead below is a sized box clipped to a triangle, centred on its
   line by arithmetic on the line's own width. Sizing the box explicitly avoids
   percentage transforms resolving against a zero-content border box, which is
   what left the heads a pixel off centre. */

.loop__node {
  background: var(--surface); border: 1px solid var(--rule);
  border-radius: var(--radius); padding: 1.15rem 1.2rem 1.3rem;
  border-top: 3px solid var(--sea);
}
.loop__node--2 { border-top-color: var(--violet); }
.loop__node--3 { border-top-color: var(--amber); }
.loop__label {
  font-family: var(--mono); font-size: 0.7rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--fg-dim);
}
.loop__node h3 { margin-top: 0.5rem; }
.loop__node p { font-size: 0.945rem; line-height: 1.6; margin-top: 0.6rem; }

.loop__edge {
  display: grid; justify-items: center; align-content: center; gap: 0.45rem;
  padding-block: 0.85rem; text-align: center;
}
/* The arrowhead is a pseudo-element of the line, not a separate box, so the two
   cannot drift apart or differ in brightness however the grid is laid out.
   Vertical here, horizontal at the wide breakpoint below. */
.loop__edge-line {
  position: relative;
  width: var(--loop-line); height: 26px; align-self: center;
  background: var(--sea); opacity: 0.75;
}
/* head at the bottom of the vertical line, pointing down */
.loop__edge-line::after {
  content: ""; position: absolute; background: var(--sea);
  width: var(--head-across); height: var(--head-long);
  left: calc((var(--loop-line) - var(--head-across)) / 2);
  bottom: calc(-1 * var(--head-long));
  clip-path: polygon(0 0, 100% 0, 50% 100%);
}
.loop__edge-text {
  font-family: var(--mono); font-size: 0.715rem; line-height: 1.5;
  letter-spacing: 0.02em; color: var(--fg-dim); max-width: 26ch;
}

/* The return edge closes the cycle: a rail up the left gutter on narrow
   screens, a bracket under the row on wide ones. Its label is a sibling, not
   a child, because the draw-in animation clips the bracket's own box.

   The ends sit well inside the outer cards rather than level with their
   corners, so the rail's curves do not collide with the cards' own rounded
   corners, and it spans the full gutter so both ends meet the card edges. */
.loop__return {
  position: absolute; left: 0; top: 4.5rem; bottom: 4.5rem;
  width: var(--loop-gutter);
  border: var(--loop-line) solid var(--sea); border-right: 0;
  border-radius: 13px 0 0 13px; opacity: 0.7;
}
/* Head at the top-right of the rail, pointing right into Theme 1, which is the
   direction the return path actually arrives from. Anchored to the corner with a
   triangle rather than a rotated box, so it cannot drift off it. */
/* head at the right end of the rail's top border, pointing into Theme 1, its
   apex landing on the card edge */
.loop__return::after {
  content: ""; position: absolute; background: var(--sea);
  width: var(--head-long); height: var(--head-across);
  right: 0;
  top: calc((var(--loop-line) - var(--head-across)) / 2);
  clip-path: polygon(0 0, 100% 50%, 0 100%);
}
.loop__return-text {
  position: absolute; left: calc(var(--loop-gutter) / 2); top: 50%;
  transform: translate(-50%, -50%) rotate(180deg);
  writing-mode: vertical-rl;
  font-family: var(--mono); font-size: 0.685rem; letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--fg-dim); white-space: nowrap;
}

@media (min-width: 960px) {
  .loop { padding-left: 0; padding-bottom: 6rem; }
  .loop__nodes {
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr) auto minmax(0, 1fr);
    align-items: stretch;
  }
  .loop__edge {
    padding-block: 0; padding-inline: clamp(0.5rem, 0.9vw, 0.85rem);
    width: var(--loop-edge-w);
    grid-template-columns: minmax(0, 1fr);
    gap: 0.55rem; align-content: center; justify-items: stretch;
  }
  .loop__edge-line { width: 100%; height: var(--loop-line); }
  /* same head, turned to point along the horizontal line */
  .loop__edge-line::after {
    width: var(--head-long); height: var(--head-across);
    left: auto; bottom: auto;
    right: calc(-1 * var(--head-long));
    top: calc((var(--loop-line) - var(--head-across)) / 2);
    clip-path: polygon(0 0, 100% 50%, 0 100%);
  }
  .loop__edge-text { max-width: none; text-align: center; }
  /* The bracket's uprights land on the horizontal centres of the outer theme
     cards, not on their corners. Each column is one third of what remains after
     the two edge columns, so half a card is (100% - 2 * edge) / 6. */
  .loop__return {
    top: auto; bottom: 2.5rem; width: auto; height: 3.2rem;
    left: calc((100% - 2 * var(--loop-edge-w)) / 6);
    right: calc((100% - 2 * var(--loop-edge-w)) / 6);
    border: var(--loop-line) solid var(--sea); border-top: 0;
    border-radius: 0 0 12px 12px;
  }
  /* head on top of the left upright, pointing up into Theme 1 */
  .loop__return::after {
    width: var(--head-across); height: var(--head-long);
    right: auto; bottom: auto;
    left: calc((var(--loop-line) - var(--head-across)) / 2);
    top: calc(-1 * var(--head-long));
    clip-path: polygon(50% 0, 100% 100%, 0 100%);
  }
  .loop__return-text {
    writing-mode: horizontal-tb; left: 50%; top: auto; bottom: 0.45rem;
    transform: translateX(-50%) rotate(0deg);
  }
}

/* ------------------------------------------------------------- tables */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.table {
  width: 100%; border-collapse: collapse;
  font-family: var(--mono); font-size: 0.83rem;
}
.table caption {
  text-align: left; font-family: var(--mono); font-size: 0.755rem;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--fg-dim);
  padding-bottom: 0.7rem;
}
.table th, .table td {
  text-align: left; padding: 0.78rem 0.85rem;
  border-bottom: 1px solid var(--rule); vertical-align: top;
}
.table thead th {
  font-size: 0.7rem; font-weight: 600; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--fg-dim);
  border-bottom: 1.5px solid var(--rule); white-space: nowrap;
}
.table tbody th { font-weight: 500; color: var(--fg); }
/* time ranges must not break across the en-dash */
.table--times tbody th { white-space: nowrap; }
.table td:first-child, .table th:first-child { padding-left: 0; }
.table td:last-child, .table th:last-child { padding-right: 0; }
.table .num { white-space: nowrap; }
.table__date { color: var(--heading); font-weight: 500; white-space: nowrap; }
.table__flag {
  display: inline-flex; align-items: center; gap: 0.35rem;
  font-size: 0.68rem; letter-spacing: 0.1em; text-transform: uppercase;
  color: #a6572c;
}
.section--dark .table__flag { color: var(--amber-lt); }
.table__flag::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--amber);
}
.table tbody tr:last-child th, .table tbody tr:last-child td { border-bottom: 0; }
.table__note { font-family: var(--serif); font-size: 0.86rem; color: var(--fg-dim); line-height: 1.5; }

/* two-up person cards on phones: eight full-width portraits is a long scroll */
@media (max-width: 560px) {
  .grid--people, .grid--org { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
  .grid--people .card, .grid--org .card { padding: 0.8rem 0.85rem 0.95rem; }
  .person__name { font-size: 1rem; }
  .person__focus { font-size: 0.875rem; }
}

@media (max-width: 700px) {
  .table--stack thead { display: none; }
  .table--stack tr {
    display: block; padding-block: 0.85rem;
    border-bottom: 1px solid var(--rule);
  }
  .table--stack tr:last-child { border-bottom: 0; }
  .table--stack th, .table--stack td {
    display: grid; grid-template-columns: 5.2rem minmax(0, 1fr);
    gap: 0.75rem; padding: 0.2rem 0; border-bottom: 0;
  }
  .table--stack th[data-label]::before, .table--stack td[data-label]::before {
    content: attr(data-label);
    font-size: 0.66rem; letter-spacing: 0.1em; text-transform: uppercase;
    color: var(--fg-dim); padding-top: 0.15em;
  }
  .table--stack td:empty { display: none; }
}

/* ------------------------------------------------------------ callout */
.callout {
  border-left: 3px solid var(--amber);
  background: var(--surface);
  border-radius: 0 var(--radius) var(--radius) 0;
  padding: 1rem 1.15rem;
}
.callout--flat { background: transparent; border-left-color: var(--sea); }
.callout p { font-size: 0.955rem; }

/* ---------------------------------------------------------------- code
   Used for the LaTeX snippet in the call for papers. The block scrolls inside
   itself rather than widening the page, since template lines are long. */
code {
  font-family: var(--mono);
  font-size: 0.88em;
  background: rgba(86, 156, 157, 0.13);
  padding: 0.12em 0.34em;
  border-radius: 4px;
  overflow-wrap: break-word;
}
.code {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 0.95rem 1.05rem;
  margin-block: 1.05rem;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.code code {
  background: none; padding: 0; border-radius: 0;
  font-size: 0.83rem; line-height: 1.65;
  color: var(--fg); white-space: pre;
}

/* bullet list with square markers, used for submission topics */
.ticks { list-style: none; padding: 0; }
.ticks li { position: relative; padding-left: 1.35rem; }
.ticks li + li { margin-top: 0.5rem; }
.ticks li::before {
  content: ""; position: absolute; left: 0; top: 0.62em;
  width: 7px; height: 7px; border-radius: 2px; background: var(--sea);
}
.ticks--amber li::before { background: var(--amber); }

/* --------------------------------------------------------- references
   Hanging indent, so the author name starts each entry flush and the
   continuation lines sit under it, as in a printed bibliography. */
.refs { list-style: none; padding: 0; max-width: var(--measure); }
.refs li {
  font-size: 0.875rem; line-height: 1.5;
  padding-left: 1.7rem; text-indent: -1.7rem;
}
.refs li + li { margin-top: 0.55rem; }
.refs .refs__unlinked { color: var(--fg-dim); }

/* ---------------------------------------------------------- CTA strip */
.cta { text-align: center; }
.cta .wrap { display: grid; justify-items: center; gap: 0.9rem; }
.cta h2 { max-width: 26ch; }
.cta p { max-width: 52ch; }
.cta__actions { display: flex; flex-wrap: wrap; gap: 0.7rem; justify-content: center; margin-top: 0.5rem; }

/* -------------------------------------------------------- form embed */
/* The embedded Google Form paints no background of its own: both html and body
   in that document are transparent, and only its question cards are white. So
   the iframe's own background shows through as the form's backdrop, and setting
   it here tints the form to match the site instead of leaving a white slab.
   The form's interior cannot be styled from this page (cross-origin) — the card
   and accent colours come from the form's theme in Google Forms.

   Heights are set above the form's measured content height so the iframe never
   scrolls: 834-874px at desktop widths, 1040px at 326px wide. Deliberately not
   using scrolling="no", which would hide the submit button if the form ever
   grows past the frame. */
.formframe {
  border: 1px solid var(--rule); border-radius: var(--radius);
  background: var(--ground-sunk); overflow: hidden;
  max-width: 760px;
}
.formframe iframe {
  width: 100%; height: 1140px; border: 0; display: block;
  background: var(--ground-sunk);
  color-scheme: light;   /* keep the form light even if the OS asks for dark */
}
@media (min-width: 700px) { .formframe iframe { height: 940px; } }

/* ------------------------------------------------------------- tiers */
.tier { display: flex; flex-direction: column; border-top: 3px solid var(--rule); }
.tier--lead { border-top-color: var(--amber); }
.tier__amount {
  font-family: var(--mono); font-size: 1.02rem; font-weight: 600;
  letter-spacing: -0.01em; color: var(--heading); margin-top: 0.45rem;
}
.tier h3 { margin-top: 0.15rem; }
.tier ul { margin-top: 0.85rem; }
.tier .ticks li { font-size: 0.9rem; line-height: 1.5; }

/* ------------------------------------------------------------ footer */
.footer {
  background: var(--ink); color: #a9c2c0;
  padding-block: clamp(40px, 5vw, 64px) 1.8rem;
  font-size: 0.925rem;
}
.footer__grid {
  display: grid; gap: clamp(24px, 3vw, 40px);
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
}
.footer h2 { font-size: 1.05rem; color: #eef5f4; }
.footer .eyebrow { color: var(--sea); }
.footer a { color: #cfe1df; }
.footer a:hover { color: #fff; }
.footer__links { list-style: none; padding: 0; display: grid; gap: 0.45rem; margin-top: 0.85rem; }
.footer__links a { font-family: var(--mono); font-size: 0.815rem; text-decoration: none; }
.footer__links a:hover { text-decoration: underline; }
.footer__meta {
  margin-top: clamp(28px, 4vw, 46px); padding-top: 1.2rem;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  display: flex; flex-wrap: wrap; gap: 0.5rem 1.5rem; justify-content: space-between;
  font-family: var(--mono); font-size: 0.735rem; letter-spacing: 0.03em; color: #85a3a1;
}
.footer__blurb { max-width: 34ch; margin-top: 0.85rem; font-size: 0.93rem; line-height: 1.6; }

.skip-link {
  position: absolute; left: 50%; top: 0; transform: translate(-50%, -120%);
  z-index: 100; background: var(--amber); color: var(--ink);
  font-family: var(--mono); font-size: 0.78rem; padding: 0.6rem 1rem;
  border-radius: 0 0 8px 8px; text-decoration: none;
}
.skip-link:focus { transform: translate(-50%, 0); }

/* -------------------------------------------------- passphrase gate
   Used only by the locked build in docs/ (see tools/lock.mjs). Deliberately
   says nothing about the workshop beyond needing a passphrase. */
.gate-body {
  min-height: 100vh; min-height: 100dvh;
  display: grid; place-items: center; padding-block: clamp(2rem, 8vh, 5rem);
  position: relative; isolation: isolate; overflow: hidden;
  background: radial-gradient(125% 95% at 22% 8%, #235159 0%, #1a3a44 46%, var(--ink) 100%);
  color: #d5e2e0;
}
.gate-body::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background-image: url("../../images/hero-waves.png");
  background-image: image-set(
    url("../../images/hero-waves.webp") type("image/webp"),
    url("../../images/hero-waves.png") type("image/png"));
  background-repeat: no-repeat; background-position: center top -2rem;
  background-size: cover; opacity: 0.4;
}
.gate-body::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(180deg, rgba(15, 32, 39, 0.55) 0%, rgba(15, 32, 39, 0.9) 62%, var(--ink) 100%);
}
.gate { width: min(430px, 100% - (2 * var(--gutter))); }
.gate__card {
  display: grid; gap: 0.55rem;
  background: rgba(255, 255, 255, 0.055);
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 16px;
  padding: clamp(1.4rem, 4vw, 2.1rem);
  backdrop-filter: blur(10px);
}
.gate__mark { width: 34px; height: 34px; margin-bottom: 0.4rem; }
.gate__card .eyebrow { color: var(--cyan); }
.gate__title { font-size: clamp(1.3rem, 1.1rem + 1vw, 1.6rem); color: #f2f7f6; margin-top: 0.35rem; }
.gate__lede { font-size: 0.98rem; color: #b8d0ce; margin-bottom: 0.6rem; }
.gate__label {
  font-family: var(--mono); font-size: 0.7rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: #93aeae;
}
.gate__input {
  font-family: var(--mono); font-size: 1rem; width: 100%;
  padding: 0.7rem 0.85rem; border-radius: 9px;
  background: rgba(0, 0, 0, 0.28); color: #eef5f4;
  border: 1px solid rgba(255, 255, 255, 0.22);
}
.gate__input:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; border-color: var(--sea); }
.gate__submit { justify-content: center; margin-top: 0.55rem; }
.gate__msg {
  min-height: 1.5em; font-family: var(--mono); font-size: 0.755rem;
  line-height: 1.5; color: #93aeae; margin-top: 0.2rem;
}
.gate__msg[data-state="error"] { color: #f2a98d; }
.gate__msg[data-state="working"] { color: var(--cyan); }
.gate__card[aria-busy="true"] .gate__submit { opacity: 0.6; pointer-events: none; }

/* ------------------------------------------------------------- motion
   Every reveal is gated on .js, which an inline script in each page's head
   adds. Without JavaScript, or with reduced motion, nothing is ever hidden. */
.person__photo { transition: border-color 180ms ease; }
.person:hover .person__photo { border-color: var(--sea); }

@media (prefers-reduced-motion: no-preference) {
  .js .reveal { opacity: 0; transform: translateY(14px); }
  .js .reveal.is-in {
    opacity: 1; transform: none;
    transition: opacity 620ms cubic-bezier(0.22, 0.7, 0.25, 1) var(--d, 0ms),
                transform 620ms cubic-bezier(0.22, 0.7, 0.25, 1) var(--d, 0ms);
  }

  /* The connectors draw themselves once, then stay put. The line's length is
     animated rather than its scale, so the arrowhead travels to the end intact
     instead of being squashed along the way. */
  .js .loop__edge-line { height: 0; }
  .js .loop__edge-text,
  .js .loop__return, .js .loop__return-text { opacity: 0; }
  .js .loop.is-in .loop__edge-line {
    height: 26px;
    transition: height 620ms cubic-bezier(0.3, 0.7, 0.2, 1) 120ms;
  }
  .js .loop.is-in .loop__edge-text,
  .js .loop.is-in .loop__return,
  .js .loop.is-in .loop__return-text {
    opacity: 1;
    transition: opacity 700ms ease 420ms;
  }
  .js .loop.is-in .loop__return { opacity: 0.7; }
}
@media (min-width: 960px) and (prefers-reduced-motion: no-preference) {
  .js .loop__edge-line { height: 1.5px; width: 0; }
  .js .loop.is-in .loop__edge-line {
    width: 100%; height: 1.5px;
    transition: width 620ms cubic-bezier(0.3, 0.7, 0.2, 1) 120ms;
  }
}

@media print {
  .masthead, .nav-toggle, .cta__actions, .hero__actions { display: none !important; }
  body { background: #fff; color: #000; }
  .section--dark, .hero, .pagehead, .footer { background: #fff !important; color: #000 !important; }
  .section--dark h1, .section--dark h2, .hero h1, .pagehead h1 { color: #000 !important; }
  .hero::before, .hero::after, .pagehead::before, .pagehead::after { display: none; }
}
