/* ============================================================================
   Homepage (front-page.php) - layout for Home.dc.html, ported from the design's
   inline styles into classes. Desktop-first (1240px), then stacked on mobile.
   ========================================================================== */

/* - Masthead + section rail ----------------------------------------------
   The logo sets the page the way a publication does: its own row, real
   size, centred. The rail beneath carries the sections. The masthead
   scrolls away with the page; only the rail is a candidate for sticking
   (see the sticky note at the end of this block). */
.masthead {
  max-width: var(--page-max);
  margin: 0 auto;
  display: flex;
  justify-content: center;
  padding: 20px 48px 18px;
}
.masthead-brand { display: inline-flex; text-decoration: none; }
.masthead .nav-actions { display: none; }
.masthead-brand img { display: block; height: 60px; width: auto; }

.home-nav {
  max-width: var(--page-max);
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 16px;
  padding: 0 48px;
  /* TEMPORARY (2026-09-03, masthead out pending logo sign-off): the rail
     is the whole header, so its divider sits beneath it rather than above,
     where it would draw a stray line along the top of the page. */
  border-bottom: 2px solid var(--color-divider);
  white-space: nowrap;
  flex-wrap: nowrap;
}
.nav-sections {
  display: flex; align-items: center; gap: 26px;
  justify-content: center;
  min-width: 0; overflow-x: auto;
  /* The sections sit optically centred: the actions column on the right
     is balanced by this column starting at the page gutter. */
  grid-column: 1 / -1; grid-row: 1;
  padding: 12px 0;
}
.nav-actions {
  display: flex; align-items: center; gap: 10px;
  grid-column: 2; grid-row: 1;
  justify-self: end;
  background: var(--color-bg);
  padding-left: 16px;
}
.nav-actions .btn { padding: 7px 15px; font-size: 13px; }

@media (max-width: 860px) {
  /* Below the point where a centred masthead earns its space, fall back to
     the conventional left lockup - logo left, Donate kept on the same row,
     sections beneath. Donate is the primary call to action and must not
     disappear on a phone. */
  .masthead {
    justify-content: space-between; align-items: center;
    padding: 14px 24px 12px;
  }
  .masthead-brand img { height: 40px; }
  .masthead .nav-actions { display: flex; }
  .home-nav { padding: 0 24px; }
  .nav-sections { justify-content: flex-start; gap: 20px; }
  /* TEMPORARY (2026-09-03): with the masthead out, the rail's own Donate is
     the only one, so it stays on the row (the sections scroll beneath it)
     and only Sign up gives way. Restore the two lines below with the
     masthead:
       .home-nav { grid-template-columns: 1fr; }
       .home-nav .nav-actions { display: none; } */
  .home-nav .nav-actions .btn-ghost { display: none; }
  /* Sign up is the softer ask and lives in the footer; on a narrow screen
     the space goes to Donate. */
  .masthead .nav-actions .btn-ghost { display: none; }
}

/* To pin the section rail while the masthead scrolls away, stick the
   HEADER with a negative offset equal to the masthead's height - a sticky
   child cannot escape a short parent, so sticking the rail alone does
   nothing. Enabling this also needs .pa-controls (Play Again) to move to
   top: 46px, or the rail covers its search box.
   .site-header { position: sticky; top: -98px; z-index: 60;
                  background: var(--color-bg); } */

/* Placeholder art (mirrors the design's monospace hatched placeholders). Real
   featured images replace these; the hatch only shows when no image exists. */
.ph {
  display: flex; align-items: center; justify-content: center;
  background: repeating-linear-gradient(45deg, var(--ph-tint, var(--color-neutral-200)) 0 12px, var(--color-surface) 12px 24px);
}
.ph > span {
  font-family: ui-monospace, monospace; font-size: 12px;
  background: var(--color-bg); border: 2px solid var(--color-divider); padding: 5px 10px;
}

/* - Hero - */
.hero {
  max-width: var(--page-max); margin: 0 auto;
  border-bottom: 2px solid var(--color-divider);
}
.hero-grid { display: grid; grid-template-columns: 1fr 320px; min-height: 480px; }
.hero-main { border-right: 2px solid var(--color-divider); position: relative; display: grid; }
/* All slides occupy the same grid cell, so the hero is always as tall as the
   TALLEST slide and never resizes when the carousel cycles (no layout shift).
   The inactive slide fades out via opacity/visibility, staying in layout and
   out of the tab/AX tree. */
.hero-slide {
  grid-area: 1 / 1;
  display: grid; grid-template-columns: 1.1fr 1fr; height: 100%;
  opacity: 0; visibility: hidden;
  transition: opacity 0.4s ease;
}
.hero-slide.is-active { opacity: 1; visibility: visible; }
@media (prefers-reduced-motion: reduce) {
  .hero-slide { transition: none; }
}
.hero-copy {
  padding: 56px 48px; display: flex; flex-direction: column;
  gap: 20px; justify-content: center;
}
.hero-copy .tag { align-self: flex-start; }
.hero-copy h2 {
  font-size: 56px; line-height: 1.02; letter-spacing: -0.02em; margin: 0;
  text-wrap: pretty;
}
.hero-copy.is-post h2 { font-size: 44px; line-height: 1.06; }
.hero-lede { font-size: 18px; line-height: 1.5; margin: 0; max-width: 47ch; text-wrap: pretty; }
.hero-when { font-size: 14px; display: flex; flex-direction: column; gap: 4px; }
.hero-when .muted { opacity: 0.65; }
.hero-ctas { display: flex; gap: 12px; flex-wrap: wrap; }
.hero-art {
  position: relative; overflow: hidden;
  border-left: 2px solid var(--color-divider);
  background: var(--color-surface);
  --ph-tint: var(--newmr-red-100);
}
.hero-art.tint-blue { --ph-tint: var(--newmr-blue-100); }
/* Foreground: the whole image, aspect preserved (no crop, no distortion). */
.hero-art-fg {
  position: relative; z-index: 1;
  width: 100%; height: 100%;
  object-fit: contain;
}
/* Backdrop: a blurred, zoomed copy of the same image fills the letterbox so
   the panel never shows bare bars. --art-bg is set inline by the template. */
.hero-art.has-img::before {
  content: ""; position: absolute; inset: 0; z-index: 0;
  background-image: var(--art-bg);
  background-size: cover; background-position: center;
  filter: blur(28px) saturate(1.15);
  transform: scale(1.2);
}

.hero-dots {
  position: absolute; left: 48px; bottom: 20px;
  display: flex; gap: 8px; align-items: center;
}
.hero-dot {
  width: 14px; height: 14px; border: 2px solid var(--color-text);
  background: transparent; cursor: pointer; padding: 0;
}
.hero-dot.is-active { background: var(--color-text); }

.hero-aside {
  padding: 32px; display: flex; flex-direction: column;
  gap: 16px; justify-content: center;
}
.eyebrow {
  font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase; opacity: 0.55;
}
.hero-aside .sponsor-slot {
  border: 2px solid var(--color-divider); aspect-ratio: 4 / 3;
  --ph-tint: var(--color-neutral-200);
}
.hero-aside .sponsor-slot img { width: 100%; height: 100%; object-fit: contain; padding: 12px; }
.hero-aside .sponsor-slot .sponsor-slot-name {
  font-family: inherit; font-size: 18px; font-weight: 600; letter-spacing: normal;
  text-transform: none; background: var(--color-bg); border: 2px solid var(--color-divider);
  padding: 10px 18px;
}
.hero-aside .sponsor-invite { background: var(--color-surface); }
.hero-aside .sponsor-invite > span {
  font-family: inherit; font-size: 14px; font-weight: 600;
  background: transparent; border: 2px dashed var(--color-divider); padding: 12px 20px;
  color: var(--color-text); opacity: 0.7;
}
.hero-aside p { font-size: 14px; line-height: 1.5; margin: 0; opacity: 0.75; }

/* - Section scaffolding - */
.section {
  max-width: var(--page-max); margin: 0 auto;
  border-bottom: 2px solid var(--color-divider);
}
.section-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 16px; padding: 40px 48px 24px; flex-wrap: wrap;
}
.section-head h2 { font-size: 32px; letter-spacing: -0.015em; margin: 0; }
.section-head .head-links { display: flex; gap: 20px; font-weight: 600; font-size: 14px; }
.section-head .head-links a.to-posts { color: var(--color-accent-700); }
.section-head .head-links a.to-videos { color: var(--newmr-blue-deep); }
.section-title { padding: 40px 48px 24px; }
.section-title h2 { font-size: 32px; letter-spacing: -0.015em; margin: 0; }

