@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&family=Merriweather+Sans:wght@400;700;800&display=swap");

/* ==========================================================================
   Cornell Brooks Tech Policy Institute
   Inter for headlines and body, Merriweather Sans for section headers.
   Palette is black, white, and Cornellian red. Accents stay sparing.

   1. Tokens        2. Base           3. Header and nav    4. Search
   5. Page frames   6. Home           7. Sections          8. Lists
   9. Long-form     10. Footer        11. Motion           12. Responsive
   ========================================================================== */

/* 1. TOKENS ================================================================
   Change a value here and it propagates everywhere. Start with --red. */

:root {
  --paper: #ffffff;
  --paper-soft: #fafafa;
  --red-wash: #fcf6f6;
  --ink: #000000;
  --ink-body: #3c3c3c;
  --ink-muted: #6e6e6e;

  --red: #b31b1b;
  --accent: var(--red);

  /* Secondary palette. Swap these two for your per-image colors. */
  --field: #7b8a74;
  --sand: #bbab7e;

  --rule: #ececec;
  --rule-strong: #d8d8d8;

  --font-head: "Inter", -apple-system, "Helvetica Neue", Arial, sans-serif;
  --font-section: "Merriweather Sans", Georgia, serif;
  --font-body: "Inter", -apple-system, "Helvetica Neue", Arial, sans-serif;
  --font-mono: "SFMono-Regular", Consolas, Menlo, monospace;

  /* Total horizontal breathing room, split either side of the shell. Scales
     with the viewport so the margin does not collapse once the window drops
     below the 78rem cap. */
  --gutter: clamp(2.5rem, 9vw, 10rem);
  --shell: min(100% - var(--gutter), 78rem);
  --measure: 68ch;
  --content-col: 50rem;

  /* Distance from the shell edge to the viewport edge. Drives full-bleed
     bands. Must use 100vw, not 100%, or the maths resolves against the
     shell itself and the band stays boxed in. */
  --bleed: calc((100vw - min(100vw - var(--gutter), 78rem)) / 2);

  color-scheme: light;
}

/* 2. BASE ================================================================== */

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

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

a {
  color: inherit;
  text-decoration: none;
}

button,
input {
  font: inherit;
  color: inherit;
}

button {
  cursor: pointer;
}

em {
  font-style: italic;
}

code {
  font-family: var(--font-mono);
  font-size: 0.92em;
}

::selection {
  background: rgba(179, 27, 27, 0.16);
}

:focus-visible {
  outline: 2px solid var(--red);
  outline-offset: 3px;
}

h1,
h2,
h3 {
  margin: 0;
  letter-spacing: -0.025em;
}

h1 {
  max-width: 14ch;
  font-family: var(--font-head);
  font-size: clamp(2.6rem, 5.2vw, 4.3rem);
  font-weight: 900;
  line-height: 0.98;
  letter-spacing: -0.038em;
}

h2 {
  font-family: var(--font-section);
  font-size: 2rem;
  font-weight: 700;
  line-height: 1.14;
}

h3 {
  font-family: var(--font-head);
  font-size: 1.24rem;
  font-weight: 800;
  line-height: 1.18;
}

/* Small red kickers. The most repeated brand signal on the site. */

.eyebrow,
.section-label {
  margin: 0;
  color: var(--red);
  font-family: var(--font-section);
  font-size: 0.7rem;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

.dek {
  max-width: 48ch;
  margin: 1.5rem 0 0;
  color: var(--ink-body);
  font-size: 1.06rem;
  line-height: 1.62;
}

.skip-link {
  position: fixed;
  top: 1rem;
  left: 1rem;
  z-index: 60;
  padding: 0.65rem 0.9rem;
  background: var(--ink);
  color: #fff;
  font-size: 0.85rem;
  transform: translateY(-200%);
}

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

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* 3. HEADER AND NAVIGATION ================================================= */

.site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 2rem;
  align-items: center;
  min-height: 5.4rem;
  padding: 0.9rem clamp(1.25rem, 4vw, 3rem);
  border-bottom: 1px solid var(--rule);
  background: rgba(255, 255, 255, 0.94);
  backdrop-filter: blur(12px);
}

.brand {
  display: inline-flex;
  gap: 0.85rem;
  align-items: center;
  width: fit-content;
}

/* Height only, width auto. This is what stops the starburst squashing. */
.brand-mark {
  display: block;
  flex-shrink: 0;
  height: 3.1rem;
  width: auto;
  border: 0;
  background: none;
}

.brand-mark img {
  height: 100%;
  width: auto;
  max-width: none;
}

.brand-text {
  display: grid;
  gap: 0.1rem;
  line-height: 1.15;
}

.brand-text span:first-child {
  font-family: var(--font-head);
  font-size: 1.06rem;
  font-weight: 800;
  letter-spacing: -0.028em;
}

.brand-text span:last-child {
  font-family: var(--font-section);
  font-size: 0.66rem;
  font-weight: 400;
  color: var(--ink-muted);
}

.primary-nav,
.header-actions {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  font-size: 0.79rem;
  font-weight: 500;
}

.primary-nav {
  justify-content: center;
  scrollbar-width: none;
}

.primary-nav::-webkit-scrollbar {
  display: none;
}

.header-actions {
  justify-content: end;
  color: var(--ink-muted);
}

.header-actions:empty {
  display: none;
}

/* script.js hides the nav while it rebuilds it, then adds .is-hydrated.
   The failsafe animation restores the nav after 1.5s if that never
   happens, so a missing or broken script.js cannot leave it invisible. */
.js-enabled .primary-nav {
  visibility: hidden;
  animation: nav-failsafe 0s linear 1.5s forwards;
}

.js-enabled .primary-nav.is-hydrated {
  visibility: visible;
  animation: none;
}

@keyframes nav-failsafe {
  to { visibility: visible; }
}

.nav-group {
  position: relative;
}

.nav-group summary {
  display: block;
  padding: 0.5rem 0;
  font-weight: 500;
  cursor: pointer;
  list-style: none;
}

.nav-group summary::-webkit-details-marker {
  display: none;
}

.primary-nav a,
.primary-nav summary,
.header-actions a {
  position: relative;
  padding: 0.5rem 0;
  transition: color 160ms ease;
}

.primary-nav a::after,
.primary-nav summary::after,
.header-actions a::after {
  position: absolute;
  right: 50%;
  bottom: 0.2rem;
  left: 50%;
  height: 2px;
  content: "";
  background: var(--red);
  transition: left 180ms ease, right 180ms ease;
}

.primary-nav a:hover::after,
.primary-nav a[aria-current="page"]::after,
.nav-group:hover > summary::after,
.nav-group[open] > summary::after,
.nav-group.is-current > summary::after,
.header-actions a:hover::after {
  right: 0;
  left: 0;
}

.primary-nav a[aria-current="page"],
.nav-group.is-current > summary,
.primary-nav a:hover,
.header-actions a:hover {
  color: var(--red);
}

/* The menu sits flush against the label with its gap made from padding, so
   the mouse never crosses dead space on the way down and the hover holds. */
.dropdown-menu {
  position: absolute;
  top: 100%;
  left: 50%;
  z-index: 45;
  display: none;
  min-width: 17rem;
  margin-top: 0;
  padding: 0.9rem 0 0.4rem;
  transform: translateX(-50%);
}

.dropdown-menu::before {
  position: absolute;
  top: 0.75rem;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: -1;
  content: "";
  border: 1px solid var(--rule-strong);
  background: #fff;
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.09);
}

.nav-group:hover .dropdown-menu,
.nav-group:focus-within .dropdown-menu,
.nav-group[open] .dropdown-menu {
  display: grid;
}

.dropdown-menu a {
  display: block;
  padding: 0.6rem 1rem;
  color: var(--ink-body);
  white-space: nowrap;
}

.dropdown-menu a::after {
  display: none;
}

.dropdown-menu a:hover {
  color: var(--red);
  background: var(--paper-soft);
}

.icon-button {
  display: grid;
  place-items: center;
  width: 2.2rem;
  height: 2.2rem;
  border: 0;
  background: transparent;
}

.search-glyph {
  position: relative;
  width: 0.95rem;
  height: 0.95rem;
  border: 1.7px solid currentColor;
  border-radius: 50%;
}

.search-glyph::after {
  position: absolute;
  right: -0.4rem;
  bottom: -0.3rem;
  width: 0.52rem;
  height: 1.7px;
  content: "";
  background: currentColor;
  transform: rotate(43deg);
}

/* Top-level nav labels navigate; the caret opens the dropdown. */

.nav-group summary {
  display: flex;
  gap: 0.32rem;
  align-items: center;
}

.nav-top-link {
  padding: 0;
  font-weight: 500;
}

.nav-top-link::after {
  display: none;
}

.nav-caret {
  width: 0.34rem;
  height: 0.34rem;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  opacity: 0.5;
  transform: translateY(-0.1rem) rotate(45deg);
  transition: opacity 160ms ease, transform 160ms ease;
}

.nav-group[open] > summary .nav-caret,
.nav-group:hover > summary .nav-caret {
  opacity: 1;
}

.nav-group[open] > summary .nav-caret {
  transform: translateY(0.04rem) rotate(-135deg);
}

.dropdown-menu a:first-child {
  font-weight: 700;
  color: var(--ink);
}

/* 4. SEARCH PANEL ========================================================== */

.search-panel {
  position: sticky;
  top: 5.4rem;
  z-index: 39;
  border-bottom: 1px solid var(--rule);
  background: var(--paper-soft);
}

