/* CUMICHE site. Palette and type family come from core/ via the generated
   tokens.css. Never hardcode a brand value in this file. */

/* ---------------------------------------------------------------- fonts */

@font-face {
  font-family: 'Instrument Serif';
  src: url('../fonts/InstrumentSerif-Regular.ttf') format('truetype');
  font-weight: 400;
  font-display: swap;
}

@font-face {
  font-family: 'Fraunces';
  src: url('../fonts/Fraunces-SemiBold.ttf') format('truetype');
  font-weight: 600;
  font-display: swap;
}

@font-face {
  font-family: 'EB Garamond';
  src: url('../fonts/EBGaramond-Regular.ttf') format('truetype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'EB Garamond';
  src: url('../fonts/EBGaramond-Italic.ttf') format('truetype');
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}

@font-face {
  font-family: 'Jost';
  src: url('../fonts/Jost-Medium.ttf') format('truetype');
  font-weight: 500;
  font-display: swap;
}

/* ---------------------------------------------------------------- reset */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

/* A short page (a 404, an unpublished note) still seats its footer at the
   bottom of the viewport rather than leaving cream below it. */
body {
  margin: 0;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  background: var(--cream);
  color: var(--khaki);
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 1rem;
  line-height: 1.78;
  letter-spacing: 0.005em;
  -webkit-font-smoothing: antialiased;
}

main {
  flex: 1 0 auto;
}

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

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

/* ------------------------------------------------------------ typography */

.display {
  font-family: var(--font-display);
  font-weight: 400;
  line-height: 1.02;
  letter-spacing: -0.005em;
  margin: 0;
}

.display-xl {
  font-size: clamp(2.9rem, 8.2vw, 6.5rem);
}

.display-lg {
  font-size: clamp(2.4rem, 6.4vw, 5rem);
}

.display-md {
  font-size: clamp(1.9rem, 4vw, 3.1rem);
}

.label {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.7rem;
  line-height: 1.6;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  margin: 0;
}

.wordmark {
  font-family: var(--font-wordmark);
  font-weight: 600;
  font-size: 0.95rem;
  letter-spacing: 0.3em;
  text-transform: uppercase;
}

.prose p {
  margin: 0 0 1.5em;
  max-width: 34rem;
}

.prose p:last-child {
  margin-bottom: 0;
}

.dim {
  opacity: 0.72;
}

/* ---------------------------------------------------------------- layout */

.wrap {
  width: min(100% - 2.5rem, 76rem);
  margin-inline: auto;
}

.wrap-narrow {
  width: min(100% - 2.5rem, 40rem);
  margin-inline: auto;
}

.section {
  padding-block: clamp(4.5rem, 11vw, 9rem);
}

.rule {
  height: 1px;
  background: currentColor;
  opacity: 0.18;
  border: 0;
  margin: 0;
}

/* ----------------------------------------------------------------- media */

/* Two background layers: the photograph, then a tonal wash. If the file is
   not on disk yet the wash shows through, so a missing photo reads as an
   unfilled plate rather than a broken image. */
.media {
  background-color: var(--khaki);
  background-image: var(--media-wash);
  background-size: cover, cover;
  background-position: var(--media-pos, center), center;
  background-repeat: no-repeat;
}

/* ------------------------------------------------------------- keyboard */

/* Out of the way until it is tabbed to, then the first thing on the page. */
.skip-link {
  position: absolute;
  left: 0.75rem;
  top: 0.75rem;
  z-index: 40;
  transform: translateY(-160%);
  background: var(--khaki);
  color: var(--cream);
  font-family: var(--font-body);
  font-size: 0.68rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  padding: 0.75rem 1.25rem;
  transition: transform 0.2s ease;
}

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

/* currentColor, so the ring reads cream on the khaki blocks and khaki on
   the cream ones without a second rule. */
:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 4px;
}

/* ---------------------------------------------------------------- header */

.site-header {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--cream);
  border-bottom: 1px solid rgb(var(--khaki-rgb) / 0.16);
}

.site-header .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  min-height: 5rem;
}

/* The wordmark and the strapline are one lockup, not two elements that
   happen to sit near each other. */
.brand {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

.site-header .wordmark {
  font-size: 1.2rem;
  letter-spacing: 0.2em;
  line-height: 1;
}

/* The tagline is title case wherever it appears as part of the identity.
   It is never uppercased in CSS: the capitalisation is the brand's, and a
   text-transform would overrule it silently. */
.tagline {
  font-family: var(--font-body);
  font-weight: 500;
  letter-spacing: 0.08em;
  line-height: 1.2;
  opacity: 0.7;
  margin: 0;
}

.brand-line {
  font-size: 0.72rem;
}

.site-nav {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 3vw, 2.25rem);
}

.site-nav a {
  font-family: var(--font-body);
  font-size: 0.68rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  white-space: nowrap;
  padding-block: 0.35rem;
  border-bottom: 1px solid transparent;
  transition: border-color 0.25s ease, opacity 0.25s ease;
}

/* Three nav items plus the wordmark is more than a narrow phone fits at the
   full tracking, and the first thing to give is "The Archive" breaking across
   two lines. Tightened rather than shortened: the labels are the labels. */
@media (max-width: 30rem) {
  .site-header .wrap {
    gap: 0.75rem;
  }

  .wordmark {
    font-size: 0.85rem;
    letter-spacing: 0.2em;
  }

  .site-nav {
    gap: 0.85rem;
  }

  .site-nav a {
    font-size: 0.6rem;
    letter-spacing: 0.12em;
  }
}

.site-nav a:hover,
.site-nav a[aria-current='page'] {
  border-bottom-color: currentColor;
}

/* ------------------------------------------------------------------ hero */

.hero {
  position: relative;
  min-height: min(92svh, 54rem);
  display: flex;
  align-items: flex-end;
  color: var(--cream);
  /* The frame is landscape and a phone's box is tall, so cover throws away
     about two thirds of the width there and centring cuts straight through
     her. 36% puts her in the middle of what is left. On a wide screen the
     photograph fills the width exactly and there is no horizontal excess, so
     this only moves the narrow crop. */
  --media-pos: 36% 38%;
}

.hero::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--hero-scrim);
  /* Takes 12% off the photograph only. It filters what is painted behind this
     layer, which is the hero's background; the scrim is this layer's own
     background and paints on top of the result, and the copy sits above it at
     z-index 1, so neither is touched. A wash laid over the frame would have
     tinted it instead of dimming it. */
  -webkit-backdrop-filter: brightness(0.88);
  backdrop-filter: brightness(0.88);
  pointer-events: none;
}

