  @font-face {
    font-family: 'Libre Baskerville';
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url('../fonts/LibreBaskerville.woff2') format('woff2');
  }
:root {
    --ground: #fdfcfa;
    --ground-raised: #f5f1e5;
    --ink: #14130f;
    --ink-soft: #55503f;
    --ink-faint: #8d876e;
    --red: #d81e05;
    --blue: #0060a9;
    --yellow: #ffcc00;
    --gold: #8a6410;
    --line: #14130f;
    --line-soft: #d8d0b3;
    --code-bg: #efe9d8;
    /* Publication thumbnails: a faint warm desaturation (sepia+grayscale)
       so photographic figures read as archival plates on the parchment
       ground rather than clashing with the flat Bauhaus primaries — a
       restrained nod to worn stone/limestone rather than a full duotone. */
    --thumb-filter: grayscale(12%) sepia(8%) contrast(1.04) saturate(0.92);
  }
  @media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
      --ground: #16150f;
      --ground-raised: #211f16;
      --ink: #f3efe0;
      --ink-soft: #b3ac93;
      --ink-faint: #756e57;
      --red: #ff5a3c;
      --blue: #4fa8e8;
      --yellow: #ffd94d;
      --gold: #e8b93f;
      --line: #f3efe0;
      --line-soft: #3a3626;
      --code-bg: #211f16;
      /* Dimmed and slightly desaturated so bright figures don't glare
         against the dark ground — same archival-plate intent as light
         mode, tuned for a dark surround instead of parchment. */
      --thumb-filter: grayscale(18%) brightness(0.82) contrast(1.1) saturate(0.85);
    }
  }
  :root[data-theme="dark"] {
    --ground: #16150f;
    --ground-raised: #211f16;
    --ink: #f3efe0;
    --ink-soft: #b3ac93;
    --ink-faint: #756e57;
    --red: #ff5a3c;
    --blue: #4fa8e8;
    --yellow: #ffd94d;
    --gold: #e8b93f;
    --line: #f3efe0;
    --line-soft: #3a3626;
    --code-bg: #211f16;
    --thumb-filter: grayscale(18%) brightness(0.82) contrast(1.1) saturate(0.85);
  }

  * { box-sizing: border-box; }
  html, body { margin: 0; padding: 0; }
  body {
    background: var(--ground);
    color: var(--ink);
    font-family: Georgia, "Iowan Old Style", "Palatino Linotype", "Times New Roman", serif;
    font-size: 16px;
    line-height: 1.55;
    -webkit-font-smoothing: antialiased;
  }
  a { color: var(--blue); }
  a:focus-visible, button:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; }

  .label {
    font-family: "Century Gothic", "Avenir Next", "Futura", ui-sans-serif, system-ui, sans-serif;
    text-transform: uppercase;
    letter-spacing: 0.14em;
    font-size: 11px;
    font-weight: 600;
  }

  .page { max-width: 960px; margin: 0 auto; padding: 0 24px 56px; }

  /* ---------- Bauhaus/Lichtenstein emblem: triangle + circle + square ---------- */
  .emblem { display: inline-flex; align-items: flex-end; gap: 3px; vertical-align: middle; }
  .emblem svg { display: block; }

  /* ---------- Header ---------- */
  header.site {
    border-top: 3px solid var(--ink);
    padding: 18px 0 0;
    position: relative;
  }
  .brand-row {
    display: flex; flex-direction: column; align-items: center; gap: 5px;
    text-align: center; padding-bottom: 14px;
  }

  /* ---------- Theme toggle ---------- */
  .theme-toggle {
    position: absolute; top: 2px; right: 0;
    display: flex; border: 1.5px solid var(--ink);
  }
  .theme-toggle button {
    appearance: none; background: var(--ground); border: none;
    border-right: 1.5px solid var(--ink); cursor: pointer;
    width: 34px; height: 34px;
    display: flex; align-items: center; justify-content: center;
    color: var(--ink-soft); padding: 0;
  }
  .theme-toggle button:last-child { border-right: none; }
  .theme-toggle button svg { width: 15px; height: 15px; display: block; }
  .theme-toggle button[aria-pressed="true"] { background: var(--ink); color: var(--ground); }
  .theme-toggle button[aria-pressed="true"] svg { stroke: var(--ground); fill: var(--ground); }
  .theme-toggle button:not([aria-pressed="true"]) svg { stroke: var(--ink-soft); fill: none; }
  .theme-toggle button:hover:not([aria-pressed="true"]) { background: var(--ground-raised); }
  .brand-name {
    font-family: 'Libre Baskerville', Georgia, "Times New Roman", serif;
    font-size: 30px;
    letter-spacing: 0.08em;
    font-variant: small-caps;
    font-weight: 700;
    text-decoration: none; color: inherit; cursor: pointer;
  }
  .brand-name:hover, .brand-name:focus, .brand-name:active {
    text-decoration: none; color: inherit;
  }
  .brand-sub {
    color: var(--ink-soft);
    font-family: "Century Gothic", "Avenir Next", ui-sans-serif, system-ui, sans-serif;
    font-size: 12.5px;
    letter-spacing: 0.16em;
    text-transform: uppercase;
  }
  nav.primary {
    display: flex; justify-content: center; flex-wrap: wrap;
    border-top: 1px solid var(--line-soft);
    border-bottom: 2px solid var(--ink);
    margin-bottom: 6px;
    position: sticky; top: 0; z-index: 50;
    background: var(--ground);
  }
  .profile, section.block {
    /* Kept in sync with the nav-click scroll offset in the inline script:
       nav height minus its own border-bottom width (2px) minus a 1px
       safety margin, so a section's top border coincides with nav's
       bottom border instead of stacking into a doubled line. */
    scroll-margin-top: calc(var(--nav-height, 54px) - 3px);
  }
  nav.primary a {
    font-family: "Century Gothic", "Avenir Next", ui-sans-serif, system-ui, sans-serif;
    text-decoration: none;
    color: var(--ink);
    text-transform: uppercase;
    letter-spacing: 0.12em;
    font-size: 12.5px;
    font-weight: 600;
    padding: 10px 18px;
    border: 1px solid var(--line-soft);
    margin: -1px 0 0 -1px;
    position: relative;
    transition: background-color 0.15s ease, box-shadow 0.15s ease;
  }
  /* Every link carries a full 1px border, pulled up-and-left by 1px
     (margin: -1px 0 0 -1px) so it overlaps the previous same-row sibling's
     right edge *and* the row above's bottom edge — the standard
     border-collapse-via-negative-margin trick. This is what makes internal
     dividers a clean 1px (not two 1px borders sitting side by side = 2px)
     AND gives wrapped rows a line between them, regardless of where the
     wrap happens to fall or how many items end up per row. Don't go back
     to border-right + :first-child border-left — that's what caused the
     missing edges in the first place. */
  nav.primary a:hover {
    background-color: color-mix(in srgb, var(--gold) 14%, transparent);
    box-shadow: inset 0 0 18px color-mix(in srgb, var(--gold) 35%, transparent);
  }
  nav.primary a:active {
    background-color: color-mix(in srgb, var(--gold) 30%, transparent);
    box-shadow: inset 0 0 10px color-mix(in srgb, var(--gold) 55%, transparent);
  }
  nav.primary a[aria-current="page"] { color: var(--gold); }
  nav.primary a[aria-current="page"]::after {
    content: ""; position: absolute; left: 18px; right: 18px; bottom: 6px; height: 3px;
    background: var(--gold);
  }
  /* Positioned by JS (see the nav-row-dividers IIFE): a full-bleed line,
     edge-to-edge like the nav's own border-top/border-bottom, at each
     boundary between wrapped rows. Per-item borders alone can't do this —
     justify-content:center leaves gaps at each row's ends, so there's no
     continuous border there to collapse against. */
  .nav-row-divider { position: absolute; left: 0; right: 0; height: 0; border-top: 1px solid var(--line-soft); pointer-events: none; }

  /* ---------- Pediment divider ---------- */
  /* ---------- Profile (photo / name / affiliation + biography) ---------- */
  .profile { padding: 30px 0; }
  .profile-grid { display: grid; grid-template-columns: 250px 1fr; gap: 32px; align-items: start; }
  .profile-left { position: relative; top: 2px; }
  @media (max-width: 720px) {
    .profile-grid { grid-template-columns: 1fr; }
    .profile-grid > div:first-child { text-align: center; }
    .profile-links { justify-content: center; }
  }

  .avatar {
    width: 100%; max-width: 220px; aspect-ratio: 1 / 1; border-radius: 50%;
    border: 1px solid var(--ink);
    background: var(--ground-raised);
    margin: 0 auto 12px; position: relative; overflow: hidden;
  }
  .avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }

  .profile-name { font-family: 'Libre Baskerville', Georgia, "Times New Roman", serif; font-size: 21px; margin: 0 0 4px; font-weight: 700; letter-spacing: 0.01em; }
  .profile-title { color: var(--ink-soft); font-size: 13px; margin: 0 0 2px; }
  .profile-affil { color: var(--ink-soft); font-size: 13px; margin: 0 0 2px; }
  .profile-affil:last-of-type { margin: 0 0 12px; }
  @media (max-width: 720px) {
    /* The name/title golden-ratio pairing (21px/13px) was tuned for the
       desktop layout, where the title sits in a left-aligned paragraph of
       running text below it. Centered and alone on narrow screens, that
       same gap reads as a bigger, more awkward jump — size the title up
       a bit here rather than touching the desktop ratio. Placed *after*
       the base .profile-title/.profile-affil rules above (same specificity,
       so source order decides) — putting a same-specificity mobile
       override earlier in the file, like the first attempt at this did,
       loses to the later base rule regardless of the media query matching. */
    .profile-title, .profile-affil { font-size: 14.5px; }
  }
  .profile-links {
    list-style: none; margin: 0; padding: 12px 0 0; border-top: 1px solid var(--line-soft);
    display: flex; flex-direction: row; gap: 12px;
  }
  .profile-links a {
    display: flex; align-items: center; justify-content: center;
    width: 30px; height: 30px; color: var(--ink-soft);
    border: 1.5px solid var(--line-soft); border-radius: 50%;
  }
  .profile-links a svg { width: 15px; height: 15px; display: block; }
  .profile-links a:hover { color: var(--blue); border-color: var(--blue); }
  .cv-icon {
    width: 26px; height: 34px; border-radius: 50%;
    font-family: "Century Gothic", ui-sans-serif, sans-serif;
    font-size: 10px; letter-spacing: -0.03em; font-weight: 700;
    text-decoration: none;
  }
  .visually-hidden {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip: rect(0 0 0 0); white-space: nowrap;
  }

  .bio { position: relative; top: -2px; }
  .bio p { margin: 0 0 10px; color: var(--ink); line-height: 1.68; }
  .bio-name { font-family: 'Libre Baskerville', Georgia, "Times New Roman", serif; font-weight: 400; }

  .news-list {
    list-style: none; margin: 14px 0 0; padding: 10px 0 0; border-top: 1px solid var(--line-soft);
    display: flex; flex-direction: column; gap: 5px; font-size: 14px; color: var(--ink-soft); line-height: 1.5;
  }
  .news-date {
    font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; color: var(--ink-faint);
    margin-right: 8px;
  }

  /* ---- News popover (speech-bubble hint) ---- */
  .news-popover { position: relative; display: inline-block; vertical-align: -2px; }
  .news-popover-trigger {
    cursor: help; margin-left: 4px;
    display: inline-flex; align-items: center;
    opacity: 0.75; transition: opacity 0.15s ease;
  }
  .news-popover-trigger svg { display: block; }
  .news-popover:hover .news-popover-trigger,
  .news-popover:focus-within .news-popover-trigger { opacity: 1; }
  .news-popover-box {
    display: none;
    position: absolute; top: 100%; left: 0;
    padding-top: 10px;               /* invisible bridge — keeps hover unbroken between trigger and box */
    width: max-content; max-width: min(380px, 80vw);
    z-index: 40;
  }
  .news-popover:hover .news-popover-box,
  .news-popover:focus-within .news-popover-box,
  .news-popover-box:hover { display: block; }
  .popover-inner {
    position: relative;
    background: var(--ground-raised);
    border: 1.5px solid var(--ink);
    border-top: 3px solid var(--gold);   /* architrave line — a nod to the Greek entablature */
    padding: 12px 18px 16px;
    font-family: Georgia, "Iowan Old Style", "Palatino Linotype", "Times New Roman", serif;
    font-size: 13px; line-height: 1.62; color: var(--ink);
  }
  .popover-inner p { margin: 0 0 10px; }
  .popover-inner p:last-child { margin-bottom: 0; }
  .popover-inner p.popover-date {
    font-weight: 400 !important; font-size: 12.5px;
    letter-spacing: 0.03em; color: var(--ink-faint);
    margin-bottom: 2px;
  }
  .popover-inner p.popover-headline { font-weight: 700 !important; }
  .popover-inner p:not(.popover-headline):not(.popover-foot) { font-weight: 400 !important; }
  .popover-foot {
    margin-top: 12px; padding-top: 8px;
    border-top: 1px solid var(--line-soft);
    font-family: Georgia, "Iowan Old Style", "Palatino Linotype", "Times New Roman", serif;
    font-style: italic; font-size: 12.5px;
    color: var(--ink-faint); text-align: right;
  }
  .bio p:last-of-type { margin-bottom: 0; }
  .topic-filter { list-style: none; display: flex; flex-wrap: wrap; gap: 4px; margin: 0 0 10px; padding: 0; }
  .topic-filter li a {
    display: flex; align-items: center; gap: 5px; text-decoration: none;
    font-family: "Century Gothic", ui-sans-serif, sans-serif;
    font-size: 11px; letter-spacing: 0.05em; text-transform: uppercase;
    border: 1.5px solid var(--line-strong); color: var(--ink-soft); padding: 4px 8px;
    position: relative;
  }
  .topic-filter li a.active { border-color: var(--gold); color: var(--gold); }
  .topic-filter li a.active::after {
    content: ""; position: absolute; left: 8px; right: 8px; bottom: -5px; height: 3px;
    background: var(--gold);
  }
  .topic-filter li a:hover { border-color: var(--blue); color: var(--blue); }
  @media (max-width: 720px) {
    /* On mobile the filter pills wrap to several rows with no room to
       add row-gap (can't push rows apart without breaking the wrap
       count), so the active underline sitting 5px below the pill reads
       as floating too far from it. Pull it in closer here only. */
    .topic-filter li a.active::after { bottom: -2px; }
  }
  .filter-count {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 16px; padding: 1px 5px; border-radius: 999px;
    background: var(--ground-raised); color: var(--ink-soft);
    font-size: 10px; letter-spacing: normal;
  }
  .topic-filter li a.active .filter-count { color: var(--gold); }
  .topic-filter li a:hover .filter-count { color: var(--blue); }

  .filter-expand {
    display: flex; align-items: center; justify-content: center;
    appearance: none; cursor: pointer; background: none;
    width: 26px; height: 26px; padding: 0; line-height: 1;
    border: 1.5px solid var(--line-strong); color: var(--ink-soft);
    font-size: 14px; font-weight: 600;
    position: relative; top: 0px;
  }
  .filter-expand:hover { border-color: var(--blue); color: var(--blue); }
  .filter-expand[aria-expanded="true"] { border-color: var(--gold); color: var(--gold); }

  .filter-accordion {
    display: flex; flex-wrap: nowrap; gap: 20px;
    margin: 11px 0 4px; padding-top: 12px;
    border-top: 1px dashed var(--line-soft);
  }
  .filter-accordion[hidden] { display: none; }
  .filter-accordion-group { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; }
  .filter-accordion-label {
    font-family: "Century Gothic", ui-sans-serif, sans-serif;
    font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--ink-faint); min-width: 42px;
  }
  .filter-accordion-label--venue { min-width: 52px; }
  .filter-select {
    font-family: "Century Gothic", ui-sans-serif, sans-serif;
    font-size: 12px; color: var(--ink-soft);
    border: 1.5px solid var(--line-strong); background: var(--ground);
    padding: 4px 8px;
  }
  .filter-select:hover { border-color: var(--blue); }

  .show-all-btn {
    display: block; margin: 16px auto 0; appearance: none; cursor: pointer;
    background: none; border: 1.5px solid var(--ink); color: var(--ink);
    font-family: "Century Gothic", ui-sans-serif, sans-serif;
    font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; font-weight: 600;
    padding: 8px 18px;
  }
  .show-all-btn:hover { border-color: var(--blue); color: var(--blue); }
  .show-all-btn[hidden] { display: none; }
  .show-all-btn--sm {
    font-size: 9px; padding: 5px 12px; margin-top: 12px;
  }

  #teaching-courses.collapsed .course-card:nth-child(n+3) { display: none; }

  .pub-topics { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 0 auto; }
  .pub-topic {
    display: inline-block; appearance: none; cursor: pointer;
    font-family: "Century Gothic", ui-sans-serif, sans-serif;
    font-size: 10px; letter-spacing: 0.05em; text-transform: uppercase;
    background: none; color: var(--ink-faint); border: 1px solid var(--line-soft); padding: 2px 7px;
  }
  .pub-topic:hover { border-color: var(--blue); color: var(--blue); }

  /* ---------- Sections ---------- */
  section.block { padding: 36px 0; border-top: 2px solid var(--ink); }
  .section-head {
    display: flex; align-items: flex-start; justify-content: space-between; gap: 20px;
    margin-bottom: 14px; flex-wrap: wrap;
  }
  #about .section-head { margin-bottom: 0; }
  @media (max-width: 720px) {
    /* When the title and .note wrap onto separate lines, the 20px gap
       (meant for side-by-side spacing) reads as a big vertical gap
       between the title row and the note row — tighten it here. */
    .section-head { gap: 4px 20px; }
    /* Publications specifically: the eyebrow ("Research") and the badge
       ("Last updated...") are meant to read as a matched pair at the same
       height, but as two wrapped flex items (eyebrow+h2 as one block,
       the whole .note as another) they land many lines apart once
       wrapped. display:contents on the two wrapper divs lets their
       children join a shared grid directly, so eyebrow/badge can share
       row 1 and h2/note-sub can share row 2 — without touching the
       desktop layout (which still uses those two divs normally). */
    #publications .section-head {
      display: grid; grid-template-columns: 1fr auto; column-gap: 16px; row-gap: 2px;
    }
    #publications .section-head > div:first-child,
    #publications .section-head .note { display: contents; }
    #publications .section-head .eyebrow { grid-column: 1; grid-row: 1; margin-bottom: 0; }
    #publications .section-head h2 { grid-column: 1 / -1; grid-row: 2; }
    #publications .updated-badge { grid-column: 2; grid-row: 1; justify-self: end; }
    #publications .note-sub {
      /* Its own row below "Publications" (not sharing row 2 with it) —
         squeezed into column 2 alongside the h2, this wrapped awkwardly
         on narrow screens since there wasn't enough room for either. */
      grid-column: 1 / -1; grid-row: 3; justify-self: end; text-align: right;
      color: var(--ink-soft); font-size: 13px; max-width: 36ch;
    }
  }
  .section-head .eyebrow { color: var(--ink-faint); margin-bottom: 4px; display: block; }
  .section-head h2 { font-size: 26px; font-weight: 400; margin: 0; letter-spacing: 0.01em; }
  .section-head .note {
    color: var(--ink-soft); font-size: 13px; max-width: 36ch; text-align: right;
    margin-left: auto;   /* keeps it pinned to the right edge even when it wraps onto
                             its own flex line — "justify-content: space-between" gives up
                             and left-aligns a lone item on a wrapped line otherwise */
  }
  /* Teaching's note is a longer single sentence than other sections' — widen
     just here instead of shrinking the wording to fit the default 36ch. */
  #teaching .section-head .note { max-width: 56ch; }
  #blog .section-head .note, #blog-note { max-width: 30ch; }

  .cols { display: grid; gap: 28px; }
  .cols > * { min-width: 0; }   /* grid items default to min-width:auto — without this, a wide
                                   overflow-x:auto child (e.g. .math-demo .source) forces the
                                   whole track (and the page) wider instead of scrolling internally */
  .cols.two { grid-template-columns: 1fr 1fr; }
  .cols.blog { grid-template-columns: 210px 1fr; }
  @media (max-width: 720px) {
    .cols.two, .cols.blog { grid-template-columns: 1fr; }
  }

  /* ---- Publications ---- */
  .pub-legend { color: var(--ink-faint); font-size: 12px; }
  .pub-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
  .pub-item {
    display: grid; grid-template-columns: 160px 1fr; gap: 20px;
    padding: 18px 0; border-top: 1px solid var(--line-soft); align-items: start;
  }
  .pub-item:first-child, .pub-item.pub-item--first-visible { border-top: none; }
  .pub-thumb {
    /* 16:9, explicit integer height rather than aspect-ratio — width stays
       fixed at each breakpoint (160px desktop, 344px mobile below), and
       160*9/16 lands on an exact integer (90) but 344*9/16 doesn't
       (193.5), so both are hand-set to their nearest integer instead of
       left to aspect-ratio's fractional math. */
    width: 160px; height: 90px; background: var(--ground-raised);
    border: 1px solid var(--line-soft);
    /* Empty-placeholder X, same color/weight as the border, so an
       unfilled thumbnail doesn't read as a broken/missing image. Once a
       real thumbnail is added (an <img> filling the box), it paints over
       this and hides it automatically — no modifier class needed. */
    background-image:
      linear-gradient(to bottom right, transparent calc(50% - 0.5px), var(--line-soft) calc(50% - 0.5px), var(--line-soft) calc(50% + 0.5px), transparent calc(50% + 0.5px)),
      linear-gradient(to top right, transparent calc(50% - 0.5px), var(--line-soft) calc(50% - 0.5px), var(--line-soft) calc(50% + 0.5px), transparent calc(50% + 0.5px));
  }
  .pub-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; filter: var(--thumb-filter); }
  .pub-title { font-size: 16px; font-weight: 700; margin: 0 0 6px; line-height: 1.3; }
  .pub-item[data-featured="true"] .pub-title::before { content: "★ "; color: var(--gold); }
  .pub-meta { color: var(--ink-soft); font-size: 13px; line-height: 1.15; margin: 0; }
  .pub-venue { color: var(--ink-soft); font-size: 13px; line-height: 1.3; margin: 6px 0 0; }
  .pub-honor { color: var(--gold); font-weight: 600; margin-left: 4px; }
  .pub-footer { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 12px; }
  .pub-links { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; }
  .pub-btn {
    display: inline-flex; align-items: center; text-decoration: none;
    font-family: "Century Gothic", ui-sans-serif, sans-serif;
    font-size: 10px; letter-spacing: 0.05em; text-transform: uppercase; font-weight: 600;
    color: var(--ink-soft); background: var(--ground-raised);
    border: none; border-radius: 999px; padding: 3px 10px;
  }
  .pub-btn:hover { color: var(--blue); }
  @media (max-width: 560px) {
    .pub-item { grid-template-columns: 1fr; }
    .pub-thumb { width: 344px; height: 194px; max-width: 100%; margin: 0 auto; }
    .pub-thumb:empty, .pub-thumb:not(:has(img[src])) {
      display: none !important;
    }
  }
  .updated-badge {
    display: inline-flex; align-items: center; gap: 6px;
    font-family: "Century Gothic", ui-sans-serif, sans-serif;
    font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase;
    color: var(--gold);
  }
  .updated-badge::before {
    content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--gold);
  }

  /* ---- Teaching ---- */
  .course-card {
    border: 2px solid var(--ink); padding: 15px;
    display: flex; flex-direction: column; gap: 7px; background: var(--ground-raised);
    border-top: 5px solid var(--yellow);
  }
  .course-card .term { color: var(--ink-faint); }
  .course-card h3 { margin: 0; font-size: 20px; font-weight: 400; }
  .course-card p { margin: 0; color: var(--ink-soft); font-size: 14px; }
  .course-meta { display: flex; gap: 16px; font-size: 13px; color: var(--ink-soft); font-style: italic; }

  /* ---- Blog ---- */
  .cols.blog { transition: grid-template-columns 0.2s ease; }
  .cols.blog.sidebar-collapsed { grid-template-columns: 1fr; }
  .cols.blog.sidebar-collapsed aside { display: none; }

  .cat-panel-head {
    display: flex; align-items: center; justify-content: space-between;
    padding-bottom: 8px; margin-bottom: 6px; border-bottom: 1px solid var(--line-soft);
  }
  .cat-panel-title {
    font-family: "Century Gothic", ui-sans-serif, sans-serif;
    font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase; font-weight: 600;
    color: var(--ink-faint);
  }

  .cat-expand-wrapper { margin-bottom: 14px; }
  .cat-expand-wrapper[hidden] { display: none; }
  .cat-expand-btn {
    cursor: pointer; display: inline-flex; align-items: center; gap: 5px;
  }
  .cat-expand-btn .btn-icon {
    font-size: 11px; line-height: 1; position: relative; top: -1px;
  }

  .cat-list { list-style: none; margin: 0; padding: 0; }
  .cat-list li { border-top: 1px solid var(--line-soft); }
  .cat-list li:first-child { border-top: none; }
  .cat-list a {
    display: flex; justify-content: space-between; text-decoration: none; color: var(--ink);
    padding: 8px 0; font-size: 14px;
  }
  .cat-list a.active { color: var(--gold); }
  .cat-list .count { color: var(--ink-faint); font-family: ui-monospace, monospace; font-size: 13px; margin-right: 8px; }

  .post-card { padding: 14px 0; border-top: 1px solid var(--line-soft); }
  .post-card:first-child { border-top: none; padding-top: 0; }
  .post-card .eyebrow { color: var(--blue); margin-top: 4px; margin-bottom: 5px; display: block; }
  .post-card h3 { margin: 0 0 5px; font-size: 20px; font-weight: 400; }
  .post-card h3 a { color: var(--ink); text-decoration: none; }
  .post-card h3 a:hover { color: var(--blue); }
  .post-card p { margin: 0 0 6px; color: var(--ink-soft); }
  .post-card .meta { font-size: 13px; color: var(--ink-faint); font-style: italic; }

  /* blog.html's lone section sits directly under nav with no JS scroll
     compensation (unlike index.html's sections, which only coincide with
     nav's border-bottom when scrolled to via the nav-click handler) — so
     the section's own border-top plus nav's 6px margin-bottom would stack
     into a doubled line with a gap. Drop the border and pull the section
     up by that same 6px so nav's border-bottom reads as the one divider,
     at the same effective distance (36px padding + 6px) as before. */
  #blog-page { border-top: none; margin-top: -6px; padding-top: 42px; }

  /* ---- Blog: single-post view + empty-state (blog.html) ---- */
  .post-empty { color: var(--ink-faint); font-style: italic; padding: 8px 0; }
  .post-body { padding-top: 4px; }
  .post-body .eyebrow { color: var(--blue); margin-bottom: 6px; display: block; }
  .post-body .meta { font-size: 13px; color: var(--ink-faint); font-style: italic; display: block; margin: 0 0 18px; }
  .post-body h1, .post-body h2, .post-body h3 { font-weight: 400; margin: 28px 0 10px; }
  .post-body h2 { font-size: 22px; }
  .post-body h3 { font-size: 19px; }
  .post-body p { margin: 0 0 14px; }
  .post-body ul, .post-body ol { margin: 0 0 14px; padding-left: 22px; }
  .post-body li { margin-bottom: 4px; }
  .post-body code { background: var(--code-bg); padding: 1px 5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 0.9em; }
  .post-body pre { background: var(--code-bg); padding: 10px 12px; overflow-x: auto; }
  .post-body pre code { padding: 0; }
  .post-body blockquote { margin: 0 0 14px; padding-left: 14px; border-left: 3px solid var(--line-soft); color: var(--ink-soft); }
  .post-body .katex-display { overflow-x: auto; overflow-y: hidden; }
  .post-body .post-eyebrow { text-decoration: none; }

  /* End-of-article mark: a geometric dagger built from straight rects (not
     the typographic † glyph, which already means "co-corresponding author"
     in .pub-meta — reusing it here would misread as a footnote). Sits on
     its own centered line closing the post, distinct from the "Back to..."
     link underneath, the way a magazine end-mark precedes its own nav.
     (A solid gold square, QED-tombstone style, was tried as a
     less cross-like alternative but the dagger was preferred.) */
  .post-end-mark { text-align: center; margin: 26px 0 20px; }
  .post-end-mark svg { display: inline-block; }
  .post-back-btn {
    margin-left: 0 !important;
    margin-right: auto !important;
    display: inline-block;
    text-decoration: none;
  }

  /* ---- Math demo ---- */
  .math-demo {
    margin-top: 14px; border: 2px solid var(--ink); background: var(--ground-raised);
    padding: 15px 17px;
  }
  .math-demo .tag-row { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; }
  .math-demo .tag-row .label { color: var(--ink-faint); }
  .math-demo .lib-pill {
    font-family: ui-monospace, monospace; font-size: 11px; color: var(--blue);
    border: 1.5px solid var(--blue); padding: 2px 8px; border-radius: 2px;
  }
  .math-demo .source {
    font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 13.5px;
    background: var(--code-bg); padding: 8px 12px; color: var(--ink-soft);
    overflow-x: auto; margin-bottom: 10px; white-space: pre;
  }
  .math-demo .source .dollar { color: var(--gold); }
  .rendered { text-align: center; padding: 6px 0 4px; font-size: 20px; }
  .frac { display: inline-flex; flex-direction: column; vertical-align: middle; text-align: center; margin: 0 2px; }
  .frac .num { border-bottom: 1.4px solid var(--ink); padding: 0 4px 2px; }
  .frac .den { padding: 2px 4px 0; }
  .rendered .display-eq { font-size: 23px; margin-top: 10px; }
  .eq-num { color: var(--ink-faint); font-size: 13px; float: right; font-family: ui-monospace, monospace; }

  /* ---- About / Academic Services / Collaborators / Wity Works ---- */
  .about-bio { color: var(--ink-soft); font-size: 15px; max-width: 49ch; margin: 0; }
  .about-heading { font-size: 26px; font-weight: 400; letter-spacing: 0.01em; margin: 0 0 14px; color: var(--ink); }
  .about-block { margin-bottom: 30px; }
  .collab-block { padding-top: 22px; border-top: 1px solid var(--line-soft); margin-bottom: 30px; }
  .wity-block { padding-top: 22px; border-top: 1px solid var(--line-soft); }
  .wity-heading { font-size: 20px; font-weight: 400; letter-spacing: 0.01em; margin: 26px 0 10px; color: var(--ink); }
  .wity-heading:first-child { margin-top: 0; }
  .trivia-text { max-width: 68ch; line-height: 1.7; }
  .trivia-text a { color: var(--ink-soft); text-decoration: underline; text-underline-offset: 2px; }
  .collab-intro { color: var(--ink-soft); font-size: 15px; max-width: 68ch; margin: 0 0 14px; }
  .collab-row { font-size: 13px; color: var(--ink-soft); line-height: 1.7; margin: 0 0 4px; }
  .collab-row .collab-cat { color: var(--ink); margin-right: 6px; }
  .collab-row .collab-cat::after { content: ":"; }
  .collab-row a { color: var(--ink-soft); text-decoration: underline; text-underline-offset: 2px; }
  .collab-row a:hover { color: var(--blue); }

  /* ---------- Footer ---------- */
  footer {
    margin-top: 12px; padding-top: 20px;
    border-top: 1px solid var(--line-soft);
    font-size: 13px; color: var(--ink-soft);
  }
  .footer-cols { display: flex; justify-content: space-between; flex-wrap: wrap; gap: 20px; }
  footer .col h4 {
    font-family: "Century Gothic", ui-sans-serif, sans-serif;
    text-transform: uppercase; letter-spacing: 0.12em; font-size: 11px;
    color: var(--ink-faint); margin: 0 0 6px; font-weight: 600;
  }
  footer .col a { display: block; color: var(--ink-soft); text-decoration: none; margin-bottom: 4px; }
  footer .col a:hover { color: var(--blue); }
  .footer-bottom {
    margin-top: 28px; padding-top: 14px; padding-bottom: 24px;
    font-family: ui-monospace, "SF Mono", Menlo, monospace;
    font-size: 11px; letter-spacing: 0.04em; color: var(--ink-faint);
  }

  .annotate {
    margin-top: 10px; padding: 10px 12px; border-left: 4px solid var(--yellow);
    background: var(--ground-raised); color: var(--ink-soft); font-size: 13px;
    font-family: "Century Gothic", ui-sans-serif, sans-serif;
  }
