/* ─────────────────────────────────────────────
   Writing · the post list and each post
   Theme: DG (../dg-theme.css), the same tokens and ink tiers as the résumé and the Black Box page:
   neutral-10 (primary) · neutral-8 (secondary) · neutral-7 (meta). Gold stays decorative.
   ───────────────────────────────────────────── */

:root {
  /* Layout structure (pad-x and header-h feed the shared navigation.css) */
  --gut: clamp(var(--space-m), 0.7rem + 2.6vw, 3.25rem);
  --pad-x: clamp(var(--space-m), 6vw, 96px);
  --header-h: 56px;
  /* One reading column for posts and the list. */
  --measure: 42rem;
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
  #scroll-progress { display: none; }
}

/* ── Motion: the homepage's scroll hairline and entrances ─────────────
   Gold means "how far down the page". Each block of the post fades and rises once as it scrolls in. Entrances use
   transform, not translate, because wide figures already use translate to center themselves. */
#scroll-progress {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--color-1);
  transform: scaleX(0);
  transform-origin: left;
  z-index: 60;
}
html.js .post > .reveal {
  opacity: 0;
  transform: translateY(var(--space-s));
  transition: opacity var(--motion-large-duration) var(--motion-large-easing),
    transform var(--motion-large-duration) var(--motion-large-easing);
  transition-delay: calc(var(--i, 0) * var(--motion-duration) / 3);
}
html.js .post > .reveal.visible { opacity: 1; transform: none; }

body {
  background: var(--neutral-1);
  color: var(--neutral-10);
  font: var(--weight-ui-regular) var(--size-s) / var(--line-s) var(--font-ui);
  letter-spacing: var(--letter-spacing-s);
  text-wrap: pretty;
  -webkit-font-smoothing: antialiased;
  transition: background-color var(--motion-large-duration) var(--motion-large-easing),
    color var(--motion-large-duration) var(--motion-large-easing);
}

::selection { background: var(--neutral-10); color: var(--neutral-1); }

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

/* Underline that grows from the left (résumé). */
a.u {
  background-image: linear-gradient(currentColor, currentColor);
  background-size: 0% var(--border-s);
  background-repeat: no-repeat;
  background-position: 0 100%;
  transition: background-size var(--motion-large-duration) var(--motion-large-easing);
  padding-bottom: 1px;
}
a.u:hover, a.u:focus-visible { background-size: 100% var(--border-s); }
a.u.on { background-size: 100% var(--border-s); }
a.u.on:hover { background-size: 0% var(--border-s); }

/* Ink focus outline, not DG gold: gold on white is 2.3:1 */
:focus-visible { outline: 2px solid var(--neutral-10); outline-offset: 2px; border-radius: var(--radius-xs); }

.wrap {
  max-width: calc(var(--measure) + 2 * var(--gut));
  margin: 0 auto;
  padding: var(--space-xxl) var(--gut);
}

/* ── Type roles ──────────────────────────── */
.meta {
  font: var(--weight-ui-medium) var(--size-xs) / var(--line-xs) var(--font-ui);
  letter-spacing: var(--letter-spacing-xs);
  color: var(--neutral-7);
}
h1 {
  font: var(--weight-brand-medium) var(--size-xxl) / var(--line-xxl) var(--font-brand);
  letter-spacing: var(--letter-spacing-xxl);
  margin: var(--space-xs) 0 var(--space-xl);
}
/* A post's subtitle sits close under its title, one step down in the serif, in the secondary ink. */
.post h1:has(+ .dek) { margin-bottom: var(--space-s); }
.post .dek {
  font: var(--weight-editorial-regular) var(--size-l) / var(--line-l) var(--font-editorial);
  letter-spacing: var(--letter-spacing-l);
  color: var(--neutral-8);
  margin-bottom: var(--space-xl);
}
/* The gold words, as on the homepage: the serif's regular weight, upright, never a faked italic. Gold stays out of
   everything else except the scroll hairline. */
h1 em {
  font-family: var(--font-editorial);
  font-weight: var(--weight-editorial-regular);
  font-style: normal;
  font-synthesis: none;
  color: var(--color-1);
}

