/* ============================================================================
   callmemandy.com — STYLES
   ----------------------------------------------------------------------------
   One page, one stylesheet. The design tokens (colors, type sizes) live in
   :root at the top — change a value there and it updates everywhere.

   House rules from the design handoff, so nothing drifts later:
     • No gray. No monospace anywhere — hierarchy in small text comes from
       case, tracking and weight (Plex Sans 600, uppercase, 0.2em).
     • Newsreader is a reading serif: headings sit at 400 on purpose. Don't
       bump them to 500/600 to "fix" perceived lightness.
     • Satisfy has exactly two uses: the signature ("Amanda Miller" in the
       hero) and the ringed numerals on Product Judgment. Nowhere else. The
       24px floor still holds for the signature; the numerals sit at a 23px
       floor on Design's spec, which is 1px under it — flagged to Design,
       not resolved. Don't take either as licence for a third use.
     • Green is a result colour, never an action. Rust is the only thing a
       visitor can click. Never green and rust in the same rule or button.
     • border-radius is 0 everywhere except circles (50%).
     • Type scales with clamp() instead of media queries; every multi-column
       grid uses auto-fit + min(100%, …) so it collapses to one column on its
       own. There are no breakpoints in this file.
============================================================================ */

:root {
  /* ---- Color ---------------------------------------------------------- */
  --navy:        #1B2340;  /* body, hero, AI section                        */
  --navy-deep:   #111827;  /* contact and nav panels                        */
  --footer:      #2A3564;  /* footer ground — the site's only use of it      */
  --photo-well:  #243055;  /* portrait placeholder behind the headshot      */
  --orange:      #C85A1E;  /* Rust: borders, rules, marks, graphical objects.
                              3:1 threshold applies and it clears.
                              NEVER behind text — it measures 3.68:1 on white,
                              which fails AA at body size. Use --orange-deep. */
  --orange-hover:#E4762F;  /* button hover                                  */
  --orange-brt:  #F0873C;  /* emphasis words, hover text, icons             */
  --orange-deep: #B04E19;  /* Rust deep: ANY rust fill that carries text —
                              5.31:1 on white. Also eyebrows on light.      */
  --orange-deep-hover: #8F3E14; /* hover for the above                      */
  --white:       #FFFFFF;
  --off-white:   #F3EFE9;  /* body copy on navy                             */
  --sand:        #E8D8C6;  /* mono / meta text on navy                      */
  --linen:       #F6F2EA;  /* Linen. The Right Place band, the My Work
                              band, and any section carrying supplied
                              imagery — screenshots and line illustrations
                              arrive on their own near-white grounds       */
  --card-cream:  #FBF9F4;  /* inset fills on white                          */
  --ink:         #2B3352;  /* body copy on light                            */
  --gold:        #EFC763;  /* diagram through-line ONLY — never page type   */

  /* The green "signal" family: what happened after a decision. Outcome
     series, resolved states, shipped-on-time notes. Never an action. */
  --pine:        #2E7D5B;  /* fills and rules on light grounds              */
  --fern:        #5CB88C;  /* pine for dark grounds                         */
  --pine-deep:   #256B4E;  /* green text at small sizes on white            */

  /* ---- Layout --------------------------------------------------------- */
  /* Vertical section padding was tightened ~30% site-wide in Sept 2026. The
     middle term is what moved most: the old 6-7vw terms grew faster than the
     content did, so the wider the screen, the more the page read as spacing
     with content in it. Every section's middle term now sits in 3.4-5vw.

     If a section needs more air, raise the floor and the cap — NOT the vw
     term. Raising the vw term is how the page drifts loose again, and it only
     shows up on large monitors where it is easy to miss.

     --pad-x is not part of that scale. It sets the measure and never was the
     problem; it stays put. */
  --content-max: 1240px;
  --pad-x: clamp(20px, 4vw, 48px);
  --pad-y: clamp(40px, 4.6vw, 60px);
  --header-h: 72px;        /* used for scroll-margin under the sticky bar   */

  /* ---- Type ----------------------------------------------------------- */
  --font-body:   "IBM Plex Sans", system-ui, -apple-system, sans-serif;
  --font-head:   "Newsreader", Georgia, "Times New Roman", serif;
  --font-script: "Satisfy", "Brush Script MT", cursive;
  --t-h1:   clamp(30px, 5.4vw, 62px);
  --t-h2:   clamp(28px, 4.3vw, 54px);
  --t-h3:   clamp(21px, 2.1vw, 26px);
  --t-body-lg: clamp(16px, 1.35vw, 18.5px);
  --t-body: clamp(15px, 1.25vw, 16.5px);
  --t-nav:  clamp(12px, 1.05vw, 13.5px);

  --ease: 160ms ease;
}

/* ============================================================================
   BASE
============================================================================ */

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--navy);
  color: var(--white);
  font-family: var(--font-body);
  font-weight: 400;
  /* clip, NOT hidden. `overflow-x: hidden` computes overflow-y to auto, which
     makes body a scroll container — a documented cause of fragment links
     (#top, #contact, #how) failing to scroll, because they resolve against a
     box with nothing in it to scroll. `clip` prevents horizontal overflow the
     same way without creating that container.

     NOT verified in a real browser: fragment scrolling doesn't work in the
     automation this was built under, so the symptom couldn't be reproduced
     either way. Verified only that horizontal overflow is still clipped on
     every page at 375px and 1300px. Worth someone clicking "Skip to content"
     on the live site once. */
  overflow-x: clip;
  -webkit-font-smoothing: antialiased;
  text-wrap: pretty;
}

/* Bold emphasis is never italic. The one italic on the site is the hero's
   role line, which opts in via .hero-role. */
strong, b { font-style: normal; }

h1, h2, h3 { font-family: var(--font-head); font-weight: 400; }
h3 { font-weight: 500; }

a { color: var(--orange); text-decoration: none; }
a:hover { color: var(--orange-hover); }

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

::selection { background: var(--orange-deep); color: var(--white); }

/* Visible keyboard focus, everywhere, without touching mouse users. */
:focus-visible {
  outline: 2px solid var(--orange-brt);
  outline-offset: 3px;
}

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

/* Keyboard users get a way past the nav; hidden until focused. */
.skip-link {
  position: absolute;
  left: 12px; top: -60px;
  z-index: 100;
  background: var(--orange-deep);
  color: var(--white);
  padding: 10px 18px;
  font-size: 14px;
  transition: top var(--ease);
}
.skip-link:focus { top: 12px; color: var(--white); }

.section-inner {
  position: relative;
  max-width: var(--content-max);
  margin: 0 auto;
  padding: var(--pad-y) var(--pad-x);
}

/* Anchored sections shouldn't land underneath the sticky header. */
section[id], footer[id] { scroll-margin-top: var(--header-h); }

/* ============================================================================
   SHARED PIECES
============================================================================ */

/* The bullseye mark — ONE treatment everywhere: rust ring, ember centre.
   It was inconsistent across the site (solid-rust centres in the wordmarks,
   ember in the glyphs); design unified it.

   Sizing rule from the handoff: ring is 2px at 30px and above, 1.5px below;
   the centre dot is 40% of the diameter. Expressing the dot as a percentage
   rather than a per-size inset is what makes one component cover all four
   placements. Pure CSS, no image. */
.bullseye {
  --bullseye-size: 26px;
  --bullseye-ring: 1.5px;
  position: relative;
  display: block;
  flex-shrink: 0;
  width: var(--bullseye-size);
  height: var(--bullseye-size);
}
.bullseye::before,
.bullseye::after { content: ""; position: absolute; border-radius: 50%; }
.bullseye::before { inset: 0; border: var(--bullseye-ring) solid var(--orange); }
.bullseye::after {
  left: 50%;
  top: 50%;
  width: 40%;
  height: 40%;
  transform: translate(-50%, -50%);
  background: var(--orange-brt);
}


.wordmark-text {
  margin: 0;
  font-family: var(--font-head);
  font-size: clamp(16px, 1.6vw, 20px);
  letter-spacing: -0.01em;
  white-space: nowrap;
  color: var(--white);
}
.wordmark-text strong { font-weight: 700; color: var(--orange-brt); }

/* Every eyebrow, label and caption on the site is this treatment. It is what
   replaced the monospace layer. */
/* 16px, not 22px. An eyebrow is a label on its headline, not a block of its
   own — stacked under a section's top padding, 22px read as a third gap. */
.eyebrow {
  margin: 0 0 16px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}
.eyebrow-deep { color: var(--orange-deep); }
.eyebrow-sand { color: var(--sand); }

.h2 {
  margin: 0;
  font-family: var(--font-head);
  font-weight: 400;
  font-size: var(--t-h2);
  line-height: 1.12;
  letter-spacing: -0.02em;
}
.h2 strong { font-weight: 600; color: var(--orange); }

.arrow-out { font-size: 11px; opacity: 0.75; }
.arrow-down { font-size: 13px; opacity: 0.85; }

/* Decorative rings that bleed past their section (each section clips them). */
.deco-circle {
  position: absolute;
  display: block;
  border-radius: 50%;
  pointer-events: none;
}

/* The COPY button — same component in the header, hero, and footer. */
.btn-copy {
  background: none;
  border: 1px solid rgba(255, 255, 255, 0.35);
  color: var(--sand);
  font-family: var(--font-body);
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 9px 14px;
  cursor: pointer;
  transition: border-color var(--ease), color var(--ease);
}
.btn-copy:hover { border-color: var(--orange-brt); color: var(--orange-brt); }
.btn-copy-sm { padding: 6px 12px; }

/* ============================================================================
   HEADER
============================================================================ */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(27, 35, 64, 0.94);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid rgba(200, 90, 30, 0.55);
}

.nav {
  max-width: var(--content-max);
  margin: 0 auto;
  padding: clamp(14px, 2vw, 20px) var(--pad-x);
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: clamp(12px, 2vw, 32px);
}

.wordmark {
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--white);
}
.wordmark:hover { color: var(--white); }

/* nowrap, deliberately. With wrap, the destination list split mid-group and
   left a pipe orphaned, and Get in touch dropped onto a second line beside
   Writing where it read as a fifth destination. Below 900px the group is
   replaced wholesale rather than allowed to wrap. */
.nav-links {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  gap: clamp(14px, 2.2vw, 30px);
  font-size: var(--t-nav);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* 1px hairline between nav items. Each divider that could be orphaned by a
   flag travels inside that flag's fence, so turning a section off never
   leaves two separators side by side. */
.nav-sep {
  display: block;
  width: 1px;
  height: 12px;
  background: rgba(255, 255, 255, 0.3);
  flex-shrink: 0;
}

.nav-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--white);
  padding-bottom: 3px;
  /* Transparent by default so the hover underline causes no layout shift. */
  border-bottom: 1px solid transparent;
  transition: color var(--ease), border-color var(--ease);
}
.nav-link:hover { color: var(--orange-brt); border-bottom-color: var(--orange); }

.contact-wrap { position: relative; }

/* Get in touch is ONE control. Padding is the only thing that varies between
   the header and the hero — everything else here is shared. It had drifted
   into three different treatments across the site. */