/* The wide layout holds the copy in a column at the right, so its scrim is an
   ellipse under that column and she stays out of it. On a narrow screen the
   copy runs the full width and an ellipse at 78% leaves its left half on the
   bright of her dress, so the narrow layout gets a band instead: the whole
   width at the foot, spent by a third of the way up, which is below her. */
@media (max-width: 48rem) {
  .hero {
    --hero-scrim: linear-gradient(
      to top,
      rgb(var(--khaki-rgb) / 0.9) 0%,
      rgb(var(--khaki-rgb) / 0.78) 12%,
      rgb(var(--khaki-rgb) / 0.52) 20%,
      rgb(var(--khaki-rgb) / 0.18) 29%,
      rgb(var(--khaki-rgb) / 0) 38%
    );
  }
}

.hero .wrap {
  position: relative;
  z-index: 1;
  display: flex;
  justify-content: flex-end;
  width: min(100% - 2.5rem, 76rem);
}

/* Held to the right of the frame so the copy falls over the open, darker
   ground behind the figure rather than across her. */
.hero-copy {
  padding-block: clamp(2.5rem, 6vw, 4.5rem);
  max-width: 34rem;
  /* The type holds itself up. A shadow follows the letterforms, so it darkens
     the few pixels behind them rather than a quarter of the photograph, and
     the scrim can be light enough to read as the light falling off rather
     than as shade laid on top. Two of them: a tight one for the edges and a
     wide soft one for the ground. */
  text-shadow: 0 1px 2px rgb(var(--khaki-rgb) / 0.5), 0 2px 28px rgb(var(--khaki-rgb) / 0.55);
}

/* The hero carries a sentence now rather than a phrase, so it is set at a
   reading size instead of the poster size a three-word line could hold. */
.hero-statement {
  font-size: clamp(1.5rem, 2.5vw, 2.35rem);
  line-height: 1.24;
  margin-bottom: 2.25rem;
}

/* --------------------------------------------------------------- buttons */

.btn {
  display: inline-block;
  font-family: var(--font-body);
  font-size: 0.68rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  padding: 0.9rem 1.6rem;
  border: 1px solid currentColor;
  transition: background-color 0.3s ease, color 0.3s ease;
}

.btn:hover {
  background: var(--cream);
  color: var(--khaki);
}

.btn-khaki:hover {
  background: var(--khaki);
  color: var(--cream);
}

.link-underline {
  font-family: var(--font-body);
  font-size: 0.68rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  border-bottom: 1px solid currentColor;
  padding-bottom: 0.3rem;
  white-space: nowrap;
}

/* ------------------------------------------------------------ philosophy */

/* Sized by height, not aspect-ratio: a max-height against a ratio makes
   Chrome shrink the width instead, which pulls the plate off the right edge. */
.band {
  position: relative;
  /* The glow behind the copy is inset negatively so it reaches past the type
     on every side, and the copy sits at the right edge of the frame, so it
     ran off the page and gave the whole document a sideways scroll. It is
     decoration inside the plate and belongs inside it. */
  overflow: hidden;
  height: clamp(20rem, 56vw, 78svh);
  --media-wash: var(--band-wash);
  display: flex;
  align-items: center;
  justify-content: flex-end;
  --media-pos: center;
}

.band-copy {
  position: relative;
  /* Kept alongside the glow below rather than instead of it. The halo hugs the
     letterforms, which is where the glow is weakest: at its edges, over the
     dark trunks, the type needs contrast the wash alone does not give it. */
  text-shadow: 0 0 2px rgb(var(--cream-rgb) / 0.75), 0 1px 8px rgb(var(--cream-rgb) / 0.6);
  z-index: 1;
  isolation: isolate;
  text-align: center;
  padding: 2rem clamp(1.5rem, 6vw, 5rem);
  color: var(--khaki);
}

/* The copy sits over the brightest part of the frame, the sun on the water,
   and khaki type needs a ground there rather than a hint of one. The glow is
   stronger and reaches further than it did: near solid where the type is,
   gone before the edge of the plate, so it still reads as light on the water
   rather than as a panel laid over it. */

.band-copy .display {
  margin-bottom: 0.7rem;
}

/* A sentence, so it is set as one: the reading face in italic, the way the
   shop page sets the line under The Tending. It was a label, which meant
   11px of tracked sans under an 80px display line, too small to read over
   water and too far from the voice of the line above it. No text-transform
   anywhere near it: the capitalisation is the copy's own. */
/* The glow is back, and this records why rather than leaving the next person
   to rediscover it. It was removed because it read as a patch of haze on the
   current photograph, and removing it was worse: khaki type fell under the
   3.0 contrast floor across 38% of its own area on a desktop and 49% on a
   phone. Brightening the picture instead was tested to 2x and still left
   29.6% under the floor, because a near-black palm trunk at twice the
   brightness is still near-black against khaki.

   The real fault is the photograph. The band's rule, written in the images
   README, is that the side carrying the type stays bright and quiet, between
   130 and 170. This one runs 20 to 255 behind the type, and the glow is what
   has been covering that. A frame that keeps the rule needs none of this. */
.band-copy::before {
  content: '';
  position: absolute;
  inset: -22% -16%;
  z-index: -1;
  /* closest-side, not the default farthest-corner. This box is much wider
     than it is tall, so a gradient sized to its corners reaches the top and
     bottom edges at around half its length, where it is still nearly opaque,
     and stops dead: a straight line across the frame above and below the
     type. Sized to the nearest side it reaches zero before every edge and
     there is nothing to cut. */
  background: radial-gradient(
    ellipse closest-side at center,
    rgb(var(--cream-rgb) / 0.92) 0%,
    rgb(var(--cream-rgb) / 0.82) 42%,
    rgb(var(--cream-rgb) / 0.4) 72%,
    rgb(var(--cream-rgb) / 0) 100%
  );
  pointer-events: none;
}

.band-dek {
  font-family: var(--font-reading);
  font-style: italic;
  font-size: clamp(1.05rem, 1.6vw, 1.5rem);
  line-height: 1.4;
  letter-spacing: 0.01em;
  margin: 0;
  /* Held to a measure so it breaks under the title rather than running the
     full width of the copy block. */
  max-width: 26rem;
  margin-inline: auto;
}

/* A finished lockup rather than a photograph: it carries its own type, its
   own khaki ground, and its own margins. The band takes the artwork's exact
   ratio so nothing is ever cropped off it, and sets no type of its own. */
/* The band takes the artwork's exact ratio so nothing is cropped off it, and
   sets no type of its own: the lockup carries all four of its lines, the
   strapline included and in the brand's own title case. An earlier version
   set that line in capitals, and it was painted out and drawn here as live
   type until the artwork was redrawn. It no longer is. */
