/* ==========================================================================
   Design tokens — Nocturne design system, source of truth for colour and
   spacing. Copied verbatim from the handoff's nocturne-styles.css :root
   block; kept intact even where a token (e.g. --color-section-glow) is not
   used by this page, per the handoff README.
   ========================================================================== */
:root {
  --color-bg: #161826;
  --color-surface: #232532;
  --color-text: #e9e9ed;
  --color-accent: #9184d9;
  --color-accent-2: #a7a1db;
  --color-divider: color-mix(in srgb, #e9e9ed 16%, transparent);

  --color-neutral-100: #f3f5fe;
  --color-neutral-200: #e4e7f5;
  --color-neutral-300: #cfd3e5;
  --color-neutral-400: #b2b6ca;
  --color-neutral-500: #9397ab;
  --color-neutral-600: #75798c;
  --color-neutral-700: #595d6c;
  --color-neutral-800: #3f424d;
  --color-neutral-900: #292b31;

  --color-accent-100: #f5f4ff;
  --color-accent-200: #e7e5fe;
  --color-accent-300: #d2cefd;
  --color-accent-400: #b5abfc;
  --color-accent-500: #968ae0;
  --color-accent-600: #796cbf;
  --color-accent-700: #5d5294;
  --color-accent-800: #423a6a;
  --color-accent-900: #2b2741;

  --color-accent-2-100: #f5f4ff;
  --color-accent-2-200: #e7e5fe;
  --color-accent-2-300: #d2cefd;
  --color-accent-2-400: #b5afe8;
  --color-accent-2-500: #9690c9;
  --color-accent-2-600: #7972a9;
  --color-accent-2-700: #5c5783;
  --color-accent-2-800: #423e5d;
  --color-accent-2-900: #2b293a;

  --color-section: #262a60;
  --color-section-glow: #353b80;
  --color-section-ghost: #4c5397;

  --font-heading: "Inter", system-ui, sans-serif;
  --font-heading-weight: 500;
  --font-body: "Inter", system-ui, sans-serif;

  --space-1: 2.8px;
  --space-2: 5.6px;
  --space-3: 8.4px;
  --space-4: 11.2px;
  --space-6: 16.8px;
  --space-8: 22.4px;

  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 14px;

  --shadow-sm: 0 0 0 1px #3f424d;
  --shadow-md: 0 0 0 1px #595d6c, 0 6px 18px rgba(0,0,0,0.55);
  --shadow-lg: 0 0 0 1px #9397ab, 0 16px 40px rgba(0,0,0,0.65);
}

/* ==========================================================================
   Self-hosted fonts — Spectral (headings) and Inter (everything else).
   No Google Fonts request in production.
   ========================================================================== */
@font-face {
  font-family: "Spectral";
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url("/fonts/spectral-v15-latin-300.woff2") format("woff2");
}
@font-face {
  font-family: "Spectral";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/spectral-v15-latin-regular.woff2") format("woff2");
}
/* Italic is for the case taglines (.lead) only, below the fold, so it is not
   preloaded. Without this file the browser would fake a slanted regular. */
@font-face {
  font-family: "Spectral";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/spectral-v15-latin-italic.woff2") format("woff2");
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/inter-v20-latin-regular.woff2") format("woff2");
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/fonts/inter-v20-latin-500.woff2") format("woff2");
}

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

/* This page's type pairing: Spectral for headings, over the design system's
   default Inter. Set as a token override, not edited upstream — a second
   :root block so it wins on source order (a selector on the element itself,
   e.g. html {}, would lose to :root's higher specificity). */
:root {
  --font-heading: Spectral, Georgia, serif;
  --font-heading-weight: 400;
}

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.55;
  font-weight: 400;
}

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  line-height: 1.12;
  letter-spacing: -0.015em;
  margin: 0;
}

p { margin: 0; }

a {
  color: var(--color-accent);
  text-underline-offset: 3px;
}
a:hover { color: var(--color-accent-300); }

:focus { outline: none; }
:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
::selection { background: color-mix(in srgb, var(--color-accent) 30%, transparent); }

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 10;
  background: var(--color-surface);
  color: var(--color-text);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
}
.skip-link:focus {
  left: var(--space-4);
  top: var(--space-4);
}

/* ==========================================================================
   Utilities
   ========================================================================== */
.pad {
  padding-left: clamp(22px, 5vw, 64px);
  padding-right: clamp(22px, 5vw, 64px);
}