.btn-touch {
  padding: 9px 20px;
  background: none;
  border: 1px solid var(--orange);
  color: var(--orange-brt);
  font-family: var(--font-body);
  font-size: var(--t-nav);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background var(--ease), color var(--ease), border-color var(--ease);
}
.btn-touch:hover {
  background: var(--orange-deep);
  border-color: var(--orange-deep);
  color: var(--white);
}
.btn-touch-lg { padding: 15px 30px; font-size: 15px; }

/* Edge-aligned to its button: right in the nav, left in the hero row. */
.contact-panel {
  position: absolute;
  right: 0;
  top: 100%;
  z-index: 60;
  padding-top: 16px;   /* the gap between the header and the card */
  opacity: 0;
  transform: translateY(-6px);
  pointer-events: none;
  /* visibility (not opacity alone) is what keeps the closed panel's links out
     of the keyboard tab order; it flips after the fade-out finishes. */
  visibility: hidden;
  transition: opacity var(--ease), transform var(--ease), visibility 0s linear 160ms;
}
.contact-panel.is-open {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
  visibility: visible;
  transition: opacity var(--ease), transform var(--ease), visibility 0s;
}

.contact-panel-left { right: auto; left: 0; }

.contact-card {
  min-width: 290px;
  background: var(--navy-deep);
  border: 1px solid rgba(200, 90, 30, 0.6);
  padding: 22px 24px;
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.45);
}

.panel-label {
  margin: 0 0 6px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--orange-brt);
}

.panel-phone,
.panel-email {
  display: block;
  color: var(--white);
  letter-spacing: 0.01em;
  text-transform: none;
  transition: color var(--ease);
}
.panel-phone { margin-bottom: 20px; font-size: 17px; }
.panel-email { margin-bottom: 14px; font-size: 16px; word-break: break-all; }
.panel-phone:hover,
.panel-email:hover { color: var(--orange-brt); }

.panel-actions { display: flex; gap: 10px; }

.btn-send {
  flex: 1;
  text-align: center;
  background: var(--orange-deep);
  border: 1px solid var(--orange-deep);
  color: var(--white);
  padding: 9px 14px;
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  transition: background var(--ease), border-color var(--ease);
}
.btn-send:hover {
  background: var(--orange-deep-hover);
  border-color: var(--orange-deep-hover);
  color: var(--white);
}
.panel-actions .btn-copy { flex: 1; }

/* ============================================================================
   HERO
============================================================================ */

/* No overflow:hidden here. The hero hosts a dropdown now, and clipping the
   section cut the contact panel in half — a live bug. The rings are clipped
   at their own container instead; see .portrait. */
.hero {
  position: relative;
  background: var(--navy);
}
/* The bottom padding is deliberately tight — it lets the "right place" band
   below sit close against the hero. Don't open it back up. */
.hero-inner { padding: clamp(44px, 5vw, 68px) var(--pad-x) clamp(28px, 3.5vw, 48px); }

/* ---- Background line art -------------------------------------------------
   The same two quote files that flank the Right Place band below, reused as a
   field behind the hero. They draw in Ink and Ink is this ground, so they are
   inverted to white — which also flattens the rust nodes baked into the
   artwork, and is why one node is drawn back in separately below. If
   light-stroke versions of the files ever arrive, drop the filter AND the
   separate node rather than layering both.

   overflow: hidden is load-bearing: it crops the arcs at the hero's bounds so
   they never close into full circles. */
.hero-art {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  display: block;
  z-index: 0;
}
/* height: auto is load-bearing, not tidy-up. The width/height attributes on
   the tags reserve layout space, but the height attribute is also a used-value
   hint — without this the art renders at its full 1086px natural height and
   the aspect ratio never applies. */
.hero-art img {
  position: absolute;
  display: block;
  height: auto;
  opacity: 0.26;
  filter: brightness(0) invert(1);
}
.hero-art img:first-of-type {
  left: -4%;
  top: 0;
  width: clamp(300px, 34vw, 480px);
}
.hero-art img:last-of-type {
  right: -4%;
  bottom: 2%;
  width: clamp(280px, 31vw, 440px);
}

/* One connector, and it exits left. See the note in index.html before adding
   a second: no line art terminates inside a text column. */
.hero-connector {
  position: absolute;
  left: 0;
  top: 53%;
  width: clamp(72px, 10vw, 150px);
  height: 1px;
  background: rgba(255, 255, 255, 0.26);
  display: block;
}
/* The one rust in the layer, drawn rather than inherited — the white filter
   above flattens the nodes that are in the artwork itself. */
.hero-node {
  position: absolute;
  left: 1px;
  top: 53%;
  margin-top: -4px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  border: 1.5px solid var(--orange);
  display: block;
}

/* A wrapping flex row rather than equal auto-fit tracks: the text column needs
   more than half the width for the headline to hold its three lines.

   Both this and the credentials strip below must sit above the art layer, or
   it renders over the portrait and the copy.

   This row is 2 and the credentials strip is 1, and the ORDER MATTERS. The
   row hosts the hero's Get in touch panel, and giving the row a z-index makes
   it a stacking context — which traps that panel's own z-index inside it. At
   equal z-index the later sibling wins, so with both at 1 the credentials
   strip painted straight through the open panel, over the phone number.
   Anything added below this row has to stay under it. */
.hero-row {
  position: relative;
  z-index: 2;
  display: flex;
  flex-wrap: wrap;
  gap: clamp(32px, 4vw, 64px);
  align-items: center;
}

/* --- Portrait bullseye: the wordmark motif, scaled up ---------------------- */
/* Trims the left edge only and leaves top, right and bottom unbounded, so the
   rings still bleed off-canvas as designed while the section stays unclipped
   for the dropdown above. Any section that gains a dropdown hits this — check
   for overflow: hidden on the section first. */
.portrait {
  clip-path: inset(-100vh -100vw -100vh 0);
  position: relative;
  flex: 0 1 340px;
  width: 100%;
  max-width: min(340px, 46vw);
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}
.portrait .ring {
  position: absolute;
  display: block;
  border-radius: 50%;
  pointer-events: none;
}
.ring-1 { width: 260%; height: 260%; border: 1px solid rgba(255, 255, 255, 0.07); }
.ring-2 { width: 172%; height: 172%; border: 1px solid rgba(255, 255, 255, 0.10); }
.ring-3 { width: 128%; height: 128%; border: 1px solid rgba(200, 90, 30, 0.32); }
.ring-4 { inset: 0; border: 2px solid var(--orange); }

.portrait-photo {
  position: absolute;
  inset: 10px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--photo-well);
}
.portrait-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 22%;
}

/* --- Hero text ------------------------------------------------------------ */
.hero-text {
  position: relative;
  z-index: 2;
  flex: 1 1 460px;
  min-width: 0;
}

/* Three voices on one line: rust rule, the signature, a divider, the role.
   Nothing here is uppercase or tracked — that is deliberate, and it is what
   separates this line from every other small-text element on the site. */
.identity {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px 16px;
  margin-bottom: clamp(18px, 2vw, 26px);
}
.identity-rule {
  display: block;
  width: clamp(20px, 3vw, 44px);
  height: 2px;
  background: var(--orange);
  flex-shrink: 0;
}
/* Satisfy, and only here. Never uppercase, never tracked, never below 24px —
   the brush strokes close up under all three. */
.signature {
  margin: 0;
  font-family: var(--font-script);
  font-size: clamp(24px, 2.4vw, 28px);
  line-height: 1.1;
  padding-bottom: 2px;
  color: var(--white);
}
.identity-divider {
  display: block;
  width: 1px;
  height: 20px;
  background: rgba(255, 255, 255, 0.32);
  flex-shrink: 0;
}
/* The one italic on the site. */
.hero-role {
  margin: 0;
  font-family: var(--font-head);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(15px, 1.4vw, 18px);
  letter-spacing: 0.01em;
  color: var(--sand);
}

/* Ships hidden: its "Why?" link points at #why-mandy on a Viewpoint page that
   doesn't exist yet. Kept in the markup so restoring it is one line — remove
   the hidden attribute in index.html. */
.hero-aside {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 10px;
  margin-top: 8px;
  padding-left: calc(clamp(20px, 3vw, 44px) + 16px);
  font-size: clamp(14px, 1.2vw, 15.5px);
  color: var(--off-white);
}
.hero-aside[hidden] { display: none; }
.hero-aside strong { font-weight: 600; color: var(--orange-brt); }
.hero-aside a {
  color: var(--orange-brt);
  border-bottom: 1px solid rgba(240, 135, 60, 0.5);
  padding-bottom: 1px;
  transition: color var(--ease), border-color var(--ease);
}
.hero-aside a:hover { color: var(--white); border-bottom-color: var(--white); }

/* The three <br> breaks carry the beats. `text-wrap: nowrap` used to hold them
   absolutely, but on a clamped headline it forces horizontal overflow at narrow
   widths, so it's gone: the authored breaks hold where they fit and give way
   where they can't. The floor is 20px for the same reason.

   The headline is the argument on this page. It should be what fits first. */
.hero-title {
  margin: 0 0 clamp(24px, 3vw, 34px);
  font-weight: 400;
  font-size: clamp(20px, 3.2vw, 44px);
  line-height: 1.16;
  letter-spacing: -0.02em;
}
/* White, not ember. The type-system handoff annotates "On purpose." as
   #F0873C, but it labels that block "unchanged, for reference" while the
   Aug 24 package it refers back to says "All white, no accent color." Design
   confirmed white. Weight 600 is kept — only the colour was wrong. */
.hero-title strong { font-weight: 600; color: var(--white); }

.hero-body {
  display: flex;
  flex-direction: column;
  gap: clamp(14px, 1.5vw, 20px);
  margin: 0 0 clamp(28px, 3vw, 38px);
  max-width: 640px;
}
.hero-body p {
  margin: 0;
  font-size: var(--t-body-lg);
  line-height: 1.7;
  color: var(--off-white);
  text-wrap: pretty;
}

.cta-row {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}

.btn-primary,
.btn-secondary {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 15px 30px;
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
}
/* Rust deep, not rust: this fill carries a label. */
.btn-primary {
  background: var(--orange-deep);
  border: 1px solid var(--orange-deep);
  color: var(--white);
  transition: background var(--ease), border-color var(--ease);
}
.btn-primary:hover {
  background: var(--orange-deep-hover);
  border-color: var(--orange-deep-hover);
  color: var(--white);
}
/* Ghost until hover, then it fills — and a fill carrying a label is rust deep. */
.btn-secondary {
  background: none;
  border: 1px solid var(--orange);
  color: var(--orange-brt);
  transition: background var(--ease), border-color var(--ease), color var(--ease);
}
.btn-secondary:hover {
  background: var(--orange-deep);
  border-color: var(--orange-deep);
  color: var(--white);
}

.credentials {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: clamp(14px, 2vw, 28px);
  margin-top: clamp(40px, 4.6vw, 60px);
}
.credentials::before,
.credentials::after {
  content: "";
  flex: 1 0 48px;
  height: 1px;
  background: rgba(255, 255, 255, 0.28);
}
.credentials p {
  flex: 0 1 auto;
  margin: 0;
  text-align: center;
  font-size: clamp(11px, 1vw, 11.5px);
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--sand);
  text-wrap: balance;
}

