@import url('https://fonts.googleapis.com/css2?family=Source+Serif+4:opsz,wght@8..60,400;8..60,500;8..60,600&family=IBM+Plex+Sans:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500&display=swap');

/* Volshteyn & Associates - Variation B "The Brief"
   Persistent index-rail document layout. See design-concepts/b-the-brief.md.
   Font load via @import (not a separate enqueued <link>) per the platform lesson
   already documented in theme-a/assets/css/main.css - LiteSpeed's optimization
   pipeline strips separate font <link> tags in production. */

:root {
  /* Colors - brand-guidelines.json, same literal values as Variation A, different roles */
  --color-primary: #1C1C1A;      /* Ink Charcoal - rule lines, index text, headings */
  --color-bg: #FAF7F2;           /* Parchment Ivory - the only ground color on the page */
  --color-white: #FFFFFF;
  --color-accent: #6E1E2B;       /* Volshteyn Burgundy - single accent, never a fill */
  --color-text: #1C1C1A;
  --color-text-muted: #444444;
  --color-border-light: #E5E7EB;
  --color-border: #1C1C1A;

  /* Typography - deliberately different pairing from Variation A (Fraunces/Public Sans) */
  --font-heading: 'Source Serif 4', serif;
  --font-body: 'IBM Plex Sans', sans-serif;
  --font-mono: 'IBM Plex Mono', monospace;
  /* Type scale pushed up 2026-08-27 (Sean: "still isn't BOLD enough. Some headings and
     text are way too small and don't really 'pop' at the user" - and specifically
     "still nothing looks like super 'wow' or bold ... on mobile", so the LOW end of
     every clamp moved further than the high end). H1 40->52px at 375 and 64->80px at
     1920; H2 28->34 and 40->52; body 17->18px; the mono eyebrow and section numbers
     went up with them so the document vocabulary still reads as one system. */
  /* 3.6vw, not 6.5vw: the H1 lives in the hero's text track, which is about half the
     content width, so a viewport-proportional slope overshot its own column - at 1280
     an 80px headline in a 423px track wrapped to five lines. The 3.25rem floor is what
     Sean's "way too small" note was really about and it is unchanged from 375 to 1443. */
  /* H1 slope 3.9vw and H2 ceiling 2.875rem, not 3.6vw / 3.25rem (round 3, measured): the two
     clamps used to CROSS. H1 stayed on its 3.25rem floor until 1444px while H2 reached its
     3.25rem ceiling at 1300px, so from 1300 to 1444 - which includes 1440, the single most
     common laptop width - the page's headline rendered at exactly the same 52px as every
     section heading. Identical sizes read as a mistake, not as a hierarchy. The floors are
     untouched, so nothing changes at or below 1280 and mobile is entirely unaffected; this
     only separates the two levels in the band where they had converged. */
  /* Round 5, 2026-08-28 (measured as a RANGE, not at points). Round 3's 3.9vw left H1 on its
     3.25rem floor until 1333px while H2 reached its 2.875rem ceiling at 1150px, so H1/H2 sat at
     a flat 1.13x across the whole 1150-1333 band - the same "two levels that read as one" defect
     round 3 fixed at 1440 and re-created 300px to its left. 4.7vw lifts H1 off the floor at
     1106px, before H2 tops out, so the minimum separation anywhere in the crossing zone is now
     1.17x. The 5rem cap is unchanged and now actually binds at 1920 (80px), which is the middle
     of the 80-90px corridor design-direction.md records for a 1920 H1 on this project. */
  --text-h1: clamp(3.25rem, 4.7vw, 5rem);
  --text-h2: clamp(2.125rem, 4vw, 2.875rem);
  /* Round 3, 2026-08-27 (Sean, 19:44: "A lot of subheadings are too small"). Round 2 raised
     H1/H2 hard and left every level below them where it was, so the scale went 69 -> 52 -> 26
     -> 17 at 1920 and 52 -> 34 -> 21 -> 17 at 375: two enormous display steps and then a flat
     shelf of near-body-size subheads. The fix closes the gap from BELOW - H1 and H2 are
     untouched, every subheading level under them steps up - so the hierarchy descends smoothly
     instead of falling off a cliff. New h3 floor is 1.5rem (24px), which is the level Sean's
     note is really about: card titles and section subheads at 20.8px on a page whose H1 is 52. */
  --text-h3: clamp(1.5rem, 2.1vw, 1.9375rem);
  /* The section deck under each H2, and the FAQ questions. Was 1.0625rem - SMALLER than body
     copy, which is the single clearest instance of the reported problem.
     The 1.3125rem floor (not 1.1875rem): measured after the first pass, the step from this
     level down to body copy was only x1.06 at 375 - 19px against 18px, which is not a
     hierarchy, it is a rounding difference. Every other step on the page runs x1.2 to x1.7.
     At 21px the step is x1.17 and the deck reads as a deck at the viewport Sean has twice
     said is the one that looks too small. */
  --text-subhead: clamp(1.3125rem, 1.35vw, 1.4375rem);
  /* Small caption/meta level (rail numerals, office labels, margin-note labels, citations).
     Was a mix of 0.8125rem and 0.875rem hand-set per component; unified and raised one step. */
  --text-meta: 0.9375rem;
  --text-body: 1.125rem;
  --text-lede: clamp(1.25rem, 1.6vw, 1.4375rem);
  --leading-heading: 1.1;
  --leading-body: 1.65;

  /* Spacing */
  --space-sm: 8px;
  --space-md: 16px;
  --space-lg: 24px;
  --space-xl: 48px;
  --section-padding: clamp(48px, 6vw, 96px);
  --rail-width: 280px;
  --mobile-bar-h: 64px;
  /* The document frame now spans the full width left after the rail rather than
     stopping at a fixed 1080px column, which left a 656px dead ivory field on the
     right at 1920 and 411px at 1440 (Sean, 2026-08-27: "It looks weird that there's
     a lot of whitespace on the right. Narrowness is fine for text, but we need to
     make sure the design doesn't have too much whitespace."). Text keeps a narrow
     measure via --text-col; everything to its right is real content - exhibit
     imagery, the margin note, office cards, right-aligned ledger attributions.
     Supersedes --content-max-width: clamp(820px, 58vw, 1080px). See DL-0086/DL-0092. */
  --frame-max: 1640px;
  --frame-pad: clamp(24px, 6vw, 112px);
  --measure: 36rem;                              /* measured live: ~71 chars at 17px IBM Plex Sans */
  --text-col: clamp(18rem, 50%, var(--measure)); /* the document's text track */
  --wide-gap: clamp(24px, 3.5vw, 72px);
  --content-max-width: var(--frame-max);

  /* Effects */
  --radius-sm: 4px;
  --radius-md: 6px;
  --border-hairline: 1px solid var(--color-border-light);
  --transition-snap: 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; overflow-x: hidden; }
body {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  color: var(--color-text);
  background: var(--color-bg);
  overflow-x: hidden;
}
h1, h2, h3 {
  font-family: var(--font-heading);
  color: var(--color-primary);
  line-height: var(--leading-heading);
  margin: 0 0 var(--space-md);
  text-wrap: balance;
}
/* 600, not 500: at the DCD's serif display sizes the 500 weight read as light rather
   than authoritative, which is half of what "not bold enough" was pointing at. */
h1 { font-size: var(--text-h1); font-weight: 600; letter-spacing: -0.02em; }
h2 { font-size: var(--text-h2); font-weight: 600; letter-spacing: -0.015em; }
h3 { font-size: var(--text-h3); font-weight: 600; }
p { margin: 0 0 var(--space-md); }
.nb { white-space: nowrap; }
@media (max-width: 600px) { .nb { white-space: normal; } }
a { color: var(--color-accent); }
button { cursor: pointer; }
img { max-width: 100%; display: block; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; }
.skip-link:not(:focus) { position: absolute; left: -9999px; }
.skip-link:focus { position: fixed; top: var(--space-md); left: var(--space-md); z-index: 200; background: var(--color-primary); color: var(--color-white); padding: var(--space-sm) var(--space-md); border-radius: var(--radius-sm); }

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