.search-inner {
  display: grid;
  grid-template-columns: minmax(8rem, 13rem) minmax(14rem, 1fr);
  gap: 1rem;
  align-items: start;
  width: var(--shell);
  margin: 0 auto;
  padding: 1.3rem 0;
}

.search-inner label,
.newsletter label {
  color: var(--red);
  font-family: var(--font-section);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

.search-inner input,
.form-row input {
  width: 100%;
  min-height: 2.8rem;
  border: 0;
  border-bottom: 1px solid var(--rule-strong);
  background: transparent;
}

.search-inner input {
  font-size: 1.3rem;
  font-weight: 500;
  letter-spacing: -0.02em;
}

input[type="search"]::-webkit-search-cancel-button {
  appearance: none;
}

.search-inner input:focus-visible,
.form-row input:focus-visible {
  outline: 0;
  border-bottom-color: var(--red);
  box-shadow: 0 1px 0 var(--red);
}

#searchResults {
  grid-column: 2;
  display: grid;
  gap: 0.9rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

#searchResults li {
  padding-top: 0.7rem;
  border-top: 1px solid var(--rule);
}

#searchResults strong {
  display: block;
  font-weight: 700;
}

#searchResults span {
  display: block;
  color: var(--red);
  font-family: var(--font-section);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

#searchResults p {
  margin: 0.15rem 0 0;
  color: var(--ink-muted);
  font-size: 0.88rem;
}

/* 5. PAGE FRAMES =========================================================== */

main,
.site-footer {
  width: var(--shell);
  margin-inline: auto;
}

.article-main {
  width: min(100% - 2.5rem, 62rem);
}

/* Every page starts the same distance below the header. There are three page
   tops on this site, the homepage, the standard pages, and article and
   newsletter pages, and they all use this. More air above the title than below
   it, so the title reads as the start of the page rather than as a label
   floating over the content. */
.home-front,
.page-hero,
.article-main {
  padding-top: 6.5rem;
}

.page-hero {
  padding-bottom: 1.5rem;
}

.page-hero .eyebrow,
.article-main > .eyebrow {
  margin-bottom: 0.9rem;
}

@media (max-width: 820px) {
  .home-front,
  .page-hero,
  .article-main {
    padding-top: 3.6rem;
  }

  .page-hero {
    padding-bottom: 0.5rem;
  }
}



.page-hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: 3rem;
  align-items: center;
}

/* 6. HOME ================================================================== */

/* The stat rail that used to sit in the second column is gone, so this is a
   single column now. Leaving it at two was squeezing the hero into 70% of the
   page and stopping the full-bleed image short on the right. */
.home-grid {
  display: grid;
  gap: 3.5rem;
  align-items: start;
}

.home-lead {
  display: grid;
  gap: 2.6rem;
}

.lead-copy h1 {
  margin-top: 1.1rem;
}

.link-row,
.footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.8rem 1.8rem;
}

.link-row {
  margin-top: 2rem;
}

.link-row a,
.section-link,
.rail-module a,
.feature-columns a,
.project-major a,
.essay-copy a,
.note a,
.contact-grid a {
  position: relative;
  width: fit-content;
  padding-bottom: 0.2rem;
  font-size: 0.84rem;
  font-weight: 600;
  border-bottom: 2px solid var(--rule-strong);
  transition: border-color 160ms ease, color 160ms ease;
}

.link-row a:first-child {
  border-bottom-color: var(--red);
}

.link-row a:hover,
.section-link:hover,
.rail-module a:hover,
.feature-columns a:hover,
.project-major a:hover,
.contact-grid a:hover {
  border-bottom-color: var(--red);
  color: var(--red);
}

/* Figures. overflow hidden matters, script.js scales these inline. */

.lead-media,
.wide-media,
.publication-visual,
.article-feature-media,
.report-media,
.map-module,
.article-thumb {
  display: block;
  margin: 0;
  overflow: hidden;
  background: var(--paper-soft);
}

.lead-media img,
.wide-media img,
.article-feature-media img,
.report-media img,
.map-module img,
.article-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.lead-media img {
  aspect-ratio: 16 / 10;
}

.wide-media img,
.map-module img {
  aspect-ratio: 4 / 3;
}

figcaption,
.article-credits {
  max-width: 52ch;
  margin-top: 0.8rem;
  color: var(--ink-muted);
  font-size: 0.78rem;
  line-height: 1.5;
}

.front-rail {
  display: grid;
  gap: 2.6rem;
  align-content: start;
}

.rail-module {
  display: grid;
  gap: 0.6rem;
  align-content: start;
}

.rail-module h2 {
  font-family: var(--font-head);
  font-size: 1.16rem;
  font-weight: 800;
  line-height: 1.22;
}

.rail-module p:not(.eyebrow),
.feature-columns p,
.project-network p,
.course-grid p,
.course-strip p,
.person-profile p,
.grant-list p,
.contact-grid p,
.publication-list p,
.publication-feature p,
.news-list p,
.news-archive p,
.two-up p,
.report-body p {
  margin: 0;
  color: var(--ink-body);
  font-size: 0.93rem;
  line-height: 1.62;
}

.stat-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1.2rem;
  margin-top: 0.4rem;
}