/* ============================================================================
   "THE RIGHT PLACE FOR ME" BAND
   A shallow Linen strip between the hero and the tenets: the bullseye glyph
   and one sentence, centred as a pair.

   The near-zero vertical padding is intentional and was iterated on — the band
   is meant to read as one line of thought continuing out of the hero, not as a
   section of its own. Resist adding breathing room.
============================================================================ */

.fit-band {
  background: var(--linen);
  color: var(--navy);
}

/* Wider than the site's usual measure, and barely padded, because the SPACING
   LIVES IN THE FILES. Each mark is ~98% transparent margin, and that margin
   is what holds it off the copy — hence gap: 0. Adding a flex gap, or
   cropping the transparent area to "tighten" the asset, pushes the marks away
   from the copy and breaks the composition. */
.fit-band-inner {
  max-width: 1320px;
  margin: 0 auto;
  padding: clamp(8px, 1vw, 16px) clamp(8px, 1.5vw, 24px);
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 0;
}

/* The two files are composed differently on purpose — the opening mark sits
   centred in its frame, the closing one low and inboard. That asymmetry is
   the design; don't normalise them. And don't rebuild these in SVG: a
   hand-drawn geometric version was tried and rejected, because outlined marks
   stopped reading as quotation marks. */
.quote-mark {
  display: block;
  flex-shrink: 0;
  width: clamp(200px, 22vw, 320px);
  height: auto;
}

.fit-copy {
  margin: 0;
  flex: 0 1 auto;
  max-width: 52ch;
  font-size: clamp(17px, 1.7vw, 23px);
  line-height: 1.55;
  color: var(--ink);
  text-wrap: pretty;
}
/* Weight only, colour inherited. The closing sentence was briefly rust at 600
   and that was reverted — there is no accent anywhere in this paragraph now. */
.fit-copy strong { font-weight: 700; }

/* ============================================================================
   THE JOB AS I DO IT
============================================================================ */

/* `overflow: hidden` is load-bearing here, not tidiness. The bands bleed with
   `calc(50% - 50vw)`, and 50vw counts the scrollbar while 50% does not — so
   each band overshoots the viewport by half the scrollbar width. This absorbs
   it. Remove it and you get a horizontal scrollbar on the whole page. */
.how {
  position: relative;
  overflow: hidden;
  background: var(--white);
  color: var(--navy);
}
.how .section-inner { padding: var(--pad-y) var(--pad-x) clamp(42px, 4.6vw, 60px); }

.deco-how {
  width: 640px; height: 640px;
  border: 1px solid rgba(27, 35, 64, 0.07);
  left: -280px; top: 80px;
}

.intro-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  gap: clamp(24px, 3.5vw, 80px);
  align-items: end;
}

.lede {
  margin: 0;
  font-size: clamp(15.5px, 1.35vw, 18px);
  line-height: 1.66;
  color: var(--ink);
}

/* The two lines of the heading are block-level children, so the break holds
   without a <br> and can't be undone by a copy edit. Scoped to direct
   children: the accent starts mid-line one and runs to the end of line two,
   so the <strong> inside the first line has to stay inline. */
.how-heading > span,
.how-heading > strong { display: block; }

/* --- The four tenet bands ---------------------------------------------------
   One hairline only, here on the container, above band 1. From there down the
   tint edges do the separating. A rule sitting on top of a colour change is
   two separators doing one job. No row gap: the stripes have to touch. */
.tenets {
  display: flex;
  flex-direction: column;
  margin-top: clamp(40px, 4.5vw, 56px);
  border-top: 1px solid rgba(27, 35, 64, 0.22);
}

/* The bleed is keyed to the viewport, never to the 1240px container: a
   negative margin keyed to the container engages only above 1240px and
   silently does nothing below it. `calc(50vw - 50%)` already spans the
   container's own gutter as well as the bleed, so nothing gets added to it —
   appending the gutter again indents the band by a second helping of it. */
.tenet {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  gap: 20px clamp(32px, 5vw, 72px);
  padding-top: clamp(12px, 1.3vw, 18px);
  padding-bottom: clamp(12px, 1.3vw, 18px);
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  padding-left: calc(50vw - 50%);
  padding-right: calc(50vw - 50%);
}

/* The side flips with the ground, so the two alternations read as one pattern
   instead of two. Linen is the same #F6F2EA the Right Place band uses. */
.tenet:nth-child(even) {
  flex-direction: row-reverse;
  background: var(--linen);
}

/* This flex is the one setting that satisfies two opposing failures, both of
   which were live bugs in design:

   • Let the block GROW (flex: 1 1 380px) and it fills the track, pinning the
     figure to the far edge — ~300px of dead air between the art and the copy
     it belongs to, worst on the reversed bands.
   • Put the 62ch cap on the FLEX CHILD instead of the paragraph and the pair
     stays tight, but the leftover width parks at the main-axis end — which on
     a row-reverse band is the section's flush left edge. The copy then sits
     inboard of the figures above it and the left margin jitters down the page.

   Not growing keeps the figure one gap from its copy, and the cap on the
   paragraph drops the leftover on the inner side of the band. */
.tenet-text { flex: 0 1 min(62ch, 100%); }

.tenet-text h3 {
  margin: 0 0 12px;
  font-family: var(--font-head);
  font-weight: 500;
  font-size: var(--t-h3);
  line-height: 1.2;
  letter-spacing: -0.01em;
  text-wrap: balance;
}
.tenet-text p {
  margin: 0;
  max-width: 62ch;
  font-size: var(--t-body);
  line-height: 1.62;
  color: var(--ink);
  text-wrap: pretty;
}

/* The wrapper crops; the image does not. The art fills its square, so the
   204px cap is a vertical-rhythm control as much as a scale one — much wider
   and the figure is taller than its three lines of copy and sets the band
   height by itself.

   The 1/0.902 frame with -4.2% takes 4.2% off the top and 5.6% off the
   bottom. Measured ink starts 4.23-6.06% down and ends 5.50-6.46% up across
   the four files, so it clears the ink. Do not crop further: a deeper crop
   slices the terminal circles on the leader dots, which reads as a rendering
   fault rather than a crop. */
.tenet-fig {
  flex: 0 0 auto;
  display: block;
  width: clamp(150px, 18vw, 204px);
  aspect-ratio: 1 / 0.902;
  overflow: hidden;
}
.tenet-fig img {
  display: block;
  width: 100%;
  height: auto;
  margin-top: -4.2%;
}

/* --- My Work philosophy cards ----------------------------------------------
   All four rules below now serve one page: the flagged-off My Work page,
   whose three philosophy cards still use this grid and this mark. The home
   page carried them until the tenets became bands; nothing else references
   them. They go when My Work does. */
.tick {
  display: block;
  width: 34px;
  height: 3px;
  background: var(--orange);
  margin-bottom: 16px;
}
.principles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
  gap: clamp(24px, 3vw, 40px);
  margin-top: clamp(36px, 4vw, 48px);
}
.principle {
  padding-top: 22px;
  border-top: 1px solid rgba(27, 35, 64, 0.22);
}
.principle h3 {
  margin: 0 0 12px;
  font-weight: 700;
  font-size: var(--t-h3);
  line-height: 1.2;
  letter-spacing: -0.01em;
}
.principle p {
  margin: 0;
  font-size: var(--t-body);
  line-height: 1.62;
  color: var(--ink);
}

/* ============================================================================
   FOOTER
============================================================================ */

.site-footer {
  background: var(--footer);
  color: var(--white);
  border-top: 2px solid var(--orange);
}
.footer-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  gap: clamp(36px, 4vw, 48px);
  align-items: start;
  padding: clamp(40px, 4vw, 52px) var(--pad-x) clamp(38px, 4vw, 48px);
}

.footer-name {
  margin: 0 0 12px;
  font-weight: 400;
  font-size: clamp(25px, 2.7vw, 32px);
  letter-spacing: -0.01em;
}
/* The hero's credentials string, set as a caption rather than a claim: plain
   wrapping copy here, tracked caps between hairlines up there. One string —
   see CONTENT in build.mjs. */
.footer-credentials {
  margin: 0 0 20px;
  max-width: 34ch;
  font-size: 15.5px;
  line-height: 1.5;
  color: var(--sand);
}
.footer-lockup { display: flex; align-items: center; gap: 12px; }
.footer-lockup .wordmark-text { font-size: clamp(17px, 1.7vw, 21px); }

.footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: 28px 36px;
  align-items: flex-start;
}

.writing-card {
  flex: 1 1 230px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 24px 22px 26px;
  border: 1px solid rgba(200, 90, 30, 0.55);
  background: rgba(200, 90, 30, 0.09);
  color: var(--white);
  transition: background var(--ease);
}
.writing-card:hover { background: rgba(200, 90, 30, 0.18); color: var(--white); }
.writing-head { display: flex; align-items: center; gap: 12px; }
.writing-head svg { flex-shrink: 0; }
.writing-label {
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.writing-label .arrow-out { opacity: 0.8; }
.writing-body {
  display: block;
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--sand);
}

.link-list {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding-top: 4px;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.link-list > a,
.link-row > a {
  color: var(--white);
  transition: color var(--ease);
}
.link-list > a:hover,
.link-row > a:hover { color: var(--orange-brt); }
.link-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.link-resume { display: inline-flex; align-items: center; gap: 8px; }
.link-resume .arrow-down { font-size: 12px; opacity: 0.8; }

/* ============================================================================
   MOTION PREFERENCES
   Anyone who has asked their system to reduce motion gets no smooth scroll
   and no transitions — the panels still open, they just snap.
============================================================================ */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ============================================================================
   PRINT — the page is a link people may print or "save as PDF".
============================================================================ */

@media print {
  .site-header, .skip-link, .contact-panel, .btn-copy { display: none !important; }
  body { background: #fff; color: #000; }
  .hero, .interior-open, .artifacts, .site-footer { background: #fff; color: #000; }
}

/* ============================================================================
   MY WORK PAGE
   Flagged off in production until the copy lands. Grounds alternate navy →
   white → navy, same rule as the homepage.
============================================================================ */

.nav-link.is-current {
  color: var(--orange-brt);
  border-bottom-color: var(--orange);
}

.work-hero {
  position: relative;
  overflow: hidden;
  background: var(--navy);
}
.deco-work-hero {
  width: 720px; height: 720px;
  border: 1px solid rgba(255, 255, 255, 0.06);
  right: -300px; top: -220px;
}
.work-title {
  max-width: 900px;
  margin: 0 0 clamp(20px, 2.4vw, 30px);
  font-size: clamp(30px, 4.6vw, 58px);
  line-height: 1.12;
  letter-spacing: -0.02em;
}
.work-title strong { font-weight: 700; color: var(--orange-brt); }

.work-intro {
  max-width: 640px;
  margin: 0;
  font-size: var(--t-body-lg);
  line-height: 1.7;
  color: var(--off-white);
}

.philosophy {
  position: relative;
  overflow: hidden;
  background: var(--white);
  color: var(--navy);
}

.cases {
  position: relative;
  overflow: hidden;
  background: var(--navy);
  color: var(--white);
}

/* --- Tabs ------------------------------------------------------------------ */
.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(10px, 1.4vw, 18px);
  margin-bottom: clamp(28px, 3.4vw, 44px);
}
.tab {
  padding: 14px 22px;
  background: none;
  border: 1px solid rgba(255, 255, 255, 0.25);
  color: rgba(255, 255, 255, 0.62);
  font-family: var(--font-body);
  font-size: clamp(13px, 1.2vw, 15px);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  transition: color var(--ease), border-color var(--ease), background var(--ease);
}
.tab:hover { color: var(--white); border-color: rgba(255, 255, 255, 0.5); }
.tab[aria-selected="true"] {
  background: rgba(200, 90, 30, 0.16);
  border-color: var(--orange);
  color: var(--orange-brt);
  font-weight: 700;
}

.case-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 290px), 1fr));
  gap: clamp(26px, 3.5vw, 64px);
  align-items: start;
}
.case-heading { margin-bottom: 20px; }
.case-narrative p {
  margin: 0 0 16px;
  font-size: var(--t-body-lg);
  line-height: 1.7;
  color: var(--off-white);
  text-wrap: pretty;
}
.case-narrative p:last-child { margin-bottom: 0; }