/* Rules fade to transparent over 48px at each end — never a plain solid
   border. */
.fade-t {
  border-top: 1px solid transparent;
  border-image: linear-gradient(to right, transparent,
    var(--color-divider) 48px, var(--color-divider) calc(100% - 48px),
    transparent) 1;
}
.fade-b {
  border-bottom: 1px solid transparent;
  border-image: linear-gradient(to right, transparent,
    var(--color-divider) 48px, var(--color-divider) calc(100% - 48px),
    transparent) 1;
}
/* Fades only at the bottom, so it reads as hanging from the heading above
   it — used on the Background timeline only. */
.fade-l {
  border-left: 1px solid transparent;
  border-image: linear-gradient(to bottom, var(--color-divider),
    var(--color-divider) calc(100% - 48px), transparent) 1;
}

.nowrap { white-space: nowrap; }

.two-col {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap: clamp(28px, 4vw, 56px);
}

/* The photo, one rule for the hero (40px, a byline beside the eyebrow) and
   the contact card (64px, where the person is introduced; see the override
   below). The hero one is stored at 96px (2.4 times its display size) so it
   stays sharp on phones, the contact one at 192px (3 times); both are
   greyscale and tightly cropped from the same source so the face fills the
   circle. The ring is a 1px neutral-700 stroke, the same colour and weight
   as the circle in the header mark: a ring on a circular image, not a
   divider, so it isn't the plain solid rule the fade-* utilities exist to
   avoid. */
.avatar {
  flex: none;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid var(--color-neutral-700);
  object-fit: cover;
}
.contact-person .avatar {
  width: 64px;
  height: 64px;
}

/* Netlify Forms honeypot: must be a real, CSS-hidden text input, not
   type="hidden" — bots skip hidden inputs. */
.hidden-field {
  position: absolute;
  left: -9999px;
}

/* ==========================================================================
   Reused design-system components
   ========================================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  cursor: pointer;
  text-decoration: none;
  /* Buttons stay Inter — the heading override above would otherwise leak
     Spectral onto them. */
  font-family: Inter, system-ui, sans-serif;
  font-weight: 500;
  font-size: 14px;
  line-height: 1.2;
  color: var(--color-text);
  background: transparent;
  border: 1px solid transparent;
  padding: var(--space-2) calc(var(--space-3) * 1.2);
  border-radius: var(--radius-md);
}
.btn-primary { color: var(--color-accent); border-color: var(--color-accent); }
.btn-primary:hover { background: color-mix(in srgb, var(--color-accent) 12%, transparent); }
.btn-primary:active { background: color-mix(in srgb, var(--color-accent) 22%, transparent); }
/* The one filled control on the page, deliberately - reserved for the
   contact form's Send button, the single highest-stakes action here.
   Dark text on the accent fill (not the token's own outline colour)
   measures 5.46:1, clear of the 4.5:1 floor. */
.btn-filled {
  background: var(--color-accent);
  color: var(--color-bg);
}
.btn-filled:hover { background: var(--color-accent-600); border-color: var(--color-accent-600); }
.btn-filled:active { background: var(--color-accent-700); border-color: var(--color-accent-700); }
.btn-block { width: 100%; margin: 0; }

.field > label {
  display: block;
  font-size: 12px;
  margin-bottom: 5px;
  color: color-mix(in srgb, var(--color-text) 70%, transparent);
}
.required-mark { color: var(--color-neutral-400); }
.input {
  width: 100%;
  min-height: 36px;
  padding: 6px 10px;
  font: inherit;
  font-family: Inter, system-ui, sans-serif;
  font-size: 14px;
  color: var(--color-text);
  caret-color: var(--color-accent);
  background: var(--color-surface);
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
}
.input:hover { border-color: color-mix(in srgb, var(--color-text) 45%, transparent); }
.input:focus-visible { border-color: var(--color-accent); outline-offset: 0; }
/* display: block fixes a real inconsistency: .input is inline-block, and an
   inline-block replaced element leaves a small "descender" gap reserved
   beneath it in its container's line box - invisible on the single-line
   inputs, but a real ~6px on the textarea, which was making the gap below
   the message field measurably bigger than every other row gap. */
textarea.input { min-height: 130px; resize: vertical; display: block; }
/* Required-field validation. :user-invalid only matches once the user has
   interacted with and left a field invalid, so nothing looks wrong on
   first load - unlike plain :invalid. The native browser error bubble
   still appears alongside this; suppressing it needs JavaScript. */