/* - 3-up grids (latest, topics) - */
.grid-3 {
  display: grid; grid-template-columns: repeat(3, 1fr);
  border-top: 2px solid var(--color-divider);
}
/* The courses toolbar is a .pa-controls bar, which carries its own
   border-bottom - stacked with the grid's border-top that reads as one 4px
   rule. The toolbar's is the one that belongs to the layout, so the grid
   yields. */
.course-grid { border-top: 0; }
/* Card grids carry a border-bottom on their last row of cells, and the section
   wrapper carries its own border-bottom - stacked, they render as a double
   line. Pull the grid down 2px so the last-row cell border coincides with the
   section border into a single rule (also covers partial last rows). */
.grid-3, .grid-4 { margin-bottom: -2px; }
.cell {
  padding: 28px 48px 32px;
  border-right: 2px solid var(--color-divider);
  border-bottom: 2px solid var(--color-divider);
  display: flex; flex-direction: column; gap: 10px;
  color: var(--color-text);
}
.cell:hover { background: var(--color-surface); }
/* The course archive filters cards in place by setting [hidden] on them, and
   .cell is a display:flex column - which beats the UA's [hidden]{display:none}
   on specificity, so without this rule the filter runs, sets the attribute,
   updates the count, and nothing moves. Same rule, same reason, as
   .pa-row[hidden], .pa-year[hidden] and .people-card[hidden]. */
.cell[hidden] { display: none; }
/* Card artwork. The aperture is fixed at 21:9 and the image is shown whole
   inside it over a blurred copy of itself - see newmr_modernist_thumb(), and
   .pa-thumb, which does the same thing.

   min-height:0 is load-bearing. .cell is a column flex container, so .thumb is
   a flex item, and a flex item's automatic minimum size is its CONTENT - which
   overrode aspect-ratio and let a tall image stretch its own cell, leaving the
   grids ragged. overflow:hidden keeps anything oversized inside the frame. */
.cell .thumb {
  position: relative; isolation: isolate; overflow: hidden; min-height: 0;
  aspect-ratio: 21 / 9; border: 2px solid var(--color-divider); --ph-tint: var(--newmr-red-100);
}
.cell .thumb.tint-blue { --ph-tint: var(--newmr-blue-100); }
/* Course cards: see newmr_modernist_course_card(). The artwork is 16:9 cover
   art, so the aperture is too - a 21:9 crop was cutting the title out of it. */
.cell .thumb.is-course { aspect-ratio: 16 / 9; }
/* Artwork present means the hatched placeholder is never wanted - and 9 of
   the 22 course covers are PNGs with transparency, so the blurred backdrop
   drawn from them is transparent too and the hatch reads straight through. */
.cell .thumb.has-img { background: var(--color-surface); }
.cell .thumb.has-img::before {
  content: ""; position: absolute; inset: 0; z-index: 0;
  background-image: var(--art-bg); background-size: cover; background-position: center;
  filter: blur(18px) saturate(1.15); transform: scale(1.2);
}
.cell .thumb img {
  position: relative; z-index: 1;
  width: 100%; height: 100%; object-fit: contain; display: block;
}
.cell .kicker {
  font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase;
  font-weight: 600; color: var(--color-accent-700);
}
/* "Free" beside the Course kicker. Reads as a badge rather than more
   kicker text, because a reader scanning the catalogue is looking for
   exactly this one distinction. */
.course-free {
  display: inline-block; margin-left: 6px; padding: 1px 6px;
  /* -deep, not the bright blue: 10px bold on the bright one is 4.25:1 and
     fails AA. The card's own hover is the feedback, so the badge holds still. */
  background: var(--newmr-blue-deep); color: var(--color-bg);
  font-size: 10px; letter-spacing: 0.08em; font-weight: 700;
  vertical-align: 1px;
}
.cell .kicker.blue { color: var(--newmr-blue-deep); }
.cell .cell-title {
  font-family: var(--font-heading); font-weight: 600; font-size: 21px;
  line-height: 1.2; text-wrap: pretty;
}
.cell .cell-excerpt { font-size: 14px; line-height: 1.5; opacity: 0.75; }
.cell .cell-date { font-size: 13px; opacity: 0.55; margin-top: auto; }

/* Topic cells */
.topics .cell { border-top: 3px solid var(--newmr-blue); }
.topics .cell .cell-title { font-weight: var(--font-heading-weight); font-size: 22px; letter-spacing: -0.01em; }
.topics .cell .more { font-weight: 600; font-size: 14px; color: var(--color-accent-700); margin-top: auto; }

/* - Ways to learn - */
.learn { display: grid; grid-template-columns: repeat(3, 1fr); }
.learn .cell {
  padding: 40px 48px; border-bottom: 0; gap: 10px;
}
.learn .cell:not(:last-child) { border-right: 2px solid var(--color-divider); }
.learn .cell .learn-title { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: 24px; }
.learn .cell .learn-body { font-size: 15px; line-height: 1.5; opacity: 0.8; }
.learn .cell .more { font-weight: 600; font-size: 14px; color: var(--color-accent-700); }