.case-meta {
  display: flex;
  flex-direction: column;
  gap: 26px;
  padding-top: 6px;
}
.meta-label {
  margin: 0 0 8px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--orange-brt);
}
.meta-value { margin: 0; font-size: 16.5px; line-height: 1.55; color: var(--white); }
.meta-rule { display: block; height: 1px; background: rgba(255, 255, 255, 0.18); }

/* ============================================================================
   DIAGRAMS
   Everything here is namespaced .dg- . Gold is the through-line and is only
   allowed inside these rules — a test enforces that, because gold as page type
   is explicitly out.

   Colour is never the only signal: the three arrival series differ by stroke
   weight and dash as well as hue.
============================================================================ */

.dg {
  position: relative;
  overflow: hidden;
  margin: clamp(30px, 4vw, 52px) 0 0;
  padding: clamp(24px, 3.2vw, 44px);
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.02);
}
.dg-deco { position: absolute; border-radius: 50%; pointer-events: none; }
.dg-deco-a {
  width: 640px; height: 640px;
  border: 1px solid rgba(255, 255, 255, 0.05);
  left: -300px; bottom: -320px;
}
.dg-deco-b {
  width: 520px; height: 520px;
  border: 1px solid rgba(255, 255, 255, 0.06);
  right: -260px; top: -240px;
}

.dg-caption {
  margin-top: clamp(20px, 2.4vw, 30px);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--sand);
}

.dg-gold { color: var(--gold); }

/* --- Diagram 1: arrivals → convergence → structure ------------------------- */
.dg-arrivals {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  gap: clamp(20px, 2.6vw, 36px);
}
.dg-arrival { flex: 1 1 200px; }
.dg-bar { display: block; margin-bottom: 14px; transform-origin: left center; }
.dg-bar-gold   { height: 4px; background: var(--gold); }
.dg-bar-solid  { height: 3px; background: var(--white); }
.dg-bar-dashed {
  height: 3px;
  background: repeating-linear-gradient(90deg, #FFFFFF 0 11px, transparent 11px 20px);
}
.dg-arrival-label {
  margin: 0 0 6px;
  font-size: clamp(15px, 1.4vw, 17px);
  font-weight: 700;
  color: var(--white);
}
.dg-arrival-body {
  margin: 0;
  font-size: clamp(14px, 1.25vw, 15.5px);
  line-height: 1.55;
  color: var(--off-white);
}

.dg-converge {
  position: relative;
  display: block;
  width: 100%;
  height: clamp(64px, 8vw, 104px);
}

.dg-structure {
  position: relative;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 190px), 1fr));
  border: 1px solid rgba(255, 255, 255, 0.5);
  background: rgba(255, 255, 255, 0.04);
}
.dg-cell {
  padding: clamp(18px, 2vw, 26px);
  border-right: 1px solid rgba(255, 255, 255, 0.22);
}
.dg-cell:last-child { border-right: 0; }
.dg-num {
  margin: 0 0 10px;
  font-family: var(--font-head);
  font-weight: 400;
  font-size: 21px;
  color: var(--gold);
}
.dg-cell-title {
  margin: 0 0 8px;
  font-size: clamp(17px, 1.6vw, 21px);
  font-weight: 700;
  color: var(--white);
}
.dg-cell-body {
  margin: 0;
  font-size: clamp(14px, 1.25vw, 15.5px);
  line-height: 1.55;
  color: var(--off-white);
}

.dg-closing {
  position: relative;
  max-width: 44ch;
  margin: clamp(22px, 2.6vw, 34px) 0 0;
  font-size: clamp(17px, 1.75vw, 23px);
  font-weight: 500;
  line-height: 1.4;
  color: var(--white);
}

/* --- Diagram 1 motion ------------------------------------------------------
   Plays once, on arrival.

   The starting (hidden) state is scoped to .js, which an inline script in the
   page head sets before first paint. Without JavaScript none of these rules
   apply and the diagram simply renders finished — rather than sitting at
   opacity 0 forever waiting for a script that never ran. */
.js .dg-arrival { opacity: 0; transform: translate(-26px, -10px); }
.js .dg-bar { transform: scaleX(0); }
.js .dg-curve { stroke-dasharray: 420; stroke-dashoffset: 420; }
.js .dg-curve-dashed { opacity: 0; }
.js .dg-cell { opacity: 0; transform: translateY(14px); }
.js .dg-closing { opacity: 0; }

.dg.is-played .dg-arrival {
  opacity: 1;
  transform: translate(0, 0);
  transition: opacity 380ms ease, transform 380ms ease;
}
.dg.is-played .dg-arrival:nth-child(2) { transition-delay: 150ms; }
.dg.is-played .dg-arrival:nth-child(3) { transition-delay: 300ms; }

.dg.is-played .dg-bar {
  transform: scaleX(1);
  transition: transform 420ms ease;
}
.dg.is-played .dg-arrival:nth-child(2) .dg-bar { transition-delay: 150ms; }
.dg.is-played .dg-arrival:nth-child(3) .dg-bar { transition-delay: 300ms; }

/* The 400ms hold between the bars landing and the curves starting is
   deliberate: it gives the viewer time to read the three arrivals before they
   resolve into one. */
.dg.is-played .dg-curve {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 700ms cubic-bezier(0.16, 0.8, 0.3, 1) 1120ms;
}
.dg.is-played .dg-curve-dashed {
  opacity: 1;
  transition: opacity 700ms ease 1120ms, stroke-dashoffset 700ms cubic-bezier(0.16, 0.8, 0.3, 1) 1120ms;
}

.dg.is-played .dg-cell {
  opacity: 1;
  transform: translateY(0);
  transition: opacity 340ms ease 1780ms, transform 340ms ease 1780ms;
}
.dg.is-played .dg-cell:nth-child(2) { transition-delay: 1930ms; }
.dg.is-played .dg-cell:nth-child(3) { transition-delay: 2080ms; }

.dg.is-played .dg-closing { opacity: 1; transition: opacity 520ms ease 2460ms; }

/* --- Diagram 2: the tradeoff (static) -------------------------------------- */
.dg-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 14px 32px;
  margin-bottom: clamp(18px, 2.2vw, 28px);
}
.dg-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  font-size: clamp(14px, 1.25vw, 15.5px);
  color: var(--off-white);
}
.dg-legend-strong { font-weight: 700; }
.dg-swatch { display: block; width: 34px; flex-shrink: 0; }
.dg-swatch-white { height: 2px; background: var(--white); }
.dg-swatch-gold { height: 5px; background: var(--gold); }

.dg-plot { position: relative; height: clamp(300px, 36vw, 420px); }
.dg-plot svg { position: absolute; inset: 0; width: 100%; height: 100%; }

.dg-axis,
.dg-xlabel,
.dg-note { position: absolute; margin: 0; }

.dg-axis {
  font-size: clamp(11px, 1vw, 12.5px);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sand);
}
.dg-axis-y { left: 0; top: 0; }
.dg-axis-x { right: 0; bottom: 0; }

.dg-xlabel {
  top: 87%;
  transform: translateX(-50%);
  font-size: clamp(11px, 1vw, 12.5px);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sand);
}

.dg-note {
  max-width: 22ch;
  font-size: clamp(13px, 1.15vw, 15.5px);
  line-height: 1.4;
  color: var(--white);
}
.dg-note-strong { font-weight: 700; }
.dg-note-mid { font-weight: 500; }

.dg-footnote {
  max-width: 70ch;
  margin: clamp(22px, 2.6vw, 32px) 0 0;
  padding-left: clamp(14px, 1.6vw, 20px);
  border-left: 3px solid var(--gold);
  font-size: clamp(15px, 1.3vw, 16.5px);
  line-height: 1.6;
  color: var(--off-white);
}

/* Reduced motion, and the no-JS case: render the diagram complete and static.
   Nothing is ever left at opacity 0 waiting for a script that didn't run. */
@media (prefers-reduced-motion: reduce) {
  .dg-arrival, .dg-cell, .dg-closing, .dg-curve-dashed { opacity: 1 !important; transform: none !important; }
  .dg-bar { transform: scaleX(1) !important; }
  .dg-curve { stroke-dashoffset: 0 !important; }
  .dg *, .dg *::before, .dg *::after { transition: none !important; }
}

/* ============================================================================
   NAV DROPDOWN
   Click only, never hover. Hover-to-open has no touch equivalent, so it was
   never a working affordance on a phone — the standing rule now is that every
   interactive treatment works there.
============================================================================ */

