/* ==========================================================================
   samuelmelrose.com | style.css
   Paper ground, ink text, blue accent. IBM Plex Sans body, IBM Plex Mono
   labels, Archivo display. No scroll animation anywhere.

   Case study structure this expects:
     div.cs-top  > section.cs-header > a.back + p.cs-meta + h1 + p.outcome
                                     + dl.data-plate
                 + figure.cs-hero    > .cs-hero-media + figcaption
     main.cs-body > .cs-text  > section.cs-section > .cs-label
                                                   + details.cs-content
                  + .cs-photos
     nav.cs-nav
   ========================================================================== */

:root {
  --paper:  #f6f3ee;
  --ink:    #22201d;
  --mid:    #6b665f;
  --soft:   #4a463f;
  --rule:   #ddd8d0;
  --shade:  #eae6df;
  --bar:    #dcd5ca;   /* nav bar: a step deeper than --shade so the header
                          reads separately from the case study masthead band */
  --bar-edge: #cbc4b6;
  --accent: #1868c9;
  --accent-2: #124d94;

  --font-display: "Archivo", sans-serif;
  --font-body:    "IBM Plex Sans", sans-serif;
  --font-mono:    "IBM Plex Mono", monospace;

  --wrap: 1400px;
  --pad: 24px;

  /* Page margin on case study pages. Every full-bleed band uses this, so the
     header, hero, data plate, body and footer nav all stay on one edge.
     Fluid rather than breakpoint-snapped, so the margin tracks the viewport
     continuously instead of jumping at fixed widths. Anchored at 20px/700px
     and 112px/1400px. */
  --cs-pad: clamp(20px, 13vw - 71px, 112px);

  /* How far the case study photo rail pulls in from that right edge. Raise it
     to walk the photos further toward the centre; the text column pays for it. */
  --photo-inset: 20px;
}

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

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

.photo img, figure img, .cs-hero-media img { filter: saturate(.88) brightness(1.02); }

a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-2); text-decoration: underline; }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 var(--pad); }

/* Type ------------------------------------------------------------------- */

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.1;
  margin: 0 0 0.5em;
  letter-spacing: -0.02em;
}

h1 { font-size: clamp(2.1rem, 4.2vw, 3.2rem); line-height: 1.06; }
h2 { font-size: clamp(1.4rem, 2.4vw, 1.9rem); }
h3 { font-size: 1.15rem; }

p { margin: 0 0 1em; color: var(--soft); }
p strong { color: var(--ink); }

/* The section labels are <h2>s, so the page outline runs h1 > h2 > h3 the way
   a reader jumping by headings expects. They are not meant to look like
   headings though, so the display font, weight and line height that h1-h4
   carry are all overridden back to the label treatment here. */
.eyebrow, .section-label {
  font-family: var(--font-mono);
  font-size: 0.9rem;
  font-weight: 400;
  line-height: 1.65;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--mid);
  margin: 0 0 1.2rem;
}

/* Header ----------------------------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--bar);
  border-bottom: 1px solid var(--bar-edge);
}

/* Vertical rhythm matches the case study header: padding rather than a fixed
   height, so both bars come out the same depth. */
.site-header .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  max-width: none;
  margin: 0;
  padding: 25px var(--cs-pad);
}

.logo {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.5rem;
  color: var(--ink);
}

.logo:hover { text-decoration: none; color: var(--ink); }
.logo span { color: var(--accent); }

/* One nav treatment site-wide: mono, uppercase, ink. Case study pages used to
   override this; they no longer need to. */
.site-nav a {
  font-family: var(--font-mono);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
  margin-left: 32px;
}
.site-nav a:hover { color: var(--accent); text-decoration: none; }

/* Flex so the Work dropdown's wrapper sits inline with the other links. */
.site-nav { display: flex; align-items: center; }

.nav-item { position: relative; }

/* Work is a button rather than a link: it opens the case study list instead
   of navigating, and "All work" inside the panel covers the old jump. */
.site-nav .nav-work {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-left: 32px;
  padding: 0;
  font-family: var(--font-mono);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
  background: none;
  border: 0;
  cursor: pointer;
}

.site-nav .nav-work:hover { color: var(--accent); }

.nav-work .chev {
  width: 7px;
  height: 7px;
  margin-top: -3px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg);
  transition: transform 150ms ease;
}

.nav-work[aria-expanded="true"] .chev { transform: rotate(-135deg); margin-top: 2px; }