.btn { display: inline-flex; align-items: center; justify-content: center; min-height: 52px; padding: 16px 34px; font-family: var(--font-body); font-weight: 600; letter-spacing: 0.01em; font-size: 1.0625rem; text-decoration: none; border-radius: 2px; border: 1px solid transparent; transition: background-color var(--transition-snap), border-color var(--transition-snap), color var(--transition-snap); cursor: pointer; }
.btn--primary { background: var(--color-accent); border-color: var(--color-accent); color: var(--color-bg); }
.btn--primary:hover { background: #651c28; border-color: #651c28; }
.btn--outline { background: transparent; border-color: var(--color-primary); color: var(--color-primary); border-width: 2px; padding: 15px 33px; }
.btn--outline:hover { border-color: var(--color-accent); color: var(--color-accent); }

/* ===== Index Rail (persistent, replaces a conventional top nav) ===== */
.index-rail {
  position: fixed;
  top: 0; left: 0; bottom: 0;
  width: var(--rail-width);
  background: var(--color-bg);
  border-right: 2px solid var(--color-accent);
  overflow: hidden;
  z-index: 100;
}
/* min-height:0 + the TOC as the only scrolling child: the rail is 100vh, so at short
   viewports (1024x768) the contact block and the primary CTA fell below the fold and
   painted as a sliced sliver. The TOC now absorbs the overflow and the CTA stays pinned
   above the rail's bottom edge. See DL-0087. */
.index-rail__inner { display: flex; flex-direction: column; height: 100%; min-height: 0; padding: var(--space-lg) var(--space-lg) var(--space-md); }
.index-rail__brand { flex-shrink: 0; font-family: var(--font-heading); font-size: 1.4375rem; font-weight: 600; color: var(--color-primary); text-decoration: none; line-height: 1.25; margin-bottom: var(--space-xl); }
.index-rail__close { display: none; }
.index-rail__toc { flex: 1 1 auto; min-height: 0; overflow-y: auto; position: relative; }
.index-rail__toc-indicator { position: absolute; left: 0; width: 3px; height: 0; background: var(--color-accent); transform: translateY(0); transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1), height 0.35s cubic-bezier(0.16, 1, 0.3, 1); pointer-events: none; opacity: 0; }
.index-rail__toc-indicator.is-tracking { opacity: 1; }
.index-rail__toc ol { list-style: none; margin: 0; padding: 0; counter-reset: none; }
.index-rail__toc li { border-bottom: 1px solid var(--color-border-light); }
.index-rail__toc a { display: flex; align-items: baseline; gap: var(--space-sm); padding: 0.65em 0 0.65em var(--space-md); min-height: 44px; align-items: center; text-decoration: none; color: var(--color-text-muted); font-size: 1.0625rem; font-weight: 500; border-bottom: 2px solid transparent; transition: color var(--transition-snap), border-color var(--transition-snap); }
.index-rail__num { font-family: var(--font-mono); font-size: var(--text-meta); font-weight: 500; color: var(--color-accent); }
.index-rail__toc a:hover { color: var(--color-primary); border-bottom-color: var(--color-accent); }
.index-rail__toc a.is-active { color: var(--color-primary); }
.index-rail__contact { flex-shrink: 0; display: flex; flex-direction: column; gap: var(--space-sm); margin: var(--space-lg) 0 var(--space-md); font-size: var(--text-meta); }
.index-rail__contact a { color: var(--color-text-muted); text-decoration: none; min-height: 44px; display: flex; align-items: center; }
.index-rail__contact a:hover { color: var(--color-accent); }
.index-rail__lang-toggle { flex-shrink: 0; display: inline-flex; align-items: center; gap: var(--space-sm); width: fit-content; min-height: 44px; margin-bottom: var(--space-lg); padding: 0.25em 0.75em; background: transparent; border: 1px solid var(--color-border-light); border-radius: var(--radius-sm); font-family: var(--font-mono); font-size: var(--text-meta); font-weight: 500; color: var(--color-text-muted); cursor: pointer; letter-spacing: 0.04em; transition: border-color var(--transition-snap); }
.index-rail__lang-toggle:hover { border-color: var(--color-accent); }
.index-rail__lang-toggle .is-active { color: var(--color-accent); font-weight: 600; }
.index-rail__cta { flex-shrink: 0; width: 100%; text-align: center; justify-content: center; text-wrap: balance; }

.index-rail__mobile-toggle { display: none; }
.index-rail__overlay { display: none; }
.mobile-bar { display: none; }
.site-menu, .site-menu__overlay, .site-menu__toggle { display: none; }