.nav-dropdown {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

/* One control, not two. The 44px minimum lives on the trigger itself, and the
   negative margin absorbs it so the box doesn't push the header taller — that
   was a live bug, and it stays load-bearing here. Inherits the nav's type
   rather than restating it. */
.nav-trigger {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 44px;
  padding: 11px 0;
  margin: -11px 0;
  background: none;
  border: none;
  border-bottom: 1px solid transparent;
  color: var(--white);
  font-family: inherit;
  font-size: inherit;
  font-weight: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  cursor: pointer;
  transition: color var(--ease), border-color var(--ease);
}
.nav-trigger:hover { color: var(--orange-brt); }
.nav-trigger[aria-expanded="true"],
.nav-trigger.is-current {
  color: var(--orange-brt);
  border-bottom-color: var(--orange);
}

.nav-caret-glyph {
  font-size: 9px;
  line-height: 1;
  transition: transform var(--ease);
}
.nav-trigger[aria-expanded="true"] .nav-caret-glyph { transform: rotate(180deg); }

/* Left-aligned to the trigger. The Get in touch panel in the same header is
   right-aligned — each panel edge-aligns to its own button, and My Work sits
   mid-row rather than at the end. */
.nav-panel {
  position: absolute;
  left: 0;
  top: 100%;
  z-index: 60;
  margin-top: 14px;
  min-width: 250px;   /* fits the Coming soon marker */
  padding: 8px 22px;
  background: var(--navy-deep);
  border: 1px solid rgba(200, 90, 30, 0.6);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  pointer-events: none;
  transition: opacity var(--ease), transform var(--ease), visibility 0s linear 160ms;
}
.nav-panel.is-open {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  pointer-events: auto;
  transition: opacity var(--ease), transform var(--ease), visibility 0s;
}

/* 44px rows, flush against each other, separated by a hairline rather than a
   gap — the gap-separated version failed the touch minimum. */
.nav-panel a {
  display: flex;
  align-items: center;
  height: 44px;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  color: var(--white);
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
  transition: color var(--ease);
}
.nav-panel a:last-child { border-bottom: 0; }
.nav-panel a:hover { color: var(--orange-brt); }
/* A page under My Work marks the group's trigger AND its own child — never
   one without the other, or the same page disagrees with itself depending on
   whether the menu is open. */
.nav-panel a[aria-current="page"] { color: var(--orange-brt); }

/* A destination that doesn't exist yet: listed, unlinked, marked. Nothing in
   the row is clickable. */
.nav-soon {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  height: 44px;
  margin: 0;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  color: #8E95A8;              /* 5.98:1 on Ink — measured */
}
.nav-soon-tag {
  flex-shrink: 0;
  padding: 4px 8px;
  border: 1px solid rgba(255, 255, 255, 0.28);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

/* ============================================================================
   INTERIOR PAGES
   The pattern Writing will inherit. No hero and no hero layout: interior
   pages open at the breadcrumb, then eyebrow-with-rule, then h1, with the
   intro STACKED beneath rather than beside it. The home page's
   headline-beside-paragraph pairing is a home-page device — reusing it makes
   an interior page read as a second home page.

   Grounds go white, navy, white. The opening is white so the sticky navy
   header reads as chrome rather than as a hero.
============================================================================ */

.interior-open {
  position: relative;
  overflow: hidden;
  background: var(--white);
  color: var(--navy);
}

/* Lighter on top than the site's standard section, heavier underneath. The
   breadcrumb's Home link is already a 44px-tall box, so it supplies its own
   air above; the extra below separates the opening from the navy band it
   hands off to. */
.interior-open .section-inner {
  padding: clamp(28px, 3.4vw, 42px) var(--pad-x) clamp(38px, 4vw, 54px);
}

/* Home / current. Not a back arrow — where you are matters more than how to
   leave. */
.crumbs {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin: 0 0 clamp(26px, 3.2vw, 42px);
  padding: 0;
  list-style: none;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.crumbs a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--orange-deep);
  transition: color var(--ease);
}
.crumbs a:hover { color: var(--orange-deep-hover); }
.crumbs span { color: #5A6178; }
.crumb-sep { color: rgba(27, 35, 64, 0.4); }

/* The trail carries the nav's real depth, so a page under My Work reads
   Home / My Work / Product Judgment. The My Work crumb is a plain <span>, not
   a link: My Work is a group rather than a destination, and a crumb that
   looks clickable and isn't would break that in the one place the visitor is
   checking where they are. */

/* Navy ground. Only the Case Studies shell still opens on navy; these values
   retire when it moves to the white opening ground with the rest of its
   design. */
.crumbs-navy a { color: var(--orange-brt); }
.crumbs-navy a:hover { color: var(--white); }
.crumbs-navy span { color: #8E95A8; }        /* 5.15:1 on navy — measured */
.crumbs-navy .crumb-sep { color: rgba(255, 255, 255, 0.4); }

/* Headline and intro share one measure, and it is narrower than the section:
   the opening's right-hand third belongs to the figure.

   The third term is the one that does the work, and it is why the measure is
   capped rather than the art pushed further right. With a flat 720px measure,
   clearance between the last glyph and the figure's first ink measured 5.9px
   at 924px on AI + Me — and pushing the art out does not converge, because
   the image is height-driven: a longer opening makes the section taller,
   which makes the image wider inside the same fixed-width box, which drives
   its ink further left again. Cap the measure and the clearance stops being
   an accident of how much copy the page happens to carry. Above ~1225px the
   third term stops binding and the 720px cap governs. */
.interior-lede { max-width: min(100%, 720px, calc(62vw - 40px)); }

.interior-title {
  margin: 0 0 clamp(20px, 2.4vw, 30px);
  font-size: clamp(30px, 4.6vw, 58px);
  line-height: 1.1;
  letter-spacing: -0.02em;
}
.interior-title strong { font-weight: 600; color: var(--orange); }

/* One stack, opening on a bold lead-in. Product Judgment carries one
   paragraph and AI + Me three; they are the same size, face and colour either
   way, so the container handles both counts without a variant. */
.interior-intro {
  display: flex;
  flex-direction: column;
  gap: clamp(16px, 1.7vw, 22px);
  max-width: 60ch;
}
.interior-intro p {
  margin: 0;
  font-size: clamp(15.5px, 1.35vw, 18px);
  line-height: 1.66;
  color: var(--ink);
  text-wrap: pretty;
}
.interior-intro strong { font-weight: 600; color: var(--navy); }

/* ============================================================================
   CASE STUDIES
   A case is a numbered sequence of beats. The numbers are what make it read
   as a sequence rather than as four headed paragraphs.

   This is the one place on the site where an eyebrow sits ABOVE a heading
   rather than replacing one: the eyebrow names the beat's function, the h2
   says what happened. There is no case title in the body — the selected tab
   already names it — no heading ornaments, and no lead paragraphs. Every
   paragraph in a case is body copy at one size.
============================================================================ */

/* Deliberately NOT .cases — the retired My Work page already owns that class
   and sets a navy ground and overflow: hidden on it. The overflow was leaking
   onto this section, which must not carry it: same constraint the header
   dropdowns impose. */
.case-studies {
  position: relative;
  background: var(--linen);
  color: var(--navy);
}

/* ---- The folder tabs -----------------------------------------------------
   NOT a control above the case. They are the front edge of the linen section,
   standing on the white ground at the foot of the opening — which is why this
   strip's own ground is white and the selected tab's is linen.

   The join is the whole device:
     · every tab pulls down 1px and sits at z-index 1
     · the selected tab's bottom border is LINEN, not transparent, so it
       paints over the panel's edge and the two become one shape
     · the selected tab is 3px taller, which is what makes an unselected tab
       read as recessed rather than merely unhighlighted

   Not sticky. A sticky version was built and rejected: a tab that detaches
   and floats under the header stops being the section's edge. */
.case-tabstrip { background: var(--white); }

.case-tabs {
  max-width: var(--content-max);
  margin: 0 auto;
  padding: 0 var(--pad-x);
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 6px;
}

.case-tab {
  position: relative;
  z-index: 1;
  margin-bottom: -1px;
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  /* A button centres its text by default. That only shows once a label wraps
     — which the pending tab's does at phone width, where it takes the whole
     row — and a centred label beside a left-aligned one reads as a mistake. */
  text-align: left;
  min-height: 40px;
  padding: 10px clamp(18px, 2vw, 26px);
  font-size: clamp(12.5px, 1.15vw, 14.5px);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #5A6178;
  background: rgba(27, 35, 64, 0.05);
  border: 1px solid rgba(27, 35, 64, 0.12);
  border-bottom-color: rgba(27, 35, 64, 0.16);
  cursor: pointer;
  transition: color 160ms ease, background 160ms ease;
}
.case-tab:hover { color: var(--orange-deep); }

.case-tab[aria-selected="true"] {
  padding-top: 13px;
  padding-bottom: 13px;
  font-weight: 700;
  color: var(--orange-deep);
  background: var(--linen);
  border-color: rgba(27, 35, 64, 0.16);
  border-top: 2px solid var(--orange);
  border-bottom-color: var(--linen);
  cursor: default;
}

/* ---- The case panel ------------------------------------------------------
   Named .case-panel, not .case-body. The home page's flagged case cards owned
   .case-body as a paragraph style and it was setting a font-size and colour on
   this container. Those cards have since been deleted, so the collision is
   gone — but the name stays: .case-panel says what this is, and reviving
   .case-body would only re-create the trap for whatever claims it next. */
/* The whole case is ONE grid, and every beat sits in column 1 so the reading
   edge never moves. Beat spacing is the grid's row gap — do not put margins
   on beats.

   Three things were built and cut here; none of them should come back:
     · a 41/59 paired opener (01 beside 02) — two beats at two measures, and
       the reader re-finds the line length one beat in;
     · float:right on the plate with copy wrapping it — the beat holding the
       plate then runs full width above it and half width beside it, two line
       lengths inside one beat;
     · the plate spanning only the beats it fits beside — it stretches a row
       and opens a gap between beats wide enough to read as a missing section.
   Wrapping copy around the plate isn't achievable at this page width without
   one of those defects. All are worse than the empty column they solve. */
.case-panel {
  display: grid;
  grid-template-columns: 56fr 44fr;
  column-gap: clamp(32px, 4vw, 56px);
  row-gap: clamp(40px, 4.5vw, 60px);
  align-items: start;
}
.case-panel:focus-visible { outline: 2px solid var(--orange); outline-offset: -2px; }
.case-panel[hidden] { display: none; }

.case-panels {
  position: relative;
  max-width: var(--content-max);
  margin: 0 auto;
  padding: clamp(30px, 3.2vw, 40px) var(--pad-x) clamp(40px, 3.6vw, 50px);
}

/* No max-width on a beat — the column sets the measure, which lands around
   55–70ch depending on viewport. */
.beat { grid-column: 1; }

.beat-eyebrow {
  margin: 0 0 10px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--orange-deep);
}
.beat h2 {
  margin: 0 0 16px;
  font-family: var(--font-head);
  font-weight: 400;
  font-size: clamp(23px, 2.4vw, 30px);
  line-height: 1.16;
  letter-spacing: -0.015em;
  color: var(--navy);
}
/* :not() rather than a bare `.beat p`, because the eyebrow is a <p> too and a
   blanket rule outguns it: `.beat p` is (0,1,1) against `.beat-eyebrow`'s
   (0,1,0), so the eyebrow silently rendered at body size in Slate with no gap
   beneath it. Exactly the collision `.pair-row > div p` exists to avoid over
   on Product Judgment — a class name in the selector keeps the two rules from
   ever addressing the same element. */
.beat p:not(.beat-eyebrow) {
  font-size: clamp(15px, 1.2vw, 16px);
  line-height: 1.62;
  color: var(--ink);
  text-wrap: pretty;
}

/* RHYTHM is kept separate from typography, and every labelled paragraph is
   excluded from the default. The two got tangled once already: `.beat-p` set
   its own 22px gaps and never won, because `.beat p:not(...) + p` is (0,2,2)
   against `.beat-p + .beat-p` at (0,2,0), so beat 03 ran at a flat 18px.
   Add any new labelled paragraph class to BOTH :not() lists. */
.beat p:not(.beat-eyebrow):not(.beat-p):not(.callout-primary) { margin: 0; }
/* The callout is excluded as a TARGET so its own 24px wins, but it must stay
   eligible as a PREDECESSOR — excluding it from both halves left the sentence
   after it matching nothing, so it fell back to margin: 0 and sat flush
   against the rule. */
.beat p:not(.beat-eyebrow):not(.beat-p) + p:not(.beat-p):not(.callout-primary) { margin-top: 18px; }

/* Cap every measure, including ones that look like they can't need it: a
   300px column still needs a ch cap for its wrapped state, where it runs full
   width and would otherwise pass 90 characters. */
.beat-outcome { max-width: 74ch; }

/* Beat 03 sets its own rhythm — it opens at 22px and tightens to 18px after
   the ruled paragraph. Each selector names the class explicitly so it
   outranks the beat-wide default above rather than relying on source order. */
.beat p.beat-p { max-width: 74ch; margin: 0 0 22px; }
.beat p.beat-p.beat-p-tight { margin-bottom: 18px; }
.beat p.beat-p:last-child { margin-bottom: 0; }

/* One ruled paragraph per case. Only the indent changes — the type does not —
   and that is what distinguishes it from the callout, where the typeface does
   change. It marks the general case, the part a reader skims; the specific
   decisions around it stay flush. */
.beat-ruled {
  max-width: 72ch;
  padding-left: clamp(18px, 1.8vw, 24px);
  border-left: 3px solid var(--orange);
}

/* The case's thesis, and the two paragraphs the plate illustrates. It changes
   typeface because of that. The four-side navy rule echoes the plate's own
   frame beside it, and the fill is one step down from the linen — essentially
   the plate's ground. */
/* TWO callout treatments, told apart by size alone. Both take the same 3px
   Rust rule and nothing else: no tint, no border, no face change. A tinted
   #EFE7DF ground with negative margins was built and cut — on linen it needs
   height and bleed to register at all, and then it reads as a quotation.
   Serif went with it: face + size + rule is three signals for one emphasis. */

/* PRIMARY — the claim the case turns on, one per case. Sans, not serif, at
   125% of body. It CLOSES the beat it belongs to rather than sitting in its
   own grid row, where it would inherit the 40–60px beat gap on both sides and
   read as a stranded pull-quote — hence a margin-top of its own. */
.beat p.callout-primary {
  margin: 24px 0 0;
  padding-left: clamp(18px, 1.8vw, 24px);
  border-left: 3px solid var(--orange);
  font-weight: 400;
  font-size: clamp(18.75px, 1.5vw, 20px);
  line-height: 1.5;
  color: var(--navy);
  /* no measure of its own — it takes the column's */
}

/* SECONDARY — the general principle, one per case, inside 03. Body size. */
.callout-secondary {
  max-width: 72ch;
  padding-left: clamp(18px, 1.8vw, 24px);
  border-left: 3px solid var(--orange);
}

/* A MAT, not a frame: no border, so the artwork's own hairline reads as its
   edge. No caption either — a plate's label is drawn into the artwork.

   #F8F1EC IS A SITE COLOUR, not a per-file property. Both plates export on
   it, and a graphic that arrives on anything else gets re-exported rather
   than accommodated. That replaces the old rule of sampling each plate's own
   ground, which put two plates on one page on two different grounds — and it
   ends a swap-by-swap chase that moved this value three times in two days.

   No mix-blend-mode, unlike every other image on the site: the plate's ground
   is opaque by design and multiplying it against the mat muddies it.

   PLATES MUST BE PORTRAIT, no wider than 3:4. A landscape export shipped for
   one revision and failed twice — it covered a third of the case, left the
   lower beats beside empty ground, and rendered its labels near 8px because
   the column is narrower than the figure is wide. */
.case-plate {
  /* span 4, never 1 / -1. The rows are implicit, so -1 resolves against an
     explicit grid with no rows and the plate collapses into a single row
     partway down the case — which shipped once and read as a figure floating
     loose in the middle of the argument. */
  grid-column: 2;
  grid-row: 1 / span 4;
  align-self: start;
  /* Lets the plate overrun its column into the page gutter, never past the
     page edge. */
  width: calc(100% + var(--plate-slack));
  margin-right: calc(-1 * var(--plate-slack));
  background: #F8F1EC;
  padding: clamp(16px, 1.8vw, 24px);
}
.case-panel {
  --plate-slack: max(0px, (100vw - 1240px) / 2 + clamp(20px, 4vw, 48px) - 10px);
}

/* The plate is a control. Full-width transparent button inside the mat. */
.plate-trigger {
  position: relative;
  display: block;
  width: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
}
.plate-trigger img {
  display: block;
  width: 100%;
  height: auto;
}

/* The badge is the whole affordance — without it nothing announced the plate
   was enlargeable except the cursor, which touch and keyboard users never
   see. No help text under the mat. aria-hidden so it doesn't double the
   button's accessible name. */
.plate-zoom {
  position: absolute;
  top: 0;
  right: 0;
  width: 38px;
  height: 38px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(241, 232, 226, 0.92);
  border: 1px solid rgba(27, 35, 64, 0.22);
}

/* ---- The enlarge overlay -------------------------------------------------
   Deliberately NO height cap on the figure. max-height: 100% caps a 1000px
   portrait plate at the window, which on a 900px laptop renders it near half
   size and the overlay buys nothing. The figure exceeds the viewport and the
   scrim scrolls instead.

   And capped at NATIVE width, never above: upscaling a raster only
   interpolates and softens the labels the overlay exists to make readable. A
   new export means revisiting 764px here and on the diagrams page. */
.zoom {
  position: fixed;
  inset: 0;
  z-index: 120;
  overflow-y: auto;
  overflow-x: hidden;
  padding: clamp(16px, 3vw, 56px);
  background: rgba(27, 35, 64, 0.94);
  cursor: zoom-out;
}
.zoom[hidden] { display: none; }
.zoom img {
  display: block;
  width: 100%;
  max-width: 764px;
  height: auto;
  margin: 0 auto;
  background: #F8F1EC;
}
/* Shares the image's width so the two right edges line up. */
.zoom-all {
  max-width: 764px;
  margin: clamp(14px, 2vw, 20px) auto 0;
  text-align: right;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.zoom-all a {
  color: var(--orange-brt);
  padding-bottom: 2px;
  border-bottom: 1px solid rgba(240, 135, 60, 0.5);
  cursor: pointer;
}
.zoom-all a:hover { color: var(--white); border-bottom-color: var(--white); }

.zoom-close {
  position: fixed;
  top: clamp(12px, 2vw, 24px);
  right: clamp(12px, 2vw, 24px);
  min-width: 44px;
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(27, 35, 64, 0.9);
  border: 1px solid rgba(255, 255, 255, 0.45);
  color: #F3EFE9;
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
}
.zoom-close:hover { border-color: var(--orange-brt); color: var(--orange-brt); }

/* ============================================================================
   CASE STUDY DIAGRAMS PAGE
   Deliberately unlinked from the nav — no slot, no footer row, no dropdown
   entry. The diagrams are its only entrance, via the link under the enlarged
   figure. It is a place to go from a figure, not a section of the site.
============================================================================ */

.diagrams { background: var(--linen); color: var(--navy); }

.diagram-stack {
  display: flex;
  flex-direction: column;
  gap: clamp(56px, 6vw, 84px);
  max-width: var(--content-max);
  margin: 0 auto;
  padding: clamp(34px, 3.4vw, 46px) var(--pad-x) clamp(40px, 3.6vw, 50px);
}

/* A shared link to a figure lands on the figure, not the top of the page.
   The site's own rule only covers section[id] and footer[id], and these are
   divs. Written against the header token plus 24px of air rather than a flat
   96px — same value today, and it can't drift if the header height changes. */
.diagram[id] { scroll-margin-top: calc(var(--header-h) + 24px); }

.diagram h2 {
  margin: 0 0 16px;
  font-family: var(--font-head);
  font-weight: 400;
  font-size: clamp(23px, 2.4vw, 30px);
  line-height: 1.16;
  letter-spacing: -0.015em;
  color: var(--navy);
}
.diagram-copy {
  margin: 0;
  max-width: 74ch;
  font-size: clamp(15px, 1.2vw, 16px);
  line-height: 1.62;
  color: var(--ink);
  text-wrap: pretty;
}

.diagram-cta { margin: 18px 0 0; }
.diagram-cta a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--orange-deep);
  border-bottom: 1px solid rgba(176, 78, 25, 0.45);
  transition: color var(--ease), border-color var(--ease);
}
.diagram-cta a:hover {
  color: var(--orange-deep-hover);
  border-bottom-color: var(--orange-deep-hover);
}

/* Same mat as the case plates, and the same site ground — but static. These
   are already at full size, which is the reason this page exists, so there is
   nothing to enlarge. Capped at the artwork's native width: scaling a raster
   up only softens the labels. */
.diagram-plate {
  margin-top: clamp(20px, 2.2vw, 28px);
  max-width: 764px;
  background: #F8F1EC;
  padding: clamp(16px, 1.8vw, 24px);
}
.diagram-plate img {
  display: block;
  width: 100%;
  height: auto;
}

/* ============================================================================
   ARTIFACT BANDS
   A section of supplied imagery, and the site's third interior ground.

   Linen rather than navy, which is what the interior pattern would predict.
   Both images arrive on their own near-white grounds: on navy they sit as
   bright rectangles with hard edges and the plate reads louder than the
   artifact, and on pure white the screenshot's tan ground floats with no edge
   at all. Linen takes both — the illustration dissolves into it under
   multiply, and the screenshot needs only a hairline. It is also the warmest,
   least formal material on the site, which is what this section wants.

   Linen is the ground for a section carrying supplied imagery and is NOT an
   alternative to navy anywhere else. Navy stays meaningful by staying rare.

   The section is deliberately unfinished — see the reserved slot at the foot
   of the markup. There is no rule after band 3: the section ends on copy, and
   a fourth band drops in bringing one more rule above it.
============================================================================ */

.artifacts { background: var(--linen); color: var(--navy); }

/* The gap is smaller than it looks like it should be because each rule is a
   flex child and therefore eats a gap on BOTH sides. At the old
   clamp(52px, 6vw, 88px) the three rules added roughly 150px of dead air. */
.artifact-stack {
  display: flex;
  flex-direction: column;
  gap: clamp(34px, 4vw, 56px);
  max-width: var(--content-max);
  margin: 0 auto;
  padding: clamp(38px, 4vw, 56px) var(--pad-x);
}

/* A section eyebrow, not a headline — a serif h2 here competed with the band
   titles, which is also why those stay h2 and this stays a <p>.

   The negative bottom margin cancels most of the column gap so the label sits
   16px above its rule and reads as attached to the section rather than as a
   band of its own. Roughly -21px at desktop. */
.artifact-eyebrow { margin: 0 0 calc(16px - clamp(34px, 4vw, 56px)); }

/* Flex children of the column, not borders on the bands — a border would move
   with its band and leave the eyebrow unruled. Composited on Linen this is
   #D3D1CF, 1.36:1 against the ground. */
.artifact-rule {
  margin: 0;
  border: 0;
  border-top: 1px solid rgba(27, 35, 64, 0.16);
  width: 100%;
}

/* Each band is a wrapping flex row with both halves on the same basis, and
   the image is FIRST IN THE DOM in both. Band 2 sets row-reverse, so on
   desktop its image renders right; when the row wraps, the first DOM child
   takes the first line and the image lands above the copy either way.

   One rule therefore produces image-left, image-right and image-above-copy
   with no breakpoint of its own and no second markup path. The alternation
   carries no meaning, so nothing is lost when it collapses. The wrap lands
   near 910px — a consequence of the basis, not a declared breakpoint. Don't
   convert it to a media query. */
.artifact {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: clamp(28px, 4vw, 64px);
}
.artifact-flip { flex-direction: row-reverse; }

.artifact-media,
.artifact-copy { flex: 1 1 380px; min-width: 0; }

.artifact-copy,
.artifact-wide {
  display: flex;
  flex-direction: column;
  gap: clamp(16px, 1.7vw, 22px);
}

.artifact-copy h2,
.artifact-wide h2 {
  margin: 0;
  font-size: clamp(26px, 3.1vw, 38px);
  line-height: 1.14;
  letter-spacing: -0.02em;
}
.artifact-copy p,
.artifact-wide p {
  margin: 0;
  max-width: 54ch;
  font-size: clamp(15.5px, 1.35vw, 18px);
  line-height: 1.66;
  color: var(--ink);
  text-wrap: pretty;
}
/* Emphasis inside body copy is navy 600, never a colour — rust is 4.25:1 on
   Linen and fails AA at body size. Same treatment as the interior lead-ins. */
.artifact-copy strong { font-weight: 600; color: var(--navy); }

/* Full width is the BAND, not the line. With no image there is no half-column,
   so the copy starts at the band's left edge — but the measure still caps,
   visibly wider than the paired bands and short of the ~80ch where lines stop
   being findable. Running body copy to the full 1144px would be unreadable. */
.artifact-wide p { max-width: 72ch; }

/* The illustration's near-white ground disappears into Linen and the linework
   sits on the page rather than on a plate. No border: a border would put it
   back on a plate. */
.artifact-art {
  display: block;
  width: 100%;
  height: auto;
  mix-blend-mode: multiply;
}

/* A screenshot is framed, not blended. Multiply would multiply its palette
   against the ground and shift its colours, at which point it stops being
   evidence of a real interface. */
.artifact-shot {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid rgba(27, 35, 64, 0.18);
}

.artifact-link-row { margin: clamp(2px, 0.6vw, 6px) 0 0; max-width: none; }
.artifact-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  color: var(--orange-deep);          /* 5.4:1 on Linen — measured */
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  border-bottom: 1px solid rgba(176, 78, 25, 0.45);
  transition: color var(--ease), border-color var(--ease);
}
.artifact-link:hover {
  color: var(--orange-deep-hover);
  border-bottom-color: var(--orange-deep-hover);
}