/* ── A post ──────────────────────────────── */
.post p, .post li {
  font: var(--weight-editorial-regular) var(--size-m) / var(--line-m) var(--font-editorial);
  letter-spacing: var(--letter-spacing-m);
  color: var(--neutral-8);
}
.post p + p, .post ul + p, .post p + ul { margin-top: var(--space-m); }
.post h2 {
  font: var(--weight-editorial-regular) var(--size-l) / var(--line-l) var(--font-editorial);
  letter-spacing: var(--letter-spacing-l);
  color: var(--neutral-10);
  margin: var(--space-xxl) 0 var(--space-m);
}
/* A sub-heading sits under a section heading: the same serif one step down, in its medium weight. */
.post h3 {
  font: var(--weight-editorial-medium) var(--size-m) / var(--line-m) var(--font-editorial);
  letter-spacing: var(--letter-spacing-m);
  color: var(--neutral-10);
  margin: var(--space-xl) 0 var(--space-xs);
}
.post h2 + h3 { margin-top: var(--space-m); }
/* A quote or pull quote: the primary ink, set off by a rule along its left edge (a box shadow, as everywhere in DG). */
.post blockquote {
  margin: var(--space-l) 0;
  padding-left: var(--space-m);
  box-shadow: inset var(--border-s) 0 0 var(--neutral-4);
}
.post blockquote p { color: var(--neutral-10); }
.post ul { padding-left: var(--space-l); }
.post li + li { margin-top: var(--space-xs); }
.post li::marker { color: var(--neutral-7); }

/* Figures: screenshots and wireframes. Wide ones step out of the reading column, up to the page edge on phones. */
.post figure { margin: var(--space-xl) 0; }
.post figure.wide {
  width: min(60rem, calc(100vw - 2 * var(--gut)));
  margin-left: 50%;
  translate: -50% 0;
}
.post figure img {
  display: block;
  width: 100%;
  margin-inline: auto;
  height: auto;
  border-radius: var(--radius-s);
  box-shadow: var(--border-shadow-s);
}
/* Galleries: a full-width row of screens. By default it's a plain sideways scroll with snap, which is what readers get
   without JavaScript or with Reduce Motion. writing.js adds html.galleries-on once the Pause buttons work, and only
   then does the row loop: the set is drawn more than once so the track can slide exactly half its width and land
   where it started, the window's edges are where screens come and go, and pointer hover over the screens pauses it.
   Theme gap: DG's motion tokens are for interface transitions, so the loop's duration is set per gallery in the
   markup, scaled to its length so both rows move at the same speed. */
.post figure.gallery.bleed { width: calc(100vw - var(--scrollbar, 0px)); }
.gallery-viewport { overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; }
.gallery-viewport::-webkit-scrollbar { display: none; }
.gallery-track {
  display: flex;
  gap: var(--space-s);
  width: max-content;
  list-style: none;
}
/* The post's list spacing would add a left inset and break the half-width loop. */
.post .gallery-track { padding: 0 var(--space-s) 0 0; }
.post .gallery-track li + li { margin-top: 0; }
.gallery-track [aria-hidden="true"] { display: none; }
/* Screens share a height and keep their own shape, so no window is cropped. The height sits on the image: a
   percentage height inside a flex item would size the item from the image's natural width. */
.gallery-track li { flex: 0 0 auto; scroll-snap-align: start; }
.post .gallery-track img {
  display: block;
  width: auto;
  height: clamp(10rem, 25vw, 18.75rem);
  border-radius: var(--radius-s);
  box-shadow: var(--border-shadow-s);
}

/* Phone screens are tall, so their row is taller; scripts/build-writing.cjs uses the same 480px top height to time the
   loop. */
.post .gallery.phone .gallery-track img { height: clamp(18rem, 55vw, 30rem); }
/* A single phone screen sits centred in the text column at about the size of a phone. */
.post figure.phone:not(.gallery) { width: min(20rem, 100%); margin-inline: auto; }
.post figure.phone:not(.gallery) figcaption { text-align: center; }

/* Two or three phone screens side by side, each at about phone size. On narrow screens the row scrolls sideways a
   screen at a time rather than shrinking the screens past reading. */