/* Shaped like the artwork it carries, so it is full width at every size and
   nothing is ever cropped off it. It spent a while being given the screen's
   height instead, which left space around a 1.95:1 picture that could not be
   cropped to fill it: above and below on a tall window, and as olive bars down
   both sides on a wide one. The band is the one section that does not take the
   screen, because its lines are painted into its pixels. */
.emblem-band {
  aspect-ratio: 1689 / 867;
  --media-pos: center;
}

/* The next volume, announced over a photograph. Cream type on the same
   bottom-weighted scrim the hero uses, so the copy holds over bright grass. */
/* The frame is shown at the ratio it was composed at rather than cropped
   into a letterbox, because the subject sits centre and a tighter band puts
   the type across her. */
.volume-band {
  position: relative;
  aspect-ratio: 1823 / 863;
  display: flex;
  align-items: flex-start;
  color: var(--cream);
  --media-pos: center;
}

.volume-band::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--announce-scrim);
  pointer-events: none;
}

/* Top left, on the page's own left margin, so it opens the same way the
   Volume I block below it does: label, then title, aligned to the same
   column. It sat at the foot before, and centred rather than left aligned,
   because .wrap and a 24rem max-width were on one element and the wrap's
   auto margins centred what the max-width had narrowed. The wrap is its own
   element now and does only its job. */
.volume-band-copy {
  position: relative;
  z-index: 1;
  /* Holds the type itself, so the scrim over the photograph can be light.
     Same two shadows the hero copy uses. */
  text-shadow: 0 1px 2px rgb(var(--khaki-rgb) / 0.5), 0 2px 28px rgb(var(--khaki-rgb) / 0.55);
  /* The same measure of air the Volume I block gives its label, so the two
     open at the same height as well as on the same column. No width cap: the
     title is set at the full display size now. The cap is what keeps the line
     off her: at the full width it runs to 46% across and her sunglasses begin
     at about 44%, so the last letter of Vessel landed on her eye. Wrapped, it
     ends at 35% and the photograph is not cropped to make room. */
  padding-block: clamp(2.5rem, 6vw, 4.5rem);
  max-width: 30rem;
}

/* The size is display-lg's now, the same as the Volume I block below it, so
   the two volumes are set in one voice. It was sized down to finish before
   the figure, which was reasonable when the copy sat in the lower middle of
   the frame; at the top left it has the width to carry the full size. */
.volume-band-copy .display {
  line-height: 1.15;
  margin: 0.7rem 0 0.55rem;
  /* Balanced, so the two lines come out even and the break falls after the
     separator rather than leaving one word stranded. Left to itself the line
     broke as "Volume II · The" and "Vessel". */
  text-wrap: balance;
}

/* The band is a link now. The title carries the affordance, in the same
   understated way the note rows do: it moves rather than decorates. */
.volume-band .display {
  transition: transform 0.35s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.volume-band:hover .display,
.volume-band:focus-visible .display {
  transform: translateX(0.35rem);
}

.volume-band:focus-visible {
  outline-offset: -4px;
}

/* A 2:1 frame is only 178px tall on a phone, which is not enough to hold
   type. The box takes a squarer ratio and cover crops the sides, keeping her
   centred. No min-height: a minimum against an aspect-ratio makes the box
   grow WIDER than the viewport rather than taller. */
@media (max-width: 48rem) {
  .volume-band {
    aspect-ratio: 4 / 3;
    /* The title is the same size as the block below it at every width, and on
       a narrow screen that means it runs the full width of the frame, across
       the sun behind her. The wide crop has somewhere dark to put the line and
       this one does not, so the narrow layout carries more scrim rather than
       the photograph being darkened everywhere for a problem it only has
       here. Built from the same token, so it is still the one khaki. */
    --announce-scrim: linear-gradient(
      to bottom,
      rgb(var(--khaki-rgb) / 0.58) 0%,
      rgb(var(--khaki-rgb) / 0.36) 18%,
      rgb(var(--khaki-rgb) / 0.08) 34%,
      rgb(var(--khaki-rgb) / 0) 48%
    );
  }

  /* A cap in rem does not follow a title sized in vw: 30rem wraps the line at
     80px and leaves it on one at 38px, where it ran back across her glasses.
     The narrow layout gets a cap that wraps it there too. */
  .volume-band-copy {
    max-width: 16rem;
  }
}

/* ------------------------------------------------------------ note lists */

.volume-block {
  background: var(--khaki);
  color: var(--cream);
  padding-block: clamp(3.5rem, 8vw, 6rem);
}

/* The closing block of the homepage, and the only one there that is not a
   photograph. It takes the note list's measure rather than the deeper
   page-level one, so the whole page runs on a single rhythm: the plates meet
   edge to edge, and the two blocks that hold copy are inset by the same
   amount. */
.home-about {
  padding-block: clamp(3.5rem, 8vw, 6rem);
}

.volume-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem 2rem;
  margin-bottom: clamp(2rem, 5vw, 3.25rem);
}

.volume-cover {
  aspect-ratio: 16 / 10;
  margin-bottom: clamp(2rem, 5vw, 3.25rem);
  --media-pos: center 55%;
}

.note-list {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid rgb(var(--cream-rgb) / 0.28);
}

.note-list li {
  border-bottom: 1px solid rgb(var(--cream-rgb) / 0.28);
}

.note-row {
  display: grid;
  grid-template-columns: 3.25rem 1fr auto;
  align-items: center;
  gap: 0.75rem;
  padding-block: clamp(0.9rem, 2vw, 1.35rem);
  transition: opacity 0.3s ease;
}

.note-row .num {
  font-family: var(--font-body);
  font-size: 0.66rem;
  letter-spacing: 0.16em;
  opacity: 0.7;
}

.note-row .title {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 3.4vw, 2.5rem);
  line-height: 1.15;
  transition: transform 0.35s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.note-row .arrow {
  font-size: 1.1rem;
  opacity: 0.75;
  transition: transform 0.35s cubic-bezier(0.22, 0.61, 0.36, 1);
}

a.note-row:hover .title {
  transform: translateX(0.35rem);
}

a.note-row:hover .arrow {
  transform: translate(0.25rem, -0.25rem);
}

/* Holds the line's height where a title will go, without standing in for
   one. */
.title-withheld {
  opacity: 0.35;
}

.note-row.is-unpublished {
  opacity: 0.55;
  cursor: default;
}

.note-row .pending {
  font-family: var(--font-body);
  font-size: 0.62rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  opacity: 0.7;
}