/* The mobile crop is off by default; the full figure is on. */
.art-crop { display: none; }

/* Band 4's slot documents itself in the markup and must contribute NOTHING to
   the layout. An empty div still has zero height but a flex gap either side of
   it, which put 144px under band 3 where the section's own 72px is the whole
   of the space — reading as a closing flourish, which is exactly what this
   section must not have. display:none takes it out of the flex flow entirely.
   When band 4's copy lands, replace the div with a real band and delete this
   rule. */
.artifact-stack > [data-band="4-reserved"] { display: none; }

/* ============================================================================
   PAIRED COLUMNS
   Two halves of one argument in one navy section. A ground change would mark
   a change of subject; these are the same subject seen twice.
============================================================================ */

.paired {
  position: relative;
  overflow: hidden;
  background: var(--navy);
  color: var(--white);
}

.pair-grid {
  display: grid;
  /* Equal tracks, and min-width:0 on both so one long string can't widen its
     half against the other. Gutter is roughly twice a normal section gap, so
     the halves read as adjacent arguments rather than one block of text. */
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  gap: clamp(44px, 6.5vw, 116px);
}
.pair-half { min-width: 0; }

.pair-heading {
  margin: 0 0 clamp(22px, 2.6vw, 32px);
  font-size: clamp(26px, 3.1vw, 38px);
  line-height: 1.18;
  letter-spacing: -0.02em;
  color: var(--white);
}

