/* ==========================================================================
   Home page — layout only. All colour and type comes from tokens.css.
   ========================================================================== */

/* --- Nav ------------------------------------------------------------------ */
.nav {
  position: sticky; top: 0; z-index: 20;
  background: var(--cream);
  border-bottom: 1px solid var(--rule);
}
.nav__inner {
  max-width: var(--page-max); margin-inline: auto;
  padding: var(--s-2) var(--gutter);
  display: flex; align-items: center; gap: var(--s-3);
  flex-wrap: wrap;
}
.nav__mark {
  font-family: var(--display);
  font-variation-settings: var(--wonk-text);
  font-size: 1.3rem; letter-spacing: -0.01em;
  text-decoration: none; margin-right: auto; white-space: nowrap;
}
.nav__links { display: flex; gap: var(--s-3); flex-wrap: wrap; list-style: none; margin: 0; padding: 0; }
.nav__links a {
  text-decoration: none; font-size: 0.94rem; color: var(--muted);
  padding-block: 0.35em;
  border-bottom: 1.5px solid transparent;
  transition: color 200ms var(--ease), border-color 200ms var(--ease);
}
.nav__links a:hover, .nav__links a[aria-current="page"] { color: var(--ink); border-color: var(--accent); }

/* --- Hero ----------------------------------------------------------------- */
.hero { padding-block: clamp(2.5rem, 1.5rem + 4vw, 4.5rem) clamp(3rem, 2rem + 4vw, 5.5rem); }

/* Layered rather than split. Text and picture occupy overlapping tracks of one
   12-column grid instead of sitting either side of a gutter, so the headline
   runs into the illustration's feathered edge and the two read as one
   composition. The overlap only works because the blend leaves the picture
   with no edges — see hero-blend.jpg. */
.hero__grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  align-items: center;
}
.hero__body {
  grid-column: 1 / 8;
  grid-row: 1;
  position: relative;
  z-index: 2;
}
.hero__art--image {
  grid-column: 7 / 13;
  grid-row: 1;
  max-width: none;
  margin: 0;
}

/* Freed from a narrow column, the name can carry the section again. */
/* The hero heading is a sentence now, not the name, so the nowrap that kept
   "Belinda Bolliger" on one line has to go — it would have run the sentence
   off the page. Sized down from 5.2rem and given a measure so it breaks into
   three lines of roughly even length rather than one long and one short.
   The name still opens the nav and closes the footer. */
.hero h1 {
  /* 1.5x at desktop: 3.5rem -> 5.25rem at the top of the clamp. The floor is
     left where it was — scaling the minimum too put 50px type on a 380px
     screen, which overflowed the viewport. */
  font-size: clamp(2.1rem, 1.0rem + 4.6vw, 5.25rem);
  max-width: 11ch;
  letter-spacing: -0.03em;
  text-wrap: balance;
}
/* Closing strapline: the four areas of work, centred across the foot of the
   hero. Set in Fraunces so it reads as part of the site's typography rather
   than as a caption. */
.hero__roles {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.3em 0.9em;
  margin: clamp(2.25rem, 1rem + 3vw, 4rem) 0 0;
  font-family: var(--display);
  font-variation-settings: var(--wonk-text);
  /* Fraunces at 400 has strokes thin enough that the accent reads washed out
     at this size; 550 gives the colour back its weight. 550 is not "bold" by
     WCAG's reckoning (700), so this line counts as normal text and takes
     --accent-deep. */
  font-weight: 550;
  font-size: clamp(1.02rem, 0.86rem + 0.56vw, 1.42rem);
  line-height: 1.3;
  letter-spacing: -0.005em;
  color: var(--accent-deep);
  max-width: none;
  text-align: center;
}
/* The dot is bound to the item that follows it, so a wrapped line can never
   end on a dangling separator. */
.hero__roles span { white-space: nowrap; }
.hero__roles span + span::before { content: "\00b7"; opacity: 0.45; margin-right: 0.55em; }

/* Held clear of the overlap so running text never sits on the illustration. */
/* The roles line used to sit here and provide the separation. */
.hero__cta { display: flex; gap: var(--s-2); flex-wrap: wrap; margin-top: var(--s-4); }

.hero__art img { display: block; width: 100%; height: auto; }

/* Hero illustration.
   Left raw, it reads as a photograph pasted onto the page: a hard rectangle
   with its own cool palette sitting on cream. Three things settle it into the
   section — a soft elliptical mask so the edges dissolve into the ground
   rather than stopping, a slight desaturation so it stops out-shouting the
   restrained palette, and a warm wash to pull its blues toward the cream. */
.hero__art--image {
  display: block;
  max-width: 780px;
  margin-inline: auto;
}
/* The feather is baked into hero-blend.jpg, generated from hero.png: the
   picture dissolves into #FAF0E6 — this section's own ground — so there is no
   seam to see, plus a desaturation and warm wash so it sits in the palette.
   CSS masking could not do this: two crossed linear masks fade slowest at the
   mid-edges, which is exactly where the picture's dark foliage and night sky
   sit, so a partial fade read as a dark band rather than a dissolve.
   NOTE: the cream is baked in. If this section's background colour ever
   changes, regenerate the image. */

/* --- Cover artwork -------------------------------------------------------- */
.cover {
  display: block; width: 100%; height: auto;
  box-shadow: 0 1px 0 var(--rule), 0 18px 32px -22px rgba(23, 23, 19, 0.55);
}

/* --- Three areas ---------------------------------------------------------- */
/* This section repurposes the template's Journal grid, which is three blocks of
   category tag, then title, then description — and carries no dividers and no
   card backgrounds. Two things had drifted from that: the tag was never built,
   and a 2px ink rule was added that the template does not use.
   The tag is back, as the site's own eyebrow, whose 2px accent bar now opens
   each column in place of that rule — the same mark, a third the width and in
   the brand colour rather than the heaviest ink on the page. Whitespace does
   the separating, as it does in the template. */
.areas { display: grid; gap: var(--s-5); grid-template-columns: 1fr; }
/* The heading gets room before the columns start, the same move the shelf makes
   with its own section head — there at --s-8, here a step under it, because
   three text columns need less runway than a row of covers. */
.sec-head + .areas { margin-top: var(--s-6); }
@media (min-width: 860px) { .areas { grid-template-columns: repeat(3, 1fr); } }

/* Three shared rows — tag, title, description — so the three descriptions
   start on the same line however many lines a title runs to. "Author
   Representation" wraps where the other two do not, and without this it
   pushed its own paragraph a line below its neighbours'. Same device the
   shelf uses to keep its covers on one baseline.
   FRAMER NOTE: Framer has no subgrid. Rebuild as three stacked rows, or accept
   the ragged start. */
@supports (grid-template-rows: subgrid) {
  @media (min-width: 860px) {
    .areas { grid-template-rows: auto auto auto; }
    .area {
      display: grid;
      grid-row: span 3;
      grid-template-rows: subgrid;
      gap: var(--s-2);
    }
    /* The row gap alone now sets the spacing. */
    .area .eyebrow, .area h3 { margin: 0; }
  }
}
.area {
  text-decoration: none;
  transition: transform var(--dur) var(--ease);
}
.area h3 { margin: 0 0 var(--s-2); }
.area p:last-child { color: var(--muted); font-size: var(--t-body); margin: 0; }
/* These tags drop the eyebrow's accent dash. Elsewhere on the site the dash
   marks a single eyebrow opening a section; three of them side by side read as
   a row of bullets, which is a list marker the content is not. */
.area .eyebrow::before { display: none; }

/* Capitals in the accent, overriding the eyebrow's sentence case for these
   three only. Two things follow from the change:
   - the colour is --accent-deep, not --accent. At this size the tag is normal
     text and needs 4.5:1; the bright accent measures 2.5:1 on paper and
     --accent-deep 5.5:1. Same rule as every other accent-coloured word here.
   - capitals lose the word-shapes lowercase gives you, so they are tracked out
     and set a step heavier to stay readable at --t-meta. */
.area .eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.09em;
  font-weight: 500;
  font-size: calc(var(--t-meta) - 2px);   /* a step under the meta size */
  color: var(--accent-deep);
}

/* No underline. With the tag now coloured at rest, the hover moved onto the
   heading, plus the 2px lift the book covers use. */
.area h3 { transition: color var(--dur) var(--ease); }
.area:hover h3,
.area:focus-visible h3 { color: var(--accent-deep); }
.area:hover, .area:focus-visible { transform: translateY(-2px); }

/* "Editorial Services" fits on one line where "Author Representation" beside it
   does not, so it is broken to two to sit level with it. The break is only for
   the three-column layout; stacked, each heading has the full width. */
.area__break { display: none; }
@media (min-width: 860px) { .area__break { display: inline; } }

/* --- About teaser --------------------------------------------------------- */
.about { display: grid; gap: var(--s-5) var(--s-6); grid-template-columns: minmax(0, 0.62fr) minmax(0, 1fr); align-items: center; }
.portrait {
  width: 100%; max-width: 330px; aspect-ratio: 4 / 5;
  border-radius: 50% 50% 4px 4px / 34% 34% 4px 4px;
  overflow: hidden; position: relative;
  background: var(--shell);
  display: grid; place-items: center;
}
.portrait__note {
  position: absolute; inset: auto 0 0 0;
  background: var(--paper); border-top: 1px dashed #CFB194;
  font-size: var(--t-meta); color: #6F6255; text-align: center; padding: 0.5em;
}
.namewall {
  display: flex; flex-wrap: wrap; gap: 0.1em 0.5em;
  font-family: var(--display); font-variation-settings: var(--wonk-text);
  font-size: var(--t-h3); line-height: 1.4; color: var(--ink);
  margin: var(--s-3) 0 0; max-width: 32ch;
}
.namewall span { white-space: nowrap; }
.namewall span::after { content: ","; color: var(--muted); }
.namewall span:last-child::after { content: none; }

/* --- Shelf head ----------------------------------------------------------- */
.sec-head { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-5); align-items: end; justify-content: space-between; margin-bottom: var(--s-4); }
.sec-head p { max-width: 44ch; color: var(--muted); }

/* --- Memoir teaser -------------------------------------------------------- */
/* Split: the title block on the left, the copy and its button on the right.
   Same two-column shape the .service rows and the .notice use — a name facing
   its explanation across a gutter — so the block is not a layout of its own.
   Tops aligned rather than centres: the heading runs to two lines and the
   paragraph to four, and centring them would leave the eyebrow floating.
   The button sits under the paragraph rather than under the title, so the
   right column reads and then acts. */
.memoir {
  display: grid;
  gap: var(--s-4) var(--s-6);
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.9fr);
  align-items: start;
}
.memoir h2 { max-width: 20ch; margin-top: var(--s-2); }
.memoir .lead { font-size: var(--t-body); max-width: 46ch; margin: 0; }

/* The heading breaks at its own full stop rather than mid-sentence after
   "Let". Keep the space before the <br>: it is display:none below the
   breakpoint, and without the space the text nodes join as "story.Let". */
.memoir__break { display: none; }
@media (min-width: 700px) { .memoir__break { display: inline; } }

/* --- Contact -------------------------------------------------------------- */
.contact { text-align: center; }
.contact h2 { max-width: 18ch; margin-inline: auto; }
.contact p { margin-inline: auto; }

/* --- Footer --------------------------------------------------------------- */
/* The footer wears the same espresso as the Memoir block rather than --ink,
   so the site has one dark, not two that are a hair apart — ink and the old
   footer ground measured 1.02:1 against each other, a difference nobody can
   see but which meant two tokens to keep in step.
   Three tiers: the invitation, the directory, the small print. It listed
   links and nothing else before, which is why no arrangement of it looked
   designed — there was not enough in it to compose. */