@media (max-width: 900px) {
  /* visibility:hidden (not just the off-canvas transform) so the 15 links inside the
     closed drawer leave the tab order and the accessibility tree - DL: keyboard users
     tabbed through the whole off-screen rail before reaching any visible content.
     Delayed on the way out so the slide-away animation still plays. */
  .index-rail { top: 0; left: 0; right: 0; bottom: auto; width: 100%; height: 100vh; overflow-y: auto; transform: translateX(-100%); visibility: hidden; transition: transform var(--transition-snap), visibility 0s linear 0.2s; border-right: none; border-bottom: 2px solid var(--color-accent); }
  .index-rail.is-open { transform: translateX(0); visibility: visible; transition: transform var(--transition-snap), visibility 0s linear 0s; }

  /* DL-0124. The DL-0117 fix (a third of the index unreachable behind a silent scroll
     container) was scoped `min-width: 901px`, so the mobile Contents drawer kept the original
     chrome and the original overflow-y:auto TOC: at 375x812 the nav clipped at 334px against
     478px of links, and 07 Matters / 08 Client Log / 09 Questions simply did not exist for the
     visitor - with no scrollbar, no fade and no affordance, the list read as complete after
     "06 Bilingual Services". On the only navigation mobile has, that is a six-section firm.
     Two changes, in this order of preference:
       1. FIT the nine entries. The drawer's own chrome is compressed (brand gap 48->16, contact
          block margins and row height, language toggle gap, panel padding), which frees ~96px -
          more than the 62px the ninth entry needed at 812px - WITHOUT touching the 44px touch
          target or the link type Sean twice asked us to enlarge.
       2. Remove the silent clip regardless. The TOC is no longer a scroll container at all
          (overflow visible, flex 0 0 auto) and the panel itself scrolls, so on any viewport
          short enough that even the compressed chrome cannot fit - a 320x568 phone, a phone in
          landscape - the entries are still reachable, and reachable through the browser's own
          visible scroll, not a hidden one. A drawer that clips is worse than a drawer that
          scrolls, because it lies about what the site contains. */
  .index-rail__inner { height: auto; min-height: 100%; padding-top: calc(var(--mobile-bar-h) + var(--space-md)); padding-bottom: var(--space-md); }
  .index-rail__toc { flex: 0 0 auto; overflow: visible; min-height: auto; }
  .index-rail__brand { margin-bottom: var(--space-md); }
  .index-rail__contact { margin: var(--space-md) 0 var(--space-sm); gap: 2px; }
  .index-rail__contact a { min-height: 40px; }
  .index-rail__lang-toggle { margin-bottom: var(--space-md); }

  /* Two controls, not one (Sean 2026-08-27): "The 'contents' menu doesn't look great.
     It should maybe be a bit larger and easier to see, and don't include the hamburger
     icon so we can include it on the other side and make that actually show the full
     site menu." So the bar is now a container: a wider, bordered, clearly-tappable
     "Contents" control on the left that opens the section index, and a real hamburger on
     the right that opens the site's own navigation. Neither borrows the other's glyph. */
  .mobile-bar { display: flex; align-items: stretch; justify-content: space-between; gap: var(--space-md); position: fixed; top: 0; left: 0; right: 0; z-index: 110; min-height: var(--mobile-bar-h); padding: var(--space-sm) var(--space-md); background: var(--color-bg); border-bottom: 2px solid var(--color-accent); }
  .index-rail__mobile-toggle { display: inline-flex; align-items: center; gap: var(--space-sm); min-height: 48px; padding: 0 var(--space-lg); background: transparent; border: 2px solid var(--color-primary); border-radius: var(--radius-sm); font-family: var(--font-mono); font-size: 1rem; font-weight: 500; letter-spacing: 0.06em; text-transform: uppercase; color: var(--color-primary); }
  .index-rail__mobile-toggle[aria-expanded="true"] { background: var(--color-primary); color: var(--color-bg); }
  .site-menu__toggle { display: inline-flex; align-items: center; justify-content: center; width: 48px; min-height: 48px; background: transparent; border: 2px solid var(--color-accent); border-radius: var(--radius-sm); color: var(--color-accent); }
  .site-menu__bars { display: flex; flex-direction: column; justify-content: center; gap: 5px; width: 22px; }
  .site-menu__bars span { display: block; height: 2px; width: 100%; background: currentColor; }
  .site-menu__toggle[aria-expanded="true"] { background: var(--color-accent); color: var(--color-bg); }

  .index-rail__overlay { display: none; position: fixed; inset: 0; background: rgba(28,28,26,0.4); z-index: 99; }
  .index-rail__overlay.is-visible { display: block; }
  .index-rail__close { display: flex; align-items: center; justify-content: center; position: absolute; top: calc(var(--mobile-bar-h) + var(--space-sm)); right: var(--space-md); width: 44px; height: 44px; background: transparent; border: 1px solid var(--color-border-light); border-radius: var(--radius-sm); font-size: 1.5rem; line-height: 1; color: var(--color-primary); z-index: 111; }

  /* Same visibility:hidden discipline as the rail (DL-0093): a closed off-canvas panel
     must leave the tab order, not just slide off screen. */
  .site-menu { display: block; position: fixed; top: 0; right: 0; bottom: 0; width: min(88vw, 380px); z-index: 108; background: var(--color-bg); border-left: 2px solid var(--color-accent); transform: translateX(100%); visibility: hidden; overflow-y: auto; transition: transform var(--transition-snap), visibility 0s linear 0.2s; }
  .site-menu.is-open { transform: translateX(0); visibility: visible; transition: transform var(--transition-snap), visibility 0s linear 0s; }
  .site-menu__inner { display: flex; flex-direction: column; min-height: 100%; padding: calc(var(--mobile-bar-h) + var(--space-lg)) var(--space-lg) var(--space-lg); }
  .site-menu__close { position: absolute; top: calc(var(--mobile-bar-h) + var(--space-sm)); right: var(--space-md); display: flex; align-items: center; justify-content: center; width: 44px; height: 44px; background: transparent; border: 1px solid var(--color-border-light); border-radius: var(--radius-sm); font-size: 1.5rem; line-height: 1; color: var(--color-primary); }
  .site-menu__label { font-family: var(--font-mono); font-size: var(--text-meta); font-weight: 500; letter-spacing: 0.1em; text-transform: uppercase; color: var(--color-accent); margin-bottom: var(--space-lg); }
  .site-menu__list { list-style: none; margin: 0 0 var(--space-xl); padding: 0; }
  .site-menu__list li { border-bottom: 1px solid var(--color-border-light); }
  .site-menu__list a { display: flex; align-items: center; min-height: 60px; font-family: var(--font-heading); font-size: 1.5rem; font-weight: 600; letter-spacing: -0.01em; color: var(--color-primary); text-decoration: none; }
  .site-menu__list a:hover { color: var(--color-accent); }
  .site-menu__contact { display: flex; flex-direction: column; margin-bottom: var(--space-lg); }
  .site-menu__contact a { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-md); min-height: 48px; font-weight: 600; text-decoration: none; border-bottom: 1px solid var(--color-border-light); }
  .site-menu__contact span { font-family: var(--font-mono); font-size: 0.8125rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--color-text-muted); }
  .site-menu__cta { margin-top: auto; width: 100%; }
  .site-menu__overlay { display: none; position: fixed; inset: 0; background: rgba(28,28,26,0.4); z-index: 107; }
  .site-menu__overlay.is-visible { display: block; }
}

/* ===== Content Column ===== */
body { padding-left: var(--rail-width); }
@media (max-width: 900px) { body { padding-left: 0; padding-top: var(--mobile-bar-h); } }

.content-column > section { max-width: var(--frame-max); margin: 0; padding: var(--section-padding) var(--frame-pad); }
.section-num, .index-rail__num { font-family: var(--font-mono); }
h2 .section-num { display: inline-block; font-size: 0.5em; font-family: var(--font-mono); color: var(--color-accent); font-weight: 600; margin-right: var(--space-md); vertical-align: middle; }
.section-intro { color: var(--color-text-muted); margin-top: -0.25em; font-size: var(--text-subhead); }

/* ===== Hero ===== */
/* minmax(0,1fr) not minmax(340px,1fr): the 340px min-content floor plus the image
   track and gap exceeded the available width between the rail and the viewport at
   ~1024, pushing the hero image 16px past the right edge (clipped by overflow-x). */
.content-column > section.hero { display: grid; grid-template-columns: var(--text-col) minmax(0, 1fr); gap: var(--wide-gap); align-items: stretch; max-width: var(--frame-max); padding-top: 0; padding-bottom: clamp(24px, min(3.5vw, 4vh), 64px); padding-right: var(--frame-pad); }
/* 8vh cap keeps the hero CTAs inside the fold on short desktop viewports (1440x900). */
/* Round 3 hero reduction (Sean, 2026-08-27 19:44: "The hero section is too large on mobile
   and desktop."). Measured before: 1469px at 1920 (136vh), 1195 at 1440 (133vh), 1168 at 1280
   (146vh), 1575 at 375 (194vh) - nothing but the hero was reachable without scrolling at any
   width. Three causes, fixed in place rather than by shrinking the type Sean asked us to
   enlarge:
     (a) DESKTOP, the real one. .hero__image img is height:100% inside an auto-height grid row,
         so height:100% resolved to auto and the 941x1672 PORTRAIT source set the row from its
         intrinsic aspect: 773px wide x 1672/941 = 1373px tall at 1920. The image, not the copy,
         was sizing the hero. A definite max-height now bounds the row.
     (b) The 4-row stacked ledger box ran 274px desktop / 328px mobile inside the text column.
         Same four facts, same border, laid out as a 4-up (2x2 at <=900) register: ~110/~150px.
     (c) Padding. The old top pad ran to 120px and the bottom to a full --section-padding on a
         band that already opens the page.
   Target is a hero that ends inside the first screen with the next section's rule and H2
   visible under it - a confident opening, not a full-viewport billboard. */
/* ROUND 5: the hero's two bottom pads were width-driven only, so on a SHORT wide window
   (1440x800, 1366x768) they spent 108-115px of an already short first screen on air below the
   CTA row. Both now take the smaller of a width term and a height term, which is the same
   continuous-in-both-dimensions discipline the plate uses. The CTA's own 40px isolation zone
   (DL-0122) is untouched - this is the air BELOW the CTA row, not around it. */
.hero__text { padding-top: clamp(32px, min(6vw, 5vh), 72px); padding-bottom: clamp(24px, min(4vw, 3vh), 64px); }
.hero__image { min-height: 320px; max-height: min(74vh, 720px); overflow: hidden; align-self: stretch; }
.hero__image picture { display: block; width: 100%; height: 100%; }
.hero__image img { width: 100%; height: 100%; object-fit: cover; }
/* Art-directed mobile/tablet hero crops (DL-0090). The desktop source is 941x1672
   portrait; object-fit:cover squeezed it to a 140px letterbox strip at 375 that cropped
   out both the bridge and the skyline named in the alt text. Sean 2026-08-27: "Serve a
   separate mobile crop of the current image." b-hero-mobile.jpg is a 1:1 crop (skyline +
   One WTC + the bridge arch), b-hero-tablet.jpg a 3:2 crop of the same photograph.
   The lede moves below the CTAs at <=600 only, so the taller square crop does not push
   the H1/primary CTA out of the first screen (DL-0083 must stay PASS). */