.sub-menu {
  display: none;
  position: absolute;
  top: calc(100% + 14px);
  left: 32px;
  z-index: 20;
  min-width: 270px;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-top: 3px solid var(--accent);
  padding: 6px 0;
}

.sub-menu.is-open { display: block; }

.sub-menu a {
  display: block;
  margin: 0;
  padding: 10px 18px;
  font-size: 13px;
  letter-spacing: 0.02em;
  text-transform: none;
  color: var(--ink);
}

.sub-menu a:hover { color: var(--accent); background: var(--shade); text-decoration: none; }

/* Burger: hidden until the nav collapses at 700px. Three bars that fold into
   a cross when open, driven off aria-expanded so the state lives in one
   place and stays correct for screen readers. */
.nav-toggle {
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  width: 44px;
  height: 44px;
  padding: 0;
  background: transparent;
  border: 1px solid var(--bar-edge);
  cursor: pointer;
}

.nav-toggle span {
  display: block;
  width: 20px;
  height: 2px;
  background: var(--ink);
  transition: transform 150ms ease, opacity 150ms ease;
}

.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

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

.hero { padding: 88px 0 40px; }

.hero h1 { max-width: 22ch; margin-bottom: 1.4rem; }

.hero .standfirst {
  font-size: 1.1rem;
  line-height: 1.65;
  color: var(--soft);
  max-width: 64ch;
  margin: 0;
}

/* Photo column is sized explicitly rather than by `auto`, so its width is set
   here and its height stays pinned to .hero-photo's 400px. */
.hero-top {
  display: grid;
  grid-template-columns: 1fr clamp(320px, 34vw, 560px);
  gap: 40px;
  align-items: start;
  margin-bottom: 2.5rem;
}

.hero-photo {
  width: 100%;
  aspect-ratio: 7 / 5;
  background: var(--shade);
  border: 1px solid var(--rule);
  overflow: hidden;
}

.hero-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* pan is % of the photo's own size: negative moves the photo left/up */
  transform: scale(var(--hero-zoom, 1)) translate(var(--hero-x, 0%), var(--hero-y, 0%));
}

.triad {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 32px;
  border-top: 1px solid var(--rule);
  padding-top: 1.5rem;
}

/* h2 for the page outline, but styled as a mono label rather than a heading. */
.triad h2 {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--accent);
  margin-bottom: 0.5rem;
}

.triad p { font-size: 0.95rem; color: var(--mid); margin: 0; }

/* Work grid -------------------------------------------------------------- */

.work { padding: 48px 0 80px; }

/* Lead dome: photo left, copy right ---------------------------------------- */

/* The card carries the two-column grid, not the anchor: the blurb sits in a
   <details>, which is interactive content and so cannot live inside a link. */
.lead-dome-card {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 40px;
  align-items: center;
  margin-bottom: 3.5rem;
}

.lead-dome-card .meta { padding-top: 0; }
.lead-dome-card h3 { font-size: clamp(1.4rem, 2.2vw, 1.9rem); max-width: none; margin-bottom: 0.3rem; }

/* LPM lead: one bordered block containing all three chapters, so they read
   as parts of a single venture rather than three separate case studies. */

.lpm-lead {
  border: 1px solid var(--rule);
  border-top: 3px solid var(--accent);
  background: var(--shade);
  padding: 32px 36px 36px;
  margin: 2rem 0 3.5rem;
}

/* Headline for the whole LPM block, so it sizes with the lead dome title
   rather than the 1.15rem h3 default. */
.lpm-lead h3 {
  font-size: clamp(1.4rem, 2.2vw, 1.9rem);
  line-height: 1.15;
  margin-bottom: 1.6rem;
}

.lpm-chapters {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
  margin-bottom: 1.8rem;
}

.lpm-chapter { display: block; color: var(--ink); text-decoration: none; }

.chapter-label {
  font-family: var(--font-mono);
  font-size: 1rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 0.6rem;
}

.lpm-chapter .photo {
  aspect-ratio: 3 / 2;
  background: var(--paper);
  border: 1px solid var(--rule);
  overflow: hidden;
  transition: border-color 150ms ease;
}

.lpm-chapter .photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--tile-focus, center);
}

.lpm-chapter:hover .chapter-label { color: var(--accent-2); }
.lpm-chapter:hover .photo { border-color: var(--accent); }