.footer { background: var(--espresso); color: #CBB8A6; padding-block: var(--s-5) var(--s-4); }
/* Links take the nav's shape — a rule that arrives under the word on hover —
   rather than a text-decoration underline, which is the one link treatment
   the rest of the site never uses. */
.footer a {
  color: var(--paper); text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur) var(--ease);
}
.footer a:hover { border-bottom-color: currentColor; }

/* ── Tier one: the invitation ─────────────────────────────────────────────
   Display type at section-heading scale, so the last thing on the page is
   the size of a heading rather than the size of a link. */
.footer__call {
  display: flex; flex-wrap: wrap; align-items: center;
  justify-content: space-between; gap: var(--s-3) var(--s-4);
  padding-bottom: clamp(2rem, 1.4rem + 2.4vw, 3.25rem);
  border-bottom: 1px solid #43372B;
}
.footer__call-line {
  margin: 0; max-width: 18ch;
  font-family: var(--display); font-variation-settings: var(--wonk-display);
  font-weight: 400; font-size: clamp(1.7rem, 1.1rem + 2.4vw, 3rem);
  line-height: 1.08; letter-spacing: -0.01em; color: var(--paper);
  text-wrap: balance;
}
.footer__call-go { margin: 0; flex: none; }
/* .cta is keyed to ink on cream; on this ground it inherits and inverts. */
.footer__call-go .cta { color: inherit; border-color: currentColor; }
.footer__call-go .cta:hover { background: var(--paper); color: var(--espresso); }

/* ── Tier two: the directory ──────────────────────────────────────────── */
/* Four columns divided by hairlines. Two blocks could never hold a 1180px
   row — the fix was more to say, not more space between the same two things,
   so the site's three services get a column of their own rather than being
   buried among the page links. The rules are borders on the columns, so each
   one stops where its column's content does. */
.footer__grid {
  --col-gap: clamp(1.5rem, 0.8rem + 2.4vw, 3rem);
  /* stretch, not start: the rules are the columns' own left borders, so they
     run to whatever height the column is — and a column that stops at its
     last link gives three rules of three different lengths. */
  display: grid; align-items: stretch;
  grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr) minmax(0, 0.72fr) minmax(0, 1.28fr);
  padding-block: clamp(2rem, 1.4rem + 2.4vw, 3.25rem);
}
.footer__grid > * + * {
  border-left: 1px solid #43372B;
  padding-left: var(--col-gap);
  margin-left: var(--col-gap);
}
/* ── The contact column ───────────────────────────────────────────────── */
.footer__email { margin: 0 0 var(--s-3); max-width: none; }
/* Long enough to be the one thing in the footer that can overflow its
   column; the <wbr> in the markup lets it break after the @ rather than
   mid-word, and a step down in size usually spares it the break at all. */
.footer__email a { font-size: 0.95rem; }
/* Circles rather than bare glyphs: the bordered disc is the .cta's shape at
   icon scale, and it gives three small marks a consistent footprint whatever
   the glyph inside them weighs. */
.footer .footer__social {
  display: flex; flex-wrap: wrap; gap: var(--s-2);
  list-style: none; margin: 0; padding: 0;
}
.footer__social a {
  display: grid; place-items: center;
  width: 2.25rem; height: 2.25rem;
  border: 1px solid #5A4838; border-radius: 50%;
  border-bottom-color: #5A4838;   /* not the link underline the footer uses */
  color: var(--paper);
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
              color var(--dur) var(--ease);
}
.footer__social a:hover {
  background: var(--paper); border-color: var(--paper); color: var(--espresso);
}
.footer__social svg { width: 1.05rem; height: 1.05rem; display: block; }

.footer__mark {
  display: block;
  /* start, against the grid's stretch: a replaced element told to fill the
     row would be pulled out of its aspect ratio. */
  align-self: start;
  width: 100%;
  max-width: 11rem;
  height: auto;
  margin: 0;
}
/* The footer was the last of the old template's type on the site: DM Sans at
   meta size, against Fraunces everywhere else. The column labels take the
   uppercase, letterspaced treatment the closing quote's attribution uses, and
   the links take the nav's face and size a step down. */
.footer h4 {
  margin: 0 0 var(--s-2);
  font-family: var(--display); font-variation-settings: var(--wonk-text);
  font-size: clamp(0.78rem, 0.74rem + 0.16vw, 0.87rem); font-weight: 400;
  text-transform: uppercase; letter-spacing: 0.18em; color: #A8937E;
}
.footer ul {
  list-style: none; margin: 0; padding: 0; display: grid; gap: 0.55em;
  font-family: var(--display); font-variation-settings: var(--wonk-text);
  font-size: clamp(0.92rem, 0.88rem + 0.18vw, 1rem); line-height: 1.4;
}

/* ── Tier three: the small print ──────────────────────────────────────── */
.footer__base {
  border-top: 1px solid #43372B; padding-top: var(--s-3);
  display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-4); justify-content: space-between;
  font-family: var(--display); font-variation-settings: var(--wonk-text);
  font-size: clamp(0.85rem, 0.82rem + 0.16vw, 0.94rem);
}

/* Four columns need the full measure. Below it they pair up, and the rule
   moves to whichever column starts the right-hand side; below that they
   stack and the rules come off entirely. */
@media (max-width: 1000px) {
  .footer__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: var(--s-5); }
  .footer__grid > * + * { border-left: 0; padding-left: 0; margin-left: 0; }
  .footer__grid > :nth-child(even) {
    border-left: 1px solid #43372B;
    padding-left: var(--col-gap); margin-left: var(--col-gap);
  }
}
@media (max-width: 700px) {
  .footer__call { display: block; }
  .footer__call-go { margin-top: var(--s-3); max-width: none; }
}
@media (max-width: 620px) {
  .footer__grid { grid-template-columns: minmax(0, 1fr); row-gap: var(--s-4); }
  .footer__grid > :nth-child(even) { border-left: 0; padding-left: 0; margin-left: 0; }
}

/* --- Responsive ----------------------------------------------------------- */
@media (max-width: 860px) {
  .about, .memoir { grid-template-columns: 1fr; }
  /* Stacked: no overlap, name may wrap. */
  .hero__grid { grid-template-columns: 1fr; }
  .hero__body, .hero__art--image { grid-column: 1; grid-row: auto; }
  .hero h1 { max-width: none; }
  .hero__roles { max-width: none; }
  .hero__body { padding-inline: var(--gutter); }
  .about .portrait { max-width: 320px; }
  .sec-head { align-items: start; }
}
@media (max-width: 620px) {
  .nav__inner { gap: var(--s-2); }
  .nav__links { order: 3; width: 100%; gap: var(--s-2) var(--s-3); }
  /* Spacing for the stacked placeholder pairs. The real-cover pair stays a
     two-up grid at every width, so it is excluded. */
  .hero__art:not(.hero__art--pair) .cover:nth-child(2) { margin-bottom: var(--s-4); }
}

/* ==========================================================================
   Page hero — shared by About, Editorial, Representation, Memoir
   ========================================================================== */
.phero { padding-block: clamp(2.75rem, 1.5rem + 5vw, 5.5rem) var(--s-6); }
.phero__grid { display: grid; gap: var(--s-4) var(--s-6); grid-template-columns: minmax(0, 1fr) minmax(0, 0.92fr); align-items: center; }
.phero h1 { font-size: var(--t-h2); max-width: 14ch; }
.phero .lead { max-width: 52ch; font-size: 18px; }

/* About hero. Home already gives this same portrait the arch treatment, so
   here it is a plain upright rectangle: different shape, different proportion,
   and a crop centred on the face rather than Belinda's 12% pull. The lead
   drops to body size — at lead size it out-weighed the picture beside it. */
.phero--about .phero__grid { grid-template-columns: minmax(0,1fr) minmax(0,0.72fr); align-items: center; }
.phero--about .lead { font-size: var(--t-body); max-width: 46ch; }
.upright { width: 100%; max-width: 330px; margin-left: auto; aspect-ratio: 3 / 4; overflow: hidden; }
.upright img { width: 100%; height: 100%; object-fit: cover; object-position: 41% 50%; display: block; }
@media (max-width: 860px) {
  .phero--about .phero__grid { grid-template-columns: 1fr; }
  .upright { margin-left: 0; max-width: 300px; }
}

/* Two real covers side by side, not one above the other: stacked at the art
   column's full width they run to roughly 1400px and dwarf the headline they
   sit beside. Paired, each is about half that, and the two together read as
   books on a shelf rather than as a slideshow.
   Both are 802x1225 and 798x1225 — the same trim — so the pair aligns on both
   edges. The first is lifted by one step against the grid's `end` alignment;
   the small offset stops the pair reading as a single pasted block. */
.hero__art--pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-3);
  align-items: end;
}
.hero__art--pair .cover:first-child { margin-bottom: var(--s-4); }

/* ==========================================================================
   Big statement — a single sentence carrying a whole section
   ========================================================================== */
.statement { padding-block: var(--s-7); }
.statement p {
  font-family: var(--display);
  font-variation-settings: var(--wonk-display);
  font-size: var(--t-h2);
  line-height: 1.1;
  letter-spacing: -0.02em;
  max-width: 22ch;
  margin: 0;
  text-wrap: balance;
}
.statement cite { display: block; margin-top: var(--s-3); font-family: var(--body); font-style: normal; font-size: var(--t-meta); opacity: 0.8; }

/* ==========================================================================
   Timeline — About. A vertical rail; no dates, none were supplied.
   ========================================================================== */
/* One number governs the whole component: how far below an item's top edge the
   cap-height centre of its name falls. The dot sits there, and the rail starts
   and stops there, so the three can never drift apart.
   0.647, not the 0.6 that half a 1.2 line box would suggest: a line box is not
   centred on the capitals. Fraunces' ascent and descent leave the caps sitting
   slightly above the box's middle, so measuring from the box centre puts the
   dot about 1.5px high at desktop — invisible at 100%, obvious the moment the
   section is zoomed. This is measured off the rendered face; a change of
   display font needs it re-measured. */
.timeline { --tl-mark: calc(var(--t-h3) * 0.647);
            list-style: none; margin: 0; padding: 0; max-width: 46ch; }
/* The rail is a background stripe, not a border-left, because the first and
   last segments have to stop at their own dot rather than at the item's edge:
   a border runs the full height of the box and cannot be trimmed. As a stripe
   it can start low on the first item and end early on the last, so the rail
   begins and ends on a dot instead of overshooting into blank space at both
   ends. Losing the 1px border also puts the padding edge at the rail itself,
   which is what lets the dot's -6px sit dead centre on it. */
.timeline li {
  position: relative; padding: 0 0 var(--s-4) var(--s-4);
  background-image: linear-gradient(var(--rule), var(--rule));
  background-repeat: no-repeat;
  background-size: 1px 100%;
}
.timeline li:first-child {
  background-position: 0 var(--tl-mark);
  background-size: 1px calc(100% - var(--tl-mark));
}
.timeline li:last-child { padding-bottom: 0; background-size: 1px var(--tl-mark); }
/* --tl-mark is a distance to the cap-height centre; back off half the dot to
   get its top edge. The offset must key off the name's own size, not an `em`
   inherited from the li: the name is set at --t-h3, several steps larger than
   body text, and an li-relative em lands the dot well above the word it marks.
   The dot is 9px across, not 13: box-sizing is border-box site-wide and that
   applies to ::before too, so the 2px border is inside the declared width.
   Half of 9 is 4.5, and left is -4px so the dot's centre (-4 + 4.5 = 0.5)
   lands on the centre of the 1px rail at 0..1. */