.input:user-invalid { border-color: var(--color-accent); }
.field-hint {
  display: none;
  margin: 4px 0 0;
  font-size: 12px;
  color: var(--color-neutral-300);
}
.input:user-invalid ~ .field-hint { display: block; }

/* ==========================================================================
   Header
   ========================================================================== */
.site-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px 28px;
  padding-top: 22px;
  padding-bottom: 22px;
}
.brand {
  display: flex;
  align-items: center;
  gap: 11px;
  margin-right: auto;
  text-decoration: none;
  color: var(--color-text);
}
.brand .wordmark {
  font-family: var(--font-heading);
  font-weight: 400;
  font-size: 18px;
  letter-spacing: 0.005em;
}
/* Grouped so nav links and the Contact button wrap to a second line
   together, rather than wrapping independently as separate flex items
   of .site-header. margin-left: auto right-aligns that wrapped line to
   match .brand's own margin-right: auto on the row above, instead of
   defaulting to flush-left; a no-op on a single row, where .brand's
   auto margin already does this job. */
.header-nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  /* One gap for both the links and the button, tapering together from
     28px down to 16px at narrow widths (28px from about 560px up). On
     phones nav-links plus Contact no longer fit on one line at 28px
     (regression from "What I do" becoming "What I do now"; the label is
     now "What I do" again, which gives about 28px more room), so the gap
     has to shrink there; it must shrink for both, because the button's
     outline, not the word inside it, is what reads as its edge. An
     earlier version tapered only the links-to-button gap, which left
     the button's outline 16px from "Background" against 28px between
     the plain links, and fit at 393px with under 1px to spare. Sharing
     one value keeps the spacing even and leaves about 13px of slack at
     393px. Below about 378px nav-links' own text is already most of the
     available width, so those widths still can't fit Contact on the
     same line regardless — see the rule after this for how that
     remaining case is handled. */
  --nav-gap: clamp(16px, 5vw, 28px);
  gap: 14px var(--nav-gap);
  margin-left: auto;
}
.nav-links {
  display: flex;
  flex-wrap: wrap;
  gap: 14px var(--nav-gap);
}
/* Below ~378px, .header-nav's own children still wrap a second time:
   nav-links on one line, Contact alone on the next, inside
   .header-nav's own box rather than sharing a line with it. The
   comment above still holds for the two-line case, but a line Contact
   has entirely to itself needs its own right-alignment, the same
   device one level up: margin-left: auto pushes it to the end of
   whichever line it lands on, a no-op when it already shares a line
   with nav-links since that line is exactly as wide as its content. */
.header-nav .btn-primary {
  margin-left: auto;
}
.nav-links a {
  font-size: 13.5px;
  color: var(--color-neutral-300);
  text-decoration: none;
}
.nav-links a:hover { color: var(--color-accent-300); }

/* ==========================================================================
   Hero
   ========================================================================== */
.hero {
  position: relative;
  overflow: hidden;
  padding-top: clamp(56px, 9vw, 96px);
  padding-bottom: clamp(48px, 7vw, 80px);
  /* Smaller and softer than the original (900x350 vs 1100x420, 28% peak
     strength vs solid), so it fades out before it reaches the box edges
     instead of getting clipped mid-fade — that clipping was the visible
     "box" edge. Verified analytically: corner residual opacity drops from
     ~75% to ~15-20% across the fluid width range. */
  background: radial-gradient(900px 350px at 5% -18%, color-mix(in srgb, var(--color-accent-900) 68%, transparent), transparent 75%);
}
/* Replaces the old decorative hero-mark (a brand-mark SVG filling the
   space where a portrait would have gone). That mark had a known,
   repeatedly-fixed positioning bug: its top:44% was a percentage of
   .hero's own height, which silently drifted every time the hero copy
   gained or lost a line, and broke twice in practice. The proof panel
   below replaces it with real content rather than decoration, and as a
   flex sibling of .hero-content it start-aligns naturally — its
   position isn't derived from .hero's height at all, so it can't drift
   the same way regardless of how many lines the lede wraps to.
   Stacked by default (mobile-first): the side-by-side row, and the 50px
   padding-top that lines the panel's first label up with the h1 (the
   40px photo row above the h1, plus the gap, less the label's own
   leading; it was 27px when that row was a single line of text), only
   belong together, so they're pinned to the same explicit breakpoint
   rather than left to emerge from flex-wrap on its own — letting them
   drift apart was exactly the kind of coupling-to-content-length bug
   that broke the old hero-mark's positioning. This is a deliberate,
   narrowly-scoped exception to the no-media-queries rule: nothing else
   on the page needs genuinely different treatment in two states, this
   does. Breakpoint (820px) sits above the width the two columns' own
   flex-basis plus gap actually need to fit (~791px, solved from the
   padding and gap clamp formulas), so a visible scrollbar on some
   platforms can't tip it into wrapping right at the edge. */