/* Each blurb now lives in its chapter's cell rather than in a separate row
   below, so it stays with its own photo when the grid drops to one column.
   The rules sit on the individual blurbs instead of one shared container
   edge; since the photos are a fixed 3:2 they still line up across the row. */
.lpm-blurb {
  border-top: 1px solid var(--rule);
  margin-top: 1.4rem;
  padding-top: 1.4rem;
}

.lpm-blurb p { font-size: 0.98rem; color: var(--soft); margin: 0; }
.lpm-blurb strong { color: var(--ink); }

.grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 48px 28px;
  margin-top: 2rem;
}

.grid.three-up { grid-template-columns: repeat(3, 1fr); }

.plate { display: block; color: var(--ink); text-decoration: none; }
.plate:hover { text-decoration: none; }
.plate:hover h3 { color: var(--accent); }
.plate:hover .photo { border-color: var(--accent); }

/* Client on the first line, market on the second. Stacked rather than
   justified apart: in the three-up grid the two halves together are wider
   than the tile, so the row broke raggedly onto two lines anyway. */
.tile-meta {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  font-family: var(--font-mono);
  font-size: 0.82rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 0.9rem;
  padding-bottom: 0.7rem;
  border-bottom: 1px solid var(--rule);
}

/* Market reads as the category tag, so it carries the accent. */
.tile-meta span:last-child { color: var(--accent); }

/* Leads have the width the grid tiles don't, so client and market sit on one
   line with the market pushed right, at a larger size to match their scale. */
.lead-dome-card .tile-meta,
.lpm-lead .tile-meta {
  flex-direction: row;
  justify-content: space-between;
  align-items: baseline;
  gap: 24px;
  font-size: 1.1rem;
  letter-spacing: 0.08em;
}

/* More client work: both lines stay grey. The accent is reserved for the
   leads, so the three-up tiles sit quieter beneath them. */
.grid .tile-meta span:last-child { color: var(--mid); }

/* Grid tiles only. The lead dome and the LPM chapters sit outside .grid and
   keep their wider 3:2 frame. */
.grid .plate-card .photo { aspect-ratio: 4 / 3; }

.plate .photo {
  aspect-ratio: 3 / 2;
  background: var(--shade);
  border: 1px solid var(--rule);
  overflow: hidden;
  transition: border-color 150ms ease;
}

.plate .photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--tile-focus, center);
}

.placeholder {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 0 1rem;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--mid);
}

.plate .meta { padding-top: 1.2rem; }
.plate h3 { margin-bottom: 0.25rem; transition: color 150ms ease; }

/* Grid tiles carry their title as the main event, so size it up from the
   1.15rem default. Scoped to .grid so the lead dome keeps its own larger
   size set above — .plate h3 alone would override it by source order. */
.grid .plate-card h3 {
  font-size: clamp(1.3rem, 1.6vw, 1.5rem);
  line-height: 1.15;
}

.plate .client { font-size: 0.9rem; color: var(--mid); margin-bottom: 0.6rem; }

.plate-card .blurb {
  font-size: 0.98rem;
  color: var(--soft);
  max-width: 62ch;
  margin: 0 0 0.8rem;
}

.plate-card .result {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  line-height: 1.65;
  color: var(--accent);
  margin: 0;
  border-top: 1px solid var(--rule);
  padding-top: 0.7rem;
}

/* The lead dome's title is its own link, since the card around it is a grid
   rather than an anchor. Picks up the same hover as a whole-tile plate. */
.plate-title { display: block; color: var(--ink); }
.plate-title:hover { text-decoration: none; }
.plate-title:hover h3 { color: var(--accent); }

/* Blurb dropdowns (home page) --------------------------------------------
   Collapsed on mobile to keep the tiles scannable, forced open above 700px
   by js/home.js. The LPM blurbs keep their bold name as the summary; the
   plate tiles already show a title, so theirs is a plain "Read more". */
/* .lpm-blurb keeps the margin-top set with its rule above. */
.tile-drop { margin: 0; }

.tile-drop summary,
.lpm-blurb summary {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  cursor: pointer;
  list-style: none;
}

.tile-drop summary::-webkit-details-marker,
.lpm-blurb summary::-webkit-details-marker { display: none; }
.tile-drop summary::marker,
.lpm-blurb summary::marker { content: ""; }

.tile-drop summary {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
  padding: 10px 0;
}