.timeline li::before {
  content: ""; position: absolute; left: -4px;
  top: calc(var(--tl-mark) - 4.5px);
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--cream); border: 2px solid var(--accent);
}
.timeline b {
  display: block; font-family: var(--display); font-variation-settings: var(--wonk-text);
  font-weight: 400; font-size: var(--t-h3); line-height: 1.2;
}
.timeline span { font-size: var(--t-meta); color: var(--muted); }

/* ==========================================================================
   Service list — Editorial. A list with rules, not a grid of cards.
   ========================================================================== */
.services { border-top: 1px solid var(--rule); }
.service {
  display: grid; gap: var(--s-2) var(--s-5);
  grid-template-columns: minmax(0, 0.62fr) minmax(0, 1fr);
  padding-block: var(--s-4);
  border-bottom: 1px solid var(--rule);
}
.service h3 { margin: 0; }
.service p { margin: 0; color: var(--muted); }

.service p + p { margin-top: var(--s-2); }

/* ==========================================================================
   Notice — Representation. The submissions policy must be unmissable.
   ========================================================================== */
.notice { display: grid; gap: var(--s-3) var(--s-6); grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: start; }
.notice h2 { max-width: 16ch; }
.notice p { max-width: 48ch; }
.notice__flag {
  font-family: var(--display); font-variation-settings: var(--wonk-text);
  font-size: var(--t-h3); line-height: 1.25; margin: 0 0 var(--s-2);
}

/* ==========================================================================
   Client cards — Representation
   ========================================================================== */
.clients {
  display: grid; gap: var(--s-5) var(--s-4);
  grid-template-columns: repeat(auto-fill, minmax(255px, 1fr));
  align-items: stretch;
}
/* Cards stretch to the tallest in their row, so the different title-list
   lengths sit inside boxes of equal height. No rules: the avatars line the row
   up on their own. */
.client { display: flex; flex-direction: column; }
/* Four shared rows — avatar, name, bio, titles — so every "Selected books" in
   a row starts on the same line however long the bio above it runs. Same
   device as the Three Areas section and the shelf.
   FRAMER NOTE: Framer has no subgrid. Rebuild as four stacked rows, or accept
   the ragged start. */
@supports (grid-template-rows: subgrid) {
  .client {
    display: grid;
    grid-row: span 4;
    grid-template-rows: subgrid;
    gap: var(--s-2);
    align-content: start;
  }
  /* The row gap alone now sets the spacing. */
  .client h3, .client__bio { margin: 0; }
  .client__titles > .client__sublabel:first-child { margin-top: 0; }
}
.client__portrait {
  width: 88px; height: 88px; flex: none;
  border-radius: 50%; overflow: hidden;
  background: var(--shell); border: 1px solid var(--rule);
  display: grid; place-items: center; text-align: center;
  font-size: 0.6rem; line-height: 1.2; color: #6F6255; padding: 0.4em;
}
.client h3 { margin: var(--s-2) 0 0.3em; font-size: 1.3rem; }
.client__assoc { font-size: var(--t-meta); color: var(--muted); margin: 0 0 var(--s-2); }
.client__bio { font-size: 0.9rem; line-height: 1.55; color: var(--muted); max-width: 40ch; }
.client__books { margin: 0; padding: 0; list-style: none; font-size: 0.82rem; line-height: 1.5; color: var(--muted); display: grid; gap: 0.3em; }
.client__books li { padding-left: 0.9em; text-indent: -0.9em; }
.client__books li::before { content: "—"; color: var(--accent-deep); margin-right: 0.35em; }
/* Each client now carries two title lists — published and forthcoming — so the
   lists need a label to be told apart. Same uppercase accent tag as the Three
   Areas eyebrows, held small so the titles stay the loudest thing in the card. */
.client__sublabel {
  margin: var(--s-3) 0 0.4em;
  font-size: 0.68rem; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--accent-deep);
}
.client__sublabel + .client__books { margin-top: 0; }

/* ==========================================================================
   Endorsements — About ("What people say")
   One quote leads at reading size; the other three sit in a grid. The cards
   stretch to the row's height and their attribution is pushed to the bottom,
   so quotes of 30 and 75 words still line their names up on one baseline.
   ========================================================================== */
.say { margin: 0; }
.say blockquote {
  margin: 0;
  font-family: var(--body);
  color: var(--ink);
}
.say figcaption {
  margin-top: var(--s-2);
  font-size: var(--t-meta); color: var(--muted);
}
.say figcaption span { display: block; }
/* A step under --t-lead: in DM Sans the lead quote read heavier than the
   section heading at full lead size. Still clear of the 1.05rem grid quotes. */
.say--lead blockquote { font-size: clamp(1.06rem, 0.98rem + 0.38vw, 1.30rem); line-height: 1.4; max-width: 46ch; }
.say--lead figcaption { margin-top: var(--s-3); }

.says {
  margin-top: var(--s-6);
  display: grid; gap: var(--s-5) var(--s-4);
  grid-template-columns: repeat(auto-fill, minmax(255px, 1fr));
  align-items: stretch;
}
.says .say { display: flex; flex-direction: column; }
.says .say blockquote { font-size: 1.05rem; line-height: 1.45; }
.says .say figcaption { margin-top: auto; padding-top: var(--s-3); }

@media (max-width: 700px) {
  .says { margin-top: var(--s-5); }
  .says .say figcaption { margin-top: var(--s-2); padding-top: 0; }
}

/* ==========================================================================
   Help groups — Memoir
   ========================================================================== */
.helps { display: grid; gap: var(--s-4); grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.help { padding-top: var(--s-3); border-top: 2px solid currentColor; }
.help h3 { margin: 0 0 var(--s-2); }
.help ul { margin: 0; padding: 0; list-style: none; display: grid; gap: 0.45em; font-size: var(--t-body); opacity: 0.85; }

/* Scale — "as much or as little help as you need" */
.scale { max-width: 620px; }
.scale__bar { height: 3px; background: currentColor; opacity: 0.35; margin: var(--s-3) 0 var(--s-2); position: relative; }
.scale__bar::before, .scale__bar::after {
  content: ""; position: absolute; top: -4px; width: 11px; height: 11px;
  border-radius: 50%; background: currentColor; opacity: 1;
}
.scale__bar::before { left: 0; } .scale__bar::after { right: 0; }
.scale__ends { display: flex; justify-content: space-between; font-size: var(--t-meta); opacity: 0.85; }

/* Two sisters */
.sisters { display: grid; gap: var(--s-5) var(--s-6); grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); }
.sister__portrait {
  width: 100%; max-width: 200px; aspect-ratio: 1;
  border-radius: 50%; background: var(--shell); border: 1px solid var(--rule);
  display: grid; place-items: center; text-align: center;
  font-size: var(--t-meta); color: #6F6255; padding: var(--s-2); margin-bottom: var(--s-3);
}
.sister h3 { margin: 0 0 0.2em; }
.sister .meta { margin-bottom: var(--s-2); }

/* ==========================================================================
   Responsive — page components
   ========================================================================== */
@media (max-width: 860px) {
  .phero__grid, .service, .notice { grid-template-columns: 1fr; }
  .phero__grid { align-items: start; }
  /* Full-bleed in a one-column stack the pair would out-scale the text it
     introduces, so it is held to the width two covers need to stay readable. */
  .hero__art--pair { max-width: 460px; }
  .hero__art--pair .cover:first-child { margin-bottom: 0; }
}

/* Placeholder on the dark footer — the light-ground version is illegible there. */
.footer .placeholder {
  border-color: #5C4B3A;
  background: repeating-linear-gradient(
    -45deg, transparent, transparent 9px,
    rgba(183, 178, 168, 0.10) 9px, rgba(183, 178, 168, 0.10) 18px);
  color: #CBB8A6;
}
.footer .placeholder__label { color: var(--paper); }

/* ==========================================================================
   Real portraits. Source is near-square (1025×989); the 4:5 arch and the
   circle both crop horizontally only, so object-position steers which side
   is trimmed. 12% keeps Belinda's face clear and takes the trim off the
   airier right-hand side.
   ========================================================================== */
.portrait img,
.sister__portrait img {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 12% 50%;
  display: block;
}
/* Client avatars are square-cropped on the face at source, so the circle wants
   a straight centre crop rather than Belinda's 12% pull. */
.client__portrait img { width: 100%; height: 100%; object-fit: cover; display: block; }
.portrait:has(img), .sister__portrait:has(img), .client__portrait:has(img) {
  background: none; padding: 0;
}
.sister__portrait { overflow: hidden; }

/* ==========================================================================
   About teaser — feature layout (Home)
   The portrait carries this section, so it is sized to stand level with the
   text block rather than float inside it. Kept as a complete arch: the arch
   is the site's frame language (client cards, About hero), and cropping it
   here only would break that.
   ========================================================================== */
.about--feature {
  display: grid;
  grid-template-columns: minmax(0, 1.06fr) minmax(0, 1fr);
  gap: var(--s-4) clamp(2.5rem, 1rem + 4vw, 5rem);
  align-items: center;
}
.about--feature .portrait {
  max-width: none;
  aspect-ratio: 4 / 5;
  box-shadow: 0 30px 60px -40px rgba(23, 23, 19, 0.45);
}
.about--feature h2 { max-width: 15ch; }
.about--feature .namewall { max-width: 30ch; }

@media (max-width: 860px) {
  .about--feature { grid-template-columns: 1fr; }
  .about--feature .portrait { max-width: 420px; }
  /* The 15ch cap is there to balance against the portrait column; stacked,
     it only forces an awkward two-word first line. */
  .about--feature h2, .about--feature .namewall { max-width: none; }
}

/* ==========================================================================
   Credit line — Home teaser.
   The full typographic name wall belongs on About, where brief 8.4 asks for
   it and it has a section of its own. On the Home teaser these names are
   supporting evidence: at display size they outranked the section's own h2
   and pulled the eye off the portrait. Plain running text, phrased as the
   brief phrases it.
   ========================================================================== */
.credits {
  font-size: var(--t-body);
  line-height: 1.65;
  color: var(--muted);
  max-width: 46ch;
  margin-top: var(--s-1);
}

/* ==========================================================================
   Real book covers.
   Every cell is portrait-proportioned; the cover sits inside it at its true
   shape, bottom-aligned on the shelf baseline. Three of the seven are square
   and one is landscape, so a forced portrait crop would cut artwork off —
   on "Heads and Tails: Farm" it would remove both the rooster and the cow
   and leave the mouse. Uniform cell, uncropped cover.
   The hatch shows through only while an image is missing.
   ========================================================================== */