.hero-grid {
  display: flex;
  flex-direction: column;
  gap: 28px;
}
.hero-panel {
  display: flex;
  flex-direction: column;
  gap: 24px;
}
@media (min-width: 820px) {
  .hero-grid {
    flex-direction: row;
    flex-wrap: wrap;
    gap: clamp(28px, 4vw, 56px);
  }
  .hero-content { flex: 2 1 420px; }
  .hero-panel {
    flex: 1 1 260px;
    max-width: 360px;
    padding-top: 50px;
  }
}
.hero-panel-item {
  padding-left: 16px;
}
.hero-panel-text {
  font-family: var(--font-heading);
  font-size: 16.5px;
  line-height: 1.65;
  color: var(--color-neutral-200);
}
/* Matches .hero .eyebrow's own rule exactly, not the Current work h3
   treatment, since this sits inside the hero itself. */
.hero-panel-label {
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-neutral-400);
  margin-bottom: 6px;
}
.hero .eyebrow {
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-neutral-400);
  margin-bottom: 22px;
}
/* The photo sits in the eyebrow row, so that row is the height of the
   photo (40px) rather than one line of text (about 17px). The hero panel's
   padding-top is tied to that: see the 820px rule above. */
.hero-id {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 22px;
}
.hero-id .eyebrow { margin-bottom: 0; }
.hero h1 {
  font-weight: 300;
  font-size: clamp(34px, 5.2vw, 54px);
  line-height: 1.14;
  letter-spacing: -0.01em;
  margin-bottom: 26px;
  /* Wide enough for two lines. ch scales with the fluid font size, so it
     holds across desktop widths; narrower screens wrap to three lines on
     their own. balance evens the lines out, so neither layout strands a
     word ("land.") on its last line. */
  max-width: 27ch;
  text-wrap: balance;
}
.hero-lede {
  font-family: var(--font-heading);
  font-weight: 400;
  font-size: clamp(17.5px, 1.9vw, 20px);
  line-height: 1.65;
  margin-bottom: 18px;
  color: var(--color-neutral-200);
  /* About 60 to 68 characters a line: past ~75 readability drops. */
  max-width: 30em;
}
/* Thesis statement, not a heading - a paragraph sized between the h1 and
   body copy. Same serif and weight as the h1, reusing the Contact
   heading's scale rather than inventing a new one. */
.hero-thesis {
  font-family: var(--font-heading);
  font-weight: 400;
  font-style: italic;
  font-size: clamp(24px, 3.2vw, 30px);
  line-height: 1.3;
  margin: 28px 0 0;
}
/* The outlined .btn-primary, the same control as the header's Contact
   button, not the filled one (that is reserved for the form's Send). The
   label is the Contact heading's own words. The margins keep the visible
   gaps the old text link had: 41px from the thesis baseline to the top
   edge (cap-top then, outline now) and about 86px from the bottom edge to
   the end of the hero. */
.hero-cta {
  margin: 30px 0 6px;
}

/* ==========================================================================
   Sector band
   ========================================================================== */
/* Fill is --color-section mixed halfway toward the page background: the
   full-strength indigo was the one saturated block on the page and kept
   drawing "too bright" comments. Halfway reads clearly as a band (it still
   separates the hero from Selected work) without competing with it. */
.sectors {
  background: color-mix(in srgb, var(--color-section) 50%, var(--color-bg));
  padding-top: 24px;
  padding-bottom: 21px;
}
.sectors h2 {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-accent-200);
  margin-bottom: 9px;
}
/* Same inline-block-plus-middot device as .clients-list below, for the
   same reason: evenly spaced, unpunctuated words on a colour block read
   as a row of clickable tags or navigation, whereas the same words
   separated by dots read as a line of facts. */