.lpm-blurb summary { color: var(--ink); }

/* Collapsed on mobile, the blurb's summary is just its name, which doesn't say
   there's anything behind it. The label takes the plate tiles' mono treatment
   in the accent blue, so it carries the same colour as the chevron beside it
   and reads as the interactive part of the row. The name takes the free space
   so the pair stays grouped against that chevron rather than being spread out
   by the summary's space-between. */
.lpm-blurb summary strong { margin-right: auto; }

.lpm-blurb .lpm-more {
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent);
}

.tile-drop .chev,
.lpm-blurb .chev {
  flex-shrink: 0;
  width: 8px;
  height: 8px;
  border-right: 2px solid var(--accent);
  border-bottom: 2px solid var(--accent);
  transform: rotate(45deg);
  transition: transform 150ms ease;
}

.tile-drop[open] .chev,
.lpm-blurb[open] .chev { transform: rotate(-135deg); }

.lpm-blurb > p { margin: 0.6rem 0 0; }

/* Mobile notice ----------------------------------------------------------
   Injected by js/mobile-notice.js on small screens only, once per session. */

.mobile-notice {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(34, 32, 29, 0.55);
}

.mobile-notice.is-visible { display: flex; }

.mobile-notice-box {
  max-width: 360px;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-top: 3px solid var(--accent);
  padding: 26px 24px 24px;
}

.mobile-notice h2 {
  font-size: 1.25rem;
  line-height: 1.2;
  margin: 0 0 0.6rem;
}

.mobile-notice p {
  font-size: 0.95rem;
  color: var(--soft);
  margin: 0 0 1.4rem;
}

.mobile-notice button {
  width: 100%;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--paper);
  background: var(--ink);
  border: none;
  padding: 13px 20px;
  cursor: pointer;
}

/* Belt and braces: it should never appear on a desktop window, even if one
   is resized up while the box is open. */
@media (min-width: 701px) {
  .mobile-notice { display: none !important; }
}

/* About ------------------------------------------------------------------ */

.about { border-top: 1px solid var(--rule); padding: 80px 0; }

/* Scoped to the About section: the work section's labels share
   .section-label and stay at the quieter grey. */
.about .section-label {
  font-size: 1.1rem;
  color: var(--accent);
}

.about .cols {
  display: grid;
  grid-template-columns: 1.6fr 1fr;
  gap: 56px;
  align-items: start;
}

.spec-list {
  border: 1px solid var(--rule);
  border-top: 3px solid var(--accent);
  padding: 1.6rem;
}

.spec-list h3 {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--mid);
  margin-bottom: 1.2rem;
}

.spec-list dl { margin: 0; }

.spec-list dt {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--accent);
  margin-top: 0.9rem;
}

.spec-list dt:first-child { margin-top: 0; }
.spec-list dd { margin: 0.15rem 0 0; font-size: 0.92rem; }

/* Footer ----------------------------------------------------------------- */

.site-footer { border-top: 1px solid var(--rule); padding: 72px 0 40px; }
.contact-line { font-size: 1rem; margin-bottom: 3rem; }
.contact-line a { border-bottom: 1px solid var(--rule); padding-bottom: 2px; }
.contact-line a:hover { text-decoration: none; border-color: var(--accent-2); }

.fineprint { font-family: var(--font-mono); font-size: 0.72rem; color: var(--mid); }

/* ==========================================================================
   CASE STUDY PAGES
   Transcribed 1:1 from the Claude Design 3b page. Full bleed, 64px padding.
   ========================================================================== */

/* Header: full width on case study pages */
/* Header geometry and nav link styling now live on the base .site-header .wrap
   and .site-nav a rules, shared with the home page. Nothing to override here. */

/* Title block + hero photo: side by side, matched height ------------------
   The whole masthead sits on a tinted band closed off by a hairline, so the
   title, photo and data plate read as one zone separate from the body. The
   band runs full bleed and picks up the site header's --shade, making the
   two continuous from the top of the page down to the rule. */

/* minmax(0, 1fr) rather than a bare 1fr: a bare fr track is minmax(auto, 1fr)
   and so can never shrink below its item's min-content contribution. The hero
   carries a definite width, which is exactly that contribution, so on any
   screen narrower than ~1870px the photo column claimed its full width and the
   title, outcome and plate took whatever was left — down to ~300px on a 3:2
   1368px viewport. Flooring both tracks at 0 keeps the split honestly even. */