/* ROUND 5, DL-0125/DL-0126 - the plate is sized by HEIGHT and keeps its source aspect.
   Every previous hero pass set the plate's aspect-ratio and let it run the full column width,
   which makes the plate's HEIGHT a function of the viewport's WIDTH - so the fix could only
   ever be true at the widths it was measured at, and round 3's answer (gate the short plate on
   `max-height: 850px`) made it true only at the heights it was measured at as well. Both are
   the same mistake: the constraint is "the plate plus the copy must fit the viewport HEIGHT",
   and neither a width breakpoint nor a height breakpoint expresses it.
   The form used from here on is
       width: min(100%, calc(<height budget> * <source aspect>));  aspect-ratio: <source aspect>;
   which caps the plate's height continuously (vh) while pinning its ratio to the shipped file's
   ratio. The plate is full-column-width on tall viewports and insets from the right on short
   ones, rather than turning into a letterbox sliver; and because the ratio is fixed per band, a
   real crop at exactly that ratio can be shipped, so object-fit has nothing left to crop.
   DL-0126 is therefore closed by the same rule that closes DL-0125, not by a separate fix. */
@media (max-width: 900px) {
  .content-column > section.hero { grid-template-columns: 1fr; }
  /* margin-inline:auto, not left-aligned: on a short-and-wide window the cap insets the plate
     from the column, and an inset pinned to the left reads as the dead right field the frame
     rules exist to prevent. Centred, it reads as a plate. */
  .hero__image { aspect-ratio: 3 / 2; width: min(100%, calc(clamp(160px, 34vh, 400px) * 3 / 2)); margin-inline: auto; min-height: 0; max-height: none; order: -1; margin-bottom: var(--space-sm); border-radius: var(--radius-md); }
  .content-column > section.hero { padding-bottom: var(--space-lg); }
  .hero__lede { margin-bottom: var(--space-sm); }
  /* The text is the LAST element once the hero stacks, so its bottom padding and the hero's own
     bottom padding were stacking into 65-96px of trailing air directly above the register band. */
  .hero__text { display: flex; flex-direction: column; padding-top: var(--space-md); padding-bottom: 0; }
  .hero__ctas { order: 1; margin-top: var(--space-md); gap: var(--space-md); }
}
@media (max-width: 600px) {
  /* 5:4, not the square: the bigger 52px H1 Sean asked for added 91px to the hero stack
     and pushed the primary CTA to y=813 in an 812px viewport, i.e. one pixel out of the
     first screen - DL-0083 fails on exactly that. Trimming the crop to 5:4 and tightening
     the text's top pad gives back 73px and puts the whole button back inside the fold,
     while keeping an art-directed mobile crop rather than the letterbox DL-0090 rejected. */
  /* 16:10 rather than round 2's 5:4 gives back 58px of the first screen. b-hero-mobile.jpg is
     a 1:1 crop with the skyline at the top and the bridge along the bottom, so a shallower
     frame at the default centre position cropped the Brooklyn Bridge out - and the bridge is
     half of what the alt text promises. Biasing the fill down the source keeps both the tower
     line and the bridge arch in frame, which is DL-0090's actual acceptance test. */
  /* The <=600 source IS 16:10 now (b-hero-mobile-16x10.jpg, cropped from the 1:1
     art-directed selection at the same 72% vertical bias the CSS used to apply). The
     rendered ratio therefore equals the file's natural ratio and object-fit has nothing
     left to crop - an art-directed crop that CSS then re-crops is not art direction, and
     re-cropping is what had all but removed the Brooklyn Bridge the alt text promises. */
  /* width:100% overrides the <=900 height cap: at phone widths the column is narrow enough that
     a 16:10 plate is already well inside the height budget (DL-0083 passes at 375/390), and an
     inset plate on a 327px column would read as a mistake rather than as an exhibit. */
  .hero__image { aspect-ratio: 16 / 10; width: 100%; }
  .hero__text { padding-top: var(--space-md); }
  /* 360px (small Android) is 32px shorter than the 375 reference and failed the same
     fold test by 10px; tightening the two display gaps clears it without touching type size. */
  .hero .eyebrow { margin-bottom: var(--space-sm); }
  .hero h1 { margin-bottom: var(--space-sm); }
  .hero__image { margin-bottom: var(--space-sm); }
  /* The lede sits below the CTAs at this width only. Sean's two constraints - an
     art-directed square mobile crop AND H1 + primary CTA inside the first screen
     (DL-0083) - cannot both hold with the lede in source order at 375; measured, the
     natural order pushes the primary CTA to y=874 in an 812px viewport. The margin
     keeps it off the outline CTA's edge (DL-0102). */
  .hero__lede { order: 2; margin-top: var(--space-lg); }
}

.hero .eyebrow { font-family: var(--font-mono); text-transform: uppercase; letter-spacing: 0.1em; font-size: 1rem; font-weight: 500; color: var(--color-accent); margin-bottom: var(--space-md); }
/* Declared after the base rule, not inside the <=600 block above it: at equal specificity
   the later rule wins, and an override placed earlier in the file is silently shadowed -
   the same ordering trap the 901-1199 media block hit in round 3. At 1rem/0.1em the
   32-character eyebrow wrapped to two lines in a 327px column, costing 27px of the first
   screen for nothing. */
@media (max-width: 600px) {
  .hero .eyebrow { font-size: 0.875rem; letter-spacing: 0.06em; }
  /* 7 lines of lede at 1.65 is 231px of a 812px screen; 1.5 is still comfortable at 20px. */
  .hero__lede { line-height: 1.5; }
}
/* var(--measure), not 60ch: 60ch of the 1.15rem lede resolves to 660px, which rendered
   78-79 chars per line wherever the hero stacks full-width (768 and, after this round,
   901-1199) - over the 75 ceiling the rest of the page holds. The shared measure token
   keeps the lede on the same track as every other body block. */
.hero__lede { font-size: var(--text-lede); color: var(--color-text-muted); max-width: var(--measure); }
/* Register strip, not a stacked list (round 3, hero-height cause (b) above). The four facts
   are unchanged and still bordered as one ledger; they now run across the column as a 4-up
   with the numeral over its label, which is also the treatment that lets the numerals stay at
   the round-2 display size without the block eating a third of the hero. */
/* ===== Register band (firm credentials, relocated out of the hero in round 3) ===== */
.content-column > section.register { padding-top: 0; padding-bottom: var(--section-padding); }
/* auto-fit + a real min track, NOT repeat(4, minmax(0,1fr)). Sean, 2026-08-27: "This text is
   mangled on variation B" - at ~1000px the four 1fr tracks resolved to ~145px each while
   "Hundreds" set in IBM Plex Mono at 32px needs 154px, and because the numerals are nowrap
   they overflowed their tracks and printed over the next stat: "HundredsEN . RU2". minmax(0,1fr)
   explicitly permits a track to shrink below its content, which is what turned a tight fit into
   an overlap instead of a reflow. With a 172px floor (the widest numeral, "Hundreds" at 32px, measures 154px) the band drops to 3-up, 2-up and 1-up on
   its own as the frame narrows, so there is no width at which a numeral can collide.
   Separators are per-cell TOP rules rather than vertical rules between columns: a vertical rule
   has to know which cell ends a row, which is exactly the assumption auto-fit removes. The top
   rule is also already this design's register vocabulary (.client-log__list li, .docket--compact
   .docket__row both use it). */