.sector-list {
  display: block;
  margin: 0;
  padding: 0;
  list-style: none;
  /* 33.25px per row, the same pitch as the flex rows this replaced (the
     page's 23.25px line plus a 10px gap). A bare line-height: 2 was
     tighter than that and left the band shorter; this keeps the text
     exactly where it sat before the separators went in. */
  line-height: 33.25px;
}
.sector-list li { display: inline-block; }
.sector-list li:not(:last-child)::after {
  content: "\00a0\00b7 ";
}
/* Neutral-400, same as .meta and every other informational line on the
   page — bright neutral-100 read too close to the nav/link register and
   could pass for a clickable tag list. */
.sector-list li {
  font-size: 15px;
  color: var(--color-neutral-400);
}

/* ==========================================================================
   Selected work / case pattern
   ========================================================================== */
.work {
  padding-top: clamp(48px, 7vw, 72px);
  padding-bottom: clamp(40px, 6vw, 64px);
}
.work > h2 {
  font-size: clamp(24px, 3vw, 28px);
  margin-bottom: 6px;
}
.work-intro {
  font-size: 14px;
  color: var(--color-neutral-400);
  margin-bottom: 36px;
}

.case-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.case {
  display: flex;
  flex-wrap: wrap;
  gap: 16px clamp(20px, 3vw, 40px);
  padding: 30px 0;
}

.case-head {
  flex: 1 1 230px;
  display: flex;
  gap: 18px;
  align-items: baseline;
}
.case-num {
  font-family: var(--font-heading);
  font-size: 13px;
  color: var(--color-accent);
}
.case-head h3,
.case-head h4 {
  font-size: clamp(19px, 2.2vw, 21px);
  margin-bottom: 6px;
}
.meta {
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-neutral-400);
}

.case-body { flex: 2 1 330px; }
.case-body > * + * { margin-top: 10px; }
.lead {
  font-family: var(--font-heading);
  font-style: italic;
  /* Fluid so it stays clear of .case-head h3 (clamp(19px, 2.2vw, 21px)) at
     every width, not just the ones checked by eye: below ~857px h3 sits at
     its 19px floor, so the tagline's own floor is 18px, a 1px gap; both
     grow from there, reaching a 2px gap by desktop. Checked against
     the case body's own new 16.5px too - the floor keeps at least a 1.5px
     gap there as well. */
  font-size: clamp(18px, 2.1vw, 19px);
  line-height: 1.5;
  /* Once the body text moved to Spectral too, italic was left carrying the
     whole distinction on its own (colour and size were both very close to
     the body already). A faint accent tint restores some of what the old
     Inter-vs-Spectral contrast used to give it for free, without reading
     as a new colour choice - checked at 12/18/25% side by side against a
     real page link; even 25% stayed clearly paler than the link colour, so
     confusability isn't the constraint, look/feel is. 18% read as a
     genuine restoration; 25% started to feel like a deliberate tint in its
     own right rather than a correction. */
  color: color-mix(in srgb, var(--color-accent) 18%, var(--color-text));
}
.case-body p:not(.lead):not(.stack) {
  font-family: var(--font-heading);
  font-size: 16.5px;
  line-height: 1.65;
  color: var(--color-neutral-200);
}
.stack {
  font-size: 12px;
  color: var(--color-neutral-400);
  margin-top: 10px;
}
/* Outcome line: a short, concrete result statement, sitting right after
   .lead so it's visible to a scanning reader who never reaches the
   bottom of the case - the original placement (after .stack) only
   reached someone who'd already read the whole thing, which is the
   reader who needs it least. Paired with the tagline as a two-beat
   hook-then-payoff opening, read before any body prose.
   Same tint technique as .lead (18%, via color-mix) rather than a new
   one, so it doesn't read as a link - color-mix keeps it well short of
   the actual accent colour, and well short of --color-accent-300, which
   is already spoken for (link hover states, the current Background
   timeline row) and reads as noticeably more saturated when tried here.
   Upright, not italic: .lead already owns italic, and using it here too
   would undo the one thing (besides the rule) that keeps the two lines
   from reading as one continuous voice. The fade-l rule (reused from
   the Background timeline, not a new device) is doing the real
   differentiation work; colour only needs to support it, not carry it
   alone, which is why the tint stayed gentle even though a stronger
   colour was tempting. Not every case gets one - only built where a
   concrete, checkable fact actually exists (case 06 has its own outcome
   as a dedicated paragraph instead, added earlier, so has none here). */