.post figure.phones ul {
  display: grid;
  justify-content: center;
  gap: var(--space-l);
  padding: 0;
  list-style: none;
}
.post figure.phones-2 ul { grid-template-columns: repeat(2, minmax(0, 18rem)); }
.post figure.phones-3 ul { grid-template-columns: repeat(3, minmax(0, 18rem)); }
.post figure.phones li + li { margin-top: 0; }
@media (max-width: 640px) {
  .post figure.phones ul {
    display: flex;
    justify-content: flex-start;
    gap: var(--space-s);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
  }
  .post figure.phones ul::-webkit-scrollbar { display: none; }
  .post figure.phones li { flex: 0 0 70%; scroll-snap-align: start; }
}

html.galleries-on .gallery-viewport { overflow: hidden; }
html.galleries-on .gallery-track { animation: gallery-loop var(--gallery-duration, 80s) linear infinite; }
html.galleries-on .gallery-track [aria-hidden="true"] { display: block; }
html.galleries-on .gallery.is-paused .gallery-track { animation-play-state: paused; }
@media (hover: hover) {
  html.galleries-on .gallery-viewport:hover .gallery-track { animation-play-state: paused; }
}
@keyframes gallery-loop { to { translate: -50% 0; } }

/* Pause/Play sits in the caption, underlined so it reads as a control and not as more caption. */
.gallery-toggle {
  display: none;
  font: inherit;
  color: var(--neutral-10);
  background: linear-gradient(currentColor, currentColor) 0 100% / 100% var(--border-s) no-repeat;
  border: 0;
  padding: 0 0 1px;
  margin-left: var(--space-xs);
  cursor: pointer;
}
html.galleries-on .gallery-toggle { display: inline; }

/* The icon in each of Apple's styles, in one row on the page itself. */
.post figure.icons ul {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 6rem));
  justify-content: center;
  gap: var(--space-l);
  padding: 0;
  list-style: none;
}
.post figure.icons li + li { margin-top: 0; }
.post figure.icons img { display: block; width: 100%; height: auto; border-radius: 0; box-shadow: none; }
.post figure.icons figcaption { text-align: center; }

/* Captions sit back from the text: the smallest step in the regular weight. neutral-7 is already the lightest ink that
   passes contrast in light mode, so size and weight do the quieting, not color. */
.post figcaption {
  font: var(--weight-ui-regular) var(--size-xxs) / var(--line-xxs) var(--font-ui);
  letter-spacing: var(--letter-spacing-xxs);
  color: var(--neutral-7);
  max-width: var(--measure);
  margin: var(--space-xs) auto 0;
}
/* Full-width figures: the caption keeps the page's gutters on phones and the text column on wide screens. */
.post figure.bleed figcaption { max-width: calc(var(--measure) + 2 * var(--gut)); padding-inline: var(--gut); }

/* ── The post list ───────────────────────── */
.posts { list-style: none; }
.posts li { padding: var(--space-l) 0; box-shadow: var(--divider-top); }
.posts h2 {
  font: var(--weight-editorial-regular) var(--size-l) / var(--line-l) var(--font-editorial);
  letter-spacing: var(--letter-spacing-l);
  color: var(--neutral-10);
  margin-top: var(--space-xxs);
}
.posts p {
  font: var(--weight-editorial-regular) var(--size-m) / var(--line-m) var(--font-editorial);
  letter-spacing: var(--letter-spacing-m);
  color: var(--neutral-8);
  margin-top: var(--space-xs);
}

.foot {
  max-width: calc(var(--measure) + 2 * var(--gut));
  margin: var(--space-xxl) auto 0;
  padding: var(--space-l) var(--gut) var(--space-xxl);
  font: var(--weight-ui-regular) var(--size-xs) / var(--line-xs) var(--font-ui);
  letter-spacing: var(--letter-spacing-xs);
  color: var(--neutral-7);
}
.foot p { padding-top: var(--space-m); box-shadow: var(--divider-top); }

/* ── Narrower screens ────────────────────── */
@media (max-width: 760px) {
  h1 { font: var(--weight-brand-medium) var(--size-xl) / var(--line-xl) var(--font-brand); letter-spacing: var(--letter-spacing-xl); }
}