.cs-top {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: stretch;
  gap: 48px;
  padding: 0 var(--cs-pad) 8px;
  background: var(--shade);
  border-bottom: 1px solid var(--rule);
}

.cs-header {
  min-width: 0;
  padding: 80px 0 56px;
  display: flex;
  flex-direction: column;
  gap: 26px;
  align-items: flex-start;
}

.cs-header .back,
.cs-header .cs-meta {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--mid);
  margin: 0;
}

.cs-header .back { color: var(--accent); }

.cs-header h1 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(32px, 12px + 2.86vw, 52px);
  line-height: 1.06;
  letter-spacing: -0.025em;
  max-width: 34ch;
  text-wrap: balance;
}

.cs-header .outcome {
  margin: 0;
  font-size: 17.5px;
  line-height: 1.65;
  color: var(--soft);
  max-width: 62ch;
  text-wrap: pretty;
}

/* Hero image: fixed-width column to the right of the title, stretched to
   match the title block's height exactly ---------------------------------- */

.cs-hero {
  width: 100%;
  max-width: 800px;
  margin: 0 auto;
  padding: 80px 0 56px;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* Fixed 3:2 frame, matching the figure cards. The photo no longer stretches to
   match the title block's height, so every case study hero is the same shape. */
.cs-hero-media {
  position: relative;
  width: 100%;
  flex: none;
  aspect-ratio: 3 / 2;
  background: var(--shade);
  overflow: hidden;
}

.cs-hero-media .placeholder { position: absolute; inset: 0; z-index: 0; }

.cs-hero-media img {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--hero-focus, center);
  display: block;
}

.cs-hero > figcaption {
  padding: 14px 0 0;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--mid);
}

/* Data plate ------------------------------------------------------------- */

.data-plate {
  border: 1px solid var(--rule);
  border-left: 4px solid var(--accent);
  background: #fbf9f5;
  padding: 24px 28px;
  margin: 0;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 24px;
}

/* Inside the title block the plate only has half the page, so it runs two up.
   Source order is Client, Role, Key spec, Result, which lands Client above
   Key spec in column one and Role above Result in column two. */
.cs-header .data-plate {
  grid-template-columns: repeat(2, 1fr);
  align-self: stretch;
  gap: 22px 28px;
  /* Adds to .cs-header's 26px flex gap, so the plate sits further below the
     outcome than the other title-block elements sit from each other. */
  margin-top: 18px;
}

.data-plate dt {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 14px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent-2);
  margin-bottom: 8px;
}

.data-plate dd { margin: 0; font-size: 16px; line-height: 1.5; }

/* Body: text runs down the left, photos stack in a column on the right --- */

.cs-body {
  padding: 80px var(--cs-pad) 0;
  display: flex;
  align-items: flex-start;
  gap: 28px;
}

.cs-text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 70px;
}

/* The rail no longer runs to the same right edge as the data plate and hero:
   --photo-inset holds it off that edge so it sits nearer the middle of the
   page. The 42% term keeps it from eating the text column on narrow windows. */
.cs-photos {
  width: min(1235px, 50%);
  flex-shrink: 0;
  margin-right: var(--photo-inset);
  /* Drops the rail below the first heading so it starts against body copy. */
  margin-top: 64px;
}

/* Label sits above its paragraph so the text can use the full column width. */
.cs-section {
  display: grid;
  grid-template-columns: 1fr;
  gap: 14px;
  align-items: start;
}

.cs-label {
  font-family: var(--font-mono);
  font-size: 14px;
  font-weight: 400;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent);
}

/* Block flow, not flex: as a <details> the non-summary children get wrapped
   in a ::details-content box in current Chrome, which breaks them out of the
   flex formatting context and kills any gap between them. Margins on the
   children survive that wrapper. */
.cs-content { display: block; }

/* Accordion: cs-content is a <details>, closed by default at every width. The
   summary carries the heading and the section's opening paragraph, so a closed
   section still reads as a paragraph of prose rather than a bare headline —
   the rest of the copy is behind the chevron. */
/* Block, not flex: the heading, the lede and the Read more control stack in
   source order, so the control lands under the paragraph it opens. */
.cs-content summary {
  display: block;
  cursor: pointer;
  list-style: none;
}
.cs-content summary::-webkit-details-marker { display: none; }
.cs-content summary::marker { content: ""; }