/* - Newsletter band - */
.newsletter { background: var(--color-accent); }
.newsletter-inner {
  max-width: var(--page-max); margin: 0 auto;
  padding: 64px 48px; display: flex; align-items: flex-end;
  justify-content: space-between; gap: 32px; flex-wrap: wrap;
}
.newsletter h2 {
  font-size: 48px; line-height: 1.02; letter-spacing: -0.02em; margin: 0;
  color: #fff; max-width: 18ch; text-wrap: pretty;
}
.newsletter .btn { background: #fff; color: var(--color-accent-700); font-weight: 600; white-space: nowrap; }
.newsletter .btn:hover { background: var(--color-neutral-100); }

/* - Footer - */
.site-footer { border-top: 2px solid var(--color-divider); }
.footer-inner { max-width: var(--page-max); margin: 0 auto; }
.footer-sponsors { padding: 32px 48px; border-bottom: 2px solid var(--color-divider); }
.sponsor-grid {
  /* Columns follow the actual sponsor count (--sponsor-cols, set by the
     template) so a short roster fills the row instead of leaving a gap;
     the media queries below reflow it on smaller screens. */
  display: grid; grid-template-columns: repeat(var(--sponsor-cols, 9), 1fr);
  border: 2px solid var(--color-divider); margin-top: 12px;
}
.sponsor-cell {
  display: flex; align-items: center; justify-content: center;
  padding: 16px 8px; border-right: 2px solid var(--color-divider);
  font-size: 13px; font-weight: 600; text-align: center;
  color: var(--color-text);
}
.sponsor-cell:last-child { border-right: 0; }
a.sponsor-cell:hover { background: var(--color-surface); }
/* Artwork is the cell's face wherever the row is at its full width; below
   that the cells are too narrow for a logo to read and the name takes over
   again (see the 1240px query in the responsive section). A sponsor with no
   artwork shows its name at every width, so a mixed roster still fills the
   row. The name stays in the markup either way - hidden here, read aloud
   from the img's alt. */
.sponsor-cell.has-logo { padding: 12px 8px; min-height: 96px; }
.sponsor-cell-logo {
  display: block; max-width: 100%; max-height: 72px;
  width: auto; height: auto; object-fit: contain;
}
.has-logo .sponsor-cell-name { display: none; }
.footer-body { padding: 32px 48px; display: grid; grid-template-columns: 1.4fr 1fr; gap: 48px; }
.footer-about { font-size: 14px; line-height: 1.55; margin: 0; max-width: 52ch; opacity: 0.8; }
.footer-about a { text-decoration: underline; }
.footer-links { display: grid; grid-template-columns: auto auto; gap: 32px; font-size: 14px; justify-content: start; align-content: start; }
.footer-links .col { display: flex; flex-direction: column; gap: 6px; align-items: flex-start; }
.footer-links a { white-space: nowrap; }
.footer-legal { padding: 16px 48px; border-top: 2px solid var(--color-divider); font-size: 13px; opacity: 0.6; }

/* ============================================================================
   Responsive - the design is desktop-first; collapse cleanly on smaller screens
   ========================================================================== */
/* Sponsor artwork needs a cell wide enough to read it. The page stops
   growing at --page-max (1240px), so that is also where the sponsor row
   stops growing: at or above it - a desktop monitor - the cells run the
   logos, and below it they fall back to names. */
@media (max-width: 1239px) {
  .sponsor-cell.has-logo { padding: 16px 8px; min-height: 0; }
  .sponsor-cell-logo { display: none; }
  .has-logo .sponsor-cell-name { display: block; }
}

@media (max-width: 960px) {
  :root { --page-pad: 24px; }
  .hero-grid { grid-template-columns: 1fr; }
  .hero-main { border-right: 0; }
  .hero-slide { grid-template-columns: 1fr; }
  .hero-art { display: none; }
  .hero-copy { padding: 40px 24px; gap: 16px; }
  .hero-copy h2 { font-size: 40px; }
  .hero-copy.is-post h2 { font-size: 34px; }
  .hero-dots { left: 24px; }
  .hero-aside { border-top: 2px solid var(--color-divider); }

  .grid-3, .learn { grid-template-columns: 1fr; }
  .cell, .learn .cell { padding: 28px 24px; border-right: 0; }
  .learn .cell:not(:last-child) { border-right: 0; border-bottom: 2px solid var(--color-divider); }
  .section-head, .section-title { padding: 32px 24px 20px; }

  .newsletter-inner { padding: 40px 24px; }
  .newsletter h2 { font-size: 34px; }

  .footer-sponsors, .footer-body, .footer-legal { padding-left: 24px; padding-right: 24px; }
  .sponsor-grid { grid-template-columns: repeat(3, 1fr); }
  .footer-body { grid-template-columns: 1fr; gap: 24px; }
}

@media (max-width: 520px) {
  .footer-links { grid-template-columns: 1fr; }
  .sponsor-grid { grid-template-columns: repeat(2, 1fr); }
}


/* sponsor-cell wrapping. Cells carry only a border-RIGHT by default, which is all a
   single row needs; once the grid wraps, the rows want separating too, and the
   cell that ends the grid must stop suppressing its right border or the column
   divider stops short of the frame.

   The two bands are a RANGE query rather than the usual cascade, because the
   three-column and two-column layouts disagree about which cells are on the
   last row and the more specific three-column selectors would otherwise win
   inside the two-column band. "Last row" cannot be a fixed position - the
   roster is whatever the sponsors happen to be - so it is derived: the last
   cell, plus the ones a partial final row leaves stranded above it. */
@media (min-width: 521px) and (max-width: 960px) {
  .sponsor-cell { border-bottom: 2px solid var(--color-divider); }
  .sponsor-cell:last-child { border-right: 2px solid var(--color-divider); }
  .sponsor-cell:nth-child(3n) { border-right: 0; }
  .sponsor-cell:last-child,
  .sponsor-cell:nth-last-child(2):not(:nth-child(3n)),
  .sponsor-cell:nth-last-child(3):nth-child(3n+1) { border-bottom: 0; }
}
@media (max-width: 520px) {
  .sponsor-cell { border-bottom: 2px solid var(--color-divider); }
  .sponsor-cell:last-child { border-right: 2px solid var(--color-divider); }
  .sponsor-cell:nth-child(2n) { border-right: 0; }
  .sponsor-cell:last-child,
  .sponsor-cell:nth-last-child(2):nth-child(odd) { border-bottom: 0; }
}

/* sponsor-slot-cell wrapping. Cells carry only a border-RIGHT by default, which is all a
   single row needs; once the grid wraps, the rows want separating too, and the
   cell that ends the grid must stop suppressing its right border or the column
   divider stops short of the frame.

   The two bands are a RANGE query rather than the usual cascade, because the
   three-column and two-column layouts disagree about which cells are on the
   last row and the more specific three-column selectors would otherwise win
   inside the two-column band. "Last row" cannot be a fixed position - the
   roster is whatever the sponsors happen to be - so it is derived: the last
   cell, plus the ones a partial final row leaves stranded above it. */
@media (min-width: 521px) and (max-width: 960px) {
  .sponsor-slot-cell { border-bottom: 2px solid var(--color-divider); }
  .sponsor-slot-cell:last-child { border-right: 2px solid var(--color-divider); }
  .sponsor-slot-cell:nth-child(3n) { border-right: 0; }
  .sponsor-slot-cell:last-child,
  .sponsor-slot-cell:nth-last-child(2):not(:nth-child(3n)),
  .sponsor-slot-cell:nth-last-child(3):nth-child(3n+1) { border-bottom: 0; }
}
@media (max-width: 520px) {
  .sponsor-slot-cell { border-bottom: 2px solid var(--color-divider); }
  .sponsor-slot-cell:last-child { border-right: 2px solid var(--color-divider); }
  .sponsor-slot-cell:nth-child(2n) { border-right: 0; }
  .sponsor-slot-cell:last-child,
  .sponsor-slot-cell:nth-last-child(2):nth-child(odd) { border-bottom: 0; }
}

/* ============================================================================
   Inner pages - Blog, Events, Play Again, singles, archives, search, 404.
   Built on the same tokens + building blocks (.section, .grid-3, .cell, .ph).
   ========================================================================== */

/* Page header (Blog / Events / Play Again / archive / search) */
.page-head { padding: 48px 48px 32px; }
.page-head h1 { font-size: 56px; letter-spacing: -0.02em; line-height: 1; margin: 0 0 12px; }
.page-lede { font-size: 17px; margin: 0; max-width: 62ch; opacity: 0.8; }

/* Two-column feature (next event, featured post) */
.feature { max-width: var(--page-max); margin: 0 auto; border-bottom: 2px solid var(--color-divider); }
.feature-inner { display: grid; grid-template-columns: 1fr 1fr; position: relative; }
.feature-copy { padding: 48px; display: flex; flex-direction: column; gap: 16px; justify-content: center; }
.feature-copy .tag { align-self: flex-start; }
.feature-copy h1, .feature-copy .feature-title {
  font-family: var(--font-heading); font-weight: 800; font-size: 38px;
  line-height: 1.08; letter-spacing: -0.015em; margin: 0; text-wrap: pretty;
}
.feature-copy p, .feature-lede { font-size: 16px; line-height: 1.55; margin: 0; max-width: 56ch; opacity: 0.85; }
.feature-meta { font-size: 13px; opacity: 0.55; }
a.feature-inner { color: var(--color-text); }
a.feature-inner:hover { background: var(--color-surface); }

/* Events hero: a stretched link makes the whole feature clickable to the event
   page, while the Register/Details button stays a separate target on top. */
.feature-link { color: inherit; text-decoration: none; }
.feature-inner:has(.feature-link) { cursor: pointer; }
.feature-link::after { content: ""; position: absolute; inset: 0; z-index: 2; }
.feature .hero-ctas { position: relative; z-index: 3; }
.feature-art { isolation: isolate; }
.feature-inner:hover .feature-link { color: var(--color-accent-600); }
.feature-art {
  position: relative; overflow: hidden;
  border-left: 2px solid var(--color-divider);
  background: var(--color-surface); min-height: 320px;
  --ph-tint: var(--newmr-red-100);
}
.feature-art.tint-blue { --ph-tint: var(--newmr-blue-100); }
.feature-art .ph { width: 100%; height: 100%; min-height: inherit; }
.feature-art-fg { position: relative; z-index: 1; width: 100%; height: 100%; object-fit: contain; }
.feature-art.has-img::before {
  content: ""; position: absolute; inset: 0; z-index: 0;
  background-image: var(--art-bg); background-size: cover; background-position: center;
  filter: blur(28px) saturate(1.15); transform: scale(1.2);
}

/* Events year grids */
.year-title { padding: 40px 48px 20px; }
.year-title h2 { font-size: 32px; margin: 0; }
.grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); border-top: 2px solid var(--color-divider); }
.ev-cell {
  padding: 24px; border-right: 2px solid var(--color-divider); border-bottom: 2px solid var(--color-divider);
  display: flex; flex-direction: column; gap: 8px; color: var(--color-text);
}
.ev-cell:hover { background: var(--color-surface); }
.ev-cell .thumb {
  position: relative; isolation: isolate; overflow: hidden; min-height: 0;
  aspect-ratio: 21/9; border: 2px solid var(--color-divider); --ph-tint: var(--newmr-red-100);
}
.ev-cell .thumb.tint-blue { --ph-tint: var(--newmr-blue-100); }
.ev-cell .thumb.has-img { background: var(--color-surface); }
.ev-cell .thumb.has-img::before {
  content: ""; position: absolute; inset: 0; z-index: 0;
  background-image: var(--art-bg); background-size: cover; background-position: center;
  filter: blur(18px) saturate(1.15); transform: scale(1.2);
}
.ev-cell .thumb img {
  position: relative; z-index: 1;
  width: 100%; height: 100%; object-fit: contain; display: block;
}
.ev-date { font-size: 13px; color: var(--color-accent-700); font-weight: 600; }
.ev-cell.past .ev-date { color: inherit; opacity: 0.6; }
.ev-title { font-family: var(--font-heading); font-weight: 600; font-size: 18px; line-height: 1.25; text-wrap: pretty; }