.outcome {
  font-family: var(--font-heading);
  font-size: 16.5px;
  line-height: 1.65;
  color: color-mix(in srgb, var(--color-accent) 18%, var(--color-text));
  padding-left: 16px;
}

/* Prototype: all of a case's body except its first paragraph (the teaser,
   further down) sits behind a native <details>, so tagline, outcome and
   the teaser are the at-a-glance summary and the rest is on demand. No
   JS: the browser owns open/close, and the label swap is two spans
   switched by [open]. */
.case-more > * + * { margin-top: 10px; }
/* The 20px glyph and the padding make a 40px-high target (the label alone
   is 18px); the negative margins give the 7px each side back, so the
   layout is the same as before (26px, label 14px below the outcome) and
   the target reaches into the empty gap only, never over the text above. */
.case-more > summary {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 0;
  margin: -7px 0;
  cursor: pointer;
  list-style: none;
  font-size: 13px;
  line-height: 1.4;
  color: var(--color-neutral-300);
}
.case-more > summary::-webkit-details-marker { display: none; }
.case-more > summary::before {
  content: "+";
  content: "+" / "";
  width: 14px;
  text-align: center;
  font-size: 20px;
  font-weight: 300;
  line-height: 1;
  color: var(--color-accent);
}
.case-more[open] > summary::before {
  content: "\2013";
  content: "\2013" / "";
}
.case-more > summary:hover { color: var(--color-accent-300); }
.more-open,
.case-more[open] .more-closed { display: none; }
.case-more[open] .more-open { display: inline; }
/* Teaser: the first sentence of each case's first paragraph sits outside
   the <details>, and the rest of that paragraph is the first thing inside
   it. Every word is therefore either visible or inside the <details>,
   which the browser opens on a find-in-page match; nothing is clamped or
   hidden by hand. The two halves are separate paragraphs with the usual
   10px gap: removing it, so they read as the one paragraph they were,
   left a short line and a bare line break that looked like an error. */
/* Control below the content (first in the source, last on screen), so an
   open case ends with "Less detail" rather than putting it between the
   teaser and the rest. The paragraphs inside sit in ::details-content, not
   in the flex container itself, hence the first one's margin reset and the
   gap between the content and the control. Elsewhere the control stays
   above the content, as in a plain <details>. */
@supports selector(::details-content) {
  .case-more {
    display: flex;
    flex-direction: column-reverse;
    gap: 10px;
  }
  .case-more:not([open]) { gap: 0; }
  .case-more > p:first-of-type { margin-top: 0; }
  .case-more > summary { align-self: flex-start; }
}
/* Print: open every case, since a closed one prints without its body.
   Not the full print stylesheet (still on the backlog), only this. */
@media print {
  .case-more > summary { display: none; }
  .case-more::details-content {
    content-visibility: visible;
  }
}

/* "Also" band: one-line entries in the same rail as the six cases (same
   flex-basis values, so they wrap at the same width), but no index number
   and much tighter rows. */
.also { margin-top: clamp(36px, 5vw, 48px); }
.also h3 {
  font-size: clamp(21px, 2.6vw, 24px);
  margin-bottom: 6px;
}
.also .work-intro { margin-bottom: 18px; }
/* Closing line for the whole Selected work section, after the Also band -
   same quiet caption treatment as .work-intro (deliberately not a CTA:
   no colour, no link styling, no arrow), with its own top margin instead
   of .work-intro's bottom one, matching .also's own top-margin value for
   a consistent gap between the section's sub-blocks. */
.work-outro {
  font-size: 14px;
  color: var(--color-neutral-400);
  margin-top: clamp(36px, 5vw, 48px);
}
.case-brief {
  padding: 16px 0;
  gap: 8px clamp(20px, 3vw, 40px);
}

/* ==========================================================================
   Clients
   ========================================================================== */
/* Last section before Contact, so its bottom padding is the gap before the
   Contact rule (72px at wide widths). */
.clients { padding-bottom: clamp(48px, 7vw, 72px); }
.clients h2 {
  font-size: clamp(21px, 2.6vw, 24px);
  margin-bottom: 6px;
}
.clients-sub {
  font-size: 13.5px;
  margin-bottom: 18px;
  color: var(--color-neutral-400);
}
.clients-list {
  display: block;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 15px;
  line-height: 2;
  max-width: 92ch;
  color: var(--color-neutral-200);
}
/* inline-block keeps each name on one line. Not white-space: nowrap, which
   would also swallow the space after the separator and stop lines
   breaking between names; and unlike nowrap, a name wider than the
   container still wraps inside itself instead of overflowing. */