/* Picks up .cs-content p's size, colour and measure; only the space under the
   heading is its own, matching the 18px the collapsed paragraphs get. */
.cs-content .cs-lede { margin-top: 18px; }

/* Read more / Read less: sits under the lede in the mono uppercase accent the
   section labels and meta rows already use, so it reads as part of the page's
   label language rather than a button bolted on. */
.cs-content .cs-more {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: 18px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
  transition: color 150ms ease;
}

.cs-content summary:hover .cs-more { color: var(--accent-2); }

/* Some sections are a heading and a single paragraph, so with that paragraph
   promoted into the summary there is nothing left behind the toggle. Offering
   a Read more that opens onto nothing is worse than not offering one, so the
   control is dropped wherever the <details> has no child but its summary. */
.cs-content:not(:has(> :not(summary))) .cs-more { display: none; }
.cs-content:not(:has(> :not(summary))) summary { cursor: default; }

/* Only one of the two labels is ever in the flow. */
.cs-content .read-less { display: none; }
.cs-content[open] .read-more { display: none; }
.cs-content[open] .read-less { display: inline; }

/* currentColor rather than --accent, so the arrow picks up the label's hover
   colour with it instead of staying behind. */
.cs-content .chev {
  flex-shrink: 0;
  width: 8px;
  height: 8px;
  /* A rotated square carries its ink below the box's centre line, so it needs
     lifting to sit level with the label. Flipping it up reverses the offset. */
  margin-top: -3px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg);
  transition: transform 150ms ease;
}
.cs-content[open] .chev { transform: rotate(-135deg); margin-top: 2px; }

.cs-content h2 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 30px;
  line-height: 1.15;
  letter-spacing: -0.02em;
  max-width: 30ch;
}

.cs-content p {
  margin: 0;
  font-size: 16px;
  line-height: 1.65;
  color: var(--soft);
  max-width: 70ch;
  text-wrap: pretty;
}

.cs-content ul { margin: 0; padding-left: 20px; max-width: 70ch; }
.cs-content li { font-size: 16px; line-height: 1.7; color: var(--soft); margin-bottom: 10px; }

/* Replaces the old flex gap. :not(summary) matches an element, so this lands
   at the same specificity as the .cs-content p / ul rules above and wins on
   source order — every child but the heading gets its space back. */
.cs-content > :not(summary) { margin-top: 18px; }

/* Figure rail: two-up cards, photo above a ruled caption panel ------------ */

.figure-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  /* row-gap then column-gap: vertical spacing only, horizontal stays at 24px */
  gap: 56px 24px;
  margin: 0;
  align-items: start;
}

/* Each figure is a card: hairline box, photo, then a ruled-off caption panel
   at the base. Matches the data plate's border and fill. */
.figure-grid figure {
  margin: 0;
  background: #fbf9f5;
  border: 1px solid var(--rule);
  overflow: hidden;
  transition: border-color 150ms ease;
}

.figure-grid figure:hover { border-color: #cbc5ba; }

/* Wide frame: runs the full width of the rail. Wider crop than the 4/3
   cards so it reads differently in the sequence. */
.figure-grid .figure-wide { grid-column: 1 / -1; }

.figure-grid .figure-wide img { aspect-ratio: 3 / 2; }

.figure-grid img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  display: block;
  background: var(--shade);
}

.figure-grid figcaption {
  padding: 11px 14px 13px;
  border-top: 1px solid var(--rule);
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  line-height: 1.5;
  color: var(--mid);
}

/* Stat row --------------------------------------------------------------- */

.stat-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 32px; }

.stat-row .stat b {
  display: block;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 36px;
  letter-spacing: -0.02em;
  color: var(--ink);
}

.stat-row .stat span {
  display: block;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--mid);
  padding-top: 8px;
  line-height: 1.5;
}

/* Spec table ------------------------------------------------------------- */

.spec-table { width: 100%; max-width: 68ch; border-collapse: collapse; }

.spec-table th, .spec-table td {
  text-align: left;
  padding: 10px 16px 10px 0;
  border-bottom: 1px solid var(--rule);
  font-size: 16px;
}

.spec-table th {
  font-family: var(--font-mono);
  font-weight: 400;
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--mid);
}

.spec-table tbody td { color: var(--soft); }
.spec-table td:first-child { color: var(--ink); }

/* Prev / next ------------------------------------------------------------ */