.content-column > section.register { container-type: inline-size; }
/* .register__h styling removed with the heading itself (see front-page.php). */
.ledger-box { border: 2px solid var(--color-primary); border-radius: var(--radius-md); padding: var(--space-lg); margin: var(--space-lg) 0; display: grid; grid-template-columns: 1fr; gap: var(--space-lg); }
/* Column count comes from a CONTAINER query on the band's own width, not from the viewport.
   That is the actual lesson of this defect: the viewport breakpoint (max-width: 900px) could
   not see that --rail-width and --frame-pad had already eaten the frame, so at ~1000px the
   band was still being told to render four columns in a space that only had room for about
   two and a half. A container query asks the band how wide IT is, so the two can never
   disagree. Only 1, 2 and 4 are offered - auto-fit would also have been overlap-safe here,
   but it produced a 3-up row with a single orphaned stat beneath it at ~1000px. */
@container (min-width: 420px) { .ledger-box { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@container (min-width: 800px) { .ledger-box { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-md); padding: var(--space-md); } }
.ledger-box__row { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; min-width: 0; border-top: 2px solid var(--color-primary); padding-top: var(--space-sm); }
/* clamp(2rem, 2.4vw, 2.75rem) = 32px at 375 and 44px at 1920, up from 26/32. Round 3 raised
   --text-h3 26 -> 31 and left this alone, so the firm's signature figures ($1B+, Hundreds)
   ended up 32px against a 31px card title and a 46px section heading - the credibility
   numbers were the smallest display type on the page, which is the literal content of
   Sean's twice-given "doesn't pop" note. The slope is deliberately gentle (2.4vw): at the
   4-up container threshold the tracks are ~170px and "Hundreds" in mono needs 8 x 0.6em,
   so a steeper slope re-creates the overlap this band already shipped once. */
/* ROUND 5, DL-0128. The vw clamp above reached its 2.75rem top only at 1834px: at 1440 - the
   primary desktop target - the firm's signature figures rendered 34.56px against a 46px section
   H2, i.e. still the smallest display type on the page, which is the literal content of Sean's
   twice-given "doesn't pop" note. It was verified at 1920 and nowhere else.
   The replacement is sized from the BAND's own width (cqw), not the viewport's, for the same
   reason the column count is: --rail-width and --frame-pad have already eaten the frame, so the
   viewport does not know how much room a numeral actually has. 5.2cqw - 4px is the largest size
   at which the longest numeral, "Hundreds" (8 characters x 0.6em of IBM Plex Mono advance),
   still fits its own track in the 4-up state - measured against the track formula
   (100cqw - padding - gaps)/4 at every container width from the 4-up threshold up, so the
   DL-0119 overlap cannot come back. Measured result: 40px at 1280 (was 32), 47px at 1440 (was
   34.6), 56px from 1580 up (was 44 at 1920 only). Padding and gap tighten at 4-up to buy the
   numerals the width rather than buying it out of the type.
   RESIDUAL, recorded rather than hidden: from 1280 to ~1400 the numerals land at 40-45px
   against a 46px H2. Four tracks of an 846-950px container physically cannot hold an 8-character
   mono word at 46px, so this is the band's ceiling, not an unfixed defect - and it is 1.28-1.45x
   the docket titles, where it was 0.75x the H2 and barely 1.14x the titles before. */
.ledger-box__num { font-family: var(--font-mono); font-weight: 600; font-size: clamp(2rem, calc(5.1cqw - 4.2px), 3.5rem); letter-spacing: -0.01em; line-height: 1.1; color: var(--color-accent); white-space: nowrap; }
.ledger-box__label { font-size: 1rem; color: var(--color-text-muted); }
/* 2x2 below 900: four tracks in a 327px column would give each numeral 60px, and
   "Hundreds" set in mono at 26px needs 125px. The band still costs ~150px there against
   the 328px the same four rows cost stacked inside the hero. */
/* No column-count breakpoint any more - auto-fit reflows on its own. The floor only drops at
   the very narrowest widths so a 327px column still gets one full-width stat per row rather
   than a 190px track it cannot honour. */
@media (max-width: 430px) {
  .ledger-box { gap: var(--space-md); padding: var(--space-md) var(--space-lg); }
}
/* 40px above the CTA row, not 24. Round 3 bought hero height by cutting this from 48px to
   24px and the button gap from 24px to 16px, which put the primary CTA inside the rubric's
   40px isolation zone at all five breakpoints - it had been outside it before this round.
   Height taken out of a CTA's breathing room is not a hero fix, it is a different defect. */
.hero__ctas { display: flex; flex-wrap: wrap; gap: var(--space-lg); margin-top: 40px; }

/* ===== Docket rows (Practice Areas / Matters) ===== */
/* Exhibit track and gap trimmed so the text track keeps more of the (deliberately
   narrow) document column - measured line length was below the readability floor
   at 1440. See DL-0086. */
.docket__row { display: grid; grid-template-columns: 2.5rem minmax(0, 1fr) clamp(150px, 15vw, 240px); gap: clamp(var(--space-md), 2.2vw, var(--space-lg)); align-items: center; padding: var(--space-xl) 0; border-top: var(--border-hairline); }
.docket__row:last-child { border-bottom: var(--border-hairline); }
.docket__row-num { font-family: var(--font-mono); font-size: 1.25rem; font-weight: 500; color: var(--color-accent); }
.docket__row-body a { display: inline-flex; align-items: center; min-height: 44px; font-weight: 600; text-decoration: underline; transition: color var(--transition-snap); }
.docket__row-body a:hover { color: var(--color-primary); }
/* Pending-image plate. Every image frame carries a faint ink tint so a lazy image that has
   not decoded yet reads as a plate still coming in, not as a broken one. This is the most
   likely mechanism behind Sean's 2026-08-27 "an image is showing as broken on mobile", which
   has never reproduced as an actual load failure: measured again this round, all 12 images
   return a non-zero naturalWidth and zero responses >= 400 at 1920/768/390/375 - but they
   only do so once you WAIT for img.complete. Read at a fixed 1.5s after scrolling, six of
   them are still blank frames. The page ships ~3.1MB of full-size JPEGs with no mobile
   variants (see the round notes - flagged as a recommendation, not fixed this round). */
[class*="__exhibit"], .hero__image, .founder__portrait, .offices__media, .bilingual__media { background-color: rgba(28, 28, 26, 0.06); }
.docket__row-exhibit { width: 100%; aspect-ratio: 4 / 3; border-radius: var(--radius-md); overflow: hidden; }
.docket__row-exhibit img { width: 100%; height: 100%; object-fit: cover; }
.docket__row--no-exhibit { grid-template-columns: 2.5rem 1fr; }
.docket--compact .docket__row-body p { margin-bottom: 0; }
.docket--compact .docket__row { grid-template-columns: 2.5rem minmax(0, 1fr) clamp(120px, 12vw, 160px); padding: var(--space-lg) 0; }
.docket--compact .docket__row-exhibit { border-radius: var(--radius-sm); }
.docket--compact .docket__row-body h3 { font-size: clamp(1.375rem, 1.7vw, 1.625rem); }

@media (max-width: 900px) {
  .docket__row, .docket--compact .docket__row { grid-template-columns: 1.25rem minmax(0, 1fr); gap: var(--space-sm); }
  .docket__row-exhibit { grid-column: 1 / -1; grid-row: 3; width: 100%; margin-top: var(--space-sm); }
}

/* ===== Clauses (How We Work) ===== */
.clauses__list { list-style: none; margin: 0; padding: 0; }
.clauses__list li { display: grid; grid-template-columns: 2.5rem 1fr; gap: var(--space-lg); padding: var(--space-md) 0; border-top: var(--border-hairline); }
.clauses__list li:last-child { border-bottom: var(--border-hairline); }
.clauses__num { font-family: var(--font-mono); color: var(--color-accent); }
.clauses__list h3 { margin-bottom: var(--space-sm); }
.clauses__list p { margin-bottom: 0; color: var(--color-text-muted); }

/* ===== Founder ===== */
.founder__grid { display: grid; grid-template-columns: clamp(240px, 30vw, 340px) 1fr; gap: var(--space-xl); align-items: stretch; }
.founder__portrait { width: 100%; min-height: 400px; border-radius: var(--radius-md); overflow: hidden; }
.founder__portrait img { width: 100%; height: 100%; object-fit: cover; object-position: center top; }
.founder__body { display: flex; flex-direction: column; justify-content: center; }
.founder__body a { display: inline-flex; align-items: center; min-height: 44px; font-weight: 600; text-decoration: underline; transition: color var(--transition-snap); }
.founder__body a:hover { color: var(--color-primary); }
@media (max-width: 900px) { .founder__grid { grid-template-columns: 1fr; } .founder__portrait { min-height: 280px; } }

/* ===== Ledger table (Recognition) ===== */
.ledger-table__grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0; border-top: var(--border-hairline); border-left: var(--border-hairline); }
.ledger-table__cell { padding: var(--space-lg); border-right: var(--border-hairline); border-bottom: var(--border-hairline); }
.ledger-table__num { font-family: var(--font-mono); color: var(--color-accent); display: block; margin-bottom: var(--space-sm); }
.ledger-table__cell p { margin-bottom: 0; color: var(--color-text-muted); font-size: var(--text-body); }
@media (max-width: 560px) { .ledger-table__grid { grid-template-columns: 1fr; } }

