#updates { min-height: min(480px, 50vh); }

.updates-content {
  left: var(--gutter);
  width: 88vw;
  padding-bottom: clamp(24px, 4vh, 48px);
}

/* Three equal columns across the first three quarters of the row, separated by the page's own grid
   gap (Jan, 2026-09-20: the text was crammed against the next column; 2026-09-21: narrower columns,
   down from 90%). The gap is the shared token rather than a number of this scene's own. */
.updates-grid {
  display: grid;
  width: 75%;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  align-items: start;
  justify-content: start;
  gap: var(--grid-gap);
}
/* One wrapper per track, each a consecutive run of dates cut by `updates.js` (Jan, 2026-09-21: the
   third column is back, read down each column). Notes in a column stack one grid gap apart, whatever the neighbouring
   columns hold, which is why a column is its own box rather than a row of a shared grid. */
.update-column {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: var(--grid-gap);
}

.update-note {
  display: flex;
  min-width: 0;
  flex-direction: column;
  align-items: flex-start;
  gap: 14px;
}

.update-note-date-line {
  display: flex;
  min-height: 18px;
  align-items: center;
  gap: 8px;
}

.update-note-pin {
  display: block;
  width: 12px;
  height: 14px;
  flex: 0 0 auto;
  color: var(--green);
}

/* The body carries no type of its own: it inherits the one body declaration every paragraph on the
   page uses (Jan, 2026-09-20). Only the twelve-line clamp is this scene's. */
.update-note-body {
  display: -webkit-box;
  margin: 0;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 12;
  line-clamp: 12;
}
.update-note-body > * { margin: 0; }
.update-note-body > * + * { margin-top: 10px; }
/* A heading that opens a later section of the note stands clear of the one above it, so it reads as
   the start of the next part rather than the end of the last (Jan, 2026-09-21, WEBSITES #34). */
.update-note-body > .update-note-heading:not(:first-child) { margin-top: 28px; }
/* A markdown list keeps the body's measure: the marker hangs in the padding rather than indenting the
   column, and a bullet line wraps under its own text. */
.update-note-body ul { padding-left: 16px; list-style: none; }
.update-note-body li { position: relative; }
.update-note-body li + li { margin-top: 6px; }
/* The marker is a 4px moss-green dot rather than the browser's disc, which stood too large beside the
   body text (Jan, 2026-09-21: option J of the small-dot study). It sits on the first line's x-height
   centre, so a wrapped item keeps the dot level with its opening words. */
.update-note-body li::before {
  content: "";
  position: absolute;
  top: calc(.8em - 2px);
  left: -15px;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--green);
}
/* JetBrains Mono carries a much larger x-height than the body face, so matching sizes by the number
   does not match them on the page: at .92em an inline `rebuild` stood taller than the words either
   side of it (Jan, 2026-09-20). .8em is where the two read as one line of text. */
.update-note-body code { font-family: var(--mono); font-size: .8em; }

@media (max-width: 900px) {
  #updates { min-height: 0; }
  .updates-grid, .update-column { grid-template-columns: 1fr; gap: 44px; }
}

/* A phone in the scroll story swipes through the notes instead of stacking them (Jan, 2026-10-02,
   WEBSITES #8): one row bleeding to both screen edges, each note snapping to the gutter, the next one
   peeking in. A note keeps the desktop look, plain on the page with no card behind it, and the row
   carries no dots: under a tall note they fell below the screen (Jan, 2026-10-02). The columns stay the
   reveal steps, so the notes still arrive column by column. */
@media (max-width: 900px) {
  .story .updates-grid { display: flex; width: auto; margin: 0 calc(-1 * var(--gutter)); padding: 0 var(--gutter); overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x mandatory; scroll-padding-inline: var(--gutter); scrollbar-width: none; gap: 32px; }
  .story .updates-grid::-webkit-scrollbar { display: none; }
  .story .update-column { display: contents; }
  .story .update-note { flex: 0 0 min(82%, 420px); scroll-snap-align: start; }
}

@media (max-width: 620px) {
  .update-note { gap: 10px; }
  .update-note .btn { width: 100%; }
}