.cs-nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 24px;
  flex-wrap: wrap;
  margin: 96px var(--cs-pad) 0;
  padding: 24px 0 56px;
  border-top: 1px solid var(--rule);
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--mid);
}

.cs-nav a { color: var(--accent); }

/* Responsive ------------------------------------------------------------- */

/* Wide screens (1440p and up): the text column is flex:1, so once the page is
   wider than the copy's own 70ch measure the surplus collects as dead space
   between the two columns — text pinned left, rail pinned right. Sizing the
   text column to its content and centring the pair keeps them together, with
   the leftover width falling outside as page margin instead of between them. */
@media (min-width: 1600px) {
  .cs-body { justify-content: center; gap: 72px; }
  .cs-text { flex: 0 1 auto; width: 100%; max-width: 84ch; }
  .cs-photos { width: min(840px, 38%); margin-right: 0; }
  /* The copy's own 70ch cap would otherwise leave the widened column
     part-empty, putting the dead space straight back. */
  .cs-content p,
  .cs-content ul { max-width: none; }
}

/* Case study sections collapse at every width now, so nothing here forces
   them open — this block is only the home page's own blurb toggles. */
@media (min-width: 701px) {
  /* Home page blurbs read straight through above the breakpoint. The LPM
     summary is the blurb's own title so it stays put, just inert; the plate
     tiles' "Read more" has nothing left to say once the blurb is showing. */
  .lpm-blurb summary { cursor: default; pointer-events: none; }
  .lpm-blurb .chev,
  .lpm-blurb .lpm-more { display: none; }
  .tile-drop summary { display: none; }
}

@media (max-width: 1100px) {
  .cs-section { grid-template-columns: 1fr; gap: 14px; }
}

/* Above the Surface-class band there's width for the sections to read straight
   through, so js/case-study.js forces them open and the Read more control has
   nothing left to offer. Scoping this to [open] rather than hiding the control
   outright keeps the page usable if that script never runs: the sections stay
   closed, but the control is still there to open them. */
@media (min-width: 1401px) {
  .cs-content[open] .cs-more { display: none; }
  .cs-content[open] summary { cursor: default; }
}

/* Surface-class screens: 3:2 laptops and small desktops -------------------
   Between 901px and 1400px the masthead band is too narrow to carry the plate
   inside the title column without crushing it — at 1368px that column is only
   ~553px, and a four-up plate folded into two-up inside it reads as a cramped
   box rather than a spec strip. So the plate drops out of the title column and
   runs full width beneath both it and the photo, back to its natural four
   columns. Above 1400px there's room for the original arrangement, and below
   901px the whole masthead stacks, so this is scoped to the band in between.

   The plate is a child of .cs-header, which would trap it in the left column.
   display:contents promotes the header's children into .cs-top's own grid so
   the plate can be placed against the hero — the same trick the stacked block
   below uses. That dissolves the header's box, so its padding and its 26px
   stack gap have to move onto the grid, and the rows are placed explicitly:
   the four text elements run down column one, the photo spans all of them in
   column two, and the plate takes a full-width row of its own underneath. */
@media (min-width: 901px) and (max-width: 1400px) {
  .cs-top {
    grid-template-rows: auto auto auto 1fr auto;
    gap: 26px 48px;
    padding-top: 80px;
    padding-bottom: 56px;
  }

  .cs-header { display: contents; }

  /* Grid items stretch by default, which would blow the back link's click
     target out to the full column width. */
  .cs-header .back { grid-area: 1 / 1; justify-self: start; }
  .cs-header .cs-meta { grid-area: 2 / 1; }
  .cs-header h1 { grid-area: 3 / 1; }

  /* The 1fr row is the outcome's, so any slack from a photo taller than the
     text collects below the copy instead of stretching the gaps between it. */
  .cs-header .outcome { grid-area: 4 / 1; align-self: start; }

  .cs-hero { grid-area: 1 / 2 / 5 / 3; padding: 0; }

  .cs-header .data-plate {
    grid-area: 5 / 1 / 6 / 3;
    grid-template-columns: repeat(4, 1fr);
    gap: 24px;
    /* Adds to the grid's 26px row gap so the plate sits clear of the column
       above it, matching the breathing room it has in the wide layout. */
    margin-top: 18px;
  }
}