/* ===== Letterhead (Offices) ===== */
.letterhead__grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-xl); }
.letterhead__block { border-left: 3px solid var(--color-accent); padding-left: var(--space-lg); }
.letterhead__image { width: 100%; aspect-ratio: 4 / 3; border-radius: var(--radius-md); margin-bottom: var(--space-lg); overflow: hidden; }
.letterhead__image img { width: 100%; height: 100%; object-fit: cover; }
.letterhead__block a { display: inline-flex; align-items: center; min-height: 44px; margin-right: var(--space-md); text-decoration: underline; font-weight: 500; transition: color var(--transition-snap); }
.letterhead__block a:hover { color: var(--color-primary); }
@media (max-width: 900px) { .letterhead__grid { grid-template-columns: 1fr; gap: var(--space-lg); } }

/* ===== Parallel Text (Bilingual) ===== */
.parallel-text__grid { display: grid; grid-template-columns: 1fr clamp(240px, 30vw, 340px); gap: var(--space-xl); align-items: center; }
.parallel-text__image { width: 100%; aspect-ratio: 4 / 3; border-radius: var(--radius-md); overflow: hidden; }
.parallel-text__image img { width: 100%; height: 100%; object-fit: cover; }
@media (max-width: 900px) { .parallel-text__grid { grid-template-columns: 1fr; } .parallel-text__image { order: -1; } }
.parallel-text__quote { margin: 0 0 var(--space-lg); border-left: 3px solid var(--color-accent); padding-left: var(--space-lg); }
.parallel-text__ru { font-family: var(--font-heading); font-style: italic; font-size: 1.75rem; margin-bottom: var(--space-sm); }
.parallel-text__en { font-family: var(--font-heading); font-size: 1.75rem; color: var(--color-text-muted); margin-bottom: 0; }
.parallel-text__body { color: var(--color-text-muted); }

/* ===== Client Log (Testimonials) ===== */
.client-log__list { list-style: none; margin: 0; padding: 0; }
.client-log__list li { padding: var(--space-lg) 0; border-top: var(--border-hairline); }
.client-log__list li:last-child { border-bottom: var(--border-hairline); }
.client-log__num { font-family: var(--font-mono); color: var(--color-accent); display: block; margin-bottom: var(--space-sm); }
.client-log__list blockquote { margin: 0 0 var(--space-sm); font-family: var(--font-heading); font-size: clamp(1.25rem, 1.45vw, 1.5rem); font-style: italic; }
.client-log__list cite { font-style: normal; font-size: var(--text-meta); color: var(--color-text-muted); }

/* ===== Clause FAQ ===== */
.clause-faq__box { border: var(--border-hairline); border-radius: var(--radius-md); overflow: hidden; }
.clause-faq__box details { border-bottom: var(--border-hairline); }
.clause-faq__box details:last-child { border-bottom: none; }
/* The DCD's S-016 commits Source Serif 4 for the FAQ questions and they ship in IBM Plex Sans.
   Round 5 swapped them and REVERTED the same round: Sean considered the page fine, so a visible
   change to type he has already seen and not objected to is not ours to make unasked. Logged,
   not shipped. */
.clause-faq__box summary { display: flex; align-items: baseline; gap: var(--space-md); padding: var(--space-lg); cursor: pointer; list-style: none; font-size: var(--text-subhead); font-weight: 600; min-height: 44px; transition: background-color var(--transition-snap); }
.clause-faq__box summary:hover { background-color: rgba(110,30,43,0.05); }
.clause-faq__box summary::-webkit-details-marker { display: none; }
/* Disclosure affordance: without it the four rows read as static ruled lines and
   nothing tells a visitor the answers are there. Mono +/- in the accent, right-aligned. */
.clause-faq__box summary::after { content: '+'; margin-left: auto; flex-shrink: 0; font-family: var(--font-mono); font-size: 1.5rem; font-weight: 400; line-height: 1; color: var(--color-accent); transition: transform var(--transition-snap); }
.clause-faq__box details[open] summary::after { content: '\2212'; }
.clause-faq__num { font-family: var(--font-mono); color: var(--color-accent); flex-shrink: 0; }
/* max-width, not just padding: at 1920 a half-frame FAQ column runs 668px, which put
   the answers at 74-82 chars per line - over the readability ceiling (DL-0104). */
.clause-faq__box details p { padding: 0 var(--space-lg) var(--space-lg) calc(var(--space-lg) + 2.5rem); max-width: calc(var(--measure) + var(--space-lg) + 2.5rem); color: var(--color-text-muted); margin: 0; }
.clause-faq__box summary:focus-visible { outline: 2px solid var(--color-accent); outline-offset: -2px; }

/* ===== Final engagement CTA ===== */
.final-engagement__box { text-align: left; border: 2px solid var(--color-accent); border-radius: var(--radius-md); padding: var(--space-xl); }
.final-engagement h2 { margin-bottom: var(--space-sm); }
.final-engagement p { margin-bottom: var(--space-lg); }

/* ===== Footer ===== */
.site-footer { max-width: var(--frame-max); margin: 0 0 var(--space-xl); padding: var(--space-xl) var(--frame-pad) var(--space-lg); border-top: var(--border-hairline); }
.site-footer__inner { display: flex; flex-direction: column; gap: var(--space-md); }
.site-footer__offices { display: flex; flex-wrap: wrap; gap: var(--space-xl); margin-bottom: var(--space-md); }
.site-footer__nav { display: flex; flex-wrap: wrap; gap: var(--space-lg); }
.site-footer__office-label { font-family: var(--font-mono); font-size: var(--text-meta); font-weight: 500; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-accent); margin: 0 0 var(--space-sm); }
.site-footer__office address { font-style: normal; font-size: 1.0625rem; color: var(--color-text-muted); line-height: 1.6; }
.site-footer a { color: var(--color-text-muted); text-decoration: none; min-height: 44px; display: inline-flex; align-items: center; }
.site-footer a:hover { color: var(--color-accent); }
.site-footer__disclaimer, .site-footer__copyright { font-size: 0.8125rem; color: var(--color-text-muted); margin: 0; }
@media (max-width: 900px) { .site-footer { margin-left: auto; } }

/* ===== Margin note (the brief's right-hand marginalia) =====
   Occupies the right track of an otherwise image-free section. Content is entirely
   facts already on the page (both office numbers, the consultation CTA, the bilingual
   promise) - nothing invented. */