/* Both halves share one row structure — a mark or a numeral in a fixed track,
   then a title on its own line, then body. A bold lead-in on one side against
   titled rows on the other reads as two different components.

   Every row opens with a hairline, including the first: it's what separates
   the rows without a gap doing the work, and it runs in both columns. */
.pair-row {
  display: grid;
  grid-template-columns: 52px 1fr;   /* fixed, so both columns share one text
                                        indent. 52px is the icon diameter, and
                                        the numeral opposite is ringed to the
                                        same 52px — a bare numeral facing a
                                        52px icon left the right column
                                        reading as the lighter of the two. */
  column-gap: clamp(14px, 1.6vw, 20px);
  padding-top: 20px;
  border-top: 1px solid rgba(255, 255, 255, 0.22);
  margin-bottom: clamp(24px, 2.8vw, 34px);
}
.pair-row:last-child { margin-bottom: 0; }

.pair-row h3 {
  margin: 0 0 8px;
  font-weight: 500;
  font-size: clamp(20px, 2vw, 25px);
  line-height: 1.25;
  color: var(--white);
}
/* Scoped to the text column, NOT `.pair-row p`. The numeral is also a <p> and
   a direct child of the row, so the looser selector beat .pair-num on
   specificity and silently reset it to body size and body colour — which is
   how the numeral treatment went missing. */
.pair-row > div p {
  margin: 0;
  font-size: var(--t-body);
  line-height: 1.68;
  color: var(--off-white);
  text-wrap: pretty;
}

/* A ringed disc matching the icon diameter opposite, so the two columns read
   as one system rather than art on the left and type on the right.

   `padding-top: 3px` is load-bearing, not a spacing preference. Satisfy's
   numerals carry their optical mass below the geometric centre of the em box,
   so a flex-centred numeral sits visibly high in the ring. Under border-box
   this nets out to roughly half its value as a downward nudge, which is the
   amount that reads as centred. `line-height: 1` is required for the same
   reason — an inherited line-height reintroduces the drift.

   This is the second use of Satisfy on the site and the only one that is not
   the signature. See the header note: the face is otherwise the signature
   alone. */
.pair-num {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  margin: 0;
  padding-top: 3px;
  border: 1px solid var(--linen);
  border-radius: 50%;
  font-family: var(--font-script);
  font-weight: 400;
  font-size: clamp(23px, 2.3vw, 28px);
  line-height: 1;
  color: var(--orange-brt);
}

/* Supplied PNG art now, not a drawn mark — the ring is inside the artwork.
   So this takes NO border, background or tint: anything behind it produces
   two concentric rings. The three files are cropped to their own ring rather
   than to a common canvas, which is why their source sizes differ and why
   they must not be re-cropped or padded — scale by width/height only.

   Exported at 3x (156px) rather than the site's usual 2x. These render at
   52px with ring strokes around 1.6px, and a hairline is exactly where the
   extra density shows; the whole set costs 36KB. */
.signal-mark {
  display: block;
  width: 52px;
  height: 52px;
  margin-top: 0;
}

/* One thesis per section, spanning both columns. This is the sitewide
   callout-primary treatment on a dark ground — see `.beat p.callout-primary`,
   which is the same treatment on light. Two substitutions and no others:
   the text is white rather than navy, one step brighter than the --off-white
   body copy around it, and the rule is Rust, which on navy is a border
   colour. NOT Ember: Ember is action text on dark grounds, so a 3px Ember bar
   reads as a control.

   Do not scale it up to fill the wider column. That was the previous
   treatment and it read as a pull-quote closing the page rather than as the
   claim the section turns on. 88ch caps the line while the rule still spans
   the section. */
.pair-thesis {
  max-width: 88ch;
  margin: clamp(48px, 5.5vw, 80px) 0 0;
  padding-left: clamp(18px, 2.2vw, 24px);
  border-left: 3px solid var(--orange);
  font-family: var(--font-body);
  font-weight: 400;
  font-size: clamp(18.75px, 1.6vw, 20px);
  line-height: 1.5;
  color: var(--white);
}

/* ============================================================================
   RING MOTIF
   The hero draws three rings around the headshot at 260% / 172% / 128%.
   Interior sections reuse that figure at background scale, holding the same
   radius steps (1.51× and 1.34×) with rust innermost.

   These are NOT hero alphas dimmed down. One hairline circle can sit
   near-invisible and still work; three concentric rings at this scale read as
   an accident unless they're deliberately visible.

   Not every section gets a set — a dense one goes bare. The motif marks a
   page's openings and closings, not its working middle. (The paired section
   on this page has none.)
============================================================================ */

.rings {
  position: absolute;
  top: 50%;
  width: 0;
  height: 0;
  pointer-events: none;
}
.rings-right { right: 0; }
.rings-left { left: 0; }

.rings span {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  border: 1px solid;
  display: block;
}
.ring-a { width: 900px; height: 900px; }   /* 1.51× the next */
.ring-b { width: 596px; height: 596px; }   /* 1.34× the next */
.ring-c { width: 445px; height: 445px; }   /* rust, innermost, as in the hero */

/* The light-ground ring colours are gone with the set they coloured: the
   interior opening carries the figure now, and art and rings never stack. The
   values are recorded in design_handoff_interior_opening if a light section
   ever needs them back. */

.closing .ring-a { border-color: rgba(255, 255, 255, 0.22); }
.closing .ring-b { border-color: rgba(255, 255, 255, 0.25); }
.closing .ring-c { border-color: rgba(200, 90, 30, 0.31); }

/* ============================================================================
   INTERIOR OPENING ART
   The same motif as the rings, supplied as a drawing instead of drawn in CSS —
   its outer arcs are the ring set at a wider radius. It stands in for the ring
   set on an opening; the two never share a section.

   TWO elements, and that is the whole trick. The box clips; the image inside
   it is deliberately taller than the box.

   Do NOT collapse this to one image with `object-fit: cover`. It looks
   equivalent and is not. At narrow desktop widths the box is nearly square and
   the artwork is 4:3, so cover crops horizontally only, and the figure then
   lands pixel-flush against the section's top and bottom edges — measured at
   924px, the image's top, the section's top and the header's bottom were all
   72.94, and the image's bottom, the section's bottom and the navy band's top
   were all 436.61. It read as neatly boxed inside the white band, which is the
   opposite of the intent. `top: 0; height: 100%` inside `overflow: hidden` can
   only ever produce edge-to-edge; nothing extends past an edge, so nothing is
   cut.

   Oversizing the image inside its own clip severs both edges at EVERY width:
   130 / 2 = 65px of artwork above the section's top edge and 65px below its
   bottom, so the outer arcs are cut mid-curve at the header line and at the
   navy band. The cut is what the visitor sees.

   The figure MEETS those boundaries and does not cross them, on purpose. The
   header is navy at 0.94 with a 10px blur, so artwork passing under it renders
   at roughly 6% — invisible. Downward, `multiply` against the navy section
   renders this file's near-white ground as no change at all. A visible
   crossing would need either a nav we're willing to cover or a second asset
   with a transparent ground, and neither exists.
============================================================================ */

.open-art {
  position: absolute;
  top: 0;
  height: 100%;
  /* Scales with the viewport, not fixed. A fixed offset against a fluid
     section closed the gap between the copy and the figure to roughly nothing
     through the 900–1100px band; the two have to move apart together. */
  right: clamp(-150px, -8vw, -40px);
  width: clamp(320px, 40vw, 860px);
  overflow: hidden;
  pointer-events: none;
  display: block;
}