.clients-list li { display: inline-block; }
/* A non-breaking space glues the separator to the name before it, so a
   line break can only fall after " · ", never leaving the dot orphaned
   at the start of a line. */
.clients-list li:not(:last-child)::after {
  content: "\00a0\00b7 ";
}

/* ==========================================================================
   Expertise / Background
   ========================================================================== */
/* Bottom padding is the gap before Clients (64px at wide widths). */
.expertise-background { padding-bottom: clamp(40px, 6vw, 64px); }
.expertise h2,
.background h2 {
  font-size: clamp(21px, 2.6vw, 24px);
}
.expertise h2 { margin-bottom: 14px; }
.background h2 { margin-bottom: 6px; }
.background-intro {
  font-size: 14px;
  color: var(--color-neutral-400);
  margin-bottom: 18px;
}
.expertise-intro {
  font-family: var(--font-heading);
  font-size: 16.5px;
  line-height: 1.65;
  margin-bottom: 20px;
  color: var(--color-neutral-200);
}
.tag-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 20px;
  margin: 0;
  padding: 0;
  list-style: none;
}
/* Plain tinted text, not a pill: a bordered accent chip read as a
   clickable control, but these terms aren't links or buttons. Neutral,
   not accent, so it also can't be mistaken for the site's link colour. */
.tag-row li {
  font-size: 13px;
  color: var(--color-neutral-300);
}

.timeline {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding-left: 22px;
}
.timeline-item { font-size: 14.5px; }
.timeline-item .year { color: var(--color-neutral-400); white-space: nowrap; }
.timeline-item.is-current { color: var(--color-accent-300); }
.timeline-item.is-current .year { color: var(--color-neutral-400); }

.background-note {
  font-family: var(--font-heading);
  font-size: 16.5px;
  line-height: 1.65;
  margin-top: 14px;
  color: var(--color-neutral-300);
}
.background-link {
  font-size: 13px;
  margin-top: 14px;
}

/* ==========================================================================
   Current work
   ========================================================================== */
/* Bottom padding is the gap before Expertise / Background (56px at wide
   widths). */
.current-work { padding-bottom: clamp(40px, 6vw, 56px); }
.current-work h2 {
  font-size: clamp(21px, 2.6vw, 24px);
  margin-bottom: 18px;
}
/* Delivery leads: four blocks of the same shape (a label, an italic
   situation, the text), the first wide and in two columns of prose, then
   the other three side by side, wrapping where there is not room
   (flex-wrap, so a lone third item stretches to the full width instead of
   leaving an empty cell). */
.cw-delivery p:not(.lead),
.cw-judgement p:not(.lead) {
  font-family: var(--font-heading);
  font-size: 16.5px;
  line-height: 1.65;
  color: var(--color-neutral-200);
}
.cw-delivery > * + * { margin-top: 10px; }
.cw-delivery h3 + .lead { margin-top: 0; }
.cw-delivery { margin-bottom: clamp(32px, 4.5vw, 40px); }
.cw-row {
  display: flex;
  flex-wrap: wrap;
  gap: 24px clamp(28px, 4vw, 56px);
  align-items: flex-start;
}
.cw-row > * { flex: 1 1 260px; }
/* Delivery is plain prose that runs through two balanced columns, like a
   magazine, so the columns come out even and need no labels. Two, not
   three: about 60 characters a line at desktop instead of about 40, it
   reads as the main statement beside the narrower labelled row of three
   below it, and the page alternates two, three, two. The column width and
   gap are the same as .two-col's (300px, the same clamp), so the columns
   line up with Expertise and Background further down and drop to one at
   the same width. */
.cw-flow {
  columns: 2 300px;
  column-gap: clamp(28px, 4vw, 56px);
}
.cw-flow p { margin: 0 0 10px; }
.cw-flow p:last-child { margin-bottom: 0; }
/* The one-line situation under each label uses the case tagline style
   (.lead: Spectral italic, fluid 18 to 19px, faint accent tint) so the
   section scans as label, situation, detail, the same shape as the cases. */