/* ------------------------------------------------------------- volume ix */

.volume-index {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid rgb(var(--khaki-rgb) / 0.18);
}

.volume-index li {
  border-bottom: 1px solid rgb(var(--khaki-rgb) / 0.18);
}

.volume-index .note-row {
  grid-template-columns: 5.5rem 1fr auto;
}

/* ----------------------------------------------------------------- about */

/* The About page, and only the About page. The home section used to pair a
   portrait with its copy on this same grid; it carries a blurb now, so the
   grid and the modifier that sat on top of it are one thing again.

   An author's page rather than a profile: the writing leads and the
   portrait accompanies it. Explicit rows put the name and the biography
   first in the reading order at every width, which is the one thing source
   order cannot give both layouts at once. */
.about-grid {
  display: grid;
  gap: clamp(2.5rem, 6vw, 5rem);
  align-items: start;
}

.about-grid .about-copy {
  grid-row: 1;
}

.about-portrait {
  aspect-ratio: 4 / 5;
  --media-pos: center;
  /* Held to a size rather than filling its column, so the column's slack
     becomes space around it instead of more photograph. The width is needed
     with it: the plate is an empty element drawn in a background, so a cap
     on its own leaves it nothing to be capped from and it collapses. */
  width: 100%;
  max-width: 11.5rem;
}

@media (min-width: 60rem) {
  /* Two columns sized to their contents rather than to the page: the reading
     measure, then the portrait, with one gutter between them. Held together
     in the middle of the page instead of pushed to its outer margins, which
     is what fractional columns were doing. The margin belongs outside the
     pair, not down the middle of it. */
  .about-grid {
    grid-template-columns: minmax(0, 34rem) 13rem;
    justify-content: center;
    column-gap: clamp(3rem, 5vw, 4.5rem);
  }

  .about-grid .about-copy {
    grid-column: 1;
  }

}

/* The home section keeps the measure it had when a portrait sat beside it,
   so the type and the line length are unchanged and only the photograph is
   missing. The space it occupied is left as space. */
.home-blurb {
  max-width: 38rem;
}

/* The introduction lost a line and the section would have closed up by that
   much. The space around it is the composition, so the block keeps the height
   it had: 467px at this width, measured before the copy was shortened. */
.home-about .wrap {
  min-height: 17.2rem;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.about-copy .display {
  margin-bottom: 1.1rem;
}

.about-copy .label {
  margin-bottom: 2.25rem;
}

/* Quiet, and set apart from the introduction it follows. */
.about-link {
  display: inline-block;
  margin-top: 1rem;
}

/* A distinct section after the biography, held apart by a rule and a full
   measure of space so it reads as an aside rather than a fifth paragraph. */
.about-behind {
  margin-top: clamp(3rem, 7vw, 4.5rem);
  padding-top: clamp(1.75rem, 3.5vw, 2.5rem);
  border-top: 1px solid rgb(var(--khaki-rgb) / 0.24);
}

.about-behind .label {
  margin-bottom: 1.1rem;
}

.about-behind p:last-child {
  margin-top: 1.5rem;
}

/* ------------------------------------------------------------ note pages */

.note-page {
  padding-block: clamp(3.5rem, 9vw, 7rem);
}

.note-head {
  margin-bottom: clamp(2.5rem, 6vw, 4rem);
}

.note-head .label {
  margin-bottom: 1.25rem;
  opacity: 0.7;
}

/* The essays are set in the reading face. Jost is a geometric sans and was
   doing body-copy duty because it was the only text-sized face the brand
   had; EB Garamond is drawn for this. Larger and tighter than the sans it
   replaces, because its x-height is smaller. */
.note-body {
  font-family: var(--font-reading);
}

.note-body p {
  font-size: 1.2rem;
  line-height: 1.72;
}

.note-pending {
  border: 1px solid rgb(var(--khaki-rgb) / 0.28);
  padding: clamp(1.5rem, 4vw, 2.25rem);
}

.note-pending .label {
  margin-bottom: 0.85rem;
}

.note-pending p {
  margin: 0;
  font-size: 0.92rem;
  opacity: 0.8;
}

.note-pending code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.84em;
  word-break: break-all;
}

.note-foot {
  margin-top: clamp(3rem, 7vw, 5rem);
  padding-top: 1.5rem;
  border-top: 1px solid rgb(var(--khaki-rgb) / 0.24);
}

/* Quiet and secondary to the essay: previous, the way back up, next. */
.note-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 2rem;
  justify-content: space-between;
  align-items: baseline;
}

.note-seal {
  display: block;
  text-align: center;
  margin: 2.25rem 0 0;
}

.seal {
  font-family: var(--font-body);
  font-size: 0.66rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  opacity: 0.72;
}

/* ---------------------------------------------------------------- footer */

.site-footer {
  background: var(--khaki);
  color: var(--cream);
  padding-block: clamp(3rem, 7vw, 5rem);
}

.footer-top {
  display: flex;
  flex-wrap: wrap;
  gap: 2rem;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 0;
}

.footer-brand p {
  margin: 0;
}

.footer-tagline {
  font-size: 0.8rem;
}

.footer-wordmark {
  font-size: clamp(1.3rem, 2.6vw, 1.8rem);
  letter-spacing: 0.24em;
  line-height: 1;
  margin-bottom: 0.75rem;
}

