/* Publications page only (publications.html). Loads after styles.css and reuses
   its tokens, base typography, and the .pub-* entry classes — these are the same
   papers the homepage and résumé set, and holding one voice across the three
   pages is the point of sharing the sheet. What this layer adds is the record's
   own structure: the masthead row and the year spine.

   The spine is the page's one device, and it is the site's own motif turned
   vertical: the nav rail carries a single accent keypoint that marks where you
   are, so here a hairline rail runs down the left of each year's entries with
   one accent joint at the year — a marker on a rail, not a bullet. Reverse
   chronology is the only ordering on the page, and the spine is what encodes
   it; don't add entry numbering on top, it would say the same thing twice.
   One joint per paper was tried and taken out: it turned the rail into a list
   of markers, and the year is the only thing on this page that needs marking. */
/* 63rem rather than the résumé's 60rem, and the extra 3 are the year column's
   fault, not a change of measure: this page spends 7.5rem + 2rem of its width
   on the spine before a word is set, so at 60rem the entries column is 807px
   and the two longest author lines (TTT-Parkour's eight names, DuQuant's nine
   — 819px and 828px unbroken) each wrapped a single trailing name onto a line
   of its own. An author list is one run to be read across, not a paragraph, so
   a widow there is worse than a wider page. 62rem is the exact threshold; 63
   leaves ~27px so a font-rendering difference or one more co-author doesn't
   put it back. Titles fit at either width, so nothing else on the page moves.
   The ceiling is Bootstrap's: .container is 1140px at ≥1200px viewports, less
   its 15px gutters, so 1008px is inside it and 69rem would be the real limit.
   Below 1200px the container is 960px and the long lines wrap again — that is
   the narrow window doing its job, not a regression to chase. */
.pubs-page {
  max-width: 63rem;
  margin: 0 auto;
}

/* The rail's ink, measured against this page's background and so not in
   styles.css. --ivory-dark is the site's border token and the obvious pick,
   and it cannot do this job: #e8e6dc on the page's #faf9f5 is 1.19:1, so the
   rail was never actually drawn and the year's accent joint sat in white space
   reading as a loose bullet — the exact failure the unimate stage rail had
   before it was rebuilt. 1.67:1 is still a hairline; it is just one that
   renders. */
:root {
  --spine: #cac3b2;   /* 1.67:1 on --ivory-light */
}

/* --- Masthead --- */
/* The résumé masthead's two-sided row: what this page is on the left, the same
   record in its other database on the right. One baseline, so the 36px title
   and the 15px link read as one line. Renders with the page — nothing above the
   first year group animates (see the Entrance note in resume.css; the same
   reasoning holds here and needs no rule). */
.pubs-masthead {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 2rem;
  padding-top: 3.25rem;
  /* This is the gap *above* .pubs-note, and the note's own margin is the gap
     below it — the two together are what put the note in the masthead's block
     rather than in 2026's. So it is set small on purpose: 17px above against
     47px below, where 0.85rem used to make it 29 against 47 and the note
     floated between the two. Read them as a pair; changing one alone moves
     which block the line belongs to. */
  padding-bottom: 0.15rem;
}

.pubs-masthead h1 {
  margin: 0;
}

.pubs-scholar {
  font-size: var(--text-sm);
  white-space: nowrap;
}

.pubs-scholar a:link,
.pubs-scholar a:visited {
  color: var(--text-secondary);
  text-decoration: none;
}

.pubs-scholar a:hover {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-color: var(--accent);
  text-underline-offset: 0.16em;
}

/* --- Year spine --- */
/* Grid, not floats: the year is a landmark in its own column, and the entries
   column carries the rail. Each group is a .page-section, so it takes the
   shared section reveal from styles.css — which is also the reason the rail
   stops at each year instead of running the whole record as one bone: the
   reveal translates a group 10px, and a rail spanning two of them would
   visibly tear on the way in. The break lands on the year boundary, which is
   the one place a break says something. */
.pubs-year-group {
  display: grid;
  grid-template-columns: 7.5rem minmax(0, 1fr);
}

/* Fraunces numerals as a landmark — the display face's one appearance here,
   matching the discipline in resume.css (each face spent once). Sticky, so on
   a year with several entries the numeral keeps its group company; 5rem clears
   the sticky navbar. align-self is required — a stretched grid item has no
   room left to stick in. */
.pubs-year {
  position: sticky;
  top: 5rem;
  align-self: start;
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-h3);
  font-weight: var(--weight-semibold);
  letter-spacing: -0.01em;
  line-height: 1.2;
  color: var(--text-primary);
}

/* The rail. Its joint (::before) is the nav keypoint's twin — same 5px, same
   accent, used as a shape, never as text colour. left: -3px centres the dot on
   the 1px rule; top aligns it with the year numeral's optical centre. */
.pubs-entries {
  position: relative;
  border-left: 1px solid var(--spine);
  padding-left: 2rem;
}

.pubs-entries::before {
  content: '';
  position: absolute;
  left: -3px;
  top: 0.55rem;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--accent);
}

/* --- Entries --- */
/* The .pub-* classes arrive styled from styles.css; only the spacing changes.
   Those margins are tuned for the homepage's rows-with-thumbnails, and here
   the entries stack directly, like the résumé's publications section. */
.pubs-entry {
  margin-bottom: 1.7rem;
}

.pubs-entry:last-child {
  margin-bottom: 0;
}

.pubs-entry .pub-title {
  margin-top: 0;
}

.pubs-entry .pub-venue {
  margin-bottom: 2px;
}

/* --- Note --- */
/* The equal-contribution note leads the record rather than closing it, so it
   belongs to the masthead block above and not to 2026 below: it sits tight
   under the title and takes over the masthead's own separation from the first
   year group (hence the small padding-bottom there, which this margin
   replaces — don't set both, and see the note at that rule for the ratio the
   two hold). Still chrome ink at --text-sm: promoting it in position is not
   promoting it in voice. */
.pubs-note {
  margin: 0 0 2rem;
  font-size: var(--text-sm);
  color: var(--text-tertiary);
}

/* --- Keyboard focus --- */
/* The same ring custom-navbar.css draws, because the page's own links had
   nothing: .pub-links strips the underline, so a tabbing visitor was left with
   whatever the UA happened to paint over ivory. Quality floor, not decoration
   — and there are ~25 of these links, which is a long way to tab blind. */
.pubs-page a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* --- Narrow --- */
/* The year column has no room on a phone: the numeral moves above its group
   and the rail stays — at 1.1rem of inset it is a margin note's rule, and the
   joint still marks where the year begins. Sticky is pointless in block flow
   and is dropped with the grid. */
@media screen and (max-width: 767px) {
  .pubs-masthead {
    display: block;
    padding-top: 2.5rem;
  }

  .pubs-scholar {
    margin-top: 0.5rem;
  }

  .pubs-year-group {
    display: block;
  }

  .pubs-year {
    position: static;
    margin-bottom: 0.75rem;
  }

  .pubs-entries {
    padding-left: 1.1rem;
  }
}

/* --- Print --- */
/* Same contract as the résumé's sheet: paper gets the record, not the site. */
@media print {
  .navbar,
  .site-footer {
    display: none;
  }

  body {
    background: #fff;
  }

  .pubs-page {
    max-width: none;
  }

  .pubs-masthead {
    padding-top: 0;
  }

  .pubs-entry {
    break-inside: avoid;
  }

  a:link,
  a:visited {
    text-decoration: none;
  }
}