.book__cover--img {
  width: 100%;
  height: auto;
  background: repeating-linear-gradient(
    -45deg, #FBECDD, #FBECDD 9px, #F1DBC6 9px, #F1DBC6 18px);
  object-fit: contain;
}
.book__credit { font-size: var(--t-meta); color: var(--muted); margin: 0.1em 0 0; }

/* ══════════════════════════════════════════════════════════════════════════
   PAGE SCALE  —  above ~1720px the window gets a bigger page, not a wider one
   ══════════════════════════════════════════════════════════════════════════
   Past about 1720px a fixed-width column stops reading as a measure and starts
   reading as a page that fell over to one side: the type stays 16px, the
   container stays put, and every extra pixel of window turns into empty
   ground on the left. So above that width the root font grows with the
   viewport and everything sized in rem grows with it — container, gutters,
   headings, rules, the portrait. A 2560px window then shows the 1440px design
   at 1.49x rather than the 1440px design adrift in 1100px of cream.

   0.9302vw is 16px at 1720px exactly, so nothing changes at or below that
   width. The 26px ceiling stops a 4K panel from turning the page into large
   print; it is the single dial for the whole thing.

   The consequence, and the rule for every page that moves onto this design:
   any length that acts as a CAP or a FLOOR on a large screen must be written
   in rem, or it will pin the layout while the type around it grows. Lengths
   tied to the viewport (vw) or to a photograph's own geometry stay in px on
   purpose — see .mast's --drop and mask, which crop a picture rather than set
   a layout.

   Scoped by body class: Home and About are on this design language, the three
   build.py pages are not yet. They join by being redesigned, not by being
   listed here twice.
   ══════════════════════════════════════════════════════════════════════════ */
:root:has(body.home),
:root:has(body.sub) {
  font-size: clamp(16px, 0.9302vw, 26px);
  --page-max: 73.75rem;   /* 1180px at the 16px base */
}

/* ══════════════════════════════════════════════════════════════════════════
   HOME  —  masthead + page sections
   ══════════════════════════════════════════════════════════════════════════
   Only home.html uses these; it carries class="home" on <body>. The other four
   pages are generated by build.py and keep the .nav / .footer patterns above.
   None of these selectors collide with anything earlier in this file.

   The masthead crop is deliberate and load-bearing — see the comments inline:
   sizing is driven by viewport WIDTH so that viewport HEIGHT cannot change the
   composition, and the photo DROPS rather than zooms so the child's hair stays
   clear of the type at every breakpoint.
   ══════════════════════════════════════════════════════════════════════════ */

body.home { background: var(--paper); }

/* ══ MASTHEAD (fixed across all variants) ══════════════════════════════
   The masthead does NOT take the page scale. Every type size in here is in
   px on purpose: these positions were tuned against the photograph so the
   name, the disciplines and the tagline all clear the child's hair at every
   width, and the whole composition is already full-bleed — it never had the
   empty-margin problem the page scale exists to solve. Scaled, the copy grew
   past --mast-inner's min-height, the 1fr spacer that pins the tagline to the
   foot collapsed, and the tagline rode up onto the sky.
   --gutter and --page-max stay scaled, so the nav keeps line with the page
   below it; only the type is pinned. */
.mast {
  position: relative; isolation: isolate; overflow: hidden;
  background: var(--paper);
  --zoom: 1.0;    /* photo width as a multiple of the viewport */
  --shift: 0.40;  /* 0 = show left edge, 1 = show right edge */
  /* How far the photo sits below the top of the frame. The sky above the child's
     hair is only 20.2% of the photo, which is less than the name + disciplines
     need — so rather than zoom into the picture (which loses the valley and the
     book), the photo drops and its top edge is feathered into the paper. Narrow
     frames need a bigger drop because the type is proportionally taller. */
  --drop: clamp(56px, 180px - 6.4vw, 120px);
}
.mast__img {
  position: absolute; top: var(--drop); left: 0;
  width: calc(var(--zoom) * 100%);
  height: auto; min-height: calc(100% - var(--drop)); max-width: none;
  margin-left: calc((1 - var(--zoom)) * var(--shift) * 100%);
  object-fit: cover; object-position: 0 0;
  z-index: -2;
  /* Feathered top edge — the photo emerges from the paper, so its cool blue-grey
     top row (190,196,206) never has to match the warm ground. */
  -webkit-mask-image: linear-gradient(180deg, rgba(0,0,0,0) 0, #000 96px);
          mask-image: linear-gradient(180deg, rgba(0,0,0,0) 0, #000 96px);
}
.mast__scrim {
  position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    linear-gradient(180deg, rgba(255,251,247,.72) 0%, rgba(255,251,247,.58) 12%,
      rgba(255,251,247,.30) 28%, rgba(255,251,247,.08) 44%, rgba(255,251,247,0) 56%),
    linear-gradient(0deg,
      rgba(250,240,230,1.00) 0,
      rgba(250,240,230,0.95) calc(1.4vw * var(--zoom)),
      rgba(250,240,230,0.55) calc(4.2vw * var(--zoom)),
      rgba(250,240,230,0.18) calc(7.0vw * var(--zoom)),
      rgba(250,240,230,0.00) calc(9.5vw * var(--zoom))),
    linear-gradient(95deg, rgba(255,251,247,.55) 0%, rgba(255,251,247,.16) 34%,
      rgba(255,251,247,0) 62%);
}
.mast__inner {
  position: relative;
  max-width: var(--page-max); margin-inline: auto;
  padding: 24px var(--gutter) clamp(40px, calc(31vw * var(--zoom)), 576px);
  min-height: clamp(560px, calc(63.3vw * var(--zoom) + var(--drop)), 1280px);
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  grid-template-rows: auto auto auto 1fr auto;
}
.hnav      { grid-column: 1 / -1; grid-row: 1; }
.lockup    { display: contents; }
.lockup h1 { grid-column: 2;     grid-row: 2; }
.lockup__roles { grid-column: 1 / -1; grid-row: 3; }
.mast__tag { grid-column: 2;     grid-row: 5; justify-self: stretch; }
.mast p { max-width: none; }

/* The monogram sits opposite the links. .hnav is already the bar — on Home it
   is row 1 of the masthead grid, on About it is the whole of .subhead — so it
   becomes the flex row and the list keeps its own right alignment. Baseline
   alignment, not centre: the links carry a padding-bottom and a border for the
   current-page rule, which centring would drag out of line with the mark. */
.hnav { display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--s-3); }
.hnav__mark {
  font-family: var(--display); font-variation-settings: var(--wonk-display);
  font-size: 1.5rem; font-weight: 700; line-height: 1; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--ink); text-decoration: none;
  white-space: nowrap; transition: opacity var(--dur) var(--ease);
}
.hnav__mark:hover { opacity: 0.62; }
.hnav ul {
  list-style: none; margin: 0 0 0 auto; padding: 0;
  display: flex; flex-wrap: wrap; justify-content: flex-end;
  gap: 0.4rem clamp(1rem, 0.4rem + 1.9vw, 2.1rem);
}
.hnav ul a {
  font-family: var(--display); font-variation-settings: var(--wonk-text);
  font-size: 0.98rem; color: var(--muted); text-decoration: none;
  padding-bottom: 0.35em; border-bottom: 1px solid transparent;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.hnav ul a:hover, .hnav ul a[aria-current="page"] { color: var(--ink); border-bottom-color: var(--ink); }

.lockup h1 {
  margin: clamp(28.8px, 13.6px + 3.35vw, 65.6px) 0 0; font-family: var(--display); font-variation-settings: var(--wonk-display);
  /* The floor was 24px and the ramp only overtakes it past ~600px, so every
     phone got the same undersized name. 32px is the largest that still leaves
     "BELINDA BOLLIGER" slack inside a 390px frame — 34px held the line too,
     but flush to both gutters, with nothing spare if a fallback face measures
     wider and .mast's overflow:hidden clips it. Below ~360px the name breaks
     over two lines, which the sky band has room for. */
  font-weight: 400; font-size: clamp(32px, -19.2px + 7.2vw, 83.2px);
  line-height: .95; letter-spacing: .02em; text-transform: uppercase; color: var(--ink);
  text-align: center;
}
.lockup__roles {
  margin: clamp(11.2px, 6.4px + 1vw, 18.4px) 0 0; max-width: none;
  font-family: var(--display); font-variation-settings: var(--wonk-text);
  font-size: clamp(14.72px, 9.6px + .86vw, 21.12px); line-height: 1.5;
  color: var(--ink); text-align: center; text-wrap: balance;
}
.lockup__roles span { white-space: nowrap; }
.lockup__roles span + span::before {
  content: "|"; color: var(--rule); margin-inline: clamp(9.6px, 4px + 1.15vw, 21.6px);
}

.mast__tag p {
  margin: 0; max-width: 19ch; text-align: left;
  font-family: var(--display); font-variation-settings: var(--wonk-text);
  font-size: clamp(20.8px, 13.6px + 1.6vw, 34.4px); line-height: 1.24; color: var(--ink);
}
.mast__tag hr {
  width: 68px; height: 0; border: 0; border-top: 1px solid var(--ink);
  margin: clamp(16px, 9.6px + 1.2vw, 27.2px) 0 0; opacity: .55;
}

/* ══ LOWER — shared primitives ═════════════════════════════════════════ */
.band { padding-block: clamp(3rem, 1.8rem + 4.4vw, 5.5rem); }
.band--cream { background: var(--cream); }
.band--paper { background: var(--paper); }
.band--shell { background: var(--shell); }
.band--dark  { background: var(--espresso); color: #EADFD2; }
.wrap { max-width: var(--page-max); margin-inline: auto; padding-inline: var(--gutter); }
.wrap--narrow { max-width: 53.75rem; }

.rule-c {
  width: 4.5rem; height: 0; border: 0; border-top: 1px solid var(--rule);
  margin: clamp(2.2rem, 1.4rem + 3vw, 4rem) auto;
}
.eyebrow-s {
  margin: 0; font-family: var(--body); font-size: clamp(.72rem, .68rem + .18vw, .82rem);
  font-weight: 500; letter-spacing: .22em; text-transform: uppercase; color: var(--muted);
  max-width: none;
}
.arrow { width: 1.625rem; height: 0.8125rem; display: block; flex: none; transition: transform var(--dur) var(--ease); }

/* Acknowledgement of Country — identical in all three */
.hcountry p {
  margin-inline: auto; max-width: 68ch; text-align: center;
  font-family: var(--display); font-variation-settings: var(--wonk-text);
  font-size: .95rem; line-height: 1.7; color: var(--muted);
}


/* ══ A — MINIMAL ═══════════════════════════════════════════════════════
   Everything on one centred axis, one ground, no imagery below the fold.
   The sparest reading of the brief.
   ═══════════════════════════════════════════════════════════════════ */
.a-intro p {
  margin: 0 auto; max-width: none; text-align: center;
  font-family: var(--display); font-variation-settings: var(--wonk-text);
  font-size: clamp(1.06rem, .95rem + .5vw, 1.34rem); line-height: 1.62; color: var(--ink);
}
.a-serv h2 {
  text-align: center; margin: 0;
  font-family: var(--display); font-variation-settings: var(--wonk-text);
  font-weight: 400; font-size: clamp(1.05rem, .9rem + .55vw, 1.35rem);
  text-transform: uppercase; letter-spacing: .2em; color: var(--ink);
}
.a-cards {
  margin-top: clamp(1.8rem, 1.2rem + 2.2vw, 3rem);
  display: grid; gap: clamp(1rem, .5rem + 1.8vw, 2.2rem);
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
.a-card {
  border: 1px solid var(--rule); padding: clamp(1.6rem, 1rem + 2vw, 2.6rem) var(--s-3);
  text-align: center; text-decoration: none; color: var(--ink);
  display: flex; flex-direction: column; align-items: center; gap: var(--s-3);
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}
.a-card:hover { border-color: var(--ink); background: var(--paper); transform: translateY(-2px); }
.a-card:hover .arrow { transform: translateX(4px); }
.a-card span {
  font-family: var(--display); font-variation-settings: var(--wonk-text);
  font-size: clamp(1rem, .88rem + .45vw, 1.22rem);
  text-transform: uppercase; letter-spacing: .14em; line-height: 1.5;
}
.a-quote blockquote {
  margin: 0; text-align: center; text-wrap: balance; font-family: var(--display);
  font-variation-settings: var(--wonk-display); font-weight: 400;
  font-size: clamp(1.6rem, 1.05rem + 2.2vw, 2.8rem); line-height: 1.24; color: var(--ink);
}
.a-quote cite {
  display: block; margin-top: var(--s-3); text-align: center;
  font-family: var(--display); font-variation-settings: var(--wonk-text);
  font-style: normal; font-size: clamp(.85rem, .78rem + .3vw, 1rem);
  text-transform: uppercase; letter-spacing: .18em; color: var(--muted);
}
.a-quote cite::before { content: "— "; }

/* ══ Hamburger ═════════════════════════════════════════════════════════
   Seven links will not hold a line on a phone, and wrapping them into three
   ragged rows over the photograph eats the sky the lockup needs. So below
   860px the list leaves the bar and becomes a full-screen panel, and the bar
   keeps only the two things that must always be reachable: the monogram on
   the left, the toggle on the right.

   Every page carries it — Home over the photograph, the sub-pages over their
   cream bar — so the panel is the same object site-wide. It is still scoped to
   .hnav--burger rather than .hnav so that a nav without a toggle keeps its
   list: hiding the list is only safe where there is a button to bring it back.

   The button is drawn from one element — a bar, plus a ::before and ::after
   for the other two — so the X is a rotation of the same three strokes rather
   than a swapped icon. The middle bar fades; the outer two meet in the centre
   and cross. ════════════════════════════════════════════════════════════ */
.hnav__toggle { display: none; }

@media (max-width: 860px) {
  .hnav--burger { align-items: center; flex-wrap: nowrap; gap: var(--s-3); }

  .hnav__toggle {
    display: block; margin-left: auto; position: relative; z-index: 60;
    width: 44px; height: 44px;   /* full touch target, though the mark is 24px */
    padding: 0; border: 0; background: none; color: var(--ink); cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .hnav__bars, .hnav__bars::before, .hnav__bars::after {
    content: ""; position: absolute; left: 50%; width: 24px; height: 1.5px;
    margin-left: -12px; background: currentColor; border-radius: 1px;
    transition: transform var(--dur) var(--ease), background-color 160ms linear;
  }
  .hnav__bars        { top: 50%; margin-top: -0.75px; }
  .hnav__bars::before { top: -7px; margin-left: 0; left: 0; }
  .hnav__bars::after  { top:  7px; margin-left: 0; left: 0; }

  /* The middle stroke goes transparent rather than opacity:0 — opacity would
     make the bar an opacity group, and its ::before / ::after are the other
     two strokes, so the whole X would fade with it. */
  [aria-expanded="true"] .hnav__bars { background-color: transparent; }
  [aria-expanded="true"] .hnav__bars::before { transform: translateY(7px) rotate(45deg); }
  [aria-expanded="true"] .hnav__bars::after  { transform: translateY(-7px) rotate(-45deg); }

  /* The panel. Fixed, not absolute: the masthead scrolls, the open menu must
     not. It is always in the DOM and always laid out — visibility and opacity
     carry the transition — so the links keep their focus order and the panel
     can fade rather than snap. */
  .hnav--burger ul {
    position: fixed; inset: 0; z-index: 50;
    margin: 0; padding: 5rem var(--gutter) var(--s-4);   /* 5rem clears the bar above it */
    display: flex; flex-direction: column; flex-wrap: nowrap;
    justify-content: center; align-items: flex-start; gap: 0;
    background: var(--paper);
    overflow-y: auto; overscroll-behavior: contain;
    opacity: 0; visibility: hidden;
    transition: opacity var(--dur) var(--ease), visibility 0s linear var(--dur);
  }
  .hnav--burger[data-open] ul {
    opacity: 1; visibility: visible;
    transition: opacity var(--dur) var(--ease), visibility 0s linear 0s;
  }

  .hnav--burger ul li { width: 100%; border-bottom: 1px solid var(--rule); }
  .hnav--burger ul li:first-child { border-top: 1px solid var(--rule); }

  /* Display face at reading size, not the 0.98rem of the bar: on the panel
     each link is a destination in its own right, and a 56px row is a target
     a thumb can hit without aiming. */
  .hnav--burger ul a {
    display: block; padding: 0.9rem 0; border-bottom: 0;
    font-size: clamp(1.15rem, 1rem + 1.6vw, 1.5rem);
    line-height: 1.25; color: var(--ink);
  }
  .hnav--burger ul a[aria-current="page"] { color: var(--muted); }

  /* The panel covers the photograph, so the monogram needs the paper ground's
     ink rather than the scrim's, and it has to sit above the panel to stay
     visible beside the close button. */
  .hnav--burger[data-open] .hnav__mark { position: relative; z-index: 60; }

  /* Nothing behind the panel scrolls while it is open. */
  body.nav-open { overflow: hidden; }
}

/* ══ Narrow screens ════════════════════════════════════════════════════ */
@media (max-width: 1120px) { .mast { --zoom: 1.00; --shift: 0.44; } }
@media (max-width: 860px)  { .mast { --zoom: 1.06; --shift: 0.50; } }

/* Narrow frames crop into the photograph, and the tagline stops sitting over
   open sky: at 390px it runs across the child's sleeve, where dark ink on a
   busy mid-tone loses its edges. So the type gets a halo — a paper-coloured
   stroke, not a darker one, since the ground under it is what is too light and
   too varied rather than too dark.

   paint-order puts the stroke behind the fill, so only its outer half shows
   and the glyph keeps its drawn weight: a 3px stroke reads as a 1.5px halo,
   and Fraunces' thin strokes do not fatten. Stroking over the fill instead —
   the default order — would eat the letterforms at this size.

   Only where the crop bites. Above 860px the tagline is over the valley with
   contrast to spare, and a halo there would be a visible seam for nothing. */
@media (max-width: 860px) {
  .mast__tag p {
    paint-order: stroke fill;
    -webkit-text-stroke: 0.5px rgba(255, 251, 247, 0.62);
    text-stroke: 0.5px rgba(255, 251, 247, 0.62);
    /* The stroke alone ends on a hard edge, which over the sleeve's stripes
       reads as a cut-out rather than as light behind the type. A wide, faint
       blur under it carries the halo out to nothing. */
    text-shadow: 0 0 12px rgba(255, 251, 247, 0.5);
  }
}

@media (max-width: 700px) {
  /* Narrow frames can't host four stacked disciplines inside the sky band, so
     pair them up — that recovers ~44px — and crop in hard, biasing the window
     onto the child so the extra zoom still frames her rather than the valley. */
  .mast { --zoom: 2.0; --shift: 0.58; }
  .lockup__roles {
    display: grid; grid-template-columns: repeat(2, auto);
    justify-content: center; gap: .3em 1.1em;
    font-size: clamp(.8rem, .62rem + .52vw, .95rem);
  }
  .lockup__roles span + span::before { content: none; }
}

/* ══════════════════════════════════════════════════════════════════════════
   ABOUT  —  the second page onto the Home design language
   ══════════════════════════════════════════════════════════════════════════
   about.html is hand-authored now, like home.html, and carries class="sub" on
   <body>. It borrows Home's primitives wholesale — .band, .wrap, .hnav,
   .rule-c, .a-quote, .footer — and adds only the four things Home has no use
   for: a standalone nav bar, a floated portrait, a horizontal career rail and
   a pair of testimonial cards.

   The other three pages are still generated by build.py against the older
   .nav / .phero / .footer patterns. Nothing below collides with those.
   ══════════════════════════════════════════════════════════════════════════ */

body.sub {
  background: var(--cream); overflow-x: clip;
  /* The gap between blocks inside a band. Every section break on these pages
     is one of these, so the page has a single rhythm and it is tuned in one
     place. In rem, so it grows with the page scale past 1720px. */
  --stack: clamp(4.5rem, 2.8rem + 6.4vw, 9rem);
}

/* The nav sits on its own bar here. On Home it is row 1 of the masthead grid,
   over the photo; there is no photo on this page, so it gets the ground
   instead. It has to land in exactly the same place on both, so it takes the
   masthead's box rather than this page's measure: --page-max, not .wrap--mid,
   and the same pinned 24px above it that .mast__inner uses. The monogram
   therefore hangs a little outside the text column below it, the way Home's
   does against its centred lockup. */
.subhead { background: var(--cream); padding-block: 24px 0; }

/* One measure for the whole page. --page-max (1180px) is set for the shelf and
   the client grid; running body copy across it is too long a line, and the
   reference layout is narrower than that anyway. */
.wrap--mid { max-width: 66.25rem; }

body.sub .rule-c { margin-block: var(--stack); }
/* The last block should not sit closer to the footer than the blocks sit to
   each other. The top keeps its own value: the nav bar and .ab-top / .ed-top
   already contribute padding above the title. */
body.sub .band { padding-bottom: var(--stack); }

/* --- Page furniture, shared by every page on this design ------------------ */
/* .ptitle / .rule-l / .prose are not About's — Editorial and everything that
   follows set their heading and running copy with the same three. Only the
   floated portrait below is this page's own. */

/* --- Title + portrait ----------------------------------------------------- */
.ab-top { padding-top: clamp(1rem, 0.4rem + 2vw, 2.4rem); }

/* The float is the whole layout. The first two paragraphs set beside the
   picture and the rest run the full measure the moment it clears — no column
   count to keep in step with the copy, and nothing to re-tune when the text
   changes length. */
.ab-portrait {
  float: right;
  /* Sized so that the part standing inside the measure is always ~46% of it,
     however much of the picture is hanging off the window: 46% + (50vw - 50%)
     folds down to 50vw - 4%. Without that the photo is half the frame at
     1440px and two thirds of it at 1920. */
  width: clamp(18.75rem, calc(50vw - 4%), 51.25rem);
  /* Runs off the right-hand side of the window, not the measure. Inside a
     centred container, 50% - 50vw is exactly the distance from the content
     box's right edge to the window's, whatever the container is doing. */
  margin: calc(clamp(1rem, 0.4rem + 2vw, 2.4rem) * -1) calc(50% - 50vw)
          var(--s-4) clamp(1rem, 0.4rem + 1.6vw, 2rem);
  /* No shape-outside: the copy stops at the float's edge, which is where the
     fade begins, so the gap the reader sees is the fade itself. */
}
.ab-portrait img {
  display: block; width: 100%; height: auto;
  /* Squarer than the float is wide; the crop comes off the right, where there
     is only foliage, and off the top, which is bare weatherboard. */
  aspect-ratio: 1.05; object-fit: cover; object-position: 42% 46%;
  /* The photo emerges from the paper rather than being pasted onto it — the
     same move the Home masthead makes at its top edge, turned on its side. */
  -webkit-mask-image: linear-gradient(90deg, rgba(0,0,0,0) 0, #000 28%);
          mask-image: linear-gradient(90deg, rgba(0,0,0,0) 0, #000 28%);
}

.ptitle {
  margin: clamp(1rem, 0.4rem + 2.2vw, 2.6rem) 0 0;
  font-family: var(--display); font-variation-settings: var(--wonk-display);
  font-weight: 400; font-size: clamp(2.3rem, 1.25rem + 4.2vw, 4.4rem);
  line-height: 1.02; letter-spacing: -0.01em; color: var(--ink);
}
/* The left-hand sibling of .rule-c — under a heading rather than between
   sections, so it does not centre and it sits tight. */
.rule-l {
  width: 4rem; height: 0; border: 0; border-top: 1px solid var(--rule);
  margin: clamp(1.1rem, 0.8rem + 1vw, 1.7rem) 0 0;
}

/* Body copy is set in the display face here, as it is on Home's intro: the
   page is nine paragraphs of one voice, and DM Sans across this measure reads
   as a document rather than as her writing. */
.prose { margin-top: clamp(1.5rem, 1rem + 1.8vw, 2.4rem); }
.prose p,
.cl-grid .client__bio {
  margin: 0 0 1.15em; max-width: none;
  font-family: var(--display); font-variation-settings: var(--wonk-text);
  font-size: clamp(1rem, 0.95rem + 0.22vw, 1.09rem); line-height: 1.72;
  color: var(--ink);
}
.prose p:last-child { margin-bottom: 0; }
.prose em { font-style: italic; }
/* Document sub-headings. .ptitle--sm is a section heading and far too loud
   for a page with seven of them, so prose gets its own step between the copy
   and the title. */
.prose h2 {
  margin: clamp(1.9rem, 1.3rem + 2vw, 2.9rem) 0 clamp(0.55rem, 0.45rem + 0.4vw, 0.85rem);
  font-family: var(--display); font-variation-settings: var(--wonk-display);
  font-weight: 400; font-size: clamp(1.2rem, 1.05rem + 0.7vw, 1.55rem);
  line-height: 1.22; color: var(--ink);
}
.prose h2:first-child { margin-top: 0; }
/* Links in running copy take the accent's underline, not the nav's rule —
   inside a paragraph the underline has to be the thing that marks the link. */
.prose a {
  color: var(--ink); text-decoration: underline;
  text-decoration-color: var(--accent-deep);
  text-underline-offset: 0.18em; text-decoration-thickness: 1px;
  transition: text-decoration-color var(--dur) var(--ease);
}
.prose a:hover { text-decoration-color: var(--ink); }
.prose ul {
  margin: 0 0 1.15em; padding-left: 1.2em; max-width: none;
  font-family: var(--display); font-variation-settings: var(--wonk-text);
  font-size: clamp(1rem, 0.95rem + 0.22vw, 1.09rem); line-height: 1.72;
  color: var(--ink);
}
.prose ul:last-child { margin-bottom: 0; }
.prose li { margin: 0 0 0.3em; padding-left: 0.3em; }
.prose li:last-child { margin-bottom: 0; }
.prose li::marker { color: var(--accent-deep); }

/* --- Career rail ---------------------------------------------------------- */
/* Six equal posts. Each item is a subgrid of the rail's three rows — name,
   dot, role — so every dot lands on one line however many lines the name
   above it runs to. */
.ab-rail { margin-top: var(--stack); clear: both; max-width: none; }
.tl-h {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(6, minmax(0, 1fr));
  grid-template-rows: auto auto auto;
  /* No column gap: the rail is built out of the items themselves, and a gap
     would show as a break in the line between every pair of posts. The labels
     get their air from their own padding instead. */
  column-gap: 0;
}
.tl-h li {
  display: grid; grid-template-rows: subgrid; grid-row: span 3;
  row-gap: clamp(0.85rem, 0.6rem + 0.72vw, 1.2rem); text-align: center;
}
.tl-h b {
  align-self: end; font-weight: 400;
  font-family: var(--display); font-variation-settings: var(--wonk-text);
  font-size: clamp(0.875rem, 0.5625rem + 0.625vw, 1.3rem); line-height: 1.3; color: var(--ink);
  padding-inline: clamp(0.4rem, 0.2rem + 0.8vw, 1.2rem);
}
/* The rail is drawn item by item rather than as one line behind the row: the
   first and last posts carry only their inner half, so it begins and ends on
   a dot instead of running past them. */
.tl-h i { position: relative; height: 1px; background: var(--rule); }
.tl-h li:first-child i { background: linear-gradient(90deg, transparent 50%, var(--rule) 50%); }
.tl-h li:last-child  i { background: linear-gradient(90deg, var(--rule) 50%, transparent 50%); }
.tl-h i::before {
  content: ""; position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  width: 0.6875rem; height: 0.6875rem; border-radius: 50%; background: var(--accent);
}
.tl-h span {
  font-family: var(--display); font-variation-settings: var(--wonk-text);
  font-size: clamp(0.78rem, 0.547rem + 0.47vw, 1.1rem); line-height: 1.35; color: var(--muted);
  padding-inline: clamp(0.4rem, 0.2rem + 0.8vw, 1.2rem);
}

/* --- Testimonials --------------------------------------------------------- */
.ab-says { margin-top: var(--stack); }

/* A centred label with a short rule either side. The rules are fixed lengths,
   not flex:1 — the label is the mark, and full-width rules would read as a
   section divider the page already has in .rule-c. */
.rule-head {
  display: flex; align-items: center; justify-content: center;
  gap: clamp(0.9rem, 0.5rem + 1.6vw, 1.9rem);
}
/* The rules grow into the clamp rather than being set to it. At a fixed width
   the pair took 175px of the 350px a phone leaves after the gutter, and a
   two-word label had to break across two lines with the rules beside only the
   first — so they yield instead: the label takes the measure it needs, and
   whatever is left is split between them. Above ~700px there is slack enough
   for both to reach the max-width, which is the old fixed width, so the wide
   layout is unchanged. */
.rule-head::before, .rule-head::after {
  content: ""; flex: 1 1 auto; min-width: 1.5rem;
  max-width: clamp(3.5rem, 4rem + 6vw, 9.375rem);
  height: 0; border-top: 1px solid var(--rule);
}
.rule-head span {
  font-family: var(--display); font-variation-settings: var(--wonk-text);
  font-size: clamp(0.88rem, 0.8rem + 0.35vw, 1.05rem);
  letter-spacing: 0.24em; text-transform: uppercase; color: var(--ink);
  /* The label is the mark — it sets the line, the rules fit around it. */
  white-space: nowrap;
}

.tcards {
  margin-top: clamp(1.8rem, 1.2rem + 2.2vw, 3rem);
  display: grid; gap: clamp(1rem, 0.5rem + 1.8vw, 2.2rem);
  grid-template-columns: repeat(auto-fit, minmax(17.5rem, 1fr));
}
.tcard {
  margin: 0; border: 1px solid var(--rule); background: var(--paper);
  padding: clamp(1.5rem, 1rem + 1.8vw, 2.4rem);
  display: flex; flex-direction: column;
}
.tcard blockquote {
  margin: 0; font-family: var(--display); font-variation-settings: var(--wonk-text);
  font-size: clamp(0.95rem, 0.9rem + 0.22vw, 1.04rem); line-height: 1.6; color: var(--ink);
}
/* Pushed to the foot of the card so the two attributions sit level however
   differently the quotes above them run. */
.tcard figcaption {
  margin-top: auto; padding-top: clamp(1.2rem, 0.9rem + 1.2vw, 2rem); text-align: center;
  font-family: var(--display); font-variation-settings: var(--wonk-text);
  font-size: clamp(0.82rem, 0.78rem + 0.2vw, 0.92rem);
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink);
}
.tcard figcaption::before { content: "— "; }
.tcard figcaption span {
  display: block; margin-top: 0.45em;
  font-size: 0.86em; letter-spacing: 0.14em; color: var(--muted);
}

/* --- Narrow screens ------------------------------------------------------- */
@media (max-width: 760px) {
  .ab-portrait {
    float: none; width: auto; max-width: none; shape-outside: none;
    margin: 0 calc(var(--gutter) * -1) var(--s-4);
  }
  .ab-portrait img {
    aspect-ratio: 1.05; object-position: 38% 42%;
    -webkit-mask-image: none; mask-image: none;
  }

  /* The rail turns on its side. Six posts cannot hold a legible line across a
     phone, and a two-up grid would break the rail into unrelated segments. */
  .tl-h { grid-template-columns: 1fr; grid-template-rows: none; column-gap: 0; }
  /* The space between posts is a third grid row, not padding: the rail spans
     the rows, so padding would leave a break in the line at every post. */
  .tl-h li {
    grid-row: auto; grid-template-rows: auto auto 2rem;
    grid-template-columns: 1.75rem minmax(0, 1fr);
    row-gap: 0.2rem; column-gap: 1.05rem; text-align: left;
  }
  .tl-h li:last-child { grid-template-rows: auto auto 0; }
  .tl-h b, .tl-h span { grid-column: 2; align-self: auto; padding-inline: 0; }

  /* Sideways, the rail is no longer six labels sharing one line — it is a
     read-down list, and the horizontal sizes were floors of a clamp tuned for
     that six-across row (14px names, 12.5px roles on a phone). Off the rail
     they are simply body copy and take body sizes. */
  .tl-h b    { font-size: 1.125rem; line-height: 1.25; }
  .tl-h span { font-size: 1rem; line-height: 1.4; }

  .tl-h i {
    grid-column: 1; grid-row: 1 / -1; justify-self: center;
    width: 1px; height: 100%;
  }
  /* 0.7em is the centre of the name's first line at the size above, measured
     from the top of the post — the rail starts and stops on the dot, so this
     offset is shared by the dot and by the two end gradients. */
  .tl-h li:first-child i { background: linear-gradient(180deg, transparent 0.7em, var(--rule) 0.7em); }
  .tl-h li:last-child  i { background: linear-gradient(180deg, var(--rule) 0.7em, transparent 0.7em); }
  .tl-h i::before { top: 0.7em; width: 0.8125rem; height: 0.8125rem; transform: translate(-50%, -50%); }
}

/* ══════════════════════════════════════════════════════════════════════════
   EDITORIAL
   ══════════════════════════════════════════════════════════════════════════
   Two components of its own: the services list and the cover grid. Everything
   else — nav, title, rule, running copy, closing quote, footer — is the shared
   furniture above.
   ══════════════════════════════════════════════════════════════════════════ */

.ed-top { padding-top: clamp(1rem, 0.4rem + 2.2vw, 2.6rem); }
.ed-top .ptitle { margin-top: 0; }

/* --- Services ------------------------------------------------------------- */
/* The rows themselves are the original .services / .service pair further up
   this file — a list with rules, not a grid of cards, at --s-4 of air per row
   and --s-5 between the columns. Only two things change here: the heading gets
   the page's own title size, and the descriptions stay in the display face
   this page sets its running copy in rather than reverting to DM Sans. */
.ed-services { margin-top: var(--stack); }
.ed-services .services { margin-top: clamp(1.5rem, 1.1rem + 1.6vw, 2.4rem); }
/* "One-on-one" was breaking at a hyphen and leaving "one consultations" on
   its own line. The phrase holds together; the line breaks before the noun. */
.nowrap { white-space: nowrap; }
.ed-services .service p {
  font-family: var(--display); font-variation-settings: var(--wonk-text);
  font-size: clamp(0.98rem, 0.93rem + 0.22vw, 1.07rem); line-height: 1.6;
  max-width: 62ch;
}

/* --- Books ---------------------------------------------------------------- */
.ed-books { margin-top: var(--stack); }
.ptitle--sm { font-size: clamp(1.85rem, 1.1rem + 3.1vw, 3.4rem); }
/* Four across, not the mock-up's five: there are seven books, and five columns
   leave the second row two-sevenths full. Four gives 4 + 3 and a bigger tile
   for the artwork. */
.covers, .carousel { --cov-gap: clamp(1rem, 0.6rem + 1.4vw, 1.8rem); }
.covers {
  margin-top: clamp(3.2rem, 2.2rem + 4vw, 5.5rem);
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(1.6rem, 1rem + 2.4vw, 3rem) var(--cov-gap);
}
.bk { margin: 0; }
/* Seven covers across three trims — square, portrait and one landscape. They
   are CONTAINED in a shared box, never cropped: a uniform crop would take half
   the height off the portrait covers and cut the title off the artwork. The
   box is portrait so the tallest trim sets the size and the rest sit inside it,
   and they are aligned to its foot so the whole row stands on one shelf line
   and every caption starts level. */
/* The plate is the tile: it holds the row's shape so every caption starts
   level, whatever trim the cover is. The cover itself sizes to its own
   proportions inside it and stands on the plate's foot.
   This is why the image is not simply object-fit:contain in a fixed box — the
   shadow below is drawn on the element, and a contained image leaves the
   element the size of the box, so the shadow would hang off the artwork's
   edges rather than under it. */
.bk__plate { position: relative; aspect-ratio: 0.82; }
/* Absolutely positioned, which is the point: as a grid or flow child the
   image's own height feeds back into the track that max-height:100% resolves
   against, the percentage resolves to auto, and the tall trims push their
   plates taller than the rest — the captions stop lining up. Out of flow, the
   containing block's height is settled by aspect-ratio before the image is
   measured, so max-height has something definite to bite on. */
.bk__cover {
  position: absolute; bottom: 0; left: 50%; transform: translateX(-50%);
  display: block; width: auto; height: auto; max-width: 100%; max-height: 100%;
  box-shadow: 0 1px 0 var(--rule), 0 18px 32px -22px rgba(23, 23, 19, 0.55);
}
/* One book has no artwork yet. The plate says so rather than leaving a hole,
   and keeps the grid from reflowing when the file lands. No shadow: there is
   no book to cast one. */
.bk__cover--tbc {
  position: absolute; inset: 0;
  display: grid; place-items: center; text-align: center; padding: var(--s-2);
  border: 1.5px dashed #CFB194;
  background: repeating-linear-gradient(
    -45deg, transparent, transparent 9px,
    rgba(201, 168, 126, 0.15) 9px, rgba(201, 168, 126, 0.15) 18px);
  font-family: var(--body); font-size: var(--t-meta); line-height: 1.4;
  color: var(--muted);
}
.bk figcaption {
  margin-top: clamp(0.55rem, 0.45rem + 0.4vw, 0.85rem); text-align: center;
  font-family: var(--display); font-variation-settings: var(--wonk-text);
  line-height: 1.35;
}
.bk figcaption b {
  display: block; font-weight: 400;
  font-size: clamp(0.86rem, 0.82rem + 0.2vw, 0.96rem); color: var(--ink);
}
.bk figcaption span {
  display: block; font-size: clamp(0.8rem, 0.77rem + 0.16vw, 0.89rem); color: var(--muted);
}

@media (max-width: 900px) { .covers { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 620px) {
  .covers { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ══════════════════════════════════════════════════════════════════════════
   CLIENTS
   ══════════════════════════════════════════════════════════════════════════
   The roster is the Representation card grid — a portrait, a name, a bio and
   the title lists, stretched to a common height per row by subgrid. Only the
   portrait and the spacing are re-cut here.
   ══════════════════════════════════════════════════════════════════════════ */

.cl-top { padding-top: clamp(1rem, 0.4rem + 2.2vw, 2.6rem); }
.cl-top .ptitle { margin-top: 0; }

.cl-grid-wrap { margin-top: var(--stack); }

/* The Representation card grid, with two changes.
   One: the portrait is squared off and runs the full width of the card, so the
   picture and the column it heads share an edge instead of a 88px token sitting
   above a much wider block.
   Two: more air. Bigger gutters between cards, a bigger gap between rows, and
   the card's own subgrid rows opened from --s-2 to --s-3. */
.cl-grid {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(3rem, 2rem + 3.2vw, 5.25rem) clamp(1.5rem, 1rem + 2.2vw, 3rem);
}
.cl-grid .client__portrait {
  width: 100%; height: auto; aspect-ratio: 1;
  border-radius: 0; border: 0; overflow: hidden;
}
@supports (grid-template-rows: subgrid) {
  .cl-grid .client { gap: var(--s-3); }
}
.cl-grid .client h3 { font-size: 1.4rem; }
/* Shares .prose p's face, colour and leading, but a step down in size: the
   card column is ~290px, and at the full running-copy size that is barely
   thirty characters to a line. The bottom margin comes off too — the card's
   subgrid gap sets the spacing here. */
.cl-grid .client__bio {
  margin: 0;
  font-size: clamp(0.95rem, 0.9rem + 0.2vw, 1.02rem);
  color: #4A3F35;
}
/* The note stays quieter than the bio, but in the same face. Its margins came
   off with the title list it used to sit inside; the row gap spaces it now. */
.cl-grid .client__assoc {
  margin: 0;
  font-family: var(--display); font-variation-settings: var(--wonk-text);
  font-size: clamp(0.86rem, 0.83rem + 0.16vw, 0.95rem); line-height: 1.6;
  color: var(--muted);
}

@media (max-width: 900px) { .cl-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .cl-grid { grid-template-columns: 1fr; } }

.cl-shelf-wrap { margin-top: var(--stack); }

/* --- Books carousel (Clients only) ---------------------------------------- */
/* A scroll container, not a slider: no transformed track, no cloned slides,
   no state to keep. Swipe, drag, shift-wheel and arrow keys are the browser's
   already, and with the script gone it is still all of those — the hover
   drift in clients.html only nudges scrollLeft.
   It runs the full width of the window rather than sitting in the measure, so
   the covers are sized directly instead of by a count-per-frame: 13.6rem is
   the width a cover has in the Editorial grid at 1440, and being in rem it
   tracks the page scale past 1720 the same way that grid does. */
.carousel { position: relative; margin-top: clamp(2.75rem, 2rem + 3vw, 4.5rem); }
.carousel__track {
  display: flex; gap: var(--cov-gap);
  overflow-x: auto; overscroll-behavior-x: contain;
  /* The covers cast a shadow; without room for it the container clips it and
     grows a vertical scrollbar to compensate. */
  padding-bottom: 22px; margin-bottom: -22px;
  scrollbar-width: none;
}
.carousel__track::-webkit-scrollbar { display: none; }
.carousel__track:focus-visible { outline: 2px solid var(--ink); outline-offset: 6px; }
.carousel__track > .bk { flex: 0 0 clamp(8.5rem, 40vw, 13.6rem); }

/* Which way there is more to see. The right-hand one is permanent — the strip
   loops, so there is always another cover coming. The left only lights once
   the run has actually moved off its first cover, which keeps a veil off the
   leading cover while the strip sits at rest. */
.carousel::before, .carousel::after {
  content: ""; position: absolute; top: 0; bottom: 0; width: clamp(24px, 3vw, 48px);
  pointer-events: none; z-index: 1;
  transition: opacity var(--dur) var(--ease);
}
.carousel::before { left: 0; background: linear-gradient(90deg, var(--cream), transparent); }
.carousel::after { right: 0; background: linear-gradient(270deg, var(--cream), transparent); }
.carousel.at-start::before { opacity: 0; }

@media (max-width: 620px) {
  }

/* ══════════════════════════════════════════════════════════════════════════
   REPRESENTATION
   ══════════════════════════════════════════════════════════════════════════
   Two pieces of its own: a call to action and the enquiries panel. The
   testimonials are About's cards and the closing quote is Home's, unchanged.
   ══════════════════════════════════════════════════════════════════════════ */

.rp-top { padding-top: clamp(1rem, 0.4rem + 2.2vw, 2.6rem); }
.rp-top .ptitle { margin-top: 0; }
.rp-cta { margin: clamp(1.75rem, 1.2rem + 2vw, 2.75rem) 0 0; }

/* Borrows the nav link's shape rather than the old .btn's fill — on a page of
   running copy a filled button is the only loud thing on the page, and this
   one only goes to another page of the same site. */
.cta {
  display: inline-flex; align-items: center; gap: 0.8rem;
  font-family: var(--display); font-variation-settings: var(--wonk-text);
  font-size: clamp(1rem, 0.94rem + 0.28vw, 1.15rem);
  color: var(--ink); text-decoration: none;
  padding: 0.85em 1.7em;
  border: 1px solid var(--ink);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.cta:hover { background: var(--ink); color: var(--cream); }
.cta:hover .arrow { transform: translateX(4px); }

/* The enquiries band is the original .notice — eyebrow and headline facing the
   explanation across a gutter — on a full-bleed espresso ground. Both are
   already in this file, including the rule that turns the eyebrow's accent
   dash to currentColor on a dark ground; all this adds is even padding, since
   a band with its own colour should not inherit the asymmetric pair the cream
   sections use. */
/* Its own padding, not --stack. --stack is the gap BETWEEN sections, and the
   cream section above already ends with one — using it here too stacked two of
   them into a very tall, mostly empty box. */
/* body.sub .band sets a --stack bottom for the cream sections, and outranks a
   single class — hence the matching weight here, or this band keeps a bottom
   padding half as deep again as its top. */
body.sub .enquiries { padding-block: clamp(3.75rem, 2.5rem + 5.2vw, 7.5rem); }
/* The band borrows .notice's two-column shape, but not the old template's
   type: the heading is the same .ptitle--sm every other section heading on
   the site uses, and the copy is .prose, like every other paragraph. Both are
   keyed to --ink for a light ground, so both are handed back to the band's own
   colour here. Same maximum contrast, inverted — not a step down into muted,
   which is mixed against the cream neutrals and goes muddy on espresso. */
/* Centred against each other: the heading is two lines to the paragraph's six,
   and .notice aligns to the start, which left it hanging off the top of a much
   taller block. Centring honours margins, so both of the margins these two
   carry for their normal home — .prose sits below a rule on About, .ptitle
   below the nav — have to come off, or the columns centre their boxes and
   still print their text out of line. */
.enquiries .notice { align-items: center; }
.enquiries .prose { margin-top: 0; }
.enquiries .ptitle { margin-top: 0; color: inherit; }
.enquiries .prose p { color: inherit; }
/* The espresso ground already hands its text colour down (g-espresso sets
   --paper on the section), but .cta hardcodes ink-on-cream for the pages that
   sit on cream. Inherit instead, and invert to a paper fill on hover rather
   than ink, which would vanish against this ground. */
.enquiries .cta { color: inherit; border-color: currentColor; }
.enquiries .cta:hover { background: var(--paper); color: var(--espresso); }

/* ══════════════════════════════════════════════════════════════════════════
   MEMOIR & LIFE STORIES
   ══════════════════════════════════════════════════════════════════════════
   Reuses Representation's title block, enquiries band and closing quote, and
   Clients' card for the two-person "Who we are". Only the help-list and the
   sisters' two-up grid are its own.
   ══════════════════════════════════════════════════════════════════════════ */
.mm-top { padding-top: clamp(2rem, 1rem + 3.2vw, 4rem); }
.mm-top .ptitle { margin-top: 0; }
.mm-help, .mm-who { margin-top: var(--stack); }

/* --- Copy left, picture right --------------------------------------------
   The page's one repeated gesture: a column of copy held on the page's own
   measure, and a picture that runs off the right edge of the window.
   Flex, not grid, for the bleed: a percentage margin on a flex item resolves
   against the flex container's content box — the same thing 50% means to the
   floated portrait on About — where a grid item's would resolve against its
   own track and the arithmetic would be wrong.
   The two flex ratios are per-section: the hero wants an even split, the
   help list wants room for two columns of type, so it takes two thirds. */
.mm-split {
  display: flex; align-items: stretch;
  gap: clamp(1.75rem, 1rem + 3.4vw, 4.5rem);
  --text-flex: 1; --media-flex: 1;
}
/* The copy centres against a picture that is taller than it is. */
.mm-split__text { flex: var(--text-flex) 1 0; min-width: 0; align-self: center; }
.mm-split__media,
.mm-split .mm-sisters,
.mm-split .mm-prints { flex: var(--media-flex) 1 0; min-width: 0; }
/* A panel, not a picture dropped into the column: it takes the full height of
   the row and the photograph is cropped to it, so the two sections read as
   bands of image rather than as floating snapshots. The min-height is the
   floor for a short block of copy — in rem, so it grows with the page. */
.mm-split__media {
  position: relative;
  margin: 0 calc(50% - 50vw) 0 0;   /* to the window's right edge */
  min-height: clamp(19rem, 11rem + 26vw, 32rem);
}
.mm-split__media img {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
  /* Faded at the left, where it meets the copy; square everywhere else. */
  -webkit-mask-image: linear-gradient(90deg, rgba(0,0,0,0) 0, #000 22%);
          mask-image: linear-gradient(90deg, rgba(0,0,0,0) 0, #000 22%);
}
/* The hero picture starts well above the title, but no longer flush to the
   nav — it cancels the band's top padding and the title block's, then hands
   back a gap, so the photograph clears the navigation instead of butting
   into it. --hero-gap is that clearance. */
.mm-split--hero { --hero-gap: clamp(1.75rem, 1rem + 2.4vw, 3.25rem); }
.mm-split--hero .mm-split__media {
  margin-top: calc(var(--hero-gap)
                 - clamp(2rem, 1rem + 3.2vw, 4rem)
                 - clamp(3rem, 1.8rem + 4.4vw, 5.5rem));
  min-height: clamp(24rem, 14rem + 32vw, 40rem);
}
.mm-split--help { --text-flex: 1.3; align-items: center; }
.mm-split--who  { --text-flex: 0.9; align-items: center; }
/* The heading starts level with the tops of the two photographs rather than
   centring against them — centred, it floated in the middle of a tall column
   with nothing to hold it. */
.mm-split--who .mm-split__text { align-self: start; }
/* .ptitle carries a top margin for the sections where it follows a rule or the
   nav; here it is the first thing in its column, and that margin is the
   difference between "level with the photographs" and "nearly level". */
.mm-split--who .mm-split__text .ptitle { margin-top: 0; }
/* Two cards, not three across a full row, so they can afford a tighter gutter
   than the Clients grid — and the pictures get the width that buys. */
.mm-sisters { column-gap: clamp(1rem, 0.7rem + 1.2vw, 1.8rem); }
/* The card's row gap is set for a portrait, a name and a paragraph of bio.
   Here the third row is a one-line role, which belongs with the name above
   it, so it comes back up against it. */
.mm-sisters .client__assoc { margin-top: -0.75rem; }

/* --- The services ---------------------------------------------------------
   Seven short phrases. As bullets they read as somebody listing things in
   conversation; ruled, numbered and set in the display face at heading scale
   they read as a menu of services, which is what they are.
   One column, not two: the pictures beside them take enough of the row that
   two columns of this type broke every other service over three lines. One
   line each, seven rules deep, also stands better beside a tall picture. */
.mm-services {
  counter-reset: svc;
  margin: clamp(1.5rem, 1rem + 1.8vw, 2.4rem) 0 0; padding: 0; list-style: none;
  border-top: 1px solid var(--rule);
}
/* A block, not a flex row: ::first-letter applies to block containers only,
   and it is what lifts the initial without touching the copy in the source.
   The numeral is taken out of flow so it does not become that first letter. */
.mm-services li {
  position: relative; padding-left: 2.5em;
  padding-block: clamp(0.72rem, 0.55rem + 0.6vw, 1.05rem);
  border-bottom: 1px solid var(--rule);
  font-family: var(--display); font-variation-settings: var(--wonk-text);
  font-size: clamp(1rem, 0.92rem + 0.36vw, 1.2rem);
  line-height: 1.3; color: var(--ink);
}
.mm-services li::first-letter { text-transform: uppercase; }
.mm-services li::before {
  counter-increment: svc;
  content: counter(svc, decimal-leading-zero);
  position: absolute; left: 0; top: clamp(0.72rem, 0.55rem + 0.6vw, 1.05rem);
  font-family: var(--body); font-weight: 500; font-size: 0.66em;
  line-height: 1.95; letter-spacing: 0.1em; color: var(--accent-deep);
}
.mm-help__note {
  margin: clamp(1.25rem, 0.9rem + 1.2vw, 1.85rem) 0 0;
  font-family: var(--display); font-variation-settings: var(--wonk-text);
  font-size: clamp(1rem, 0.95rem + 0.22vw, 1.09rem); line-height: 1.72;
  color: var(--muted);
}

/* --- The prints -----------------------------------------------------------
   Three photographs laid on the page rather than one picture bled off the
   edge: this section is about photographs and family papers, so the artwork
   beside it is photographs. Percentage offsets and widths, so the whole
   arrangement scales with its column instead of falling apart at other sizes.
   The paper border and the shadow are the book plates' from Editorial. */
.mm-prints { position: relative; aspect-ratio: 0.94; align-self: center; }
.mm-print {
  position: absolute; margin: 0;
  /* A narrow, even mount rather than the deep album border it started with:
     at this size a wide white surround read as the loudest thing in the
     section. Just enough to lift the photograph off the cream. */
  background: var(--paper); padding: 1.6%;
  box-shadow: 0 1px 0 rgba(23, 23, 19, 0.08), 0 18px 30px -20px rgba(23, 23, 19, 0.5);
}
.mm-print img { display: block; width: 100%; height: auto; }
.mm-print--a { width: 63%; top: 0;     left: 0;   transform: rotate(-5deg);   z-index: 1; }
.mm-print--b { width: 51%; top: 25%;   right: 0;  transform: rotate(4.5deg);  z-index: 3; }
.mm-print--c { width: 57%; bottom: 0;  left: 0;   transform: rotate(-1.5deg); z-index: 2; }

/* The line that carries the page: bigger than the copy, smaller than the
   title, and the one place on the page that takes the accent. It sits where
   a subtitle sits, so it borrows the rule above it rather than a margin. */
.mm-lede {
  margin: clamp(1.25rem, 0.9rem + 1.4vw, 2rem) 0 0;
  font-family: var(--display); font-variation-settings: var(--wonk-display);
  font-weight: 400; font-size: clamp(1.35rem, 0.95rem + 1.65vw, 2.15rem);
  line-height: 1.2; letter-spacing: -0.005em; color: var(--accent-deep);
  text-wrap: balance;
}
.mm-lede + .prose { margin-top: clamp(1.25rem, 0.9rem + 1.4vw, 2rem); }

/* Too narrow to stand two columns side by side: the picture drops below the
   copy and trades its one-sided bleed for a bleed on both, where the mask
   would only eat into an already small photograph. */
@media (max-width: 860px) {
  .mm-split { display: block; }
  /* The pull-ups that seat each picture against the one above it on a wide
     screen would drag it over the copy once the two are stacked, so every
     one of them comes off here — including the hero's, which is the deepest. */
  .mm-split__media,
  .mm-split--hero .mm-split__media,
  .mm-split--help .mm-split__media {
    margin: clamp(1.75rem, 1rem + 3vw, 2.75rem) calc(50% - 50vw) 0;
    min-height: 0; aspect-ratio: 1.6;
  }
  .mm-split .mm-sisters { margin-top: clamp(1.75rem, 1rem + 3vw, 2.75rem); max-width: 34rem; }
  .mm-split__media img { -webkit-mask-image: none; mask-image: none; }
  /* The prints keep their scatter — they just centre under the copy and take
     a cap, so three overlapping photographs do not fill a phone screen. */
  .mm-split .mm-prints {
    margin: clamp(2rem, 1rem + 3.5vw, 3rem) auto 0;
    max-width: 26rem; width: 100%;
  }
}
@media (max-width: 560px) {
  .mm-split .mm-sisters { grid-template-columns: 1fr; max-width: 20rem; }
}

/* Sitting in the split's right-hand column now, so it gives up the cap and
   the auto margins it needed when it was a centred block of its own. */
.mm-sisters {
  margin-top: 0; max-width: none;
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.mm-sisters .client__assoc { color: var(--muted); }



/* ══════════════════════════════════════════════════════════════════════════
   CONTACT  —  form (Web3Forms) + contact-page header
   ══════════════════════════════════════════════════════════════════════════
   .w3form is shared by contact.html and the memoir page's inline form, so the
   two stay in step. Posts to Web3Forms; no backend. Progressive enhancement:
   a plain POST works with JS off, and the script upgrades it to an inline
   result message and a subject line carrying the enquiry type.
   ══════════════════════════════════════════════════════════════════════════ */

.sr-only {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* Contact page header */
.chero { padding-block: clamp(2.5rem, 1.5rem + 4vw, 5rem) clamp(1.5rem, 1rem + 2vw, 2.5rem); }
.chero h1 {
  margin: 0; max-width: 16ch;
  font-family: var(--display); font-variation-settings: var(--wonk-display);
  font-weight: 400; font-size: clamp(1.9rem, 1.1rem + 3.2vw, 3.4rem);
  line-height: 1.08; color: var(--ink);
}
.chero p.lead-c {
  margin: var(--s-3) 0 0; max-width: 54ch;
  font-family: var(--display); font-variation-settings: var(--wonk-text);
  font-size: clamp(1rem, .94rem + .3vw, 1.18rem); line-height: 1.6; color: var(--ink);
}

/* ── Form ─────────────────────────────────────────────────────────────── */
.w3form { max-width: 760px; margin: 0; }
.w3form__bot { position: absolute; left: -9999px; opacity: 0; }  /* honeypot */

.w3form__grid { display: grid; gap: var(--s-2); }
.w3form__row { display: grid; gap: var(--s-2); grid-template-columns: 1fr 1fr; }
@media (max-width: 640px) { .w3form__row { grid-template-columns: 1fr; } }

.w3form input[type="text"],
.w3form input[type="email"],
.w3form select,
.w3form textarea {
  width: 100%; display: block;
  font-family: var(--display); font-variation-settings: var(--wonk-text);
  font-size: 1rem; line-height: 1.4; color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: 2px;
  padding: 0.85em 1em;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.w3form textarea { min-height: 8.5em; resize: vertical; }
.w3form select { appearance: none; padding-right: 2.6em; cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%),
                    linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position: right 1.15em top 55%, right 0.8em top 55%;
  background-size: 6px 6px, 6px 6px; background-repeat: no-repeat; }
.w3form ::placeholder { color: var(--muted); opacity: .85; }
.w3form :focus-visible {
  outline: none; border-color: var(--accent-deep);
  box-shadow: 0 0 0 3px rgba(163, 80, 0, .18);
}
.w3form input:user-invalid, .w3form textarea:user-invalid { border-color: #A3341A; }

.w3form__send {
  margin-top: var(--s-3);
  display: inline-flex; align-items: center; gap: .7em;
  font-family: var(--display); font-variation-settings: var(--wonk-text);
  font-size: 1.05rem; line-height: 1;
  padding: 0.95em 1.6em; border: 1px solid var(--accent-deep); border-radius: 2px;
  background: var(--accent-deep); color: var(--paper);
  cursor: pointer;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.w3form__send:hover { background: var(--ink); border-color: var(--ink); }
.w3form__send svg { width: 22px; height: 11px; }
.w3form__send[aria-disabled="true"] { opacity: .6; pointer-events: none; }

.w3form__status {
  margin: var(--s-3) 0 0; max-width: 54ch;
  font-family: var(--display); font-variation-settings: var(--wonk-text);
  font-size: 1rem; line-height: 1.5;
}
.w3form__status[data-state="ok"]  { color: var(--accent-deep); }
.w3form__status[data-state="err"] { color: #A3341A; }

.w3form__note {
  margin: var(--s-3) 0 0; max-width: 60ch;
  font-family: var(--body); font-size: var(--t-meta); line-height: 1.6; color: var(--muted);
}

/* On the memoir page the form sits on the shell ground, not paper */
.g-shell .w3form input, .g-shell .w3form select, .g-shell .w3form textarea,
.band--shell .w3form input, .band--shell .w3form select, .band--shell .w3form textarea {
  background: var(--paper);
}

/* ══════════════════════════════════════════════════════════════════════════
   PRIVACY POLICY
   ══════════════════════════════════════════════════════════════════════════ */
.pp-top { padding-top: clamp(1rem, 0.4rem + 2.2vw, 2.6rem); }
.pp-top .ptitle { margin-top: 0; }
.pp-contact { font-variation-settings: var(--wonk-text); }
.pp-updated {
  margin-top: clamp(2rem, 1.4rem + 2vw, 3rem);
  padding-top: var(--s-3);
  border-top: 1px solid var(--rule);
  color: var(--muted);
}