.stat-grid span {
  display: grid;
  gap: 0.1rem;
  color: var(--ink-muted);
  font-family: var(--font-section);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.stat-grid strong {
  color: var(--ink);
  font-size: 2.1rem;
  font-weight: 900;
  line-height: 1;
  letter-spacing: -0.035em;
}

/* 7. SECTIONS ============================================================== */

.module-band,
.split-band,
.intro-section,
.page-block,
.project-network,
.people-directory,
.newsletter-panel,
.two-up,
.report-shell,
.research-index,
.news-archive,
.publication-layout {
  padding: 4rem 0;
}

/* Kicker above the heading, everything flush left. The old three-column
   version put the kicker in its own column, which indented the heading away
   from the left edge that the rest of the site lines up on. */
.section-header {
  display: grid;
  gap: 0.5rem;
  justify-items: start;
  margin-bottom: 2.6rem;
  padding-top: 1.4rem;
  border-top: 2px solid var(--ink);
}

.section-header .section-link {
  margin-top: 0.5rem;
}

.section-header.compact,
.split-band,
.newsletter-panel {
  display: grid;
  grid-template-columns: minmax(12rem, 0.34fr) minmax(22rem, 1fr);
  gap: 3rem;
  align-items: start;
}

.section-header h2,
.split-band h2,
.module-band h2,
.intro-section h2,
.two-up h2,
.newsletter-panel h2 {
  font-family: var(--font-section);
  font-size: 2.2rem;
  font-weight: 700;
  line-height: 1.12;
}

.section-header p:not(.section-label),
.newsletter-panel p,
.note {
  max-width: var(--measure);
  margin: 0;
  color: var(--ink-body);
  font-size: 0.95rem;
}

.split-band > .section-link {
  grid-column: 2;
}

/* Column sets. No boxes, no rules, no bars. Space separates them. */

.feature-columns,
.course-strip,
.course-grid,
.contact-grid,
.two-up,
.project-network {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 3rem 2.6rem;
}

.course-grid {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

.feature-columns article,
.course-strip article,
.course-grid article,
.contact-grid article,
.two-up article,
.project-network article {
  display: grid;
  gap: 0.55rem;
  align-content: start;
}

/* The bare <span> kicker inside those articles, styled as an eyebrow. */
.feature-columns article > span,
.course-strip article > span,
.course-grid article > span,
.project-network article > span,
.publication-list article > span {
  color: var(--red);
  font-family: var(--font-section);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

.project-major h2 {
  font-family: var(--font-head);
  font-size: 1.7rem;
  font-weight: 800;
}

.intro-columns {
  display: grid;
  grid-template-columns: minmax(16rem, 0.8fr) minmax(22rem, 1.2fr);
  gap: 4rem;
}

.opening {
  max-width: 18ch;
  margin: 0;
  font-family: var(--font-section);
  font-size: 2.3rem;
  font-weight: 700;
  line-height: 1.14;
  letter-spacing: -0.02em;
}

.essay-copy {
  max-width: var(--measure);
  columns: 2 17rem;
  column-gap: 2.6rem;
  color: var(--ink-body);
}

.essay-copy.single {
  columns: auto;
}

.essay-copy p {
  break-inside: avoid;
  margin: 0 0 1.1rem;
}

/* Research rows. The accent-* classes stay in the HTML and stay valid. */

.accent-slate,
.accent-bronze,
.accent-green,
.accent-red {
  --accent: var(--red);
}

/* A hub on the research page. Text leads on the left so the page keeps one
   left edge, with the hub photograph beside it. Deliberately different from a
   hub page, where the image is a full-width banner. */
.research-row {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(15rem, 0.72fr);
  gap: 3rem;
  align-items: stretch;
  padding: 2.8rem 0;
  border-top: 1px solid var(--rule);
}

/* The Explore link is pinned to the foot of the column so it lands in the same
   place in every row, whether a hub has one node or three. */
.research-copy {
  display: flex;
  flex-direction: column;
}

.research-copy .hub-link {
  margin-top: auto;
  padding-top: 1.6rem;
}

.research-dek {
  margin: 0.5rem 0 1.6rem;
  max-width: 40rem;
  color: var(--ink-body, #3a3a3a);
  font-size: 1.02rem;
  line-height: 1.55;
}

/* Nodes are indented behind a single hairline and labelled in field green, so
   they read as parts of the hub rather than as more headings competing with
   it. A rule between every node made the column look crowded, so the
   separation is now spacing and colour instead. */
.research-nodes {
  list-style: none;
  margin: 0;
  padding: 0 0 0 1.4rem;
  border-left: 2px solid var(--field);
  display: grid;
  gap: 1.05rem;
}

.node-name {
  display: block;
  font-family: var(--font-section);
  font-size: 0.88rem;
  font-weight: 700;
  color: var(--ink);
}

.node-blurb {
  display: block;
  margin-top: 0.1rem;
  color: var(--ink-muted);
  font-size: 0.88rem;
  line-height: 1.45;
}

.research-media {
  margin: 0;
}

/* The photograph fills the height of the row, so the two columns end level
   with each other rather than one running past the other. */
.research-media img {
  display: block;
  width: 100%;
  height: 100%;
  min-height: 15rem;
  object-fit: cover;
}

@media (max-width: 900px) {
  .research-row {
    grid-template-columns: minmax(0, 1fr);
    gap: 1.6rem;
  }

  .research-media {
    order: -1;
  }

  .research-media img {
    height: auto;
    aspect-ratio: 16 / 9;
  }

  .research-copy .hub-link {
    padding-top: 1.2rem;
  }
}

.research-row:first-child {
  border-top: 0;
}


.research-row h2 {
  font-family: var(--font-head);
  font-size: 1.75rem;
  font-weight: 800;
}

.research-row p {
  max-width: var(--measure);
  margin: 0.7rem 0 0;
  color: var(--ink-body);
  font-size: 0.95rem;
}

.research-row .research-dek {
  margin: 0.55rem 0 1.7rem;
}

/* 8. LISTS AND DIRECTORIES ================================================= */

.news-list,
.publication-list {
  display: grid;
  gap: 2.4rem;
}

.news-list article,
.publication-list article {
  display: grid;
  grid-template-columns: minmax(6.5rem, 8rem) minmax(0, 1fr);
  gap: 0.4rem 1.4rem;
  align-items: start;
}

.news-list article > .article-thumb,
.publication-list article > .article-thumb {
  grid-column: 1;
  grid-row: 1 / span 4;
  width: 100%;
}

.news-list article > .article-thumb img,
.publication-list article > .article-thumb img,
.news-archive article > .article-thumb img {
  aspect-ratio: 1 / 1;
}

.news-list article > time,
.news-list article > h3,
.news-list article > h2,
.news-list article > p,
.publication-list article > span,
.publication-list article > h3,
.publication-list article > p {
  grid-column: 2;
}

.news-list time,
.news-archive time {
  color: var(--red);
  font-family: var(--font-section);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

.news-list h3,
.publication-list h3,
.news-archive h2 {
  margin: 0.15rem 0 0.3rem;
  font-family: var(--font-head);
  font-size: 1.16rem;
  font-weight: 800;
  line-height: 1.22;
}

.news-list h3 a:hover,
.publication-list h3 a:hover,
.news-archive h2 a:hover,
.link-table a:hover,
.about-index a:hover,
.people-anchor-list a:hover {
  color: var(--red);
}

.news-archive {
  display: grid;
  gap: 2.6rem;
}

.news-archive article {
  display: grid;
  grid-template-columns: minmax(6.5rem, 8rem) minmax(5rem, 0.16fr) minmax(18rem, 0.68fr) minmax(14rem, 0.42fr);
  gap: 0.4rem 1.6rem;
  align-items: start;
}

/* The filter hides items with the hidden attribute. The browser default for
   that is display:none, but the rule above sets display:grid and wins, so the
   items stay on screen. This puts it back. */
.news-archive article[hidden] {
  display: none;
}

.news-archive article > .article-thumb {
  grid-column: 1;
  grid-row: 1 / span 2;
  width: 100%;
}

.news-archive article > time {
  grid-column: 2;
  grid-row: 1;
}

.news-archive article > .article-tag {
  grid-column: 2;
  grid-row: 2;
}

.news-archive article > h2 {
  grid-column: 3;
  grid-row: 1 / span 2;
  font-size: 1.4rem;
}

.news-archive article > p:not(.article-tag) {
  grid-column: 4;
  grid-row: 1 / span 2;
}

/* The small category label under each date. Same kicker treatment as the
   section labels, in field green so it reads as a tag rather than a link. */
.article-tag {
  margin: 0;
  color: var(--field-green, #7b8a74);
  font-family: var(--font-section);
  font-size: 0.66rem;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

/* Filter row above the list. Text buttons rather than ghost buttons, so a
   dormant filter does not read as a disabled control. */
.filter-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 1.6rem;
  margin: 1.4rem 0 2.6rem;
  padding: 0 0 1.4rem;
  border-bottom: 2px solid #000;
}

.filter-chip {
  padding: 0;
  border: 0;
  border-bottom: 2px solid transparent;
  background: none;
  color: #000;
  font-family: var(--font-section);
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  cursor: pointer;
}

.filter-chip:hover {
  color: var(--red);
}

.filter-chip.is-active {
  color: var(--red);
  border-bottom-color: var(--red);
}

.filter-empty {
  margin: 0 0 2.6rem;
  color: var(--ink-body, #333);
}

/* Paging is a fade rather than a slide. The items stay in one grid, so nothing
   sits offscreen and there is no horizontal overflow to clip. */
.news-archive {
  transition: opacity 0.16s ease;
}

.news-archive.is-turning {
  opacity: 0;
}

/* Page control, above the list so paging never means scrolling down. */
.news-dots {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.1rem;
  margin: -1.4rem 0 0;
}

.news-dots[hidden] {
  display: none;
}

.dot-row {
  display: flex;
  align-items: center;
  gap: 0.7rem;
}

.dot {
  width: 0.62rem;
  height: 0.62rem;
  padding: 0;
  border: 1.5px solid #000;
  border-radius: 50%;
  background: none;
  cursor: pointer;
  transition: background-color 0.2s ease, border-color 0.2s ease, transform 0.2s ease;
}

.dot:hover {
  border-color: var(--red);
  background: var(--red);
}

.dot.is-current {
  border-color: var(--red);
  background: var(--red);
  transform: scale(1.35);
  cursor: default;
}

.dot-arrow {
  padding: 0;
  border: 0;
  background: none;
  color: var(--red);
  font-size: 1.05rem;
  line-height: 1;
  cursor: pointer;
}

.dot-arrow:hover:not(:disabled) {
  transform: translateY(-1px);
}

.dot-arrow:disabled {
  color: #b9b9b9;
  cursor: default;
}

.dot-count {
  flex-basis: 100%;
  margin: 0.3rem 0 0;
  color: var(--ink-body, #333);
  font-size: 0.85rem;
}

@media (prefers-reduced-motion: reduce) {
  .news-archive,
  .dot {
    transition: none;
  }
}

.publication-layout {
  display: grid;
  grid-template-columns: minmax(18rem, 0.85fr) minmax(18rem, 1fr);
  gap: 3rem;
}

.publication-feature {
  display: grid;
  gap: 0.7rem;
  align-content: start;
}

.publication-feature h2 {
  font-family: var(--font-head);
  font-size: 1.9rem;
  font-weight: 800;
}

.metadata {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1rem;
  margin: 1.2rem 0 0;
  padding-top: 1.1rem;
  border-top: 1px solid var(--rule);
}

.metadata div {
  display: grid;
  gap: 0.2rem;
}

.metadata dt {
  color: var(--red);
  font-family: var(--font-section);
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

.metadata dd {
  margin: 0;
  font-size: 0.86rem;
  font-weight: 600;
}

.people-directory {
  display: grid;
  gap: 3.2rem;
}

.person-profile {
  display: grid;
  grid-template-columns: minmax(10rem, 0.26fr) minmax(20rem, 1fr);
  gap: 2.5rem;
  align-items: start;
}

.person-profile figure {
  margin: 0;
  overflow: hidden;
  background: var(--paper-soft);
}

.person-profile img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
}

.person-profile h2 {
  margin-top: 0.3rem;
  font-family: var(--font-head);
  font-size: 1.85rem;
  font-weight: 800;
}

.person-profile p {
  max-width: 74ch;
  margin: 0.9rem 0 0;
}

/* The generic rule above was pushing the role line down, so it no longer sat
   level with the top of the headshot. */
.person-profile .eyebrow {
  margin-top: 0;
}

/* Vertical link lists. Dividers here are functional, not decorative. */

.link-table,
.method-list,
.grant-list {
  display: grid;
  align-content: start;
}

/* Section jump lists. One compact row rather than a full-width stack, which
   was pushing the actual page content below the fold. */
.about-index,
.people-anchor-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem 1.7rem;
  margin: 1.4rem 0 1rem;
  padding: 0 0 1.4rem;
  border-bottom: 2px solid #000;
}

.about-index a,
.people-anchor-list a {
  padding: 0;
  border: 0;
  font-family: var(--font-section);
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  text-decoration: none;
  border-bottom: 2px solid transparent;
}

.about-index a:hover,
.people-anchor-list a:hover {
  color: var(--red);
  border-bottom-color: var(--red);
}

.link-table a {
  padding: 1rem 0;
  border-top: 1px solid var(--rule);
  font-size: 0.92rem;
  font-weight: 600;
}

.link-table a:first-child {
  border-top: 0;
}

.method-list div,
.grant-list article {
  padding: 1.2rem 0;
  border-top: 1px solid var(--rule);
}

.method-list div {
  display: grid;
  grid-template-columns: 3.5rem 1fr;
  gap: 0.3rem 1.5rem;
}

.grant-list article {
  font-weight: 700;
}

.method-list div:first-child,
.grant-list article:first-child {
  border-top: 0;
}

.method-list span {
  color: var(--red);
  font-family: var(--font-section);
  font-size: 0.82rem;
  font-weight: 800;
}

.method-list p {
  margin: 0;
  color: var(--ink-body);
  font-size: 0.95rem;
}

.grant-list p {
  margin: 0.3rem 0 0;
  font-weight: 400;
}

.grant-list h3 {
  margin: 0;
  font-size: 1.05rem;
}

/* Newsletter form */

.newsletter {
  display: grid;
  gap: 1rem;
}

.form-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0.9rem;
}

.form-row.two {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.form-row button {
  min-width: 8rem;
  min-height: 2.9rem;
  padding: 0 1.4rem;
  border: 0;
  background: var(--ink);
  color: #fff;
  font-size: 0.85rem;
  font-weight: 600;
  transition: background 160ms ease;
}

.form-row button:hover {
  background: var(--red);
}

#newsletterStatus {
  min-height: 1.3rem;
  margin: 0;
  color: var(--red);
  font-size: 0.85rem;
  font-weight: 600;
}

/* The one full-bleed black moment on the site. */

.quote-band {
  display: grid;
  grid-template-columns: minmax(7rem, 0.22fr) minmax(0, 1fr);
  gap: 3rem;
  align-items: center;
  margin-inline: calc(var(--bleed) * -1);
  padding: 4.6rem var(--bleed);
  background: var(--ink);
  color: #fff;
}

.quote-band blockquote {
  max-width: 34ch;
  margin: 0;
  font-family: var(--font-section);
  font-size: 2rem;
  font-weight: 400;
  line-height: 1.32;
  letter-spacing: -0.015em;
}

.quote-band p {
  margin: 1.4rem 0 0;
  color: var(--sand);
  font-family: var(--font-section);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* 9. LONG-FORM PAGES ======================================================= */

.report-shell {
  max-width: 62rem;
  margin-inline: auto;
}

.report-shell h1 {
  max-width: 18ch;
  font-size: clamp(2.4rem, 4.6vw, 3.6rem);
}

.report-abstract {
  max-width: 56ch;
  margin: 2rem 0;
  color: var(--ink-body);
  font-size: 1.4rem;
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: -0.015em;
}

.report-body,
.article-prose {
  display: grid;
  gap: 1.1rem;
  max-width: var(--measure);
  margin-top: 2.4rem;
  padding-top: 2rem;
  border-top: 1px solid var(--rule);
  color: var(--ink-body);
}

.report-body h2,
.article-prose h2 {
  margin-top: 1.6rem;
  font-family: var(--font-section);
  font-size: 1.5rem;
  color: var(--ink);
}

.article-prose p {
  margin: 0;
  font-size: 1rem;
  line-height: 1.72;
}

.article-prose a {
  color: var(--red);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.16em;
}

/* The photograph at the top of an article, and a publication cover, are the
   one place the whole image should be visible. Forcing them into a 16:9 crop
   beheaded every portrait photo. They now show at their own proportions,
   capped in height so a tall one cannot take over the page. */
.article-feature-media,
.report-media {
  display: flex;
  justify-content: flex-start;
  align-items: flex-start;
  background: none;
}

.article-feature-media img,
.report-media img {
  width: auto;
  max-width: 100%;
  height: auto;
  max-height: 34rem;
  object-fit: contain;
}

/* The labelled box shown when an article has no photograph keeps its fixed
   shape and its fill, since there is no image to preserve. */
.article-feature-media.is-placeholder {
  display: grid;
  place-items: center;
  aspect-ratio: 16 / 9;
  background: var(--paper-soft);
}

/* 10. FOOTER =============================================================== */

.site-footer {
  display: grid;
  grid-template-columns: minmax(16rem, 1fr) minmax(18rem, 0.7fr);
  gap: 2.5rem;
  margin-top: 3rem;
  padding: 3rem 0 4rem;
  border-top: 2px solid var(--ink);
}

.site-footer p {
  margin: 1.2rem 0 0;
  color: var(--ink-muted);
  font-size: 0.88rem;
  line-height: 1.6;
}


.footer-links {
  align-content: start;
  font-size: 0.85rem;
  font-weight: 600;
}

.footer-links a:hover {
  color: var(--red);
}

/* 11. MOTION =============================================================== */

.reveal {
  opacity: 1;
  transform: none;
}

.js-enabled .reveal {
  opacity: 0.01;
  transform: translateY(1rem);
  transition: opacity 620ms ease, transform 620ms cubic-bezier(0.2, 0.7, 0.2, 1);
  animation: reveal-failsafe 0s linear 2s forwards;
}

.js-enabled .reveal.in-view {
  opacity: 1;
  transform: translateY(0);
  animation: none;
}

/* Same safety net for page content. Without it, a missing script.js
   would leave most sections permanently invisible. */
@keyframes reveal-failsafe {
  to { opacity: 1; transform: none; }
}

.page-transition {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  grid-template-columns: 0.82fr 0.18fr;
  pointer-events: none;
  transform: translateX(-105%);
  will-change: transform;
}

.page-transition span:first-child {
  background: var(--ink);
}

.page-transition span:last-child {
  background: var(--red);
}

.page-transition.is-active {
  animation: wipe-cover 340ms cubic-bezier(0.72, 0, 0.22, 1) forwards;
}

.page-transition.is-returning {
  transform: translateX(0);
  animation: wipe-reveal 520ms cubic-bezier(0.2, 0.75, 0.18, 1) forwards;
}

body.is-leaving main {
  opacity: 0.6;
  transform: translateY(0.3rem);
  pointer-events: none;
  transition: opacity 240ms ease, transform 240ms ease;
}

body.is-entering main {
  animation: page-enter 480ms cubic-bezier(0.2, 0.75, 0.18, 1) both;
}

@keyframes wipe-cover {
  from { transform: translateX(-105%); }
  to   { transform: translateX(0); }
}

@keyframes wipe-reveal {
  from { transform: translateX(0); }
  to   { transform: translateX(105%); }
}

@keyframes page-enter {
  from { opacity: 0.3; transform: translateY(0.65rem); }
  to   { opacity: 1; transform: translateY(0); }
}

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

/* 12. RESPONSIVE =========================================================== */

@media (max-width: 1180px) {
  .site-header {
    grid-template-columns: 1fr auto;
    row-gap: 0.4rem;
  }

  .home-grid,
  .page-hero-grid,
  .intro-columns,
  .publication-layout,
  .split-band,
  .section-header,
  .section-header.compact,
  .newsletter-panel {
    grid-template-columns: 1fr;
    gap: 2.4rem;
  }

  .split-band > .section-link {
    grid-column: 1;
  }

  .feature-columns,
  .course-strip,
  .course-grid,
  .contact-grid,
  .two-up,
  .project-network {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .news-archive article {
    grid-template-columns: minmax(6rem, 7.5rem) minmax(0, 1fr);
  }

  .news-archive article > time,
  .news-archive article > .article-tag,
  .news-archive article > h2,
  .news-archive article > p:not(.article-tag) {
    grid-column: 2;
    grid-row: auto;
  }

  .news-archive article > .article-thumb {
    grid-row: 1 / span 4;
  }
}

@media (max-width: 820px) {
  :root {
    --gutter: clamp(2rem, 8vw, 4rem);
  }

  body {
    font-size: 15px;
  }

  .site-header {
    min-height: 4.6rem;
    padding: 0.75rem 1rem;
  }

  .brand-mark {
    height: 2.5rem;
  }

  .brand-text span:first-child {
    font-size: 0.95rem;
  }

  .search-panel {
    top: 7.4rem;
  }

  .search-inner,
  .metadata,
  .stat-grid,
  .research-row,
  .person-profile,
  .form-row,
  .form-row.two,
  .site-footer,
  .feature-columns,
  .course-strip,
  .course-grid,
  .contact-grid,
  .two-up,
  .project-network,
  .method-list div {
    grid-template-columns: 1fr;
  }

  #searchResults {
    grid-column: 1;
  }

  .module-band,
  .split-band,
  .intro-section,
  .page-block,
  .project-network,
  .people-directory,
  .newsletter-panel,
  .two-up,
  .report-shell,
  .research-index,
  .news-archive,
  .publication-layout,
  .quote-band {
    padding-top: 3rem;
    padding-bottom: 3rem;
  }

  .section-header {
    margin-bottom: 2rem;
  }

  .essay-copy {
    columns: auto;
  }

  .person-profile figure {
    max-width: 15rem;
  }

  .quote-band blockquote {
    font-size: 1.6rem;
  }

  .report-abstract {
    font-size: 1.2rem;
  }

  .form-row button {
    width: 100%;
  }
}

@media (max-width: 560px) {
  .news-list article,
  .publication-list article,
  .news-archive article {
    grid-template-columns: 1fr;
    gap: 0.5rem;
  }

  .news-list article > *,
  .publication-list article > *,
  .news-archive article > * {
    grid-column: 1;
    grid-row: auto;
  }

  .news-list article > .article-thumb img,
  .publication-list article > .article-thumb img,
  .news-archive article > .article-thumb img {
    aspect-ratio: 16 / 10;
  }
}

/* ==========================================================================
   PDF documents attached to an article or publication
   ========================================================================== */

.pdf-block {
  margin-top: 3rem;
  padding-top: 2rem;
  border-top: 1px solid var(--rule);
}

.pdf-block h2 {
  max-width: 30ch;
  margin: 0.4rem 0 0.6rem;
  font-family: var(--font-head);
  font-size: 1.5rem;
  font-weight: 800;
}

.pdf-detail {
  margin: 0;
  color: var(--ink-muted);
  font-family: var(--font-section);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.pdf-block .link-row {
  margin: 1.3rem 0 1.8rem;
}

/* The inline reader. Hidden on small screens, where mobile browsers
   render embedded PDFs unreliably and the download link serves better. */
.pdf-viewer {
  display: block;
  width: 100%;
  height: 80vh;
  min-height: 30rem;
  border: 0;
  outline: 1px solid var(--rule-strong);
  background: var(--paper-soft);
}

.pdf-fallback {
  padding: 2rem;
  color: var(--ink-muted);
}

.pdf-fallback a {
  color: var(--red);
  text-decoration: underline;
}

@media (max-width: 820px) {
  .pdf-viewer {
    display: none;
  }
}

/* Anchor links land below the sticky header instead of underneath it. */
[id] {
  scroll-margin-top: 7rem;
}

@media (max-width: 820px) {
  [id] {
    scroll-margin-top: 6rem;
  }
}

/* Section headings on the People directory. The section name appears once.
   Space separates the groups rather than a rule, so the page stays quiet. */
.group-header {
  display: grid;
  gap: 0.6rem;
  margin-bottom: 1.8rem;
}

.group-header h2 {
  font-family: var(--font-section);
  font-size: 1.75rem;
  font-weight: 700;
}

.group-header p {
  margin: 0;
  color: var(--ink-body);
  font-size: 0.95rem;
}

.people-directory {
  padding: 4.2rem 0 0;
}

/* A profile with no headshot spans the full width instead of leaving a gap. */
.person-profile.no-photo {
  grid-template-columns: 1fr;
}

/* ==========================================================================
   Publications listing. Even two-column grid with fixed-ratio thumbnails,
   so cards line up regardless of how tall the source images are.
   ========================================================================== */

.publication-layout {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 3.5rem 3rem;
  align-items: start;
}

.publication-feature {
  display: grid;
  gap: 0.5rem;
  align-content: start;
}

.publication-feature > .article-thumb {
  display: block;
  width: 100%;
  margin-bottom: 0.6rem;
}

.publication-feature > .article-thumb img {
  width: 100%;
  height: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
}

.publication-feature h2 {
  margin: 0;
  font-family: var(--font-head);
  font-size: 1.45rem;
  font-weight: 800;
  line-height: 1.18;
}

.publication-feature .metadata {
  margin-top: 0.9rem;
}

.publication-feature .link-row {
  margin-top: 1.1rem;
}

@media (max-width: 820px) {
  .publication-layout {
    grid-template-columns: 1fr;
    gap: 2.8rem;
  }
}

/* Make a Gift sits apart from the navigation as a call to action. */
.header-actions .gift-link {
  padding: 0.55rem 1.1rem;
  background: var(--red);
  color: #fff;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  transition: background 160ms ease;
}

.header-actions .gift-link::after {
  display: none;
}

.header-actions .gift-link:hover {
  background: var(--ink);
  color: #fff;
}

@media (max-width: 820px) {
  .header-actions .gift-link {
    padding: 0.45rem 0.85rem;
    font-size: 0.72rem;
  }
}

/* ==========================================================================
   Header at medium and small widths.

   The nav previously became a horizontal scroll container below 1180px, and
   a scroll container clips anything positioned inside it, so the dropdown
   panels were being cut off rather than failing to open. The nav now shrinks
   and wraps instead of scrolling, and the header stays on one row for longer.
   ========================================================================== */

@media (max-width: 1180px) {
  .site-header {
    grid-template-columns: auto minmax(0, 1fr) auto;
    gap: 1.2rem;
    row-gap: 0;
    min-height: 4.8rem;
    padding-inline: 1.25rem;
  }

  .primary-nav {
    grid-column: auto;
    justify-content: center;
    flex-wrap: wrap;
    gap: 0.35rem 0.9rem;
    overflow: visible;
    font-size: 0.74rem;
    padding-bottom: 0;
  }

  .brand-mark {
    height: 2.6rem;
  }

  .brand-text span:first-child {
    font-size: 0.92rem;
  }

  .brand-text span:last-child {
    font-size: 0.62rem;
  }
}

/* Below this the three columns stop fitting, so the nav takes its own row.
   It still wraps rather than scrolling, so dropdowns are never clipped. */
@media (max-width: 900px) {
  .site-header {
    grid-template-columns: minmax(0, 1fr) auto;
    row-gap: 0.6rem;
    padding-block: 0.7rem;
  }

  .primary-nav {
    grid-column: 1 / -1;
    justify-content: flex-start;
    gap: 0.3rem 1rem;
  }

  /* On a phone an absolutely positioned panel runs off the side of the screen,
     which is why the menus looked missing. Below this width the panel drops
     into the flow instead and takes a full row of the wrapped nav. */
  /* The panel drops below the whole nav as a full-width sheet rather than
     taking a row of its own. That way the nav items never move when a menu
     opens, which is what made them scatter across three rows. */
  .site-header {
    overflow: visible;
  }

  /* The panel is positioned against the header itself, so it spans the full
     width of the screen rather than only the nav, and no page content shows
     down the side of it. */
  .nav-group {
    position: static;
  }

  /* Menus open on click here, since there is no floating panel to hover into. */
  .nav-group:hover .dropdown-menu,
  .nav-group:focus-within .dropdown-menu {
    display: none;
  }

  .nav-group[open] .dropdown-menu {
    display: grid;
  }

  /* One tap or click opens the menu rather than following the link, on a mouse
     as well as a touch screen. The section page is reachable from the first
     item inside, "All News", "All Publications" and so on. */
  .nav-top-link {
    pointer-events: none;
  }

  .dropdown-menu {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    width: auto;
    min-width: 0;
    z-index: 60;
    padding: 0.6rem 0 0.8rem var(--bleed, 1.25rem);
    background: var(--paper);
    border-top: 2px solid var(--red);
    box-shadow: 0 14px 28px rgba(0, 0, 0, 0.12);
    transform: none;
  }

  .dropdown-menu::before {
    display: none;
  }

  .dropdown-menu a {
    padding: 0.42rem 0;
  }

  /* The jump rows wrap onto several lines on a narrow screen, so they need
     tighter, more even spacing than they do on a desktop. */
  .about-index,
  .people-anchor-list,
  .filter-bar,
  .hub-bar {
    gap: 0.55rem 1.1rem;
    padding-bottom: 1rem;
  }

  .about-index a,
  .people-anchor-list a,
  .hub-bar a {
    font-size: 0.68rem;
    letter-spacing: 0.07em;
  }
}

@media (max-width: 560px) {
  .primary-nav {
    font-size: 0.72rem;
    gap: 0.25rem 0.85rem;
  }

  .header-actions .gift-link {
    padding: 0.4rem 0.7rem;
    font-size: 0.68rem;
  }
}

/* ==========================================================================
   Newsletter issues. Sections are optional and come from the content file,
   so a month with no events simply omits that block.
   ========================================================================== */

.newsletter .nl-section {
  margin-top: 3.2rem;
  padding-top: 1.6rem;
  border-top: 2px solid var(--ink);
}

.newsletter .nl-section h2 {
  font-family: var(--font-section);
  font-size: 1.5rem;
  font-weight: 700;
}

.newsletter .nl-note {
  max-width: var(--measure);
  margin: 0.6rem 0 0;
  color: var(--ink-body);
  font-size: 0.95rem;
}

.nl-items {
  display: grid;
  gap: 2.2rem;
  margin-top: 1.6rem;
}

.nl-item {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 1.2rem;
  align-items: start;
}

.nl-item:has(figure) {
  grid-template-columns: minmax(7rem, 11rem) minmax(0, 1fr);
}

.nl-item figure {
  margin: 0;
  overflow: hidden;
  background: var(--paper-soft);
}

.nl-item figure img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

.nl-meta {
  margin: 0 0 0.3rem;
  color: var(--red);
  font-family: var(--font-section);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

.nl-item h3 {
  margin: 0 0 0.4rem;
  font-size: 1.16rem;
}

.nl-item p:not(.nl-meta):not(.link-row) {
  max-width: var(--measure);
  margin: 0;
  color: var(--ink-body);
  font-size: 0.93rem;
  line-height: 1.62;
}

.nl-item .link-row {
  margin-top: 0.8rem;
}

/* Community updates. A name column keeps a long run scannable. */
.nl-updates {
  margin-top: 1.4rem;
}

.nl-update {
  display: grid;
  grid-template-columns: minmax(9rem, 12rem) minmax(0, 1fr);
  gap: 1.2rem;
  padding: 0.9rem 0;
  border-top: 1px solid var(--rule);
}

.nl-update:first-child {
  border-top: 0;
}

.nl-who {
  margin: 0;
  font-size: 0.86rem;
  font-weight: 700;
}

.nl-update p:not(.nl-who) {
  margin: 0;
  color: var(--ink-body);
  font-size: 0.92rem;
  line-height: 1.6;
}

.nl-update a {
  color: var(--red);
  text-decoration: underline;
  text-underline-offset: 0.16em;
}

/* Newsletter archive. A row per year, twelve months across, so the issues
   you have and the gaps between them are both visible at a glance. */

.nl-archive {
  display: grid;
  gap: 1.6rem;
  max-width: var(--measure);
  margin-top: 1.8rem;
}

.nl-year {
  display: grid;
  grid-template-columns: 4.5rem minmax(0, 1fr);
  gap: 1.2rem;
  align-items: baseline;
  padding-top: 1rem;
  border-top: 1px solid var(--rule);
}

.nl-year-label {
  margin: 0;
  font-size: 1.5rem;
  font-weight: 900;
  letter-spacing: -0.03em;
}

.nl-months {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: 0.3rem;
}

.nl-months a,
.nl-months span {
  display: grid;
  place-items: center;
  padding: 0.5rem 0.1rem;
  font-family: var(--font-section);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  text-transform: uppercase;
}

.nl-months a {
  background: var(--red);
  color: #fff;
  transition: background 160ms ease;
}

.nl-months a:hover {
  background: var(--ink);
}

.nl-months span {
  color: #c9c9c9;
  background: var(--paper-soft);
}

@media (max-width: 820px) {
  .nl-item:has(figure),
  .nl-update,
  .newsletter-archive a {
    grid-template-columns: 1fr;
    gap: 0.5rem;
  }

  .nl-item figure {
    max-width: 12rem;
  }
}

@media (max-width: 700px) {
  .nl-year {
    grid-template-columns: 1fr;
    gap: 0.6rem;
  }

  .nl-months {
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: 0.25rem;
  }
}

/* ==========================================================================
   Image placeholders. Shown when a news item has no photo yet, so the
   layout holds. Adding an "image:" line to the file replaces it.
   ========================================================================== */

.article-thumb.is-placeholder,
.article-feature-media.is-placeholder {
  display: grid;
  place-items: center;
  background: var(--paper-soft);
  outline: 1px solid var(--rule);
}

.article-thumb.is-placeholder {
  aspect-ratio: 1 / 1;
}

.article-feature-media.is-placeholder {
  aspect-ratio: 16 / 9;
}

.article-thumb.is-placeholder span,
.article-feature-media.is-placeholder span {
  padding: 0 0.6rem;
  color: #b8b8b8;
  font-family: var(--font-section);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-align: center;
  text-transform: uppercase;
}

.article-feature-media.is-placeholder span {
  font-size: 0.78rem;
}

@media (max-width: 560px) {
  .article-thumb.is-placeholder {
    aspect-ratio: 16 / 10;
  }
}

/* ==========================================================================
   Section headers that sit flush left, matching the page hero above them.
   Used where a two-column header would push the heading off the left edge.
   ========================================================================== */

.block-header {
  margin-bottom: 2rem;
  padding-top: 2.2rem;
  border-top: 2px solid var(--ink);
}

.block-header h2 {
  margin: 0.5rem 0 0;
  font-family: var(--font-section);
  font-size: 1.75rem;
  font-weight: 700;
}

.block-header p:not(.section-label) {
  margin: 0.6rem 0 0;
  color: var(--ink-body);
  font-size: 0.95rem;
  line-height: 1.6;
}

/* Every block on a listing page shares one content column, so the left and
   right edges line up down the whole page rather than section by section. */
.block-header,
.news-archive,
.news-list,
.nl-archive {
  max-width: var(--content-col);
}

/* Featured annual report on the homepage. Cover on the left, summary beside it,
   collapsing to a single column on narrow screens. */
.report-feature {
  display: grid;
  grid-template-columns: minmax(11rem, 15rem) minmax(0, 1fr);
  gap: 2.4rem;
  align-items: start;
}

.report-cover img {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid #e2e2e2;
}

.report-copy p {
  margin: 0 0 1rem;
  max-width: 42rem;
}

@media (max-width: 820px) {
  .report-feature {
    grid-template-columns: minmax(0, 1fr);
    gap: 1.6rem;
  }

  .report-cover {
    max-width: 14rem;
  }
}

/* Grants list on the About page. Funder, amount and period across the top row,
   the detail beneath, collapsing to a single column on narrow screens. */
.grant-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 1.8rem;
}

.grant-list li {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(6rem, 0.4fr) minmax(5rem, 0.35fr);
  gap: 0.3rem 1.6rem;
  padding-top: 1.4rem;
  border-top: 1px solid #d8d8d8;
}

.grant-funder {
  grid-column: 1;
  margin: 0;
  font-weight: 600;
}

.grant-amount {
  grid-column: 2;
  margin: 0;
  font-family: var(--font-section);
  font-weight: 700;
  color: var(--red);
}

.grant-period {
  grid-column: 3;
  margin: 0;
  font-family: var(--font-section);
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-body, #444);
}

.grant-detail {
  grid-column: 1 / -1;
  margin: 0.2rem 0 0;
  max-width: 46rem;
  color: var(--ink-body, #333);
}

@media (max-width: 820px) {
  .grant-list li {
    grid-template-columns: minmax(0, 1fr) auto;
  }

  .grant-funder { grid-column: 1; }
  .grant-amount { grid-column: 2; }
  .grant-period { grid-column: 1 / -1; }
}

/* Individual research hub pages. Description on the left, focus list beside it. */
.hub-intro {
  display: block;
}

.hub-body p {
  margin: 0 0 1.1rem;
  max-width: 44rem;
}

.hub-nodes {
  list-style: none;
  margin: 0.8rem 0 0;
  padding: 0;
  display: grid;
  gap: 0.55rem;
}

.hub-nodes li {
  padding-bottom: 0.55rem;
  border-bottom: 1px solid #e4e4e4;
  font-family: var(--font-section);
  font-size: 0.84rem;
}

.hub-link {
  margin-top: 0.9rem;
}



/* Hub team. A short team lays out as a normal row. Once it passes five people
   the strip scrolls sideways, which is native browser scrolling, so it still
   works if the arrow script never runs. */
.team-strip {
  position: relative;
}

.team-track {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(9.5rem, 1fr);
  gap: 1.6rem;
}

.team-strip.is-slider .team-track {
  grid-auto-columns: 9.5rem;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  scroll-padding-left: 0;
  padding-bottom: 1rem;
  scrollbar-width: thin;
}

.team-strip.is-slider .team-card {
  scroll-snap-align: start;
}

.team-card {
  position: relative;
  display: block;
  text-decoration: none;
  color: inherit;
}

/* Divides the hub leads from the rest of the team. It sits in the gap between
   two cards, so it separates them without shifting anything. */
.team-card.starts-members::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: -0.8rem;
  border-left: 1px solid #dcdcdc;
}

.team-card img,
.team-nophoto {
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  background: #efefef;
  transition: filter 0.2s ease;
}

.team-card:hover img {
  filter: grayscale(100%);
}

.team-name {
  margin: 0.7rem 0 0.15rem;
  font-weight: 600;
  font-size: 0.95rem;
  line-height: 1.25;
}

.team-card:hover .team-name {
  color: var(--red);
}

.team-role {
  margin: 0;
  font-family: var(--font-section);
  font-size: 0.7rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-body, #555);
}

.team-controls {
  display: flex;
  gap: 1rem;
  margin-top: 1rem;
}

.team-arrow {
  padding: 0;
  border: 0;
  background: none;
  color: var(--red);
  font-size: 1.05rem;
  line-height: 1;
  cursor: pointer;
}

.team-arrow:disabled {
  color: #b9b9b9;
  cursor: default;
}

@media (max-width: 820px) {
  .team-track,
  .team-strip.is-slider .team-track {
    grid-auto-columns: 8rem;
    overflow-x: auto;
  }
}

/* The header is sticky, so an anchored profile needs room above it or the jump
   lands with the name hidden behind the header. */
.person-profile,
.people-directory {
  scroll-margin-top: 7rem;
}

/* Hidden overflow items on a hub news list, and the button that reveals them.
   Without this the [hidden] attribute loses to the grid display rule. */
.news-list article[hidden] {
  display: none;
}

.show-all {
  padding: 0;
  border: 0;
  border-bottom: 1px solid var(--red);
  background: none;
  color: var(--red);
  font: inherit;
  cursor: pointer;
}

/* Junior Fellow recruitment on the About page. */
.jobs-feature {
  display: grid;
  grid-template-columns: minmax(0, 1.7fr) minmax(13rem, 0.55fr);
  gap: 3rem;
  align-items: start;
}

.jobs-copy h3 {
  margin: 0 0 0.9rem;
  font-size: 1.35rem;
}

.jobs-copy p {
  margin: 0 0 1.1rem;
  max-width: 44rem;
}

.jobs-facts {
  list-style: none;
  margin: 0.8rem 0 1.4rem;
  padding: 0;
  display: grid;
  gap: 0.9rem;
}

.jobs-facts li {
  padding-bottom: 0.9rem;
  border-bottom: 1px solid #e4e4e4;
  font-size: 0.9rem;
  line-height: 1.4;
}

.jobs-facts span {
  display: block;
  font-family: var(--font-section);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--red);
}

.jobs-other {
  margin: 2.4rem 0 0;
  padding-top: 1.4rem;
  border-top: 1px solid #d8d8d8;
  max-width: 44rem;
  color: var(--ink-body, #444);
}

@media (max-width: 900px) {
  .jobs-feature {
    grid-template-columns: minmax(0, 1fr);
    gap: 2rem;
  }
}

/* Hub banner on the research page. Same treatment as the jump rows on People
   and About. */
.hub-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem 1.6rem;
  margin: 1.4rem 0 1rem;
  padding: 0 0 1.4rem;
  border-bottom: 2px solid #000;
}

.hub-bar a {
  display: inline-flex;
  align-items: baseline;
  padding: 0;
  border: 0;
  border-bottom: 2px solid transparent;
  color: #000;
  font-family: var(--font-section);
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  text-decoration: none;
}

.hub-bar a:hover {
  color: var(--red);
  border-bottom-color: var(--red);
}

/* The header is sticky, so a hub jumped to needs room above it. */
.research-row {
  scroll-margin-top: 7rem;
}

/* Research hub carousel on the homepage. Native sideways scrolling, so swipe
   and trackpad work whether or not the arrow script runs. */
.hub-strip {
  position: relative;
}

.hub-track {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(17rem, 20rem);
  gap: 1.6rem;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  padding-bottom: 1rem;
  scrollbar-width: thin;
}

.hub-card {
  display: flex;
  flex-direction: column;
  padding: 0;
  border: 1px solid #ddd;
  background: none;
  color: inherit;
  text-decoration: none;
  scroll-snap-align: start;
  transition: border-color 0.2s ease, background-color 0.2s ease;
}

.hub-card:hover {
  border-color: var(--red);
  background: var(--paper-soft, #faf9f7);
}

.hub-card-name {
  margin: 0;
  font-family: var(--font-section);
  font-size: 1.12rem;
  font-weight: 700;
  line-height: 1.2;
}

.hub-card:hover .hub-card-name {
  color: var(--red);
}

.hub-card-dek {
  margin: 0;
  color: var(--ink-body, #444);
  font-size: 0.9rem;
  line-height: 1.45;
}

.hub-card-nodes {
  list-style: none;
  margin: 0.2rem 0 auto;
  padding: 0;
  display: grid;
  gap: 0.35rem;
}

.hub-card-nodes li {
  font-family: var(--font-section);
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-body, #666);
}

.hub-card-go {
  margin-top: 1rem;
  padding-top: 0.7rem;
  border-top: 1px solid #e2e2e2;
  color: var(--red);
  font-family: var(--font-section);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

.hub-controls {
  display: flex;
  gap: 1rem;
  margin-top: 1rem;
}

.hub-arrow {
  padding: 0;
  border: 0;
  background: none;
  color: var(--red);
  font-size: 1.05rem;
  line-height: 1;
  cursor: pointer;
}

.hub-arrow:disabled {
  color: #b9b9b9;
  cursor: default;
}

/* Annual report figures, attributed to the year so they stay true. */
.report-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
  gap: 1.4rem 2rem;
  margin: 2rem 0 0;
  padding-top: 1.4rem;
  border-top: 1px solid #d8d8d8;
}

.report-stats div {
  display: grid;
  gap: 0.25rem;
}

.report-stats dt {
  font-family: var(--font-head);
  font-size: 1.9rem;
  font-weight: 900;
  letter-spacing: -0.03em;
  line-height: 1;
}

.report-stats dd {
  margin: 0;
  color: var(--ink-body, #555);
  font-size: 0.82rem;
  line-height: 1.35;
}

/* Pull quote band. */
.quote-band figure {
  margin: 0;
  max-width: 54rem;
}

/* The quotation mark sits on its own line above the text. Floating it beside
   the first line meant it landed on top of the first word. */
.quote-band blockquote {
  margin: 0;
  font-family: var(--font-head);
  font-size: clamp(1.5rem, 2.8vw, 2.2rem);
  font-weight: 800;
  line-height: 1.22;
  letter-spacing: -0.02em;
}

.quote-band blockquote::before {
  content: "\201C";
  display: block;
  margin-bottom: -0.28em;
  color: var(--sand, #bbab7e);
  font-size: 2.6em;
  line-height: 0.8;
}

.quote-band figcaption {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.6rem;
  margin: 2rem 0 0;
  padding-top: 1.1rem;
  border-top: 1px solid rgba(255, 255, 255, 0.28);
}

.quote-name {
  font-family: var(--font-section);
  font-size: 0.86rem;
  font-weight: 700;
  letter-spacing: 0.04em;
}

.quote-role {
  color: var(--sand, #bbab7e);
  font-family: var(--font-section);
  font-size: 0.72rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

@media (max-width: 820px) {
  .hub-track {
    grid-auto-columns: minmax(14rem, 16rem);
  }

  .quote-band blockquote::before {
    font-size: 2.2em;
  }
}

/* Hub imagery. Cards crop to a band at the top; hub pages run a wider banner. */
/* Full width of the card. The padding lives on the body below, so the image
   needs no negative margins and cannot fall short of the edges. */
.hub-card-media {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

.hub-card-body {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 0.7rem;
  padding: 1.5rem 1.5rem 1.4rem;
}

.hub-hero {
  margin: 0 0 2.4rem;
}

.hub-hero img {
  display: block;
  width: 100%;
  aspect-ratio: 21 / 9;
  object-fit: cover;
}

@media (max-width: 820px) {
  .hub-hero img {
    aspect-ratio: 16 / 9;
  }
}

/* Homepage hero. The image runs the full content width beneath the headline
   rather than sitting as a stranded block, and carries a caption so it does
   some work rather than only decorating. */
.home-lead {
  gap: 2rem;
}

.lead-media img {
  display: block;
  width: 100%;
  aspect-ratio: 21 / 9;
  object-fit: cover;
}

.lead-media figcaption {
  max-width: 46rem;
  margin-top: 0.5rem;
  color: var(--ink-muted, #8a8a8a);
  font-size: 0.7rem;
  line-height: 1.4;
}

@media (max-width: 900px) {
  .lead-media img {
    aspect-ratio: 16 / 9;
  }
}

/* The course running next, marked out from the full catalogue. */
.course-next {
  border-left: 3px solid var(--red);
  padding-left: 1.2rem;
}

/* Event photography strip. Scrolls sideways like the hub cards. */
.shot-strip {
  position: relative;
}

.shot-track {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(20rem, 26rem);
  gap: 1.6rem;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  padding-bottom: 1rem;
  scrollbar-width: thin;
}

.shot {
  margin: 0;
  scroll-snap-align: start;
}

.shot img {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  transition: opacity 0.2s ease;
}

.shot-link {
  display: block;
  color: inherit;
  text-decoration: none;
}

.shot-link:hover img {
  opacity: 0.88;
}

.shot-go {
  display: block;
  margin-top: 0.5rem;
  color: var(--red);
  font-family: var(--font-section);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

.shot-link:hover .shot-go {
  text-decoration: underline;
}

.shot figcaption {
  margin-top: 0.8rem;
  color: var(--ink-body, #555);
  font-size: 0.86rem;
  line-height: 1.45;
}

.shot-meta {
  display: block;
  margin-bottom: 0.25rem;
  color: var(--red);
  font-family: var(--font-section);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

.shot-controls {
  display: flex;
  gap: 1rem;
  margin-top: 1rem;
}

.shot-arrow {
  padding: 0;
  border: 0;
  background: none;
  color: var(--red);
  font-size: 1.05rem;
  line-height: 1;
  cursor: pointer;
}

.shot-arrow:disabled {
  color: #b9b9b9;
  cursor: default;
}

@media (max-width: 820px) {
  .shot-track {
    grid-auto-columns: minmax(15rem, 18rem);
  }
}

/* Footer social links. */
.footer-social {
  display: flex;
  flex-wrap: wrap;
  gap: 1.2rem;
  margin: 1.4rem 0 0;
}

.footer-social a {
  color: inherit;
  font-family: var(--font-section);
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  text-decoration: none;
  border-bottom: 2px solid transparent;
}

.footer-social a:hover {
  color: var(--red);
  border-bottom-color: var(--red);
}

/* The footer closes with the institute's own mark, matching the header, rather
   than the university lockup. */
.footer-brand {
  display: inline-flex;
  align-items: center;
  gap: 0.85rem;
  margin-bottom: 1.4rem;
  color: var(--ink);
  text-decoration: none;
}

.footer-mark {
  display: block;
  width: 3.2rem;
  height: auto;
}

.footer-name {
  font-family: var(--font-head);
  font-size: 1.15rem;
  font-weight: 800;
  letter-spacing: -0.02em;
}

@media (max-width: 820px) {
  .footer-mark {
    width: 2.6rem;
  }
}

/* Photographer credit under a hub banner. Required by some licences, so it is
   quiet but present rather than hidden. */
.hub-hero figcaption {
  margin-top: 0.6rem;
  color: var(--ink-muted, #777);
  font-size: 0.76rem;
}

.hub-hero figcaption a {
  color: inherit;
}

/* Full-bleed hero. The page content sits inside a centred shell, so this pulls
   the image out to both edges of the window and puts the caption back inside
   the shell where the rest of the text lines up. */
/* The hero sits within the same margins as the rest of the page, at the ratio
   the photograph was cropped to. Capping its height instead cropped the
   subject out of the frame. */
.lead-media img {
  width: 100%;
  aspect-ratio: 12 / 5;
  object-fit: cover;
}

.lead-media figcaption span {
  color: inherit;
}

.lead-media figcaption span a {
  color: inherit;
}

@media (max-width: 820px) {
  .lead-media img {
    aspect-ratio: 16 / 9;
  }

}

/* The institute mark on the dark band, opposite the quote. */
/* The white-on-black starburst, so no CSS trickery is needed to make it read
   on the dark band. */
.quote-mark-logo {
  display: block;
  width: min(11rem, 100%);
  height: auto;
  justify-self: start;
}

@media (max-width: 900px) {
  .quote-band {
    grid-template-columns: minmax(0, 1fr);
  }

  .quote-mark-logo {
    width: min(7rem, 100%);
  }
}

/* On any touch device, one tap opens the menu. Without this the link inside
   the summary fires as well, which is what made it take two taps to get
   anywhere. The section page is still reachable from the first item in the
   menu, "All News", "All Publications" and so on. */
@media (hover: none) {
  .nav-top-link {
    pointer-events: none;
  }

  .nav-group summary {
    cursor: default;
  }
}

/* Research nodes. Set apart from the hub's own description above, so a reader
   can tell the overview from the individual projects inside it. */
.node-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: 2.2rem 2.6rem;
}

/* In a three-column grid the columns already read as separate, so the nodes
   need no rule of their own. On the research page they are a vertical list and
   do carry one. */
.node h3 {
  margin: 0 0 0.5rem;
  font-family: var(--font-section);
  font-size: 1rem;
  font-weight: 700;
}

.node p {
  margin: 0;
  color: var(--ink-body);
  font-size: 0.92rem;
  line-height: 1.55;
}

/* Hub pages stack four or five blocks, each carrying 4rem of its own padding
   on top of the rule and padding inside its header. Together that opened large
   empty bands between the description, the nodes and the team, so the blocks
   sit closer to one another here than on a listing page. */
.hub-block {
  padding: 3rem 0 0;
}

#about-hub.hub-block {
  padding-top: 2rem;
}

/* The node grid and the team strip run the full content width, so their
   headings and rules should too, rather than stopping short at the narrower
   column used for article listings. */
#nodes .block-header,
#team .block-header {
  max-width: none;
}

.hub-hero {
  margin-bottom: 0;
}

/* A heading block that introduces the list directly beneath it. Both carried a
   full 4rem of padding, which left a large gap between a heading and the thing
   it was heading. */
.page-block.is-lead-in {
  padding-bottom: 0;
}

.is-follow-on {
  padding-top: 1.4rem;
}

/* Hidden publications. Without this the [hidden] attribute loses to the grid
   display rule, the same trap as the news list. */
.publication-layout article[hidden],
.news-list article[hidden] {
  display: none;
}

.filter-empty {
  padding: 2rem 0 3rem;
  color: var(--ink-muted);
}

/* The publications filter row is set to match the jump row on the People page,
   which carries its own rule directly beneath the chips. The section heading
   below it therefore drops its own rule, so there is one line rather than two. */
.publication-filters {
  margin: 1.4rem 0 1rem;
  padding: 0 0 1.4rem;
  border-bottom: 2px solid var(--ink);
}

#research .block-header {
  padding-top: 0;
  border-top: 0;
}

#research.page-block {
  padding-top: 4.2rem;
}

/* Phones. The photo sits above the text rather than beside it.

   The desktop rules place the date, label, title and summary in column 2 using
   selectors like ".news-archive article > time". Those are more specific than
   the old phone rule ".news-archive article > *", so on a phone the text stayed
   in column 2, the grid quietly made a second column for it, and the photo
   column shrank to nothing. Every news photo was invisible on a phone. Naming
   the same elements here at equal specificity, later in the file, fixes it. */
@media (max-width: 560px) {
  .news-archive article {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 0.45rem;
  }

  .news-archive article > .article-thumb,
  .news-archive article > time,
  .news-archive article > .article-tag,
  .news-archive article > h2,
  .news-archive article > p:not(.article-tag) {
    grid-column: 1;
    grid-row: auto;
  }

  .news-archive article > .article-thumb {
    width: 100%;
    margin-bottom: 0.4rem;
  }

  .news-archive article > .article-thumb img,
  .news-archive article > .article-thumb.is-placeholder {
    display: block;
    width: 100%;
    aspect-ratio: 16 / 10;
    object-fit: cover;
  }
}

/* The same collision on the shorter lists used by hub pages and the
   Publications page, which pin their text to column 2 in the same way. */
@media (max-width: 560px) {
  .news-list article,
  .publication-list article {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 0.45rem;
  }

  .news-list article > .article-thumb,
  .news-list article > time,
  .news-list article > h3,
  .news-list article > h2,
  .news-list article > p,
  .publication-list article > .article-thumb,
  .publication-list article > span,
  .publication-list article > h3,
  .publication-list article > p {
    grid-column: 1;
    grid-row: auto;
  }

  .news-list article > .article-thumb,
  .publication-list article > .article-thumb {
    margin-bottom: 0.4rem;
  }

  .news-list article > .article-thumb img,
  .news-list article > .article-thumb.is-placeholder,
  .publication-list article > .article-thumb img {
    display: block;
    width: 100%;
    aspect-ratio: 16 / 10;
    object-fit: cover;
  }
}

/* ==========================================================================
   Signals. Two kinds of piece in one chronological list. A note is a short
   row, the same shape as a news row. A column is a longer piece and is given
   the width and type size to match.
   ========================================================================== */

.signals-archive {
  display: grid;
  gap: 2.8rem;
}

/* A column is marked by a pale red wash and a larger headline, and by nothing
   else. One byline line, no badge, no rule, no read-more link. */
.signal-column {
  display: grid;
  grid-template-columns: minmax(0, 0.4fr) minmax(0, 1fr);
  gap: 1.5rem 2.2rem;
  align-items: center;
  padding: 2.1rem 2.2rem;
  background: var(--red-wash);
}

.signal-column .column-media img {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

.signal-column .column-byline {
  margin: 0 0 0.7rem;
  color: var(--ink-muted);
  font-family: var(--font-section);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

.signal-column .column-byline span {
  color: var(--red);
}

.signal-column h2 {
  margin: 0;
  max-width: 26ch;
  font-family: var(--font-head);
  font-size: clamp(1.45rem, 2vw, 1.8rem);
  font-weight: 800;
  line-height: 1.16;
  letter-spacing: -0.02em;
}

.signal-column .column-dek {
  margin: 0.65rem 0 0;
  max-width: 54ch;
  color: var(--ink-body);
  font-size: 0.97rem;
  line-height: 1.55;
}

/* Without a photograph the text runs the full width rather than leaving a gap
   where the picture would have been. */
.signal-column:not(:has(.column-media)) {
  grid-template-columns: minmax(0, 1fr);
}

@media (max-width: 720px) {
  .signal-column {
    grid-template-columns: minmax(0, 1fr);
    gap: 1.1rem;
    padding: 1.5rem 1.4rem 1.7rem;
  }

  .signal-column .column-media img {
    aspect-ratio: 16 / 9;
  }
}

.article-main.is-column .article-prose {
  max-width: 34rem;
  font-size: 1.08rem;
  line-height: 1.72;
}

.article-main.is-column .article-prose p + p {
  margin-top: 1.1rem;
}

/* A note is a short row: small square photo, then date, author, headline and
   summary stacked beside it. Defined in full here rather than borrowing the
   news page's rules, so the two can change independently. */
.signal-note {
  display: grid;
  grid-template-columns: minmax(6.5rem, 8rem) minmax(0, 1fr);
  column-gap: 1.6rem;
  row-gap: 0.3rem;
  align-items: start;
  padding-bottom: 2rem;
  border-bottom: 1px solid var(--rule);
}

.signal-note[hidden] {
  display: none;
}

.signal-note > .article-thumb {
  grid-column: 1;
  grid-row: 1 / span 4;
  width: 100%;
}

.signal-note > .article-thumb img {
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
}

.signal-note > .article-thumb.is-placeholder {
  display: grid;
  place-items: center;
  aspect-ratio: 1 / 1;
  background: var(--paper-soft);
  border: 1px solid var(--rule);
}

.signal-note > .article-thumb.is-placeholder span {
  color: var(--ink-muted);
  font-family: var(--font-section);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.signal-note > time,
.signal-note > .article-tag,
.signal-note > h2,
.signal-note > p:not(.article-tag) {
  grid-column: 2;
  grid-row: auto;
  margin: 0;
}

.signal-note > time {
  color: var(--red);
  font-family: var(--font-section);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.signal-note > .article-tag {
  color: var(--ink-muted);
  font-family: var(--font-section);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.06em;
}

.signal-note > h2 {
  margin-top: 0.15rem;
  font-family: var(--font-head);
  font-size: 1.28rem;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.015em;
}

.signal-note > p:not(.article-tag) {
  margin-top: 0.3rem;
  max-width: 52ch;
  color: var(--ink-body);
}

@media (max-width: 560px) {
  .signal-note {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 0.4rem;
  }

  /* Named one by one. A wildcard here loses to the rules above that place
     each element in column 2, which leaves the photo column at zero width. */
  .signal-note > .article-thumb,
  .signal-note > time,
  .signal-note > .article-tag,
  .signal-note > h2,
  .signal-note > p:not(.article-tag) {
    grid-column: 1;
    grid-row: auto;
  }

  .signal-note > .article-thumb {
    margin-bottom: 0.4rem;
  }

  .signal-note > .article-thumb img {
    aspect-ratio: 16 / 10;
  }

  /* A note with no photo shows text only on a phone. A full-width grey box
     takes more room than it is worth on a small screen. */
  .signal-note > .article-thumb.is-placeholder {
    display: none;
  }
}

/* A top-level nav item with no dropdown, such as Signals. A dropdown item is a
   summary with its own padding wrapped around a link with padding of its own,
   so a plain link needs both to sit level with its neighbours. The current-page
   underline is already handled for any link in the nav. */
.primary-nav .nav-single {
  display: flex;
  align-items: center;
  padding: 1rem 0;
  font-weight: 500;
}

/* Photo credit under an article's header image. Quiet, but present, since a
   borrowed photograph usually has to name its photographer. */
.article-feature-media figcaption {
  margin-top: 0.55rem;
  color: var(--ink-muted);
  font-size: 0.72rem;
  line-height: 1.45;
}

.article-feature-media figcaption a {
  color: inherit;
}

/* An author's role beside their name, so a reader knows the standing of the
   person writing. */
.article-credits .author-role {
  color: var(--ink-muted);
}