.cw-delivery .lead,
.cw-judgement .lead { margin-bottom: 8px; }
.cw-delivery .lead + .cw-flow { margin-top: 0; }
/* Small-caps run-in labels, not a second layer of section heading - same
   treatment as .sectors h2 and .meta (Inter, since the h1-h6 rule would
   otherwise hand these Spectral). Still real headings (four sibling h3s
   under the section's h2) with their own ids, so the heading outline and
   direct-linking both still work. */
.current-work h3 {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-neutral-400);
  /* 10px, not the hero panel label's 6px: measured from the label's
     baseline to the top of the capitals below, the hero panel is 18px
     (its text is 16.5px with 1.65 leading) and this section's italic
     lines are tighter (19px with 1.5 leading), so equal margins looked
     unequal. 10px makes them match. */
  margin-bottom: 10px;
}

/* ==========================================================================
   Contact
   ========================================================================== */
.contact {
  padding-top: clamp(48px, 7vw, 64px);
  padding-bottom: clamp(48px, 7vw, 64px);
  background: linear-gradient(180deg, transparent, var(--color-surface));
}
.contact h2 {
  font-size: clamp(24px, 3.2vw, 30px);
  margin-bottom: 14px;
  max-width: 18ch;
}
.contact-intro {
  font-family: var(--font-heading);
  font-size: 16.5px;
  line-height: 1.65;
  margin-bottom: 22px;
  color: var(--color-neutral-200);
}
.contact-note {
  font-size: 13.5px;
  color: var(--color-neutral-400);
  margin-bottom: 12px;
}
.contact-details {
  display: flex;
  flex-direction: column;
  gap: 7px;
  font-size: 13.5px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.contact-details .text-muted { color: var(--color-neutral-400); }
/* Who you'd be writing to, set off from the pitch above by a faded rule. */
.contact-person {
  display: flex;
  align-items: center;
  gap: 16px;
  /* Adjacent margins collapse to the larger, so this replaces the
     note's 12px bottom margin rather than adding to it. 22px each side
     of the rule measures about 28px by eye (text baseline to rule above,
     rule to the capitals' top below): the name's line box has more
     built-in leading than the note's, so equal numbers would look
     unequal. */
  margin-top: 22px;
  padding-top: 22px;
}
.contact-name {
  font-family: var(--font-heading);
  font-size: 18px;
  line-height: 1.3;
  color: var(--color-text);
  margin-bottom: 6px;
}

.form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 210px), 1fr));
  gap: 14px;
}
/* Each field sizes to its own content rather than stretching to match a
   taller sibling in the same row (e.g. one showing a validation hint). */
.form-grid .field { align-self: start; }
.form-grid .field-wide { grid-column: 1 / -1; }
/* Send gets its own full-width row rather than sharing one with Timeline -
   it was reading as though it belonged to that field rather than the whole
   form (same grid treatment as any other paired input). */
.form-actions { grid-column: 1 / -1; }
.form-note {
  grid-column: 1 / -1;
  margin: 2px 0 0;
  font-size: 12px;
  line-height: 1.6;
  color: var(--color-neutral-400);
}

/* ==========================================================================
   Footer
   ========================================================================== */
.site-footer {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 20px;
  padding-top: 22px;
  padding-bottom: 22px;
  font-size: 12px;
  color: var(--color-neutral-400);
}
.site-footer .domain { margin-right: auto; }

/* ==========================================================================
   Centered single-message pages (thanks, 404)
   ========================================================================== */
.page-wrap {
  max-width: 1180px;
  margin: 0 auto;
  background: var(--color-bg);
}
.centered-page {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
.simple-hero {
  flex: 1;
  display: flex;
  align-items: center;
  padding-top: clamp(64px, 12vw, 120px);
  padding-bottom: clamp(64px, 12vw, 120px);
  background: radial-gradient(1100px 420px at 10% -12%, var(--color-accent-900), transparent 70%);
}
.simple-hero h1 {
  font-weight: 300;
  font-size: clamp(30px, 4.4vw, 44px);
  line-height: 1.14;
  letter-spacing: -0.01em;
  margin-bottom: 22px;
  max-width: 20ch;
}
.simple-hero .lede {
  font-family: var(--font-heading);
  font-weight: 400;
  font-size: clamp(17.5px, 1.9vw, 20px);
  line-height: 1.65;
  max-width: 52ch;
  margin-bottom: 28px;
  color: var(--color-neutral-200);
}
.thanks-urgent {
  font-size: 14px;
  color: var(--color-neutral-300);
}
.back-link {
  margin-top: 32px;
  font-size: 14px;
}