.margin-note { border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: var(--space-lg); align-self: start; }
.margin-note__label { font-family: var(--font-mono); font-size: var(--text-meta); letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-accent); margin-bottom: var(--space-md); }
.margin-note__body { color: var(--color-text-muted); font-size: 1.0625rem; }
.margin-note__list { list-style: none; margin: 0 0 var(--space-lg); padding: 0; }
.margin-note__list li { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-md); border-bottom: 1px solid var(--color-border-light); }
.margin-note__list li:last-child { border-bottom: none; }
.margin-note__list span { font-family: var(--font-mono); font-size: var(--text-meta); color: var(--color-text-muted); }
.margin-note__list a { min-height: 44px; display: inline-flex; align-items: center; text-decoration: none; font-weight: 600; }
.margin-note__list a:hover { color: var(--color-primary); }
.margin-note .btn { width: 100%; }
.clauses__grid, .client-log__grid { display: grid; gap: var(--wide-gap); }

/* 901-1199: the wide document grid has not kicked in yet and the hero row still
   stretches to the text column's height, rendering the portrait source as a
   full-height 1:4 pillarbox strip (275x1179 at 1024). Cap it, and give the split
   sections their full width back so the measure recovers. See DL-0101. */
/* ===== Short desktop viewports (laptops) ===== */
/* Two defects, both only visible when the viewport is SHORT rather than narrow, which is why
   a breakpoint set that tests 1024x768 and 1440x900 by width alone kept missing them.
   Found in the round-3 review.

   1. THE RAIL WAS HIDING A THIRD OF THE SITE INDEX. .index-rail__toc is a scroll container,
      so at 1024x768 its 9 links needed 478px and got 323px: 07 Matters, 08 Client Log and
      09 Questions were scrolled out of view with no scrollbar, no fade, no affordance of any
      kind. A visitor on the most ordinary laptop resolution saw a six-item firm. It is not a
      clipping bug - it is worse, because the rail looked complete. Round 3 made it worse by
      raising the rail links 16->17px and the brand 21.6->23px, but the collision pre-dates
      this round at 1440x900 too (460px of space for 478px of links, so 09 was already cut).
      Fixed by giving the TOC the room instead of shrinking the type Sean asked us to enlarge:
      the rail's own chrome (brand gap, contact block, language toggle, CTA) is compressed at
      short heights, and the link rows tighten from 0.65em to 0.4em of vertical padding. The
      44px touch floor is deliberately kept - the rail is pointer-only, but the target size is
      still the right default.
   2. THE 1024 HERO WAS 138% OF VIEWPORT. Round 3's hero pass measured 1920/1440/1280/768/390/
      375 and skipped 1024 - the one width where the hero STACKS, so a 3:2 plate sits above the
      copy and the whole text column starts below the fold. A shallower plate at short heights
      brings it back. */
@media (min-width: 901px) and (max-height: 950px) {
  .index-rail__inner { padding-top: var(--space-md); padding-bottom: var(--space-sm); }
  .index-rail__brand { margin-bottom: var(--space-lg); }
  .index-rail__toc a { padding-top: 0.4em; padding-bottom: 0.4em; }
  .index-rail__contact { margin: var(--space-md) 0 var(--space-sm); gap: 2px; }
  .index-rail__contact a { min-height: 32px; }
  .index-rail__lang-toggle { margin-bottom: var(--space-md); }
  .index-rail .btn { min-height: 44px; padding: 10px 20px; font-size: 1rem; }
}
/* The stacked-hero band specifically: a 3:2 plate is 480px of a 768px screen before the
   headline starts. 21:9 keeps a real photographic plate while leaving the H1, the lede and
   the CTAs room to land inside the first screen. */
/* Selectors are deliberately over-specific (.content-column > section.hero .hero__image, not
   .hero__image). This block has to beat the 901-1279 block BELOW it, which sets aspect-ratio
   3/2 on the same element - and at equal specificity the later rule wins regardless of how
   narrow its media query is. Ordering has now silently swallowed a fix three times on this
   theme (the 901-1199 block in round 3, the <=600 eyebrow override earlier this round, and
   this one), so the height rules are pinned by specificity instead of by position. */
/* ROUND 5, DL-0125. The block that used to live here was gated `max-height: 850px`, so the
   short-hero treatment applied only to short windows: measured on the live plain URL, any
   1025-1279 window taller than 850px got the 3:2 plate back and the hero ran 113-139% of
   viewport with the primary CTA below the fold (1024x900 119.1%, 1152x900 129.5%, 1100x1000
   112.7%, 1279x900 133.8%). The gate is gone. The band now uses the height-budgeted plate form
   documented above, which is continuous in BOTH dimensions and therefore has no "just outside
   the measured set" to fail in: 32vh caps the plate, 12/5 pins its ratio to the shipped
   b-hero-pano-12x5.jpg, and the reclaimed padding buys the copy the rest. */
@media (min-width: 901px) and (max-width: 1279px) {
  .content-column > section.hero .hero__image { aspect-ratio: 12 / 5; width: min(100%, calc(clamp(180px, 32vh, 380px) * 12 / 5)); margin-inline: auto; min-height: 0; max-height: none; margin-bottom: var(--space-md); }
  .content-column > section.hero { padding-top: var(--space-lg); padding-bottom: var(--space-lg); }
  .content-column > section.hero .hero__text { padding-bottom: 0; }
}

@media (min-width: 901px) and (max-width: 1279px) {
  /* The 280px rail plus a 6vw frame pad on both sides leaves only 622px of content at
     1024, which starved every track in this band: the hero lede measured 31-37 chars
     per line and the practice-area exhibits fell back to 154x115. Narrowing the rail and
     the pad in this band only recovers ~100px, which is what puts the measure back above
     the 45-char floor and the exhibits back at a legible 16:9. See DL-0101. */
  :root { --rail-width: 232px; --frame-pad: clamp(24px, 3.5vw, 48px); }
  /* Hero stacks in this band rather than splitting. Side by side, the image track can
     only take what is left after a 45-char measure, which at 1024 is 291px - a small
     inset floating beside a much taller text column, not a hero. Stacked at 16:9 it
     spans the full 720px content width, the same treatment that already reads correctly
     at 768. The rail's own always-visible "Schedule a Consultation" CTA carries the
     in-fold conversion path at this height, so pushing the hero CTAs below 768 costs
     nothing (they were already at y=815 before this change). 3:2, not 16:9, so the
     b-hero-tablet.jpg source (1200x800) fills the frame with no second crop - the
     <picture> media query was widened to 1199 for the same reason. */
  /* padding-top and the plate's ratio/height are set by the ROUND 5 block above, which is
     pinned by specificity (.content-column > section.hero .hero__image) precisely so that
     adding rules here can never silently shadow it again - the ordering trap that has now
     swallowed a correct fix four times on this theme. Do not re-add aspect-ratio,
     margin-bottom or padding-top for the hero here. */
  .content-column > section.hero { grid-template-columns: 1fr; }
  .hero__image { min-height: 0; order: -1; border-radius: var(--radius-md); }
  .hero__text { padding-top: 0; }
  .docket__row { grid-template-columns: 2.5rem minmax(0, 1fr) clamp(200px, 22vw, 300px); }
  .docket--compact .docket__row { grid-template-columns: 2.5rem minmax(0, 1fr) clamp(180px, 20vw, 260px); }
  .docket__row-exhibit { aspect-ratio: 16 / 9; }
  .founder__grid, .parallel-text__grid { grid-template-columns: 1fr; }
  /* The stacked grid let the bio run the full 720px content width at 1024, measured at
     84-85 chars per line - the widest prose on the page and well over the 75 ceiling. */
  .founder__grid p, .parallel-text__grid p { max-width: var(--measure); }
  .founder__portrait { aspect-ratio: 16 / 9; min-height: 0; }
  .parallel-text__image { aspect-ratio: 16 / 9; }
  .ledger-table__grid { grid-template-columns: 1fr; }
}

/* ===== Wide-frame document grid (>=1280px) =====
   The frame runs the full width left of the viewport edge, so every section has to put
   real content in its right-hand track: exhibit imagery grows to fill it, the image-free
   "How We Work" section gains a margin note, the Client Log becomes a three-up register
   of cards, Representative Matters becomes an exhibit grid, and the FAQ splits into two
   clause columns.

   1280, not 1200: measured at 1200 the wide grid switched on before there was width for
   it - the hero text column fell to 388px, the hero image to 346px with 254px of dead air
   above it, and the H1 went to four lines, so 1199 rendered better than 1200. The 901-1199
   band rules were widened to 1279 to match. */