/* A note row under a section (archive link + hint) */
.section-note { padding: 24px 48px 48px; display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.section-note .hint { font-size: 14px; opacity: 0.6; }
.section-note .hint a { text-decoration: underline; }

/* Play Again - archive controls (sticky search + year jump rail) */
.pa-controls { position: sticky; top: 0; z-index: 20; background: var(--color-bg); border-bottom: 2px solid var(--color-divider); }
.pa-controls-inner { max-width: var(--page-max); margin: 0 auto; padding: 12px 48px; display: flex; gap: 20px; align-items: center; flex-wrap: wrap; }
.pa-search { font: inherit; font-size: 15px; padding: 9px 14px; border: 2px solid var(--color-divider); background: var(--color-surface); color: var(--color-text); flex: 1 1 240px; min-width: 200px; max-width: 400px; }
.pa-search::placeholder { color: color-mix(in srgb, var(--color-text) 45%, transparent); }
.pa-search:focus-visible { outline: none; border-color: var(--color-accent); }
.pa-count { font-size: 13px; color: color-mix(in srgb, var(--color-text) 55%, transparent); font-variant-numeric: tabular-nums; white-space: nowrap; }
.pa-years { display: flex; gap: 2px; overflow-x: auto; flex: 1 1 auto; scrollbar-width: thin; }
.pa-years a { font-family: var(--font-heading); font-weight: 600; font-size: 13px; padding: 6px 9px; color: color-mix(in srgb, var(--color-text) 68%, transparent); white-space: nowrap; text-decoration: none; }
.pa-years a:hover { color: var(--color-accent); }
.pa-years a.dim { opacity: 0.28; }

.pa-list { max-width: var(--page-max); margin: 0 auto; }
.pa-year[hidden] { display: none; }
.pa-year-h {
  font-family: var(--font-heading); font-weight: 800; font-size: 24px;
  margin: 0; padding: 30px 48px 10px; scroll-margin-top: 68px;
  border-top: 2px solid var(--color-divider);
}
.pa-list > .pa-year:first-child .pa-year-h { border-top: 0; }

/* Play Again - recording rows */
.pa-row {
  display: grid; grid-template-columns: 168px 1fr auto; align-items: center; gap: 28px;
  padding: 14px 48px;
  border-bottom: 1px solid color-mix(in srgb, var(--color-text) 15%, transparent);
  color: var(--color-text);
}
.pa-row[hidden] { display: none; }
.pa-row:hover { background: var(--color-surface); }
/* Fixed 16:9 thumbnail, centred with the row padding as breathing room so
   adjacent thumbs never touch (was: stretched full-height into a strip). */
.pa-thumb {
  position: relative; width: 168px; aspect-ratio: 16 / 9; overflow: hidden;
  border: 2px solid var(--color-divider);
  display: flex; align-items: center; justify-content: center;
  background: repeating-linear-gradient(45deg, var(--newmr-blue-100) 0 10px, var(--color-surface) 10px 20px);
}
.pa-thumb > span { font-family: ui-monospace, monospace; font-size: 11px; background: var(--color-bg); border: 2px solid var(--color-divider); padding: 3px 8px; }
/* Contain the artwork whole (no crop) over a blurred, zoomed copy of itself. */
.pa-thumb.has-img { background: var(--color-surface); }
.pa-thumb.has-img::before {
  content: ""; position: absolute; inset: 0; z-index: 0;
  background-image: var(--art-bg); background-size: cover; background-position: center;
  filter: blur(12px) saturate(1.2); transform: scale(1.35);
}
.pa-thumb-img { position: relative; z-index: 1; width: 100%; height: 100%; object-fit: contain; display: block; }
/* Play badge over the artwork, accent-red on row hover */
.pa-play {
  position: absolute; z-index: 2; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 34px; height: 34px; display: grid; place-content: center;
  background: color-mix(in srgb, #14100f 55%, transparent);
}
.pa-play::after {
  content: ""; width: 0; height: 0; border-style: solid; border-width: 7px 0 7px 12px;
  border-color: transparent transparent transparent #fff; transform: translateX(2px);
}
.pa-row:hover .pa-play { background: var(--color-accent); }
.pa-body { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.pa-title { font-family: var(--font-heading); font-weight: 600; font-size: 20px; line-height: 1.25; text-wrap: pretty; }
.pa-date { font-size: 13px; opacity: 0.6; }
.pa-watch { font-weight: 600; font-size: 14px; color: var(--color-accent-700); text-align: right; white-space: nowrap; }

/* Recording detail (an event's presentations) */
.rec-table { width: 100%; border-collapse: collapse; }
.rec-table th { text-align: left; font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; color: color-mix(in srgb, var(--color-text) 60%, transparent); padding: 12px 16px; border-bottom: 2px solid var(--color-divider); }
.rec-table td { padding: 14px 16px; border-bottom: 1px solid var(--color-divider); vertical-align: top; font-size: 15px; }
.rec-table tr:hover td { background: color-mix(in srgb, var(--color-text) 4%, transparent); }
.rec-table a { color: var(--color-accent-700); font-weight: 600; }

/* Articles: single post / page / event / presentation / person */
.article { max-width: 820px; margin: 0 auto; padding: 48px; }
.article-full { max-width: var(--page-max); }
.article-head { margin-bottom: 24px; }
.article-head h1 { font-size: 44px; line-height: 1.08; letter-spacing: -0.02em; margin: 0 0 12px; text-wrap: pretty; }
.article-meta { font-size: 13px; opacity: 0.55; display: flex; gap: 12px; flex-wrap: wrap; }
/* Featured image banner: whole image (contain) over a blurred backdrop of
   itself, capped to a 16:9 height so tall/odd images never dominate. */
.article-feature {
  position: relative; overflow: hidden; isolation: isolate;
  margin: 0 0 28px; border: 2px solid var(--color-divider);
  background: var(--color-surface); aspect-ratio: 16 / 9;
}
.article-feature::before {
  content: ""; position: absolute; inset: 0; z-index: 0;
  background-image: var(--art-bg); background-size: cover; background-position: center;
  filter: blur(26px) saturate(1.15); transform: scale(1.2);
}
.article-feature-img { position: relative; z-index: 1; width: 100%; height: 100%; object-fit: contain; display: block; }
/* Person portrait keeps its natural shape (not a banner). */
.person-photo { margin: 0 0 24px; max-width: 220px; border: 2px solid var(--color-divider); }
.person-photo img { width: 100%; height: auto; display: block; }
.article-body { font-size: 17px; line-height: 1.65; }
.article-body > * + * { margin-top: 1.1em; }
.article-body h2 { font-size: 28px; margin-top: 1.6em; }
.article-body h3 { font-size: 22px; margin-top: 1.4em; }
.article-body a { color: var(--color-accent-700); text-decoration: underline; }
.article-body img { height: auto; border: 2px solid var(--color-divider); }
.article-body ul, .article-body ol { padding-left: 1.4em; }
.article-body li + li { margin-top: 0.4em; }
.article-body blockquote { border-left: 3px solid var(--color-accent); margin: 1.2em 0; padding: 0.2em 0 0.2em 1.2em; opacity: 0.9; }
.article-video { margin: 0 0 28px; }
.article-video video, .article-video iframe { width: 100%; aspect-ratio: 16/9; border: 2px solid var(--color-divider); background: #000; }

/* Comments (comments.php). Same column as .article so the discussion reads as
   a continuation of the piece, with a rule marking it off. Nesting is styled
   for the day Settings > Discussion turns threading back on; with it off the
   walker renders flat and .children never appears. */
.comments {
  max-width: 820px; margin: 0 auto; padding: 0 48px 48px;
  border-top: 2px solid var(--color-divider); padding-top: 36px;
}
.comments-title {
  font-size: 22px; letter-spacing: -0.01em; margin: 0 0 20px;
}
.comment-list, .pingback-list { list-style: none; margin: 0; padding: 0; }
.comment-list > li + li { margin-top: 4px; }
.comment-item .children {
  list-style: none; margin: 4px 0 0; padding: 0 0 0 28px;
  border-left: 2px solid var(--color-divider);
}
.comment-body { padding: 20px 0; border-top: 1px solid var(--color-divider); }
.comment-list > li:first-child > .comment-body { border-top: 0; padding-top: 0; }
.comment-head { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; }
.comment-avatar {
  position: relative; width: 44px; height: 44px; flex: 0 0 44px;
  display: block; overflow: hidden;
  border: 2px solid var(--color-divider); background: var(--color-surface);
}
/* Initials underneath, the avatar over them: an opaque Gravatar hides these,
   the transparent "blank" default does not. See newmr_modernist_comment_avatar(). */
.comment-monogram {
  position: absolute; inset: 0; display: grid; place-content: center;
  font-family: var(--font-heading); font-weight: 800; font-size: 16px; line-height: 1;
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
}
.comment-avatar img {
  position: relative; z-index: 1;
  width: 100%; height: 100%; object-fit: cover; display: block;
}
.comment-who { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.comment-author { font-weight: 700; font-size: 15px; }
.comment-author a { color: var(--color-text); }
.comment-author a:hover { color: var(--color-accent-600); }
.comment-when { font-size: 13px; opacity: 0.55; }
.comment-when:hover { opacity: 0.85; }
.comment-text { font-size: 16px; line-height: 1.6; }
.comment-text > * + * { margin-top: 0.9em; }
.comment-text a { color: var(--color-accent-700); text-decoration: underline; }
.comment-pending { font-size: 14px; color: var(--color-accent-700); margin: 0 0 8px; }
.comment-actions { margin-top: 10px; font-size: 14px; font-weight: 600; }
.comment-actions a { color: var(--color-accent-700); }
.comment-nav { display: flex; gap: 20px; margin-top: 20px; font-size: 14px; font-weight: 600; }
.comments-closed { font-size: 14px; opacity: 0.6; margin: 24px 0 0; }

/* The form. Flat fields in the same language as the Play Again search box. */
.comment-form { margin-top: 32px; display: flex; flex-direction: column; gap: 14px; }
.comment-form p { margin: 0; }
.comment-notes, .comment-form-cookies-consent label { font-size: 13px; opacity: 0.65; }
.comment-form label { display: block; font-size: 13px; font-weight: 600; margin-bottom: 6px; }
.comment-form input[type="text"],
.comment-form input[type="email"],
.comment-form input[type="url"],
.comment-form textarea {
  font: inherit; font-size: 15px; width: 100%; padding: 10px 14px;
  border: 2px solid var(--color-divider); background: var(--color-surface);
  color: var(--color-text); border-radius: 0;
}
.comment-form textarea { resize: vertical; min-height: 140px; }
.comment-form input:focus-visible, .comment-form textarea:focus-visible {
  outline: none; border-color: var(--color-accent);
}
.comment-form-cookies-consent {
  display: flex; align-items: flex-start; gap: 8px;
}
.comment-form-cookies-consent input { margin-top: 3px; }
.comment-form-cookies-consent label { margin-bottom: 0; font-weight: 400; }
.comment-form .form-submit { margin-top: 4px; }
.comment-form .btn { width: auto; align-self: flex-start; }
#cancel-comment-reply-link { font-size: 14px; font-weight: 600; margin-left: 12px; color: var(--color-accent-700); }

/* Pingbacks: the incoming links, kept out of the conversation above. */
.pingbacks { margin-top: 40px; border-top: 1px solid var(--color-divider); padding-top: 20px; }
.pingbacks-title {
  font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase;
  font-weight: 600; margin: 0 0 12px; opacity: 0.55;
}
.pingback-list li { font-size: 14px; line-height: 1.5; opacity: 0.75; }
.pingback-list li + li { margin-top: 6px; }
.pingback-list a { color: var(--color-accent-700); }
/* Core's ping() wraps each one in .comment-body, which would otherwise pick up
   the padded, ruled treatment a real comment gets. */
.pingback-list .comment-body { padding: 0; border-top: 0; }
.pingback-list .comment-body p { margin: 0; }

@media (max-width: 960px) {
  .comments { padding-left: 24px; padding-right: 24px; }
  .comment-item .children { padding-left: 16px; }
}

/* Pagination (paginate_links type=list -> <ul class="page-numbers">) */
.pager { padding: 24px 48px 48px; }
.pager ul.page-numbers { list-style: none; margin: 0; padding: 0; display: flex; gap: 12px; flex-wrap: wrap; align-items: center; }
.pager ul.page-numbers > li { display: flex; margin: 0; }
.pager a.page-numbers, .pager span.page-numbers {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 40px; height: 40px; padding: 0 12px;
  border: 2px solid var(--color-divider); font-weight: 600; font-size: 14px; color: var(--color-text);
}
.pager span.page-numbers.current { background: var(--color-accent); color: var(--color-bg); border-color: var(--color-accent); }
.pager a.page-numbers:hover { background: var(--color-surface); }
.pager .page-numbers.dots { border: 0; min-width: 0; padding: 0 4px; }

/* The last block before the footer must not add a rule of its own - the
   footer already has a border-top, else the two stack into a double line. */
.site-main > .section:last-child,
.site-main > .feature:last-child { border-bottom: 0; }

/* Notices (search empty / 404) */
.notice { max-width: var(--page-max); margin: 0 auto; padding: 48px; }
.notice p { font-size: 17px; opacity: 0.8; }

/* People archive reuses .grid-3/.cell with square thumbs. A face wants to fill
   its frame, so this one keeps the cover fit and drops the blurred backdrop. */
.people .cell .thumb { aspect-ratio: 1 / 1; }
.people .cell .thumb img { object-fit: cover; }
.people .cell .thumb.has-img::before { content: none; }

/* Subject archives (taxonomy-subject.php): the chips rail above the mixed
   grid. Chips are tag-shaped links (flat, 0-radius via the tokens); the
   current term is filled with the accent, the "All <hub>" back link reads
   as a pointer in accent text. */
.subject-chips { padding: 28px 48px 24px; display: flex; flex-wrap: wrap; gap: 8px; }
.subject-chip {
  border: 2px solid var(--color-divider); background: var(--color-bg);
  color: var(--color-text); font-weight: 600; padding: 5px 12px;
}
a.subject-chip:hover { background: var(--color-surface); border-color: var(--color-text); color: var(--color-text); }
.subject-chip.is-back { color: var(--color-accent-700); }
.subject-chip.is-current { background: var(--color-accent); border-color: var(--color-accent); color: var(--color-bg); }
a.subject-chip.is-current:hover { background: var(--color-accent-600); border-color: var(--color-accent-600); color: var(--color-bg); }

/* Related rail (newmr_modernist_related_rail) under single articles. The
   article blocks it follows carry no bottom rule of their own, so the
   section takes a top border to mark itself off; everything inside reuses
   .section-title / .grid-3 / .cell as-is. */
.related-section { border-top: 2px solid var(--color-divider); }

/* Hub sponsor slot (taxonomy-subject.php): a labelled strip of sponsor
   logos after the content grid on top-level subject terms. Same language
   as the footer sponsor grid - flat, 0-radius, a framed grid of divider-
   bordered cells whose column count follows the roster (--sponsor-cols,
   set by the template). Scoped as .section.sponsor-slot so the hero-aside
   premium slot (also .sponsor-slot) keeps its own styling. */
.section.sponsor-slot { padding: 32px 48px 40px; }
.sponsor-slot-title {
  font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase;
  font-weight: 600; margin: 0; opacity: 0.55;
}
.sponsor-slot-grid {
  display: grid; grid-template-columns: repeat(var(--sponsor-cols, 6), 1fr);
  border: 2px solid var(--color-divider); margin-top: 12px;
}
.sponsor-slot-cell {
  display: flex; align-items: center; justify-content: center;
  min-height: 104px; padding: 16px;
  border-right: 2px solid var(--color-divider);
  color: var(--color-text);
}
.sponsor-slot-cell:last-child { border-right: 0; }
a.sponsor-slot-cell:hover { background: var(--color-surface); }
.sponsor-slot-cell img { max-width: 100%; max-height: 72px; width: auto; height: auto; object-fit: contain; }
.sponsor-slot-name { font-size: 13px; font-weight: 600; text-align: center; }

@media (max-width: 960px) {
  .section.sponsor-slot { padding: 32px 24px; }
  .sponsor-slot-grid { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 520px) {
  .sponsor-slot-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 960px) {
  .page-head { padding: 40px 24px 24px; }
  .page-head h1 { font-size: 40px; }
  .feature-inner { grid-template-columns: 1fr; }
  .feature-art { border-left: 0; aspect-ratio: 16 / 9; min-height: 0; }
  .feature-copy { padding: 32px 24px; }
  .feature-copy h1, .feature-copy .feature-title { font-size: 30px; }
  .year-title { padding: 32px 24px 16px; }
  .grid-4 { grid-template-columns: repeat(2, 1fr); }
  .ev-cell:nth-child(2n) { border-right: 0; }
  .section-note { padding: 24px; }
  .pa-row { grid-template-columns: 120px 1fr; gap: 16px; padding: 12px 24px; }
  .pa-thumb { width: 120px; }
  .pa-watch { display: none; }
  .pa-controls-inner, .pa-year-h { padding-left: 24px; padding-right: 24px; }
  .article, .notice { padding: 32px 24px; }
  .article-head h1 { font-size: 32px; }
  .pager { padding: 24px; }
  .subject-chips { padding: 20px 24px 16px; }
}
@media (max-width: 520px) {
  .grid-4 { grid-template-columns: 1fr; }
  .ev-cell { border-right: 0; }
  /* The Speaker column stays at every width: it is the only route from an
     event page to a speaker profile. The table already sits in an overflow-x
     wrapper, so it scrolls inside its own box rather than dropping a column -
     tighten the cells instead. */
  .rec-table th, .rec-table td { padding: 10px 12px; }
}

/* ============================================================================
   Kicker - promoted to a base rule.
   It was only ever styled as a descendant of .cell; the person hero, the topic
   block and the timeline rows all use it outside any cell. The existing
   .cell .kicker / .cell .kicker.blue rules are more specific, so every card
   surface renders exactly as before.
   ========================================================================== */
.kicker {
  font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase;
  font-weight: 600; color: var(--color-accent-700);
}

/* ============================================================================
   Play Again - subject filter pills (page-play-again.php list branch)
   nav.pa-filters is the LAST child of the existing .pa-controls-inner flex
   row, so it takes a full-width flex basis and drops onto its own line under
   the search box and year rail, inheriting the bar's gutters. Up to ten pills
   can render, so the rail wraps rather than scrolls.
   ========================================================================== */
.pa-filters {
  flex: 1 0 100%;
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
}
/* These are <button>s, not <a>s: reset the UA styling down to the flat
   0-radius, 2px-divider language the .subject-chip rail already uses. */
.pa-filter {
  font: inherit; font-size: 13px; font-weight: 600; line-height: 1.2;
  padding: 5px 12px; margin: 0;
  border: 2px solid var(--color-divider); border-radius: 0;
  background: var(--color-bg); color: var(--color-text);
  -webkit-appearance: none; appearance: none;
  cursor: pointer; white-space: nowrap;
}
.pa-filter:hover { background: var(--color-surface); border-color: var(--color-text); }
.pa-filter.is-current {
  background: var(--color-accent); border-color: var(--color-accent); color: var(--color-bg);
}
.pa-filter.is-current:hover { background: var(--color-accent-600); border-color: var(--color-accent-600); }
.pa-filter:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
/* Accent outline on an accent fill is invisible - switch to ink. */
.pa-filter.is-current:focus-visible { outline-color: var(--color-text); }

/* The pill rail adds a second row to the sticky controls bar, so a year jump
   needs a deeper landing offset than the single-row bar's 68px. */
.pa-list .pa-year-h { scroll-margin-top: 128px; }

/* ============================================================================
   Play Again - speaker credits
   a.pa-speaker in the event recordings table and in the single-recording
   credit line. Inside .rec-table the action links (Session / Watch / Slides)
   are accent red; speaker names stay ink so the row does not read as four
   identical buttons.
   ========================================================================== */
a.pa-speaker,
.rec-table a.pa-speaker {
  color: var(--color-text); font-weight: 600;
  text-decoration: underline; text-decoration-thickness: 1px;
  text-decoration-color: color-mix(in srgb, var(--color-text) 35%, transparent);
  text-underline-offset: 3px;
}
a.pa-speaker:hover,
.rec-table a.pa-speaker:hover { color: var(--color-accent-600); text-decoration-color: currentColor; }
a.pa-speaker:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

/* Credit line under the h1 on /play-again/<talk> (inside .article-head). */
.pa-credits {
  font-size: 15px; line-height: 1.5; margin: 0;
  color: color-mix(in srgb, var(--color-text) 72%, transparent);
}

/* ============================================================================
   Person profile (single-person.php)
   A full-bleed stack of banded sections, same rhythm as taxonomy-subject.php
   and the Play Again list. Every stat number renders at the same size and
   weight whether it says 1 or 166 - there is deliberately no emphasis variant
   keyed on magnitude.
   ========================================================================== */

/* - hero - */
.person-hero {
  display: grid; grid-template-columns: 220px 1fr; gap: 32px;
  padding: 44px var(--page-pad) 40px;
}
.person-hero-photo {
  align-self: start;
  width: 220px; max-width: 100%; aspect-ratio: 1 / 1; overflow: hidden;
  border: 2px solid var(--color-divider); background: var(--color-surface);
}
.person-hero-photo img { width: 100%; height: 100%; object-fit: cover; }
/* Initials, never a silhouette or a stock avatar. */
.person-hero-photo.is-monogram { display: grid; place-content: center; }
.person-hero-photo.is-monogram > span {
  font-family: var(--font-heading); font-weight: 800; font-size: 56px;
  line-height: 1; letter-spacing: 0.01em;
  color: color-mix(in srgb, var(--color-text) 62%, transparent);
}
.person-hero-body {
  display: flex; flex-direction: column; align-items: flex-start; gap: 10px;
  min-width: 0;
}
.person-name {
  font-size: 44px; line-height: 1.08; letter-spacing: -0.02em;
  margin: 0; text-wrap: pretty;
}
.person-role { font-size: 18px; line-height: 1.4; margin: 0; opacity: 0.85; }
.person-meta {
  font-size: 13px; line-height: 1.5; margin: 0; opacity: 0.55;
  font-variant-numeric: tabular-nums;
}
/* One fact per line: the record, the topics, the region. A long span still
   wraps onto a second line of its own rather than running into the next. */
.person-meta span { display: block; text-wrap: pretty; }
.person-share {
  margin-top: auto; padding-top: 10px;
  display: flex; gap: 12px; flex-wrap: wrap;
}
/* One <button> and one <a> that must render identically - the button needs the
   full UA reset. The [hidden] rule matters: the copy-link control ships hidden
   and only the clipboard-capable script unhides it. */
.person-share-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  font-family: var(--font-heading); font-weight: 600; font-size: 14px;
  line-height: 1.2; padding: 8px 14px; margin: 0;
  border: 2px solid var(--color-divider); border-radius: 0;
  background: transparent; color: var(--color-text);
  -webkit-appearance: none; appearance: none;
  cursor: pointer; text-decoration: none; white-space: nowrap;
}
.person-share-btn[hidden] { display: none; }
.person-share-btn:hover { background: var(--color-surface); color: var(--color-text); }
.person-share-btn:active { background: color-mix(in srgb, var(--color-text) 14%, transparent); }
.person-share-btn:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

/* - stat strip -
   Same visual language as .sponsor-slot-grid: a framed row of cells split by
   2px rules. The hero's bottom border is the strip's top edge, and the strip
   carries its own bottom rule, so no two borders ever stack. Column count
   comes from --person-stat-cols, set inline by the template. */
.person-stats {
  max-width: var(--page-max); margin: 0 auto;
  display: grid; grid-template-columns: repeat(var(--person-stat-cols, 3), 1fr);
  border-bottom: 2px solid var(--color-divider);
}
.person-stat {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 6px; min-height: 104px; padding: 16px; text-align: center;
  border-right: 2px solid var(--color-divider);
}
.person-stat:last-child { border-right: 0; }
.person-stat-n {
  font-family: var(--font-heading); font-weight: 800; font-size: 34px;
  line-height: 1; font-variant-numeric: tabular-nums;
}
.person-stat-l {
  font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase;
  font-weight: 600; opacity: 0.6;
}

/* - topic chips -
   A sibling of the .subject-chip rail: same border, fill and weight. The
   kicker takes a full row of the flex so the chips wrap beneath it, and the
   chips are printed with no whitespace between them, so the gap is the only
   thing separating them. */
.person-topics {
  max-width: var(--page-max); margin: 0 auto;
  padding: 24px var(--page-pad) 26px;
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  border-bottom: 2px solid var(--color-divider);
}
.person-topics .kicker { flex: 1 0 100%; }
.person-topic {
  display: inline-flex; align-items: center;
  font-size: 11px; letter-spacing: 0.02em; font-weight: 600;
  padding: 5px 12px;
  border: 2px solid var(--color-divider); background: var(--color-bg);
  color: var(--color-text);
}
a.person-topic:hover { background: var(--color-surface); border-color: var(--color-text); color: var(--color-text); }
/* Chips are buttons that filter the sessions below in place. Reset the UA
   button styling, and keep .is-static (too few sessions to filter) inert. */
button.person-topic {
  font-family: inherit; line-height: inherit; cursor: pointer;
  -webkit-appearance: none; appearance: none;
}
button.person-topic:hover { background: var(--color-surface); border-color: var(--color-text); }
button.person-topic.is-active { background: var(--color-text); border-color: var(--color-text); color: var(--color-bg); }
button.person-topic.is-active:hover { background: var(--color-text); border-color: var(--color-text); }
.person-topic.is-static { cursor: default; }
/* The lead topic reads exactly like the current chip on a subject archive. */
.person-topic.is-lead { background: var(--color-accent); border-color: var(--color-accent); color: var(--color-bg); }
a.person-topic.is-lead:hover { background: var(--color-accent-600); border-color: var(--color-accent-600); color: var(--color-bg); }
button.person-topic.is-lead:hover { background: var(--color-accent-600); border-color: var(--color-accent-600); }
button.person-topic.is-lead.is-active { background: var(--color-text); border-color: var(--color-text); color: var(--color-bg); }
/* Filter feedback under the sessions, with an inline way back to everything. */
.person-filter-note {
  margin: 20px 48px 0; font-size: 13px; opacity: 0.7; cursor: pointer;
  text-decoration: underline; text-underline-offset: 3px;
}
@media (max-width: 960px) { .person-filter-note { margin-left: 24px; margin-right: 24px; } }
.person-topic:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.person-topic.is-lead:focus-visible { outline-color: var(--color-text); }

/* - empty states -
   The missing-bio sentence stands in for the .article block, so it takes the
   same page frame as .notice. The editor nudge is a surface band, never a
   percentage and never a progress bar, and it is only ever rendered for a
   user who can edit the profile. */
.person-empty { max-width: var(--page-max); margin: 0 auto; padding: 40px var(--page-pad); }
.person-empty p { font-size: 17px; line-height: 1.6; margin: 0; opacity: 0.8; }
.person-empty.is-editor {
  background: var(--color-surface);
  border-top: 2px solid var(--color-divider);
  border-bottom: 2px solid var(--color-divider);
  padding: 16px var(--page-pad);
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
}
.person-empty.is-editor p { font-size: 14px; opacity: 0.7; }

/* - timeline -
   Rows reuse the Play Again band verbatim, so one talk arrives as a wide,
   image-led feature rather than a one-row table. The block that precedes it
   (.article, .person-empty) carries no rule of its own, hence the top border;
   the trailing hairline of the last row is dropped so it does not stack with
   the section's own 2px bottom rule. */
.person-timeline { border-top: 2px solid var(--color-divider); }
.person-timeline .pa-row:last-child { border-bottom: 0; }
.person-year {
  font-family: var(--font-heading); font-weight: 800; font-size: 24px;
  margin: 0; padding: 30px var(--page-pad) 10px;
  border-top: 2px solid var(--color-divider);
  font-variant-numeric: tabular-nums;
}
/* The first year sits directly under the section title - no rule, no gap. */
.person-timeline .person-year:first-of-type { border-top: 0; padding-top: 0; }
/* The editor band closes with its own rule, so the timeline must not add a
   second one directly beneath it. */
.person-empty.is-editor + .person-timeline { border-top: 0; }
/* .related-section brings its own top border for the case where it follows an
   unruled .article; after the timeline section that would be a double line. */
.person-timeline + .related-section { border-top: 0; }

/* The foot CTA is the only .section-note in the theme that is a direct child
   of .site-main, so it needs the page frame the enclosing .section usually
   supplies. */
.site-main > .section-note { max-width: var(--page-max); margin: 0 auto; }

/* ============================================================================
   Speaker index (archive-person.php)
   The toolbar is a clone of .pa-controls (it already reuses .pa-controls-inner,
   .pa-count and the .pa-years rail markup); the roster is per-letter .pa-year
   groups, each holding a .grid-4 of cards.
   ========================================================================== */
.people-toolbar {
  position: sticky; top: 0; z-index: 20;
  background: var(--color-bg);
  border-bottom: 2px solid var(--color-divider);
}
.people-search {
  font: inherit; font-size: 15px; padding: 9px 14px;
  border: 2px solid var(--color-divider); background: var(--color-surface);
  color: var(--color-text);
  flex: 1 1 240px; min-width: 200px; max-width: 400px;
}
.people-search::placeholder { color: color-mix(in srgb, var(--color-text) 45%, transparent); }
.people-search:focus-visible { outline: none; border-color: var(--color-accent); }

.people-grid { max-width: var(--page-max); margin: 0 auto; }
/* The toolbar already closes with a 2px rule, so the first letter heading must
   not add one (the .pa-list version of this rule does not reach here). */
.people-grid > .pa-year:first-child .pa-year-h { border-top: 0; }

.people-card {
  padding: 20px 20px 24px;
  border-right: 2px solid var(--color-divider);
  border-bottom: 2px solid var(--color-divider);
  display: flex; flex-direction: column; gap: 8px;
  color: var(--color-text);
}
/* The client-side filter sets [hidden]; without this the flex display wins. */
.people-card[hidden] { display: none; }
.people-card:hover { background: var(--color-surface); }
.people-card:focus-visible { outline: 2px solid var(--color-accent); outline-offset: -4px; }
.people-card-photo {
  display: block; aspect-ratio: 1 / 1; overflow: hidden;
  border: 2px solid var(--color-divider); background: var(--color-surface);
}
.people-card-photo img { width: 100%; height: 100%; object-fit: cover; }
.people-card-photo.is-monogram { display: grid; place-content: center; }
.people-card-photo.is-monogram > span {
  font-family: var(--font-heading); font-weight: 800; font-size: 40px;
  line-height: 1; letter-spacing: 0.01em;
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
}
.people-card-name {
  font-family: var(--font-heading); font-weight: 600; font-size: 18px;
  line-height: 1.25; text-wrap: pretty;
}
.people-card-role { font-size: 14px; line-height: 1.4; opacity: 0.75; }
.people-card-stat {
  font-size: 13px; opacity: 0.55; margin-top: auto;
  font-variant-numeric: tabular-nums;
}
/* 4 columns at the page max, then 3 / 2 / 1. Card borders follow the .ev-cell
   idiom in this same .grid-4 container: every card keeps its right rule (they
   frame the column like the events grid does), and only the 2-up and 1-up
   layouts drop the end-of-row one. */
@media (max-width: 1240px) {
  .people-grid .grid-4 { grid-template-columns: repeat(3, 1fr); }
}

/* ============================================================================
   Courses (archive-course.php, single-course.php, the rail on a profile)

   No new vocabulary: the archive is .pa-controls + .grid-3/.cell, the single
   page is .article, and the only genuinely new objects are the booking call to
   action and the NewMR editorial note - both of which are the same flat,
   0-radius, 2px-divider box everything else on the site is made of.
   ========================================================================== */

/* The archive can carry two pill rails (subject, and level when the catalogue
   has more than one), each a flex:1 0 100% child of .pa-controls-inner, so
   they stack onto their own rows under the search box. Tighten the row gap so
   two rails do not push the first card off a laptop screen. */
.pa-controls-inner .pa-filters + .pa-filters { margin-top: -8px; }

/* - single course - */
/* The kicker is a <span> inside .article-head, where nothing else is inline. */
.course-single .article-head .kicker { display: block; margin-bottom: 10px; }
.course-taught-by {
  font-size: 16px; line-height: 1.4; margin: 0 0 10px;
}
.course-taught-by a { color: var(--color-accent-700); font-weight: 600; }

/* The booking call to action. It is the only outbound link on the page, so it
   gets a box of its own rather than a button loose in the prose - and the note
   sits inside the same box, because "this happens somewhere else" is part of
   the offer, not a footnote to it. */
.course-cta {
  margin: 0 0 28px; padding: 20px 24px;
  border: 2px solid var(--color-divider); background: var(--color-surface);
  display: flex; align-items: center; gap: 16px 20px; flex-wrap: wrap;
}
.course-cta-btn { white-space: nowrap; }
.course-cta-note {
  font-size: 13px; line-height: 1.5; margin: 0; opacity: 0.7;
  flex: 1 1 260px; min-width: 0;
}

/* The editorial note is the one block on the page NewMR writes. It is marked
   off from the synced body above it rather than blended into it. */
.course-note {
  margin: 28px 0 0; padding: 20px 24px;
  border: 2px solid var(--color-divider); background: var(--color-surface);
}
.course-note .kicker { display: block; margin-bottom: 8px; }
.course-note p { font-size: 15px; line-height: 1.6; margin: 0; opacity: 0.85; }

/* The chips rail closes with its own 2px rule; .related-section brings a
   border-top for the case where it follows an unruled .article. Together they
   are a double line. Same fix as .person-timeline + .related-section. */
.course-subjects + .related-section { border-top: 0; }

/* - courses on a speaker profile - */
/* The rail sits between the session timeline and the "More on ..." rail, and
   both of its neighbours already carry a rule on the facing edge. */
.person-courses + .related-section { border-top: 0; }

@media (max-width: 640px) {
  /* A 44px-tall button beside a two-line note is a cramped row on a phone;
     the note wraps under it and the button takes the full column. */
  .course-cta { padding: 16px 20px; }
  .course-cta-btn { width: 100%; text-align: center; }
}

/* ============================================================================
   New surfaces - responsive
   ========================================================================== */
@media (max-width: 960px) {
  /* Deeper landing offset: the controls bar wraps further at this width. */
  .pa-list .pa-year-h { scroll-margin-top: 160px; }

  .person-hero { grid-template-columns: 1fr; gap: 24px; padding: 32px var(--page-pad) 28px; }
  .person-name { font-size: 34px; }
  .person-role { font-size: 16px; }

  .person-stats { grid-template-columns: repeat(3, 1fr); }
  .person-stat { border-top: 2px solid var(--color-divider); }
  .person-stat:nth-child(-n+3) { border-top: 0; }
  .person-stat:nth-child(3n) { border-right: 0; }
  .person-stat-n { font-size: 30px; }

  .person-empty { padding: 32px var(--page-pad); }
  .person-year { padding-top: 24px; }

  .people-grid .grid-4 { grid-template-columns: repeat(2, 1fr); }
  .people-grid .people-card { padding: 16px 16px 20px; }
  .people-grid .people-card:nth-child(2n) { border-right: 0; }
}

@media (max-width: 520px) {
  .person-hero-photo { width: 160px; }
  .person-hero-photo.is-monogram > span { font-size: 44px; }

  .person-stats { grid-template-columns: repeat(2, 1fr); }
  .person-stat:nth-child(-n+3) { border-top: 2px solid var(--color-divider); }
  .person-stat:nth-child(-n+2) { border-top: 0; }
  .person-stat:nth-child(3n) { border-right: 2px solid var(--color-divider); }
  .person-stat:nth-child(2n) { border-right: 0; }
  /* Re-stated after the nth rules above: an odd trailing tile sits alone in
     its row and must not carry a stub rule. */
  .person-stat:last-child { border-right: 0; }

  .people-grid .grid-4 { grid-template-columns: 1fr; }
  .people-grid .people-card,
  .people-grid .people-card:nth-child(2n) { border-right: 0; }
}

/* - Featured speakers strip (home) -------------------------------------------
   A horizontal rank of the most prolific contributors. Reuses the framed
   cell language of the sponsor grid: one box, cells split by 2px rules. */
.speakers .section-title { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; }
.speakers .section-title a { font-size: 14px; font-weight: 600; text-decoration: none; color: var(--color-accent-700); }
.speakers .section-title a:hover { color: var(--color-accent-600); text-decoration: underline; }
.speaker-strip {
  display: grid; grid-template-columns: repeat(6, 1fr);
  border: 2px solid var(--color-divider);
  margin: 0 48px 48px;
}
.speaker-card {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: 8px; padding: 22px 14px 20px;
  border-right: 2px solid var(--color-divider);
  text-decoration: none; color: var(--color-text);
}
.speaker-card:last-child { border-right: 0; }
.speaker-card:hover { background: var(--color-surface); }
.speaker-photo {
  width: 84px; height: 84px; display: block; overflow: hidden;
  border: 2px solid var(--color-divider); background: var(--color-surface);
}
.speaker-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.speaker-photo.is-monogram { display: grid; place-content: center; }
.speaker-photo.is-monogram > span {
  font-family: var(--font-heading); font-weight: 800; font-size: 30px; line-height: 1;
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
}
.speaker-name { font-weight: 700; font-size: 15px; line-height: 1.25; }
.speaker-role { font-size: 12px; opacity: 0.7; line-height: 1.3; }
.speaker-stat {
  font-family: ui-monospace, monospace; font-size: 11px; letter-spacing: 0.04em;
  text-transform: uppercase; opacity: 0.6; font-variant-numeric: tabular-nums;
  margin-top: auto; padding-top: 6px;
}
.speaker-card:hover .speaker-name { color: var(--color-accent-700); }
/* The strip draws its own border on all four sides, so a card on the LAST row
   must not draw a bottom border of its own - stacked, the two read as a single
   4px rule - while every row above it needs one.

   Same shape as .sponsor-cell and .sponsor-slot-cell above, and the same two
   traps. The bands are a RANGE query rather than the usual cascade because
   nth-child(3n) means "last column" at three columns and "middle of a row" at
   two, so letting the wider band cascade rubs out a divider that belongs
   there. And "last row" cannot be a fixed position, since how many speakers
   appear is editorial (Settings > General), so it is derived from the end.

   Three grids now share this logic. If a fourth appears, give them a common
   class rather than a fourth copy. */
@media (min-width: 521px) and (max-width: 960px) {
  .speaker-strip { grid-template-columns: repeat(3, 1fr); margin: 0 24px 32px; }
  .speaker-card { border-bottom: 2px solid var(--color-divider); }
  .speaker-card:last-child { border-right: 2px solid var(--color-divider); }
  .speaker-card:nth-child(3n) { border-right: 0; }
  .speaker-card:last-child,
  .speaker-card:nth-last-child(2):not(:nth-child(3n)),
  .speaker-card:nth-last-child(3):nth-child(3n+1) { border-bottom: 0; }
}
@media (max-width: 520px) {
  .speaker-strip { grid-template-columns: repeat(2, 1fr); margin: 0 24px 32px; }
  .speaker-card { border-bottom: 2px solid var(--color-divider); }
  .speaker-card:last-child { border-right: 2px solid var(--color-divider); }
  .speaker-card:nth-child(2n) { border-right: 0; }
  .speaker-card:last-child,
  .speaker-card:nth-last-child(2):nth-child(odd) { border-bottom: 0; }
}

/* - Classic editor alignment ---------------------------------------------
   497 published posts float an image right, 59 left, 43 centre. Without
   these the images stack full width and a decade of posts reflows. The
   float is dropped on narrow screens, where a floated 300px image beside
   a 17px measure leaves an unreadable column of text. */
.article-body .alignright {
  float: right; margin: 0.3em 0 1em 1.6em; max-width: 50%;
}
.article-body .alignleft {
  float: left; margin: 0.3em 1.6em 1em 0; max-width: 50%;
}
.article-body .aligncenter {
  display: block; margin-left: auto; margin-right: auto;
}
.article-body .alignnone { display: block; }
/* Floats must not escape their article or overlap what follows. */
.article-body::after { content: ""; display: block; clear: both; }
.article-body h2, .article-body h3 { clear: both; }
/* Gutenberg image blocks carry the alignment on the figure. */
.article-body figure.alignright, .article-body figure.alignleft { max-width: 50%; }
.article-body figure.aligncenter { text-align: center; }
.article-body figure img { display: block; }
.article-body figcaption {
  font-size: 13px; opacity: 0.7; margin-top: 6px; line-height: 1.4;
}
@media (max-width: 640px) {
  .article-body .alignright, .article-body .alignleft,
  .article-body figure.alignright, .article-body figure.alignleft {
    float: none; margin-left: 0; margin-right: 0; max-width: 100%;
  }
}