@media (max-width: 900px) {
  .grid { grid-template-columns: 1fr; }
  .grid.three-up { grid-template-columns: 1fr; }
  .about .cols { grid-template-columns: 1fr; gap: 36px; }
  .triad { grid-template-columns: 1fr; gap: 20px; }
  .data-plate { grid-template-columns: repeat(2, 1fr); }
  .stat-row { grid-template-columns: repeat(2, 1fr); }
  /* Stacked masthead: hero photo between the outcome and the data plate.
     The plate lives inside .cs-header, so display:contents promotes the
     header's children into this flex row — otherwise the hero and the plate
     sit at different levels and can't be ordered against each other. The
     header's own padding and 26px gap move up here with them. */
  .cs-top {
    display: flex;
    flex-direction: column;
    gap: 26px;
    padding-top: 48px;
    padding-bottom: 32px;
  }
  .cs-header { display: contents; }
  .cs-header .back { align-self: flex-start; }
  /* max-width goes: stacked, the photo runs the full band width so its edges
     stay flush with the title and the plate above and below it. */
  .cs-hero { order: 2; width: 100%; max-width: none; margin: 0; padding: 0; }
  .cs-header .data-plate { order: 3; margin-top: 0; }
  .cs-hero-media { aspect-ratio: 3 / 2; }
  .cs-body { flex-direction: column; gap: 56px; }
  .cs-photos { width: 100%; margin-right: 0; }
  .hero { padding: 64px 0 48px; }
  .hero-top { grid-template-columns: 1fr; }
  /* Stacked above the text, so it takes the column width rather than the
     narrow 140px it needed back when its height was fixed at 400px. */
  .hero-photo { width: min(100%, 480px); order: -1; }
  .lead-dome-card { grid-template-columns: 1fr; gap: 20px; }
  .lpm-lead { padding: 24px 24px 28px; }
  .lpm-chapters { grid-template-columns: 1fr; gap: 28px; }

  /* The leads' 1.1rem meta row is a desktop treatment: it relies on width the
     two spans no longer have here, and with no wrap allowed the labels break
     mid-phrase. Back to the grid tiles' size, and allowed to wrap as a unit. */
  .lpm-lead .tile-meta,
  .lead-dome-card .tile-meta {
    font-size: 0.82rem;
    gap: 6px 16px;
    flex-wrap: wrap;
  }
}

/* The spine only collapses to stacked headings on genuinely narrow screens */
@media (max-width: 700px) {
  .cs-section { grid-template-columns: 1fr; gap: 14px; }
  .figure-grid { grid-template-columns: 1fr; }
  .data-plate,
  .cs-header .data-plate { grid-template-columns: 1fr; }
  .stat-row { grid-template-columns: repeat(2, 1fr); }

  /* Nav collapses behind the burger. The wrap wraps so the open panel drops
     onto its own full-width row beneath the logo and button. */
  .nav-toggle { display: flex; }
  .site-header .wrap { flex-wrap: wrap; }
  .site-nav {
    display: none;
    flex-basis: 100%;
    flex-direction: column;
    padding-top: 12px;
  }
  .site-nav.is-open { display: flex; }
  .site-nav a {
    margin-left: 0;
    padding: 14px 0;
    border-top: 1px solid var(--bar-edge);
  }

  /* The case study list expands in place inside the burger panel rather than
     floating over the page as it does on desktop. The column keeps Work and
     its list centred, matching the other links under .site-nav's
     align-items:center — a full-width button would sit hard left instead. */
  .nav-item {
    display: flex;
    flex-direction: column;
    align-items: center;
  }
  .site-nav .nav-work {
    justify-content: center;
    margin-left: 0;
    padding: 14px 0;
    border-top: 1px solid var(--bar-edge);
  }
  .sub-menu {
    position: static;
    min-width: 0;
    background: transparent;
    border: 0;
    padding: 0 0 6px;
    text-align: center;
  }
  .sub-menu a {
    padding: 11px 0;
    border-top: 0;
    color: var(--soft);
  }
}

@media (max-width: 480px) {
  .data-plate { grid-template-columns: 1fr; }
  .cs-nav .wrap { flex-direction: column; }
  .tile-meta { flex-direction: column; gap: 4px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
}

@media print {
  body { background: #fff; font-size: 11pt; }
  .site-header, .site-nav, .cs-nav { display: none; }
  .photo img, figure img, .cs-hero-media img { filter: none; }
  .data-plate, .spec-list { border-color: #999; }
  a { color: #000; }
}