.footer-links {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.footer-links a {
  font-family: var(--font-body);
  font-size: 0.68rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  opacity: 0.85;
}

.footer-links a:hover {
  opacity: 1;
}

/* The notes carry their own section breaks: a rule in five of them, the
   brand's middle dot in the other two. Both are authored, so both render. */
.note-rule {
  margin: 2.75rem 0;
}

.note-break {
  text-align: center;
  letter-spacing: 0.3em;
  opacity: 0.5;
  margin: 2.75rem 0;
}

.note-body h2 {
  margin: 2.5rem 0 1rem;
}

.note-body a {
  border-bottom: 1px solid rgb(var(--khaki-rgb) / 0.4);
}

/* ------------------------------------------------------------------ shop */

/* The product page reuses the two-column grid and prose column from /about/.
   Only the plate ratio and the meta row are its own. */
/* The archive's index reserves a fixed first column for "Volume I". A product
   may have no format yet, so the shop's collapses instead of leaving the title
   behind an empty indent. */
/* Generous, deliberate space. The page is a statement, not a holding page. */
/* Its own grid. It borrowed .about-grid for a while, which was fine until
   that grid was sized to the About page's measure and this page silently
   inherited a 13rem column for its copy. Two pages, two jobs. */
.shop-placeholder {
  padding-block: clamp(3rem, 10vh, 7rem);
  display: grid;
  gap: clamp(2.5rem, 6vw, 5rem);
  align-items: center;
}

@media (min-width: 60rem) {
  .shop-placeholder {
    grid-template-columns: minmax(0, 0.85fr) minmax(0, 1fr);
  }
}

/* The mockup is a 2:3 frame, and the plate takes that ratio so the book is
   shown whole rather than cropped into a shape it was not made for. */
.shop-plate {
  aspect-ratio: 2 / 3;
  --media-pos: center;
}

.shop-title {
  margin: 1.5rem 0 0.9rem;
}

/* Quieter than the title, and italic: an editorial aside rather than a
   second headline. */
.shop-subline {
  font-family: var(--font-reading);
  font-style: italic;
  font-size: clamp(1.2rem, 2.2vw, 1.6rem);
  line-height: 1.3;
  margin: 0 0 2.25rem;
  opacity: 0.85;
}

/* A restrained measure, narrower than the prose column, set in the reading
   face rather than the label face. */
.shop-body {
  font-family: var(--font-reading);
  font-size: 1.05rem;
  line-height: 1.7;
  max-width: 30rem;
  margin: 0 0 1.35rem;
}

/* The 2.75rem was the gap before COMING SOON, set on the only paragraph
   there was. With two, it belongs to the last one: between paragraphs it is
   a paragraph break, not a section break. */
.shop-body:last-of-type {
  margin-bottom: 2.75rem;
}

.shop-note {
  margin: 0;
}

.shop-index .note-row {
  grid-template-columns: auto 1fr auto;
}

.product-plate {
  aspect-ratio: 4 / 5;
  --media-pos: center;
}

.product-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.75rem;
  margin: 0 0 2rem;
}

.product-buy {
  margin: 2.5rem 0 1rem;
}

/* --------------------------------------------------------------- motion  */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}

/* --------------------------------------------------------------- consent */

/* Quiet by construction: the site's own two colours, the site's own faces,
   one hairline rule, and no motion. It should read as the last paragraph of
   the page rather than as a widget that arrived from somewhere else. */

.consent-banner {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 60;
  background: var(--cream);
  color: var(--khaki);
  border-top: 1px solid rgb(var(--khaki-rgb) / 0.22);
  /* Above the page, so the shadow stays a whisper: enough to lift the bar off
     a photograph, not enough to read as a card. */
  box-shadow: 0 -1px 24px rgb(var(--khaki-rgb) / 0.08);
  padding-block: clamp(1.25rem, 3vw, 1.75rem);
}

.consent-banner-inner {
  width: min(100% - 2.5rem, 76rem);
  margin-inline: auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: clamp(1rem, 3vw, 2.5rem);
}

.consent-banner-copy {
  flex: 1 1 22rem;
  min-width: 0;
}

.consent-banner-title {
  margin: 0 0 0.5rem;
}

.consent-banner-text {
  margin: 0;
  font-family: var(--font-reading);
  font-size: 0.95rem;
  line-height: 1.7;
  max-width: 46rem;
}

.consent-banner-actions,
.consent-sheet-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
}

/* Accept and Reject are the same element with the same weight. Nothing here
   makes one of them the easy one. */