@media (min-width: 1280px) {
  .content-column > section.hero { align-items: center; }
  /* ROUND 5, DL-0126. The two-column plate had NO ratio of its own: its width came from the
     grid track and its height from `align-self: stretch` against the text column, so the
     rendered ratio was whatever the viewport happened to make it and object-fit:cover threw
     away the difference. Measured against the source's own 941x1672: 18% off at 1440, 106% off
     at 1920 - i.e. more than half the photograph discarded, and a different half at every
     width. Now the plate is a fixed 3:4 and b-hero-desktop-3x4.jpg is cropped to exactly 3:4
     from the same frame (spire down to the tower base, both subjects the alt text names), so
     the shipped pixels are the displayed pixels at every width in the band. The width cap
     keeps the old min(74vh, 720px) height ceiling that bounds the hero at 1920. */
  .hero__image { aspect-ratio: 3 / 4; width: min(100%, calc(min(74vh, 720px) * 3 / 4)); min-height: 0; max-height: none; align-self: center; }

  .docket__row { grid-template-columns: 2.5rem var(--text-col) minmax(0, 1fr); gap: var(--wide-gap); }

  /* DL-0107: the wide-frame block had given .docket--compact byte-identical column values
     to the base .docket__row - same 40px/576px/666px tracks, same 666x374 exhibits - so
     Representative Matters rendered as an exact repeat of Practice Areas, two ~2000px-tall
     sections reading as the same section twice. The DCD asks for "the same row treatment,
     smaller"; at this frame width "smaller rows" would just reintroduce a dead right field,
     so the compact variant becomes a three-up exhibit register instead: same numerals, same
     hairline rules, same type, different skeleton. */
  .docket--compact { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-lg); align-items: start; }
  .docket--compact > h2 { grid-column: 1 / -1; }
  /* single column inside the card: with the numeral in its own 40px track the body copy lost
     40px of an already narrow card. The numeral now sits on its own line above the title,
     which is also closer to how an exhibit label reads on a real document. */
  .docket--compact .docket__row { display: grid; grid-template-columns: minmax(0, 1fr); grid-template-areas: "exhibit" "num" "body"; gap: var(--space-sm); padding: var(--space-lg) 0 0; border-top: 2px solid var(--color-primary); border-bottom: none; align-items: start; }
  .docket--compact .docket__row:last-child { border-bottom: none; }
  .docket--compact .docket__row-exhibit { grid-area: exhibit; aspect-ratio: 4 / 3; margin-bottom: var(--space-sm); }
  .docket--compact .docket__row-num { grid-area: num; }
  .docket--compact .docket__row-body { grid-area: body; }
  .docket__row-exhibit { aspect-ratio: 16 / 9; }

  .clauses__grid { grid-template-columns: var(--text-col) minmax(0, 1fr); align-items: start; }

  /* aspect-ratio, not min-height: the portrait div had no ratio, so once its track
     widened to ~790px the img's intrinsic portrait aspect made the section 1,285px tall. */
  .founder__grid { grid-template-columns: minmax(0, 1fr) var(--text-col); }
  .founder__portrait { aspect-ratio: 3 / 2; min-height: 0; }
  /* center, not "center top": in a landscape frame the top of this portrait source is
     window and bookcase only - the desk, open book and clock that ARE the subject sit
     mid-frame. */
  .founder__portrait img { object-position: center; }

  .letterhead__image { aspect-ratio: 3 / 2; }

  .parallel-text__grid { grid-template-columns: var(--text-col) minmax(0, 1fr); }
  .parallel-text__image { aspect-ratio: 3 / 2; }

  /* DL-0106: the previous treatment put the quote in the text track and floated the
     attribution under a hairline at the frame's right edge. Measured, that left more than
     900px of the 1638px frame empty on 56% of the section's inked rows (p75 71%) - a
     signature rule tethered to the smallest type on the page, drawing the eye to exactly
     the emptiness it was meant to hide. Three entries across the frame instead: each is a
     ruled register card that occupies its own column, so the section fills the width with
     content rather than with a device. */
  /* stretch, not start: the three quotes differ in length, and with start-aligned tracks
     the closing hairline under each attribution landed at three different heights. */
  /* repeat(3), not auto-fit: there are exactly three entries, and auto-fit dropped to two
     columns below 1600, which left the third card alone on a second row with half the frame
     empty beside it - the same void DL-0106 was logged for, moved down one row. */
  .client-log__list { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-lg); align-items: stretch; }
  .client-log__list li { display: flex; flex-direction: column; border-top: 2px solid var(--color-primary); padding-top: var(--space-lg); }
  /* DL-0127: the base `li:last-child { border-bottom }` is a STACKED-list rule - in a stacked
     list the last entry needs a closing rule, in a three-column grid the "last" entry is just
     the right-hand column, so entry 3 alone grew a hairline under it and its cite sat 1px lower
     than the other two. The register discipline of this section is top rules only. */
  .client-log__list li:last-child { border-bottom: none; }
  .client-log__num { margin-bottom: var(--space-md); }
  .client-log__list blockquote { flex: 1 1 auto; margin-bottom: var(--space-lg); }
  .client-log__list cite { display: block; border-top: 1px solid var(--color-border-light); padding-top: var(--space-sm); }

  .clause-faq__box { display: grid; grid-template-columns: 1fr 1fr; }
  .clause-faq__box details { border-bottom: none; border-right: var(--border-hairline); }
  .clause-faq__box details:nth-child(2n) { border-right: none; }
  .clause-faq__box details:nth-child(-n+2) { border-bottom: var(--border-hairline); }

  .final-engagement__box { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--wide-gap); align-items: center; }
  .final-engagement__box .btn { justify-self: end; }
  .final-engagement__copy p { margin-bottom: 0; }
}

/* ===== Reveal-on-scroll: quick, no vertical translate (per DCD motion identity) ===== */
.js .reveal { opacity: 0; transition: opacity 0.22s cubic-bezier(0.4, 0, 0.2, 1); }
.js .reveal.is-visible { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .js .reveal { opacity: 1; transition: none; } }

/* 1280-1599: the three-up exhibit register above needs about 456px a card to hold a
   readable measure; at 1440 it gave 313px and the matter descriptions fell to 26-39 chars
   per line. In this band Representative Matters keeps the base row skeleton but takes a
   capped exhibit track instead of a 1fr one, so the difference from Practice Areas is the
   proportion (DL-0107 still holds: 280px vs 353px exhibits at 1440) and the freed width
   goes to the text rather than to a dead field. */
@media (min-width: 1280px) and (max-width: 1599px) {
  .docket--compact { display: block; }
  .docket--compact .docket__row { display: grid; grid-template-columns: 2.5rem minmax(0, 1fr) clamp(240px, 20vw, 300px); grid-template-areas: none; gap: var(--wide-gap); padding: var(--space-lg) 0; border-top: var(--border-hairline); align-items: center; }
  /* grid-area MUST be reset to auto. The >=1280 block assigns named areas
     (exhibit/num/body) to these three children; clearing grid-template-areas on the parent
     without clearing the children left every named placement dangling, which grid resolves
     by inventing implicit named lines - the row computed as
     "40px 0px 288px 0px 457.656px" and the body copy was thrown to x=896, off the right of
     its own exhibit. Measured before the fix; this is why the section rendered as images
     with no text at 1280-1599. */
  .docket--compact .docket__row-num,
  .docket--compact .docket__row-body,
  .docket--compact .docket__row-exhibit { grid-area: auto; }
  .docket--compact .docket__row-exhibit { aspect-ratio: 3 / 2; margin-bottom: 0; }
  .docket--compact .docket__row-body p { max-width: var(--measure); }
}