.open-art img {
  position: absolute;
  /* Pinned right. The focal point and its bracket are the subject; the lines
     entering from the left are approach. As the space narrows the left is
     given up and the focal point stays in the section at every width. */
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  height: calc(100% + 130px);
  width: auto;
  max-width: none;
  /* Required, not cosmetic: the file has no alpha. Multiply drops its
     near-white ground onto the section's white instead of drawing a visible
     plate over it. */
  mix-blend-mode: multiply;
  user-select: none;
}

/* ============================================================================
   ONWARD LIST
   The closing component for a screen that argues and needs to route the
   reader to the evidence. Sits inside the closing section on its existing
   ground — it is not an interruption band, and Linen stays reserved for the
   Right Place band.
============================================================================ */

.closing {
  position: relative;
  overflow: hidden;
  background: var(--white);
  color: var(--navy);
}

.onward-rule {
  display: block;
  width: 100%;
  height: 2px;
  background: var(--orange);
  margin-bottom: clamp(20px, 2.4vw, 30px);
}

.onward-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px 32px;
  margin-bottom: clamp(18px, 2vw, 26px);
}
.onward-head h2 {
  margin: 0;
  font-size: clamp(24px, 2.8vw, 34px);
  letter-spacing: -0.02em;
}
.onward-head p { margin: 0; font-size: var(--t-body); color: var(--ink); }

.onward-list { margin: 0; padding: 0; list-style: none; }
.onward-list li { border-top: 1px solid rgba(27, 35, 64, 0.18); }
.onward-list li:last-child { border-bottom: 1px solid rgba(27, 35, 64, 0.18); }

/* Text links, not buttons. The whole row is the target. */
.onward-list a,
.onward-pending {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 16px;
  min-height: 44px;
  padding: 14px 0;
  color: var(--orange-deep);
  transition: color var(--ease);
}
.onward-list a:hover { color: var(--orange-deep-hover); }

.onward-name {
  font-family: var(--font-head);
  font-weight: 500;
  font-size: clamp(19px, 1.9vw, 22px);
}
.onward-desc {
  flex: 1;
  font-size: var(--t-body);
  color: var(--ink);
}
.onward-arrow { font-size: 18px; }

/* Newsreader 500 at 20px isn't WCAG bold, so the large-text 3:1 allowance
   doesn't apply and this has to clear 4.5:1. #6B7285 measures 4.85:1 on
   white; an earlier #8A90A2 measured 3.19:1 and failed. */
.onward-pending { color: #6B7285; }
.onward-pending .onward-desc { color: #5A6178; }
.onward-tag {
  flex-shrink: 0;
  padding: 4px 8px;
  border: 1px solid rgba(27, 35, 64, 0.28);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

/* ============================================================================
   RESPONSIVE HEADER
   The site has no breakpoints anywhere else — type is clamp() and grids are
   auto-fit. The header is the exception, and it's a replacement rather than a
   reflow: below 900px the logo lockup, four tracked-caps destinations, three
   pipes and the bordered action stop fitting on one line even at the clamp
   floor, and wrapping is what the spec forbids.

   Standing rule: below 900px the nav is replaced, never wrapped.
============================================================================ */

.nav-burger,
.mobile-menu { display: none; }

@media (max-width: 899px) {
  .nav-links { display: none; }
  .nav-burger { display: flex; }
  .mobile-menu { display: block; }

  /* The hero's credentials strip goes. It's a fixed 11px tracked-caps string
     between two rules, and at phone width it ran to four lines of very small
     caps for a line that reads as a claim, not as information someone needs
     here. The same string still ships in the footer as plain caption copy —
     one string, one setting, on mobile. */
  .credentials { display: none; }

  /* Touch sizing for the tabs: 14px of vertical padding against 13px, and a
     44px floor against 40px. Keyed to the site's one breakpoint rather than
     to (hover: none), because the site models "phone" at 899px everywhere
     else and a second query would be a second breakpoint. */
  .case-tab { min-height: 44px; }
  .case-tab[aria-selected="true"] { padding-top: 14px; padding-bottom: 14px; }

  /* One column, same row gap. */
  .case-panel { grid-template-columns: 1fr; }

  /* The plate still drops, and the distinction is deliberate: a case plate is
     load-bearing CONTENT that cannot be read at phone width, where the
     opening art is decoration that only has to register. Its alt text carries
     the reading. */
  .case-plate { display: none; }

  /* The band stacks instead of squeezing the row. The ±18px pull aligns the
     DRAWING to the text edge rather than the file's transparent margin — the
     marks are mostly margin, so without it they sit visibly inset. */
  .fit-band-inner {
    max-width: var(--content-max);
    padding: 8px 20px 12px;
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
  }
  .quote-mark { width: 150px; }
  .quote-open { align-self: flex-start; margin-left: -18px; }
  .quote-close { align-self: flex-end; margin-right: -18px; }
  .fit-copy { font-size: 17px; }

  /* Simplify, don't scale: one mark, no connector, no node. The portrait's
     own rings stay at every width — they belong to this system rather than
     being a separate ornament. */
  .hero-art img:last-of-type,
  .hero-connector,
  .hero-node { display: none; }
  .hero-art img:first-of-type {
    left: -16%;
    top: -2%;
    width: 230px;
    opacity: 0.22;
  }

  /* The opening art now HOLDS at every width — it is the only thing telling
     one interior opening from another, and a phone reader who loses it lands
     on three pages that look identical.

     These are a second, tuned instance rather than the desktop values scaled
     down. The desktop clamp floors at 320px, which on a phone puts a
     near-full-strength figure directly behind the headline. Narrowing the
     box, cutting the overhang and halving the strength keeps the mark present
     as a watermark behind the right edge without touching the text. */
  .open-art {
    right: -46px;
    width: 230px;
    opacity: 0.42;
  }
  .open-art img { height: calc(100% + 60px); }

  /* The Living PRD figure crops to the component that carries the meaning.
     At phone width the full figure renders every part too small to read, so
     the band swaps to a fixed box holding an oversized image — the same
     technique as the opening art. The window lands on 14–80% across and
     22–58% down: the tabbed panel with its active tab and both inactive ones,
     plus the first journey lanes. The header, stakeholder and timeline zones
     are given up on purpose.

     Known limitation, flagged to design: even cropped, the tab labels land
     around 5px. The component is recognisable by shape and by the rust active
     tab, but the words are not readable. Landing the labels needs a simplified
     variant of the asset, not a different crop. */
  .art-full { display: none; }
  .art-crop {
    display: block;
    position: relative;
    width: 100%;
    padding-bottom: 41%;
    overflow: hidden;
  }
  .art-crop img {
    position: absolute;
    left: -21.2%;
    top: -61%;
    width: 151.5%;
    max-width: none;
    height: auto;
    mix-blend-mode: multiply;
  }
}

/* Three bars in a 44px target. No border and no fill — Get in touch stays the
   only bordered element in the header at every width. The negative margin
   aligns the bars with the header's content edge rather than the target's. */
.nav-burger {
  width: 44px;
  height: 44px;
  margin-right: -11px;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
}
.nav-burger-bars {
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.nav-burger-bars i {
  display: block;
  width: 22px;
  height: 2px;
  background: var(--white);
  transition: transform 180ms ease, opacity 120ms ease;
}
.nav-burger[aria-expanded="true"] i:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-burger[aria-expanded="true"] i:nth-child(2) { opacity: 0; }
.nav-burger[aria-expanded="true"] i:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* An overlay, not a push: content below the header must not reflow when it
   opens. Always in the DOM — unmounting it kills the close transition. */
.mobile-menu {
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  z-index: 60;
  max-height: calc(100vh - 72px);
  overflow-y: auto;
  padding: 6px clamp(20px, 4vw, 48px) 22px;
  background: var(--navy-deep);
  border-top: 1px solid rgba(200, 90, 30, 0.55);
  opacity: 0;
  transform: translateY(-6px);
  pointer-events: none;
  transition: opacity var(--ease), transform var(--ease);
}
.mobile-menu.is-open {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

/* Rows carry their own dividers — no pipes, and no hover states, because
   there is no hover here. */
.m-row {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-height: 54px;
  padding: 0;
  background: none;
  border: none;
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
  color: var(--white);
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-align: left;
  cursor: pointer;
}
.m-row-trigger { justify-content: space-between; }

/* Current page: Ember plus a rust bar on the row's left edge. The desktop
   underline doesn't survive a full-bleed row; a left bar is the same rust
   doing the same job in a layout that has an edge to hang it on. */
.m-row.is-current,
.m-child.is-current {
  color: var(--orange-brt);
  box-shadow: inset 2px 0 0 var(--orange);
  padding-left: 12px;
}

.m-caret {
  font-size: 9px;
  line-height: 1;
  transition: transform var(--ease);
}
[aria-expanded="true"] > .m-caret { transform: rotate(180deg); }
.m-row-trigger[aria-expanded="true"] { color: var(--orange-brt); }

.m-children {
  display: none;
  margin-left: 16px;
  padding-left: 16px;
  border-left: 2px solid var(--orange);
}
.m-children.is-open { display: block; }

.m-child {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 50px;
  margin: 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
  color: var(--white);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.m-child:last-child { border-bottom: 0; }
.m-child-soon { color: #8E95A8; }
.m-soon-tag {
  flex-shrink: 0;
  padding: 4px 8px;
  border: 1px solid rgba(255, 255, 255, 0.28);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.14em;
}

/* The one action, below its own rule. */
.m-action {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid rgba(200, 90, 30, 0.55);
  padding-bottom: 20px;
}
.m-touch {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  height: 52px;
  padding: 0 16px;
  background: none;
  border: 1px solid var(--orange);
  color: var(--orange-brt);
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
}

.m-touch-panel { display: none; padding-top: 14px; }
.m-touch-panel.is-open { display: block; }

.m-label {
  margin: 0 0 4px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--orange-brt);
}
.m-phone,
.m-email {
  display: flex;
  align-items: center;
  min-height: 48px;
  color: var(--white);
}
.m-phone { font-size: 17px; }
.m-email { font-size: 16px; word-break: break-all; margin-bottom: 6px; }

.m-actions { display: flex; gap: 10px; }
/* White text on a rust fill always uses the deep value — and this is the only
   filled action in the panel. */
.m-send,
.m-copy {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  font-family: var(--font-body);
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
}
.m-send {
  background: var(--orange-deep);
  border: 1px solid var(--orange-deep);
  color: var(--white);
}
.m-copy {
  background: none;
  border: 1px solid rgba(255, 255, 255, 0.35);
  color: var(--sand);
}

/* Not in the mobile-nav handoff, but found while verifying it: the hero's
   Get in touch panel is 290px wide and left-anchored to its button, which sits
   mid-row. On a 390px phone that put its right edge at 477px and gave the home
   page a horizontal scrollbar — and the panel itself ran off screen when
   opened.

   Below the breakpoint it spans the CTA row instead of hanging off the button:
   .contact-wrap goes static so the panel resolves against .cta-row. */
@media (max-width: 899px) {
  .hero .cta-row { position: relative; }
  .hero .contact-wrap { position: static; }
  .hero .contact-panel { left: 0; right: 0; }
  .hero .contact-card { min-width: 0; }
}