.consent-btn {
  background: transparent;
  color: inherit;
  cursor: pointer;
  font: inherit;
  font-family: var(--font-body);
  font-size: 0.68rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

.consent-btn:hover {
  background: var(--khaki);
  color: var(--cream);
}

.consent-btn-save {
  background: var(--khaki);
  color: var(--cream);
}

.consent-btn-save:hover {
  background: transparent;
  color: var(--khaki);
}

.consent-plain {
  background: none;
  border: 0;
  padding: 0.9rem 0;
  cursor: pointer;
  color: inherit;
  font-family: var(--font-body);
  font-size: 0.68rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  border-bottom: 1px solid currentColor;
}

/* ------------------------------------------------------- preference panel */

/* The hidden attribute is a UA display:none, and any author display wins
   over it. The panel is a flex box, so without this it ships open. */
.consent[hidden],
.consent-banner[hidden],
.consent-panel[hidden] {
  display: none;
}

.consent-panel {
  position: fixed;
  inset: 0;
  z-index: 70;
  background: rgb(var(--khaki-rgb) / 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(1rem, 4vw, 3rem);
  overflow-y: auto;
}

.consent-sheet {
  background: var(--cream);
  color: var(--khaki);
  border: 1px solid rgb(var(--khaki-rgb) / 0.22);
  width: min(100%, 38rem);
  max-height: 100%;
  overflow-y: auto;
  padding: clamp(1.5rem, 4vw, 2.75rem);
}

.consent-sheet-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
}

.consent-panel-title {
  margin: 0;
}

.consent-close {
  background: none;
  border: 0;
  cursor: pointer;
  color: inherit;
  font-size: 1.5rem;
  line-height: 1;
  padding: 0.25rem 0.5rem;
}

.consent-sheet-text {
  font-family: var(--font-reading);
  font-size: 0.95rem;
  line-height: 1.7;
  margin: 0.75rem 0 1.75rem;
}

.consent-categories {
  list-style: none;
  margin: 0 0 1.75rem;
  padding: 0;
}

.consent-category {
  border-top: 1px solid rgb(var(--khaki-rgb) / 0.18);
  padding-block: 1.25rem;
}

.consent-category:last-child {
  border-bottom: 1px solid rgb(var(--khaki-rgb) / 0.18);
}

.consent-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.consent-check {
  /* Native control, kept native: it is already keyboard operable, already
     announced correctly, and already understood. Only its colour is ours. */
  accent-color: var(--khaki);
  width: 1.05rem;
  height: 1.05rem;
  flex: none;
  margin: 0;
}

.consent-name {
  cursor: pointer;
  margin: 0;
}

.consent-check:disabled + .consent-name {
  cursor: default;
}

.consent-always {
  margin: 0 0 0 auto;
  font-size: 0.6rem;
}

.consent-summary {
  font-family: var(--font-reading);
  font-size: 0.92rem;
  line-height: 1.7;
  margin: 0.6rem 0 0;
}

.consent-used {
  font-family: var(--font-body);
  font-size: 0.66rem;
  letter-spacing: 0.12em;
  margin: 0.5rem 0 0;
}

/* .dim is 0.72, which puts khaki on cream at 3.48:1 and under the 4.5:1 that
   text this size needs. Quieter than the copy above it, still readable. */
.consent-used.dim {
  opacity: 0.88;
}

.consent-more {
  margin: 1.5rem 0 0;
}

/* ------------------------------------------------- footer and the page */

.footer-privacy {
  margin: 1.75rem 0 0;
}

.footer-choices {
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  color: inherit;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.68rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  border-bottom: 1px solid currentColor;
  padding-bottom: 0.3rem;
}

.privacy-heading {
  margin: 2.5rem 0 0.75rem;
}

/* The reading column is 40rem and the inventory wants more than that, so the
   table steps out of the column and centres itself on the page. It is the one
   thing on the note that is a table rather than prose, and the prose keeps its
   measure either way. */
.privacy-table-wrap {
  border: 1px solid rgb(var(--khaki-rgb) / 0.18);
  width: min(100%, 76rem);
  margin-inline: auto;
}

@media (min-width: 52rem) {
  .privacy-table-wrap {
    width: min(76rem, calc(100vw - 2.5rem));
    margin-left: 50%;
    transform: translateX(-50%);
  }
}

.privacy-table {
  border-collapse: collapse;
  width: 100%;
  font-family: var(--font-body);
  font-size: 0.78rem;
  line-height: 1.6;
}

.privacy-table th,
.privacy-table td {
  text-align: left;
  vertical-align: top;
  padding: 0.85rem 1rem;
  border-bottom: 1px solid rgb(var(--khaki-rgb) / 0.14);
}

.privacy-table th {
  font-size: 0.62rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

.privacy-table tr:last-child td {
  border-bottom: 0;
}

/* Below the width a six-column table can hold, each entry becomes a stack of
   labelled lines. Nothing is cut off and nothing has to be scrolled sideways
   to be read, which is what a table in a reading column otherwise costs. */
@media (max-width: 52rem) {
  .privacy-table,
  .privacy-table tbody,
  .privacy-table tr,
  .privacy-table td {
    display: block;
    width: auto;
  }

  .privacy-table thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .privacy-table tr {
    padding: 0.5rem 0;
  }

  .privacy-table tr + tr {
    border-top: 1px solid rgb(var(--khaki-rgb) / 0.18);
  }

  .privacy-table td {
    border-bottom: 0;
    padding: 0.45rem 1rem;
  }

  .privacy-table td::before {
    content: attr(data-label);
    display: block;
    font-size: 0.6rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    opacity: 0.88;
    margin-bottom: 0.15rem;
  }
}

.privacy-reopen {
  margin-top: 2.5rem;
}

@media (max-width: 40rem) {
  .consent-banner-actions .consent-btn {
    flex: 1 1 auto;
    text-align: center;
  }

  .consent-sheet-actions .consent-btn {
    flex: 1 1 100%;
    text-align: center;
  }
}

.footer-legal {
  font-family: var(--font-body);
  font-size: 0.66rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  opacity: 0.88;
  margin: 1.25rem 0 0;
}

/* -------------------------------------------------------------- colophon */

/* The About page is one column of document. The portrait lives inside it,
   after the paragraph that says what the picture is, rather than beside the
   page in a plate of its own. */

.about-page {
  padding-bottom: 2rem;
  /* The two columns and the gutter between them, and no wider. The page uses
     .wrap so it shares the site's gutters, but the composition is held to its
     own measure so the rule under it runs the width of the content rather
     than the width of the page. */
  max-width: 51.5rem;
  margin-inline: auto;
}

/* The biography and the portrait. Its own grid rather than .about-grid, which
   the product page owns: borrowing that one is how the shop ended up laid out
   by this page before. */
.about-lede {
  display: grid;
  /* No row gap. The space between the name and the writing is the role's own
     margin, which is tuned to it; a gap here would add to that and then have
     to be subtracted again. */
  row-gap: 0;
}

/* Stacked, this is the gap between the last line of the writing and the
   photograph. It is set here rather than as a row gap because the only row
   boundary that wants space is this one. */
.about-lede .about-figure {
  margin: clamp(2.75rem, 7vw, 3.75rem) 0 0;
}

@media (min-width: 60rem) {
  /* The reading measure, then the portrait, with one gutter between. Sized to
     their contents rather than in fractions, so the slack falls outside the
     pair instead of down the middle of it. */
  .about-lede {
    grid-template-columns: minmax(0, 1fr) 13rem;
    column-gap: clamp(3rem, 5vw, 4.5rem);
  }

  .about-head {
    grid-column: 1;
    grid-row: 1;
  }

  .about-body {
    grid-column: 1;
    grid-row: 2;
  }

  /* The second row, so the photograph begins where the writing begins and the
     name keeps the top of the page to itself. */
  .about-lede .about-figure {
    grid-column: 2;
    grid-row: 2;
    margin: 0;
  }
}

/* The page opens on her, so the biography above the colophon takes the body
   face and measure the colophon does. It is her writing either way. */
.about-role {
  margin: 1.1rem 0 2.5rem;
}

.about-body p {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 0.97rem;
  line-height: 1.95;
  margin: 0 0 1.85rem;
  max-width: 34rem;
}

/* Her account of the work, under the biography and the portrait. The hairline
   above it is the one that used to open the colophon, and it is drawn here
   instead: the rule belongs to whichever section comes first after the
   biography, and the imagery disclosure that follows is close enough to this
   to need no second line between them. */
.about-practice {
  margin-top: clamp(3rem, 6vw, 4rem);
  padding-top: clamp(2.5rem, 5vw, 3.5rem);
  border-top: 1px solid rgb(var(--khaki-rgb) / 0.26);
}

/* Understated, and the same label the imagery disclosure uses, so the two read
   as a pair of quiet sections rather than one announcing itself over another.
   It sets no rule of its own: the section above it carries that. */
.about-section-label {
  margin: 0 0 1.6rem;
  max-width: 34rem;
  opacity: 0.88;
}

/* The same face, size and measure as the biography. It is her writing too. */
.about-practice p {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 0.97rem;
  line-height: 1.95;
  margin: 0 0 1.85rem;
  max-width: 34rem;
}

.about-practice p:last-child {
  margin-bottom: 0;
}

/* The colophon opens the second half of the page, so it is titled rather than
   labelled: a section front inside a document, between her and the making.

   While the colophon is held back this holds only the imagery disclosure,
   which follows The Practice as a quieter sibling rather than a new half of
   the page: no rule between them, and less air than a section front takes. */
.colophon {
  margin-top: 4rem;
  padding-top: 3.5rem;
  border-top: 1px solid rgb(var(--khaki-rgb) / 0.26);
}

.about-practice + .colophon {
  margin-top: clamp(2.25rem, 4.5vw, 3rem);
  padding-top: 0;
  border-top: 0;
}

/* First in its block, so it draws no rule of its own. */
.about-practice + .colophon .colophon-heading:first-child {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}

.colophon-title {
  font-size: clamp(2.1rem, 4.4vw, 3.4rem);
  margin: 0;
}

/* The body is the label face, not the reading face. That is her own ruling,
   written into the typeface list on this very page: EB Garamond is for the
   notes. The reading face appears here three times only, where it is doing
   something a label cannot: the opening line, the pull, and the names of the
   faces set in the face they name. */
.colophon p {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 0.97rem;
  line-height: 1.95;
  margin: 0 0 1.85rem;
  max-width: 34rem;
}

.colophon-lede {
  font-family: var(--font-reading) !important;
  font-size: 1.3rem !important;
  line-height: 1.6 !important;
  max-width: 32rem;
  margin: 1.35rem 0 0 !important;
}

.colophon-pull {
  font-family: var(--font-reading) !important;
  font-style: italic;
  font-size: 1.18rem !important;
  line-height: 1.7 !important;
  opacity: 0.88;
}

/* Unless it is the first thing in the block, which already drew one. With the
   colophon held back the imagery heading leads, and its own rule would have
   landed a hair below the block's. */
.colophon-heading:first-child {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}

/* Each section opens on a rule, the way a document's parts do. */
.colophon-heading {
  margin: 4rem 0 1.6rem;
  padding-top: 1.75rem;
  border-top: 1px solid rgb(var(--khaki-rgb) / 0.26);
  max-width: 34rem;
  opacity: 0.88;
}

/* --------------------------------------------------------- the typefaces */

.colophon-faces {
  list-style: none;
  padding: 0;
  margin: 0 0 1.85rem;
  max-width: 34rem;
}

.colophon-faces li {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 0.97rem;
  line-height: 2.1;
}

/* Each face named in the face it names. */
.colophon-face {
  font-family: var(--font-reading);
  font-style: italic;
  font-size: 1.18rem;
}

.colophon-faces li:nth-child(1) .colophon-face {
  font-family: var(--font-wordmark);
  font-style: normal;
  font-size: 1rem;
  letter-spacing: 0.08em;
}

.colophon-faces li:nth-child(2) .colophon-face {
  font-family: var(--font-display);
  font-style: normal;
  font-size: 1.25rem;
}

.colophon-faces li:nth-child(4) .colophon-face {
  font-family: var(--font-body);
  font-style: normal;
  font-size: 1rem;
  letter-spacing: 0.1em;
}

/* ------------------------------------------------------- custom tools */

.colophon-systems {
  margin: 0 0 2rem;
  max-width: 34rem;
}

.colophon-system {
  padding: 1.6rem 0;
  border-top: 1px solid rgb(var(--khaki-rgb) / 0.2);
}

.colophon-system:first-child {
  border-top: 0;
  padding-top: 0;
}

.colophon-system-name {
  margin: 0 0 0.75rem;
}

.colophon-system-role {
  font-weight: 400;
  letter-spacing: 0.16em;
  opacity: 0.82;
}

.colophon-system p {
  margin: 0;
}

/* ---------------------------------------------------------- the portrait */

.about-figure {
  margin: 0;
  max-width: 34rem;
}

.about-figure .about-portrait {
  width: 12.25rem;
  max-width: 100%;
  aspect-ratio: 196 / 228;
  grid-row: auto;
}

.about-credit {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 0.72rem;
  letter-spacing: 0.05em;
  line-height: 1.7;
  max-width: 24rem;
  margin-top: 1rem;
  opacity: 0.88;
}


/* ---------------------------------------------------------- the sign-off */

.colophon-signature {
  margin-top: 4.75rem;
  padding-top: 2.5rem;
  border-top: 1px solid rgb(var(--khaki-rgb) / 0.26);
  max-width: 34rem;
}

.colophon-signature p {
  margin: 0;
  max-width: none;
}

.colophon-wordmark {
  font-size: 1.06rem;
}

.colophon-tagline {
  font-family: var(--font-reading);
  font-style: italic;
  font-size: 1.06rem;
  margin-top: 0.35rem;
  opacity: 0.88;
}

.colophon-name {
  font-family: var(--font-display) !important;
  font-size: 2rem !important;
  line-height: 1.1 !important;
  margin-top: 1.85rem !important;
}

.colophon-role {
  margin-top: 0.75rem;
  opacity: 0.88;
}

@media (max-width: 54rem) {
  .colophon-heading {
    margin-top: 3.5rem;
  }
  .colophon-lede {
    font-size: 1.18rem !important;
  }
}

/* A note belonging to the tool above it rather than to the list. Set apart
   from that tool's own description so the two do not read as one paragraph. */
.colophon-system-note {
  margin-top: 1.1rem !important;
  font-style: italic;
  opacity: 0.88;
}

/* A volume page listed its notes and stopped. Every note can get back to its
   volume, and now a volume can get back to the index that holds it. */
.volume-foot {
  margin-top: clamp(2.5rem, 5vw, 4rem);
  padding-top: 2rem;
  /* The rule takes the ground it is standing on. The archive index is cream,
     so its rule is khaki; a volume block is khaki, so its rule is cream. One
     declaration, and the ground sets the colour rather than a second class. */
  border-top: 1px solid var(--foot-rule, rgb(var(--khaki-rgb) / 0.26));
}

.volume-block .volume-foot {
  --foot-rule: rgb(var(--cream-rgb) / 0.22);
}

.volume-nav {
  display: flex;
  justify-content: center;
}

/* The band title sets its own size rather than taking display-lg. At display-lg
   "Volume II · The Vessel" needs more width than the 30rem cap above allows,
   so it wrapped and left the separator stranded at the end of the first line.
   Nothing in CSS can drop a separator only when a line breaks, so the line is
   sized to hold on one instead.

   The size is set against the photograph, not the box. Measured on the Volume
   II frame: the line starts at 2% across and her sunglasses begin at about 44%,
   and the text runs 21.5% of the band's width for every 31px of type. 48px puts
   the last letter at about 35%, which clears her with room to spare.

   Wide layout only. Below 48rem the band crops to 4/3 and the 16rem cap wraps
   the line deliberately, because at one line the narrow frame has no dark place
   to put it. That layout is left exactly as it was. */
@media (min-width: 48.0625rem) {
  .volume-band-copy .display {
    font-size: clamp(2rem, 4.4vw, 3rem);
    text-wrap: nowrap;
  }
}

/* ===================================================== one frame at a time */

/* The home page is a stack of full-bleed photographs, and every one of them
   was sized to its own ratio rather than to the screen. On a wide window that
   left each section shorter than the space below the header, so the top of the
   next photograph sat under the bottom of the current one and two frames
   competed at once. Each is now given the screen it is standing in.

   The header is sticky and opaque, so the readable area is the viewport less
   the header. That height is exact rather than estimated: .site-header .wrap
   carries min-height: 5rem and the header draws a 1px rule under it, measured
   at 81px at 1680, 1024, 834 and 393 wide. The nav never wraps, so the header
   is the same height at every width the site supports.

   svh rather than vh, because on a phone vh is the viewport with the browser
   chrome retracted: using it here would make every section taller than the
   screen it is meant to fit. */
:root {
  --header-h: calc(5rem + 1px);
  --screen: calc(100svh - var(--header-h));
}

@media (min-width: 48.0625rem) {
  /* The hero was min(92svh, 54rem). The cap is what produced the gap on a
     large display: 54rem is 864px, and the screen below the header was 919. */
  .hero {
    min-height: 0;
    height: var(--screen);
  }

  .band {
    height: var(--screen);
  }

  /* These two carried aspect-ratio so the photograph was never cropped. The
     ratio has to go for the frame to fill the screen, and cover then crops the
     sides instead of letterboxing. The subject sits centre in both, so the
     crop takes background rather than her, and the title is positioned against
     the box rather than the image so it does not move. */
  .volume-band {
    aspect-ratio: auto;
    height: var(--screen);
  }

}

/* A phone is the opposite problem: the bands are 295px against an 852px screen,
   so three frames stack into one view. They are not given the whole screen,
   because a 2:1 photograph forced into a 1:2 box keeps a quarter of its width
   and throws the composition away. They are given enough that one frame leads
   and the next is a hint rather than a competitor. */
@media (max-width: 48rem) {
  /* The hero was min(92svh, 54rem), and 92svh on a phone is 13px more than the
     screen below the header, so it alone kept a sliver of the next frame. */
  .hero {
    min-height: 0;
    height: var(--screen);
  }

  /* The emblem is not in this list any more. It was, so that it stood at the
     same height as the photographs around it on a phone, and that is the same
     instruction as filling the screen on a desktop: it gives the band a height
     its artwork cannot fill, and something has to go in the space. The two
     cannot both be had. Matching heights is the one given up, because the
     thing it was bought with turned out to be visible olive panels. */
  .band,
  .volume-band {
    aspect-ratio: auto;
    height: 66svh;
  }

  /* The copy moves to the foot of the frame. A taller box crops more off the
     sides, which walks a centred subject leftward into the title: at the top
     left the line landed across her face. Nudging the crop would fix this one
     photograph and break the next, so the copy moves instead of the picture.
     The foot of a tall frame is where a standing subject is least likely to
     be, and it is where the hero already puts its own line. */
  .volume-band {
    align-items: flex-end;
    --announce-scrim: linear-gradient(
      to top,
      rgb(var(--khaki-rgb) / 0.62) 0%,
      rgb(var(--khaki-rgb) / 0.4) 18%,
      rgb(var(--khaki-rgb) / 0.1) 36%,
      rgb(var(--khaki-rgb) / 0) 52%
    );
  }
}

/* ------------------------------------------------------- the scroll cue */

/* The hero fills the screen now, which makes it less obvious that anything is
   below it. A hairline at the right edge with a mark travelling down it, set
   against the photograph in the same cream as the copy. It belongs to the hero
   rather than to the window, so it leaves with the hero on the first scroll
   instead of following the reader down the page. */
.hero::before {
  content: '';
  position: absolute;
  right: clamp(1rem, 3vw, 2.75rem);
  bottom: 0;
  width: 1px;
  height: clamp(3.5rem, 8vh, 6rem);
  background: linear-gradient(
    to bottom,
    rgb(var(--cream-rgb) / 0),
    rgb(var(--cream-rgb) / 0.55)
  );
  z-index: 2;
  pointer-events: none;
}

.hero .scroll-cue {
  position: absolute;
  right: clamp(1rem, 3vw, 2.75rem);
  bottom: clamp(4.5rem, 9vh, 7.25rem);
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  transform: rotate(180deg);
  writing-mode: vertical-rl;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.6rem;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: rgb(var(--cream-rgb) / 0.82);
  text-shadow: 0 1px 6px rgb(var(--khaki-rgb) / 0.55);
  pointer-events: none;
}

/* The mark that travels. Motion is the whole point of it, so it is the one
   thing that stops entirely when the reader has asked for less. */
.hero .scroll-cue::after {
  content: '';
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: rgb(var(--cream-rgb) / 0.9);
  animation: scroll-cue-travel 2.4s ease-in-out infinite;
}

@keyframes scroll-cue-travel {
  0% { transform: translateY(-0.35rem); opacity: 0; }
  28% { opacity: 1; }
  72% { opacity: 1; }
  100% { transform: translateY(0.9rem); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .hero .scroll-cue::after {
    animation: none;
    opacity: 0.9;
  }
}

/* Below this the hero is tall and narrow and the right edge is where a thumb
   rests, so the cue would sit under it. */
@media (max-width: 30rem) {
  .hero::before,
  .hero .scroll-cue {
    display: none;
  }
}

/* ----------------------------------------------------------- moving plate */

/* A plate whose photograph also exists as a short film. The still stays on the
   section as a background and the video lies over it, covering the same box,
   so the picture is what shows until the first frame is painted and again if
   it never is. They are the same scene, so the swap is invisible.

   Layering inside the plate: the still, the video, the haze, then whatever
   copy the section carries, which keeps the z-index it already had. */
.plate-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--media-pos, center);
  z-index: 0;
  pointer-events: none;
}

/* A warm veil over the moving picture, drawn from the brand's own cream so it
   reads as light in the air rather than a filter. Weighted to the top left,
   where the sun is in this frame, and almost nothing by the right side, where
   the copy sits and has its own contrast to hold. */
.plate-haze {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(
      ellipse 62% 58% at 34% 24%,
      rgb(var(--cream-rgb) / 0.2) 0%,
      rgb(var(--cream-rgb) / 0.09) 44%,
      rgb(var(--cream-rgb) / 0) 74%
    ),
    linear-gradient(
      to bottom,
      rgb(var(--cream-rgb) / 0.07) 0%,
      rgb(var(--cream-rgb) / 0) 34%
    );
}

/* Asked for less motion, given none: the video is taken out rather than
   paused, so the photograph underneath is what the plate is, and the file is
   never fetched. The haze goes with it, because it was painted for the moving
   picture and the still was graded without it. */
@media (prefers-reduced-motion: reduce) {
  .plate-video,
  .plate-haze {
    display: none;
  }
}
