/* ============================================================
   Attieh & Chebli — components.css
   Every component in the locked inventory (§7.3), to the
   locked specifications (§3.3). Surface-agnostic: all color
   through the contextual tokens set by .surface-* classes.
   ============================================================ */

/* ============================================================
   HEADER
   Utility bar + primary bar. Dark identity surface.
   Homepage variant: .header-transparent over the hero.
   ============================================================ */

.site-header {
  position: sticky;
  inset-block-start: 0;
  z-index: 100;
  background-color: var(--surface);
  transition: background-color var(--motion-header) var(--ease-standard),
              box-shadow var(--motion-header) var(--ease-standard);
}

.site-header.is-scrolled {
  box-shadow: var(--elevation-sticky);
}

.header-transparent {
  position: absolute;
  inset-inline: 0;
  background-color: transparent;
}

.header-transparent.is-scrolled {
  position: fixed;
  background-color: var(--surface);
}

/* ---- Utility bar ---- */

.utility-bar {
  border-block-end: var(--rule-width) solid var(--rule);
}

.utility-bar-inner {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-5);
  padding-block: var(--space-2);
  font-size: var(--size-overline);
  color: var(--text-muted);
}

.utility-group {
  display: flex;
  align-items: center;
  gap: var(--space-4);
}

.utility-sep {
  inline-size: var(--rule-width);
  block-size: 1em;
  background-color: var(--rule);
}

.utility-offices a,
.utility-lang a {
  text-decoration: none;
  color: var(--text-muted);
}

.utility-offices a:hover,
.utility-lang a:hover {
  color: var(--accent);
}

.utility-lang [aria-current] {
  color: var(--text);
}

/* AR/FR disabled site-wide (owner task) -- translations aren't
   ready yet. Kept visible rather than removed so it's clear more
   languages are coming, but non-interactive: no href (not a real
   link, not in tab order without an explicit tabindex), aria-disabled
   for assistive tech, pointer-events:none as the enforcement layer
   since a stray click handler elsewhere couldn't accidentally act on
   it, dimmed to signal the disabled state visually. EN is unaffected. */
.utility-lang a[aria-disabled="true"] {
  opacity: 0.4;
  pointer-events: none;
  cursor: not-allowed;
}

.utility-lang a[aria-disabled="true"]:hover {
  color: var(--text-muted);
}

@media (max-width: 899px) {
  .utility-bar { display: none; }
}

/* ---- Primary bar ---- */

.primary-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-6);
  padding-block: var(--header-bar-block);
  transition: padding var(--motion-header) var(--ease-standard);
}

.is-compressed .primary-bar {
  padding-block: var(--header-bar-block-compressed);
}

.brand {
  display: inline-block;
  text-decoration: none;
}

/* Fallback wordmark — replaced by the exact Corporate A BQ
   logo SVG before launch (§7.6); never re-set in a substitute face. */
.brand-wordmark {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--size-h3);
  line-height: 1;
  color: var(--text);
  letter-spacing: 0.01em;
  white-space: nowrap;
}

/* Header wordmark (owner task, 2026-08-21): after a same-day back-
   and-forth trying to match the header to the full logo artwork
   (smaller ampersand, then Corporate A BQ + versal caps, then a
   corrected ampersand size), the owner asked to just match it to the
   footer instead -- .footer-brand .brand-wordmark below is plain
   Cormorant Garamond text with no per-character sizing at all. The
   header is now the same: no .amp override, no versal spans (markup
   reverted to plain "Attieh &amp; Chebli" to match). Font-size still
   differs from the footer (--size-h3 vs --size-h4, header.brand-
   wordmark's own base rule above) since that's the pre-existing,
   untouched size difference between the two contexts -- "similar to
   the footer" was about the ampersand/caps treatment, not making the
   two identical in scale. Corporate A BQ's @font-face is left active
   in fonts.css/assets/fonts/ in case this is picked up again later;
   nothing in the header currently references it. */

/* ---- Primary nav ---- */

.nav-primary {
  display: none;
}

@media (min-width: 900px) {
  .nav-primary {
    display: flex;
    align-items: center;
    gap: var(--space-6);
  }
}

.nav-item {
  position: relative;
}

.nav-link {
  display: inline-block;
  position: relative;
  padding-block: var(--space-2);
  font-size: var(--size-nav);
  font-weight: 500;
  color: var(--text);
  text-decoration: none;
  background: none;
  border: 0;
  cursor: pointer;
}

/* Active/hover: 1px bronze detail underline, offset 8px,
   animating from the start. */
.nav-link::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: calc(-1 * var(--space-1));
  block-size: var(--rule-width);
  background-color: var(--accent-detail);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform var(--motion-base) var(--ease-standard);
}

.nav-link:hover::after,
.nav-link[aria-current="page"]::after,
.nav-item.is-open > .nav-link::after {
  transform: scaleX(1);
}

.nav-link:hover {
  color: var(--text);
}

/* Contact — the distinguished ghost button */
.nav-cta {
  display: inline-block;
  padding: var(--space-2) var(--space-4);
  border: var(--rule-width) solid var(--btn-fg);
  color: var(--btn-fg);
  font-size: var(--size-nav);
  font-weight: 500;
  text-decoration: none;
  transition: background-color var(--motion-base) var(--ease-standard),
              color var(--motion-base) var(--ease-standard);
}

.nav-cta:hover {
  background-color: var(--btn-fg);
  color: var(--btn-fill-text);
  text-decoration: none;
}

/* ---- Dropdown panels (structured panels, not mega menus) ---- */

.nav-panel {
  position: absolute;
  inset-block-start: 100%;
  inset-inline-start: 0;
  min-inline-size: 16rem;
  padding: var(--space-5);
  background-color: var(--navy-900);
  border: var(--rule-width) solid var(--rule);
  box-shadow: var(--elevation-dropdown);
  opacity: 0;
  transform: translateY(var(--space-1));
  visibility: hidden;
  transition: opacity var(--motion-dropdown) var(--ease-out),
              transform var(--motion-dropdown) var(--ease-out),
              visibility 0s linear var(--motion-dropdown);
}

.nav-item.is-open > .nav-panel {
  opacity: 1;
  transform: translateY(0);
  visibility: visible;
  transition-delay: 0s;
}

.nav-panel a {
  display: block;
  padding-block: var(--space-2);
  font-size: var(--size-nav);
  color: var(--text-on-dark);
  text-decoration: none;
  white-space: nowrap;
}

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

/* Insights hierarchy (owner task): "All Insights" is the section's
   parent destination and keeps the panel's normal left alignment;
   "Guides & Publications" and "Library" are its subsections and are
   offset one small spacing token to the right. Alignment alone carries
   the hierarchy — no bullets, tree lines, arrows, icons or boxes. The
   slightly muted tone is the same subordinate treatment .drawer-sub
   links already use, not a new colour. Reused by the mobile drawer
   below so both navigations read identically. */
.nav-panel a.nav-sub,
.drawer-sub a.nav-sub {
  padding-inline-start: var(--space-4);
  color: var(--text-muted);
}

.nav-panel a.nav-sub:hover,
.drawer-sub a.nav-sub:hover {
  color: var(--accent-hover);
}

.nav-panel-columns {
  display: flex;
  gap: var(--space-7);
  /* Wide panel: anchor to the item's end edge so it never
     overflows the viewport (hidden panels keep layout size). */
  inset-inline-start: auto;
  inset-inline-end: 0;
}

.nav-panel-col .overline {
  margin-block-end: var(--space-3);
  white-space: nowrap;
}

/* ---- Nav toggle (mobile) ---- */

.nav-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2);
  background: none;
  border: 0;
  color: var(--text);
  font-size: var(--size-nav);
  cursor: pointer;
}

@media (min-width: 900px) {
  .nav-toggle { display: none; }
}

/* ============================================================
   DRAWER — single full-screen mobile navigation
   ============================================================ */

/* Markup carries .surface-darkest; all color is contextual. */
.drawer {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  flex-direction: column;
  padding: var(--space-5) var(--side-pad) var(--space-7);
  overflow-y: auto;
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--motion-base) var(--ease-standard),
              visibility 0s linear var(--motion-base);
}

.drawer.is-open {
  opacity: 1;
  visibility: visible;
  transition-delay: 0s;
}

.drawer-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-block-end: var(--space-5);
  border-block-end: var(--rule-width) solid var(--rule);
  margin-block-end: var(--space-5);
}

.drawer-close {
  background: none;
  border: 0;
  color: var(--text);
  padding: var(--space-2);
  cursor: pointer;
}

.drawer-link {
  display: block;
  padding-block: var(--space-3);
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--size-h3);
  color: var(--text);
  text-decoration: none;
}

.drawer-link:hover {
  color: var(--accent-hover);
}

/* Drawer accordion triggers (The Firm / Capabilities / Insights on
   mobile and tablet) reuse the existing .accordion-trigger mechanism
   from main.js (aria-expanded toggling, aria-controls, one-open-
   per-group) so no new JS is needed. .accordion-trigger is a
   general-purpose component (font-size: var(--size-body), font-
   weight: 500, hover color: var(--accent)) meant for its own,
   non-drawer use elsewhere — left untouched here so any future
   non-drawer accordion keeps sensible defaults. This combined-class
   rule instead restates every .drawer-link typography/color property
   these buttons need, explicitly, so nothing about .accordion-trigger
   (now or added later) can leak through:
   - font-family/font-weight/font-size/color mirror .drawer-link
     exactly; color and font-size carry !important because those are
     the two properties .accordion-trigger's base rule and its own
     :hover rule (color: var(--accent), a light blue on dark
     surfaces) directly compete for — normal-weight declarations here
     already win on specificity (.drawer-link.accordion-trigger is
     two classes vs .accordion-trigger's one), but !important removes
     any doubt, present or future.
   - appearance: none removes the browser's native <button> widget
     hinting (unstyled buttons default to appearance: auto; <a> tags
     never have this) so no platform-specific rendering variance is
     possible.
   - padding-inline: 0 removes the browser's own default inline
     button padding (~6px), which .accordion-trigger's padding-block-
     only reset never touched — without this the trigger's label sat
     indented relative to the plain-<a> drawer-link items beside it.
   Scoped to elements carrying both classes only — does not touch
   .drawer-link, .accordion-trigger, or any other component
   elsewhere. */
.drawer-link.accordion-trigger {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--size-h3) !important;
  color: var(--text) !important;
  padding-block: var(--space-3);
  padding-inline: 0;
  appearance: none;
}

.drawer-link.accordion-trigger:hover {
  color: var(--accent-hover) !important;
}

.drawer-sub {
  padding-inline-start: var(--space-4);
}

.drawer-sub a {
  display: block;
  padding-block: var(--space-2);
  font-size: var(--size-nav);
  color: var(--text-muted);
  text-decoration: none;
}

.drawer-sub a:hover {
  color: var(--accent-hover);
}

/* Persistent contact block at drawer foot */
.drawer-contact {
  margin-block-start: auto;
  padding-block-start: var(--space-6);
  border-block-start: var(--rule-width) solid var(--rule);
  font-size: var(--size-small);
  color: var(--text-muted);
}

/* Owner task: the two office rows previously ran together (the global
   reset zeroes p margins), so the second gets a clear interval -- enough
   that the two entries read as separate offices and scan quickly.
   This is margin BETWEEN the blocks only: line-height inside each block
   is untouched, so each office stays internally compact. */
.drawer-contact p + p {
  margin-block-start: var(--space-5);
}

/* The city name is the only clickable part of the row. Weight is the
   only change: size, family and colour stay inherited from
   .drawer-contact, and the underline is the site's standard inline-link
   treatment, matching the email links beside it. */
.drawer-office-city {
  font-weight: 600;
}

/* ============================================================
   BUTTONS & EDITORIAL LINKS
   One .btn per viewport-height; secondary = .link-editorial.
   ============================================================ */

.btn {
  display: inline-block;
  padding: var(--space-3) var(--space-5);
  border: var(--rule-width) solid var(--btn-fg);
  background: transparent;
  color: var(--btn-fg);
  font-family: var(--font-text);
  font-size: var(--size-nav);
  font-weight: 500;
  letter-spacing: 0.02em;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--motion-base) var(--ease-standard),
              color var(--motion-base) var(--ease-standard);
}

.btn:hover {
  background-color: var(--btn-fg);
  color: var(--btn-fill-text);
  text-decoration: none;
}

/* Editorial link: text + extending gold rule + typographic "→" */
.link-editorial {
  display: inline-block;
  position: relative;
  padding-block-end: var(--space-2);
  font-size: var(--size-nav);
  font-weight: 500;
  color: var(--text);
  text-decoration: none;
}

.link-editorial::after {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  inset-block-end: 0;
  inline-size: var(--rule-accent-length);
  block-size: var(--rule-width);
  background-color: var(--accent-detail);
  transition: inline-size var(--motion-base) var(--ease-standard);
}

.link-editorial:hover {
  color: var(--accent);
  text-decoration: none;
}

.link-editorial:hover::after {
  inline-size: 100%;
}

/* Owner task (revised: all three homepage Capabilities subsections,
   not just International): each "Explore ___ Practice ->" moved from
   a .stack-6 sibling below its .grid-cards to a 4th grid item inside
   it, so it can be positioned per-breakpoint with the grid itself
   instead of just flowing full-width under the row. Scoped to
   #capabilities (the homepage section's own id) rather than a bare
   .grid-cards selector, since .grid-cards is also used on the
   capability hub pages (capabilities/international/, /lebanon/,
   /united-states/) and several /preview/ sandbox pages -- this rule
   should only ever touch the three homepage rows. Below 640px
   .grid-cards is a single column, so the CTA already lands in its
   own row under the 3 cards with no extra CSS -- matches "keep the
   current mobile position" without duplicating any rules.
   Typography/hover/underline are all inherited from .link-editorial
   above, untouched. */
@media (min-width: 640px) and (max-width: 899.98px) {
  /* Tablet (2 columns): normal grid auto-placement already puts this
     4th item in column 2 row 2 -- the cell beside card 3 (card 3
     lands in column 1 row 2, since cards 1-2 fill row 1) -- so no
     grid-column/row is needed, only vertical centering so it reads
     as balanced against card 3's taller box rather than pinned to
     the top of the cell. */
  #capabilities .grid-cards > .link-editorial {
    align-self: center;
    justify-self: start;
  }
}

@media (min-width: 900px) {
  /* Desktop (3 columns): span the full row so the link still reads
     as one line beneath all three cards -- not merely under card 1
     -- and as the transition into the next subsection below, left-
     aligned (justify-self: start) to match the subsection's own
     overline/title at the row's start. (Reverted: an earlier pass
     centered this CTA and the title together, but the owner asked to
     undo that back to this left-aligned version.) */
  #capabilities .grid-cards > .link-editorial {
    grid-column: 1 / -1;
    justify-self: start;
  }
}

/* ============================================================
   SECTION / PAGE HEADERS — the signature stack
   .overline → .rule-accent → heading → optional .lead
   ============================================================ */

.section-header {
  margin-block-end: var(--space-7);
}

.section-header .rule-accent {
  margin-block-end: var(--space-5);
}

.section-header .lead {
  margin-block-start: var(--space-5);
}

/* ---- Canonical BODY -> CTA spacing ----
   Semantic contract: whatever immediately follows a section's body
   copy and invites action (a bordered .btn or an editorial
   .link-editorial) sits var(--space-5) (24px) below it, regardless
   of which CTA element renders it — the button's own internal
   padding and the link's own underline are never what supply this
   external gap.

   Structural note (the "For Law Firms" bug): when such a CTA is a
   *direct sibling* of .section-header inside a .stack-7 container
   (only one homepage section does this — .section-header's own
   trailing margin (--space-7, 48px, correct for the unrelated
   "heading-block -> content group/list" relationship used e.g. by
   Capabilities) and .stack-7's generic sibling gap (also 48px) both
   land on the CTA at once, because .btn is display:inline-block and
   inline-block boxes never participate in margin collapsing — so
   the two 48px margins simply added together into a 96px gap
   instead of collapsing into one. Below, .section-header's own
   trailing margin is zeroed for precisely this adjacency (nothing
   else it's used for is affected — no other page pairs a bare
   .btn/.link-editorial directly against .section-header inside
   .stack-7), and the CTA's incoming margin becomes the single,
   correct 24px source. */
.section-header + .btn,
.section-header + .link-editorial {
  margin-block-start: var(--space-5);
}

.section-header:has(+ .btn),
.section-header:has(+ .link-editorial) {
  margin-block-end: 0;
}

.split-intro .rule-accent {
  margin-block-end: var(--space-5);
}

.page-header {
  padding-block: var(--space-8) var(--space-9);
}

.page-header .breadcrumb {
  margin-block-end: var(--space-6);
}

.page-header .rule-accent {
  margin-block-end: var(--space-5);
}

.page-header .lead {
  margin-block-start: var(--space-5);
  color: var(--text-muted);
}

/* Animated-wordmark hero override, shared by #about-hero and
   #alliances-hero. Asymmetric, deliberate exception to the site's
   usual left-aligned .page-header flow: ONLY the animated wordmark
   is centered — relative to the full hero canvas (.container's full
   width), not the text column — while .container itself stays a
   plain block so the overline/rule/H1 keep normal left-aligned flow
   beneath it. margin-inline:auto on the video is what centers it; no
   flex/text-align is applied to the container or its text children.
   Both ids get identical rules (grouped selectors) rather than one
   generic class, matching this codebase's established per-page-id
   override convention (e.g. #lebanon-hero, #international-hero). */
/* Top padding tightened from .page-header's default --space-8 (64px)
   to --space-6 (32px) for these heroes only -- the gap above the
   centered video read as excess blank navy. Bottom padding is left
   at the shared --space-9 so the breathing room into the section
   below is untouched. */
#about-hero.page-header,
#alliances-hero.page-header {
  padding-block: var(--space-6) var(--space-9);
}

/* Wordmark sizes bumped again (~7% over the previous 21/28.5/38/46.5rem
   caps) per owner-requested further enlargement, judged against the
   visible animated logo (verified via canvas alpha-sampling to fill
   ~95% of the video frame, so the box size closely tracks the visible
   mark). The 1200px-tier percentage was raised alongside its rem cap
   since it, not the rem value, is what actually binds at 1280px. */
#about-hero .hero-wordmark-video,
#alliances-hero .hero-wordmark-video {
  display: block;
  margin-inline: auto;
  max-inline-size: min(92%, 22.5rem);
  margin-block-end: var(--space-7);
}

@media (min-width: 640px) {
  #about-hero .hero-wordmark-video,
  #alliances-hero .hero-wordmark-video {
    max-inline-size: min(82%, 30.5rem);
  }
}

@media (min-width: 900px) {
  #about-hero .hero-wordmark-video,
  #alliances-hero .hero-wordmark-video {
    max-inline-size: min(72%, 40.5rem);
    margin-block-end: var(--space-8);
  }
}

@media (min-width: 1200px) {
  #about-hero .hero-wordmark-video,
  #alliances-hero .hero-wordmark-video {
    max-inline-size: min(68%, 49.5rem);
  }
}

/* ============================================================
   Profile hero (owner task) -- scoped to .profile-hero, used by
   Maguy Chebli's and Carl Attieh's people pages, so .page-header's
   other consumers are untouched.

   <640px: single column, natural DOM order (overline, rule, h1,
   lead, muted, portrait) would put the portrait LAST -- the brief
   wants it between the overline and the name instead. .maguy-hero-text
   is promoted via display:contents (the same interleaving technique
   this codebase already uses for split-founder/split-scope's own
   mobile reordering) so its children become direct flex items of
   .maguy-hero-grid, and `order` puts the portrait at position 2:
   overline/rule (order 0, unchanged) -> portrait (order 2) ->
   h1/lead/muted (order 3, DOM order preserved as the tiebreak).

   >=640px: .maguy-hero-text reverts to a normal block (one grid
   item, left column); the portrait becomes the right column via
   explicit grid-column placement, which is order-independent -- no
   contents/order needed above this breakpoint. */
.profile-hero .maguy-hero-grid {
  display: flex;
  flex-direction: column;
  margin-block-start: var(--space-6);
}

.profile-hero .maguy-hero-text {
  display: contents;
}

.profile-hero .maguy-hero-text .overline,
.profile-hero .maguy-hero-text .rule-accent {
  order: 0;
}

.profile-hero .maguy-hero-portrait {
  order: 2;
  margin-block: var(--space-5);
}

.profile-hero .maguy-hero-text h1,
.profile-hero .maguy-hero-text .lead,
.profile-hero .maguy-hero-text .text-muted,
.profile-hero .maguy-hero-text .hero-actions {
  order: 3;
}

.profile-hero .maguy-hero-text .rule-accent {
  margin-block-end: var(--space-5);
}

.profile-hero .maguy-hero-text h1 {
  margin-block-end: var(--space-4);
}

.profile-hero .maguy-hero-text .text-muted {
  margin-block-start: var(--space-2);
  color: var(--text-muted);
}

/* Portrait: fixed pixel circle (never vw-based, so it's a true
   circle at every width -- the same reasoning already documented on
   the Leadership page's .leadership-profile-portrait), thin bronze
   border, object-position: center top reuses the exact crop already
   calibrated for Maguy there rather than re-deriving it. */
.profile-hero .maguy-hero-portrait {
  inline-size: 10rem;
  block-size: 10rem;
  border-radius: 50%;
  overflow: hidden;
  border: 1.5px solid var(--accent-detail);
  flex-shrink: 0;
}

.profile-hero .maguy-hero-portrait img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  object-position: center top;
  filter: var(--img-grade);
}

@media (min-width: 640px) {
  .profile-hero .maguy-hero-grid {
    display: grid;
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    column-gap: var(--space-7);
    align-items: center;
    margin-block-start: var(--space-7);
  }

  .profile-hero .maguy-hero-text {
    display: block;
  }

  .profile-hero .maguy-hero-portrait {
    justify-self: end;
    margin-block: 0;
    inline-size: 13.75rem;
    block-size: 13.75rem;
  }
}

@media (min-width: 900px) {
  .profile-hero .maguy-hero-portrait {
    inline-size: 16.25rem;
    block-size: 16.25rem;
  }
}

@media (min-width: 1200px) {
  .profile-hero .maguy-hero-portrait {
    inline-size: 20rem;
    block-size: 20rem;
  }
}

/* ============================================================
   Maguy Chebli — Profile / Practice Focus section head (owner
   correction). Replaces the earlier .split-intro/.split-body 2-col
   rail for these two sections: the left rail read as isolated dead
   space, and the owner wants each section's supporting line (the
   small overline label) positioned directly under its title rather
   than beside it in a separate column. Single column now, full
   container width -- headings and the practice list already fill
   the width on their own; .flow-measure still caps paragraph line
   length independently. Order differs per section (Practice Focus:
   h2 then overline; Profile: two overlines, no h2) so spacing is a
   single generic sibling rule rather than position-specific
   margins. */
/* Bug fix: the earlier generic ">* + *{margin-block-start:space-3}"
   rule was overriding .rule-accent's own margin-block-start
   (var(--space-4), 16px, its normal overline-\>rule gap set in
   layout.css) down to 12px, and only left 12px before the heading --
   both tighter than the sitewide overline-\>rule-\>heading rhythm
   (16px / 24px) that .section-header already establishes elsewhere.
   Matching that exact convention here instead of a flat value:
   .rule-accent keeps its own built-in top margin untouched, and its
   margin-block-end is set to var(--space-5) (24px) for the gap into
   the heading that follows. */
.maguy-section-head {
  margin-block-end: var(--space-7);
}

.maguy-section-head .rule-accent {
  margin-block-end: var(--space-5);
}

/* ============================================================
   Maguy Chebli — Practice Focus editorial link list (owner task).
   Scoped to this page only; not a variant of .list-ruled (that
   pattern has no link/arrow row of its own and this shouldn't
   change its behavior elsewhere). Hairline rows, no card, no
   background, no border-radius -- the whole row is one link for a
   larger hit area, matching .link-editorial's hover color/underline
   language rather than inventing a new hover style. */
.maguy-practice-list {
  list-style: none;
  padding-inline-start: 0;
  margin-block-start: var(--space-6);
}

.maguy-practice-list > li {
  border-block-end: var(--rule-width) solid var(--rule);
}

.maguy-practice-list > li:first-child {
  border-block-start: var(--rule-width) solid var(--rule);
}

/* Desktop (owner task): 2 disciplines per row instead of one long
   single-column stack. Matches this page's own desktop cut (1200px,
   same as the hero/section-head breakpoints above) rather than
   turning on at tablet too. :first-child's border-top rule above
   only covers item 1; nth-child(-n+2) adds it to item 2 as well so
   the whole first ROW gets a top rule, not just its left cell. */
@media (min-width: 1200px) {
  .maguy-practice-list {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    column-gap: var(--space-7);
  }

  .maguy-practice-list > li:nth-child(-n+2) {
    border-block-start: var(--rule-width) solid var(--rule);
  }
}

.maguy-practice-list a {
  display: flex;
  align-items: baseline;
  gap: var(--space-4);
  padding-block: var(--space-4);
  color: var(--text);
  text-decoration: none;
}

.maguy-practice-list-num {
  flex: 0 0 auto;
  font-size: var(--size-small);
  font-weight: 600;
  color: var(--accent);
}

.maguy-practice-list-title {
  flex: 1 1 auto;
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--size-h4);
}

.maguy-practice-list-arrow {
  flex: 0 0 auto;
  color: var(--accent-detail);
  transition: transform var(--motion-base) var(--ease-standard);
}

.maguy-practice-list a:hover .maguy-practice-list-title {
  color: var(--accent);
}

.maguy-practice-list a:hover .maguy-practice-list-arrow {
  transform: translateX(4px);
}

/* H1 editorial measure: without a cap the H1 ran near full container
   width at wide desktop, wrapping only by accident. 30ch gives it a
   deliberate two-line break at desktop while still filling naturally
   at narrower widths where it already wraps to 2-3 lines on its own.
   Font size is untouched -- this only constrains line length. */
/* max-inline-size forces the 2-line wrap; text-wrap:balance (base.css,
   applied globally to headings) then picks the actual break point for
   even line lengths -- this is the site's existing controlled-break
   heading system, so no manual <br> is used or needed here. */
#about-hero h1 {
  max-inline-size: 30ch;
}

/* Founder portrait, desktop only (>=900px, once the split is two
   columns). The grid's 1.6fr/0.9fr split already keeps the rail
   secondary to the biography, but at wide viewports that still
   renders the portrait taller than the desired secondary presence
   in the composition — cap its width so it reads clearly as
   supporting the text rather than competing with it. The trailing
   margin-block-start is a small editorial offset: the rail's default
   grid-stretch alignment put the portrait's top flush with the row
   (level with the overline), which read as too high; shifting it
   down by one token lands it near the H2 instead, still above the
   first paragraph. */
@media (min-width: 900px) {
  .split-founder .split-rail img {
    max-inline-size: min(100%, 22rem);
    margin-block-start: var(--space-8);
  }
}

/* Founder portrait, stacked breakpoints (<900px). At full column
   width the corrected portrait still read as oversized (previously
   near-full container width) -- cap it to a restrained, centered
   editorial size instead of letting it fill the stacked column. */
@media (max-width: 899.98px) {
  .split-founder .split-rail {
    display: flex;
    justify-content: center;
  }

  .split-founder .split-rail img {
    max-inline-size: min(82%, 320px);
  }
}

/* U.S. Market Entry "Scope" illustration, desktop only (>=900px).
   Same reasoning as the Founder portrait above: the rail's default
   grid-stretch alignment puts the image flush with the row top
   (level with the SCOPE overline), which reads as competing with it.
   Shifting down lands the image nearer the heading/list start
   instead, per owner task. The 88% cap is a modest ~12% reduction
   from the previous full-column-width render (owner task: "too
   large"), applied as a percentage of the rail column so the
   reduction stays proportional at every desktop tier rather than
   only at one viewport width. */
@media (min-width: 900px) {
  .split-scope .split-rail img {
    max-inline-size: 88%;
    margin-block-start: var(--space-7);
  }
}

/* IP-United-States Scope illustration (owner task, 2026-08-20).
   Landscape-oriented (1536x1024), unlike the portrait-oriented (2:3)
   reference image (US Market Entry) the shared .split-scope rule
   above was tuned for -- several iterations landed here:

   Final approach (owner: match the reference's occupied pixel AREA,
   not its literal width/percentage, since the aspect ratio genuinely
   differs; and reuse the same responsive behavior/mechanism as the
   reference otherwise). Measured the reference at a 1280px viewport:
   412x618 = ~254,864px2. A landscape image can only reach a
   comparable area within a WIDER column (portrait images get more
   area per unit width, so matching width alone would under-fill);
   #ip-us-scope widens the rail column (5 of 12 grid columns -> 7,
   main correspondingly 6 -> 5), then max-inline-size: 92% of that
   wider column -- measured to land at ~618x412 (~254,700px2),
   matching the reference within under 1%. Still percentage-based off
   the column like the reference (not a fixed px override), so it
   stays fluid across desktop breakpoints the same way.

   align-self:center on the rail column also replaces the reference's
   own fixed margin-block-start push-down with proper grid vertical
   centering, per owner request ("towards the middle of the
   section") -- the reference's own fixed-offset approach was not
   copied here since centering was explicitly asked for on this page.

   Follow-up (owner, same day): text wider, image further right, and
   less space between them. Column split changed from main 1-6/rail
   6-13 (5/7 of 12) to main 1-8/rail 8-13 (7/5) -- text gets more
   columns (wider) and the rail's own start line moves from column 6
   to column 8 (further right), while also narrowing the rail itself.
   column-gap overridden down from the shared .split gutter
   (--gutter: 32px at this width) to --space-4 (16px) to close the
   gap between the two columns; row-gap is left at the default since
   this split never wraps to a second row at desktop widths anyway. */
/* Bug fix (2026-08-20): grid-column was unconditional (not scoped to
   >=900px), so below 900px it forced a 12-column implicit grid on a
   .split that should collapse to a single mobile/tablet column
   (.split's own grid-template-columns:1fr rule below 900px) -- the
   explicit grid-column:7/13 request made the browser auto-create
   implicit columns to satisfy it instead, breaking the shared
   .split-scope mobile/tablet stacking (measured at 768px: 12
   columns, 168px-wide image, instead of the single-column layout
   with a properly centered ~70%-width image). All four page-specific
   overrides now share one >=900px-scoped block, matching how the
   base .split-main/.split-rail column rules themselves are scoped
   in layout.css. */
@media (min-width: 900px) {
  #ip-us-scope .split-main { grid-column: 1 / 7; }
  #ip-us-scope .split-rail { grid-column: 7 / 13; }

  #ip-us-scope .split {
    column-gap: var(--space-4);
  }

  #ip-us-scope .split-rail {
    align-self: center;
  }

  .split-scope .split-rail img.ip-us-scope-img {
    max-inline-size: 100%;
    margin-block-start: 0;
    /* Was 92%; at less than 100% the image doesn't fill its column
       and left-aligns by default (leftover space fell on the right) --
       margin-inline-start:auto still applies so it stays flush right
       if anything ever caps it below 100% again. */
    margin-inline-start: auto;
  }
}

/* Scope illustration, stacked breakpoints (<900px): centered,
   restrained relative to the Founder portrait's mobile cap since
   this image's portrait-oriented (2:3) aspect ratio would otherwise
   read as very tall at full column width. */
@media (max-width: 899.98px) {
  .split-scope .split-rail {
    display: flex;
    justify-content: center;
  }

  .split-scope .split-rail img {
    max-inline-size: min(70%, 380px);
    margin-block-start: 0;
  }
}

/* Alliances "The Network" illustration, desktop only (>=900px).
   Enlarged per owner task (~30% wider than the original 78%-of-
   column render) -- the smaller version read as a stray decorative
   insert rather than a real secondary visual. The rail column itself
   was also widened in layout.css to give this larger image room
   without exceeding it. Left-aligned within the rail (no horizontal
   centering) so it sits close to the gutter/text column rather than
   pinned to the outer edge. Vertically centered within the rail via
   flex (rather than nudged down from the top with a margin) per
   owner task -- the rail already stretches to the full height of the
   long text column, so centering here lands the image near the
   section's vertical middle instead of anchored to the heading. */
@media (min-width: 900px) {
  .split-network .split-rail {
    display: flex;
    align-items: center;
  }

  .split-network .split-rail img {
    max-inline-size: 88%;
  }
}

/* Network illustration, stacked breakpoints (<900px): centered,
   restrained. The image is landscape (3:2), so a wider percentage
   cap than the portrait-oriented Founder/Scope images still keeps a
   sensible rendered height. */
@media (max-width: 899.98px) {
  .split-network .split-rail {
    display: flex;
    justify-content: center;
  }

  .split-network .split-rail img {
    max-inline-size: min(85%, 480px);
  }
}

/* ============================================================
   CARDS — one grammar: hairline top rule → overline →
   display-serif title → muted text → editorial link.
   Typography-only for practice cards (no images).
   ============================================================ */

.card {
  position: relative;
  border-block-start: var(--rule-width) solid var(--rule);
  padding-block-start: var(--space-5);
  transition: transform var(--motion-base) var(--ease-standard),
              border-color var(--motion-base) var(--ease-standard);
}

/* Homepage Capabilities section only: a short bronze segment at the
   leading edge of each discipline card's top rule, so each of the
   three disciplines within a Practice has an unmistakable visual
   beginning once they stack into one column on mobile/tablet.
   Reuses the exact tokens the "monogram" rule under section
   overlines already uses elsewhere (--rule-accent-length/thickness,
   --accent-detail) — approved via
   /preview/capabilities-options/dividers/. Scoped to
   #capabilities .grid-cards .card (the homepage section carries the
   id specifically so this never reaches the .grid-cards .card markup
   reused on the International/United States Practice hub pages and
   the Beirut office page, which share the same class names) — the
   Beirut/Houston .card office tiles elsewhere on the homepage (a
   different, unscoped container) are unaffected either way.
   Mobile/tablet only (<900px): at the >=900px 3-column desktop tier
   the short dash sits awkwardly next to the sitewide short-gold-rule
   vocabulary already used for section accents and link underlines,
   so desktop drops it in favor of one continuous line (below). */
@media (max-width: 899px) {
  #capabilities .grid-cards .card::before {
    content: "";
    position: absolute;
    inset-block-start: calc(var(--rule-width) * -1);
    inset-inline-start: 0;
    inline-size: var(--rule-accent-length);
    block-size: var(--rule-accent-thickness);
    background-color: var(--accent-detail);
  }
}

/* Resting long continuation line, raised one notch above the
   sitewide --rule-width (1px) hairline so it reads at rest rather
   than only on interaction, at every width (mobile's "stronger
   resting line" and desktop's "slightly more visible than the
   current faint hairline" are the same value). The hover/active
   state below changes only this line's COLOR (--rule ->
   --accent-detail); it has never had a distinct width, so leaving
   width unset there means it simply inherits this same 1.5px at
   every state — the hover "boldness" continues to come entirely
   from color contrast, same as before this change, and on desktop
   this is now the ENTIRE top line since the dash above is hidden
   there. Scoped to #capabilities, matching the ::before rule
   above. */
#capabilities .grid-cards .card {
  border-block-start-width: 1.5px;
}

/* Mobile/tablet only (<900px): warm-paper surface on each discipline
   card, using --surface-raised (--paper-100 in this section's
   .surface-light context) — the same token .practice-label and
   .card-filled already use, not a new color. Uniform padding makes
   room so text doesn't sit flush against the new background edges.
   Desktop intentionally excludes this: at >=900px the discipline
   areas stay the plain typography-led surface, closer in spirit to
   the International Practice page, with no card-box appearance. */
@media (max-width: 899px) {
  #capabilities .grid-cards .card {
    background-color: var(--surface-raised);
    padding: var(--space-5);
  }
}

/* Desktop only (>=900px): slightly stronger separation between
   Practice groups than the sitewide .stack-7 rhythm (--space-7,
   48px) gives every direct child of the Capabilities container,
   including the section header. Targeting the sibling-of-a-sibling
   .stack-6 + .stack-6 relationship (ID-selector specificity, no
   !important needed) reaches only Practice-group-to-Practice-group
   transitions — International Practice's own group, which follows
   the section header rather than another .stack-6, is untouched, and
   the +16px step (--space-7 -> --space-8) doesn't touch the gap
   between the three discipline cards within a row at all. */
@media (min-width: 900px) {
  #capabilities .stack-6 + .stack-6 {
    margin-block-start: var(--space-8);
  }
}

/* Desktop-only (>=900px, the tier where .grid-cards becomes a 3-up
   row): give every discipline title a shared reserved height (two
   title-lines' worth, computed from the existing --size-h3/
   --leading-h3 tokens — none of the 9 current discipline titles wrap
   past 2 lines at any tested desktop width, so this reliably covers
   the real content without a guessed pixel value) so the supporting
   paragraph begins at the same level under every card regardless of
   whether its own title takes 1 or 2 lines. flex + align-items:
   center then balances a shorter, 1-line title vertically within
   that reserved height rather than pinning it to the top with dead
   space below; a 2-line title simply fills the height, unaffected.
   (CSS subgrid — the more "correct" way to derive this height live
   from each row's actual tallest sibling — was tried first but does
   not render in this environment's browser, so this fixed-but-
   token-sourced height is the reliable alternative.) Below 900px
   .grid-cards reverts to a single column (or the 2-up tablet tier)
   where every card already sits in its own row, so no equalization
   is meaningful there and none is applied — mobile/tablet keep their
   natural stacked behavior untouched. */
@media (min-width: 900px) {
  #capabilities .grid-cards .card-title {
    display: flex;
    align-items: center;
    min-block-size: calc(var(--size-h3) * var(--leading-h3) * 2);
  }
}

/* Lebanon Practice page — "The Practice" discipline grid, matched to
   the homepage Capabilities discipline-card system above. Same
   selectors and values, re-scoped to #lebanon-practice-grid (the id
   on this page's own "The Practice" section) instead of duplicating
   the ruleset under a shared class: dash + thickened line on mobile/
   tablet, dash hidden on desktop, warm-paper card surface on mobile/
   tablet only, desktop title-height alignment. No group-spacing rule
   here — unlike the homepage's three Practice-group .stack-6 blocks,
   this page has a single discipline grid, so that relationship does
   not exist to normalize. */
@media (max-width: 899px) {
  #lebanon-practice-grid .grid-cards .card::before {
    content: "";
    position: absolute;
    inset-block-start: calc(var(--rule-width) * -1);
    inset-inline-start: 0;
    inline-size: var(--rule-accent-length);
    block-size: var(--rule-accent-thickness);
    background-color: var(--accent-detail);
  }
}

#lebanon-practice-grid .grid-cards .card {
  border-block-start-width: 1.5px;
}

@media (max-width: 899px) {
  #lebanon-practice-grid .grid-cards .card {
    background-color: var(--surface-raised);
    padding: var(--space-5);
  }
}

@media (min-width: 900px) {
  #lebanon-practice-grid .grid-cards .card-title {
    display: flex;
    align-items: center;
    min-block-size: calc(var(--size-h3) * var(--leading-h3) * 2);
  }
}

/* International Practice page — "The Practice" discipline grid
   (owner task, 2026-08-20), matched to the same homepage Capabilities
   / Lebanon Practice discipline-card system above. Same selectors
   and values, re-scoped to #international-practice-grid. This
   section was originally surface-dark; --surface-raised resolved
   correctly either way (navy-800 there, paper-100 now that it's
   surface-light, same as Lebanon), so switching the section's own
   surface later the same day needed no change here. No group-spacing
   rule here, same reasoning as Lebanon: a single discipline grid,
   not multiple Practice-group blocks. */
@media (max-width: 899px) {
  #international-practice-grid .grid-cards .card::before {
    content: "";
    position: absolute;
    inset-block-start: calc(var(--rule-width) * -1);
    inset-inline-start: 0;
    inline-size: var(--rule-accent-length);
    block-size: var(--rule-accent-thickness);
    background-color: var(--accent-detail);
  }
}

#international-practice-grid .grid-cards .card {
  border-block-start-width: 1.5px;
}

@media (max-width: 899px) {
  #international-practice-grid .grid-cards .card {
    background-color: var(--surface-raised);
    padding: var(--space-5);
  }
}

@media (min-width: 900px) {
  #international-practice-grid .grid-cards .card-title {
    display: flex;
    align-items: center;
    min-block-size: calc(var(--size-h3) * var(--leading-h3) * 2);
  }
}

/* International Practice's "The Practice" grid has 8 cards in one
   flat .grid-cards, unlike the homepage's three Practice groups
   (always exactly 3 cards each) -- at the shared .grid-cards rule's
   fixed 3-column desktop tier, 8 doesn't divide evenly: 3+3+2,
   leaving the last row with an empty gap in the 3rd column, measured
   directly (rowTops confirmed 3 distinct rows, last row 2 cards).
   Owner asked for "the same rules as the homepage" cards, and the
   homepage never exposes this case, so there's no existing pattern
   to copy -- this is the standard CSS trick for it instead: when the
   trailing row has exactly 2 items, nth-child(3n+1) (first-of-a-row)
   combined with nth-last-child(2) (second-to-last overall) uniquely
   matches only that row's first card, shifting it to column 2 so the
   pair sits in columns 2-3 rather than 1-2 with a dangling 3rd gap.
   A parallel rule handles a single trailing item the same way, so
   this keeps working correctly if a card is ever added or removed
   without needing to update a hardcoded count. */
@media (min-width: 900px) {
  #international-practice-grid .grid-cards > .card:nth-child(3n+1):nth-last-child(2),
  #international-practice-grid .grid-cards > .card:nth-child(3n+1):nth-last-child(1) {
    grid-column: 2;
  }
}

/* United States Practice page — "The Practice" discipline grid
   (owner task, 2026-08-20), same treatment as International Practice
   and Lebanon Practice above. Already surface-light like Lebanon (no
   surface change needed), and six cards divide evenly into two full
   3-column rows at the desktop tier, so no row-centering rule is
   needed either -- only the base dash/border/card-surface/title-
   height set. */
@media (max-width: 899px) {
  #us-practice-grid .grid-cards .card::before {
    content: "";
    position: absolute;
    inset-block-start: calc(var(--rule-width) * -1);
    inset-inline-start: 0;
    inline-size: var(--rule-accent-length);
    block-size: var(--rule-accent-thickness);
    background-color: var(--accent-detail);
  }
}

#us-practice-grid .grid-cards .card {
  border-block-start-width: 1.5px;
}

@media (max-width: 899px) {
  #us-practice-grid .grid-cards .card {
    background-color: var(--surface-raised);
    padding: var(--space-5);
  }
}

@media (min-width: 900px) {
  #us-practice-grid .grid-cards .card-title {
    display: flex;
    align-items: center;
    min-block-size: calc(var(--size-h3) * var(--leading-h3) * 2);
  }
}

/* Practice-title band (International/United States/Lebanon Practice
   overlines on the homepage Capabilities section): a flat warm-paper
   label so each Practice group announces itself, especially once the
   three Practices stack vertically on mobile. --surface-raised
   resolves to --paper-100 in this section's .surface-light context —
   the same warm-paper token already used for .card-filled elsewhere,
   not a new color. Deliberately unboxed beyond a background + modest
   padding: no border, no shadow, no rounded corners. */
.practice-label {
  display: inline-block;
  background-color: var(--surface-raised);
  padding-block: var(--space-2);
  padding-inline: var(--space-3);
}

.card > * + * {
  margin-block-start: var(--space-3);
}

.card-title {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--size-h3);
  line-height: var(--leading-h3);
  transition: color var(--motion-base) var(--ease-standard);
}

/* Card titles wrap the stretched link */
.card-title a {
  color: inherit;
  text-decoration: none;
}

.card-title a::before {
  content: "";
  position: absolute;
  inset: 0;
}

.card-text {
  color: var(--text-muted);
  font-size: var(--size-small);
  line-height: var(--leading-small);
}

.card-meta {
  font-size: var(--size-overline);
  letter-spacing: var(--tracking-overline);
  text-transform: uppercase;
  color: var(--text-muted);
}

/* Contact page "Offices" directory (owner task, revised for
   symmetry): an open editorial replacement for the previous
   .table/.table-stack presentation. Beirut has two phone numbers and
   Houston has one, so the two columns' content is naturally different
   heights -- without extra help, "Email" and the maps below would
   land at different vertical positions per column. CSS subgrid fixes
   this properly: the parent defines 5 shared row tracks (heading,
   address, telephone, email, map), each row's height is the tallest
   of the two columns' content for that row, and each
   .office-directory-col subgrids onto those same tracks -- so every
   field lines up across both columns with no JS and no fixed
   heights. The divider is now a dedicated middle grid column (an
   empty presentational element) rather than a border+padding on the
   second column, so both content columns stay exactly equal width
   (equal-width columns -> equal-size maps, since each map is 100% of
   its own column with the same aspect-ratio). */
.office-directory {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-8);
}

/* Owner task: mobile now gets the same hairline divider treatment as
   desktop, just rotated -- a horizontal rule between the Beirut and
   Houston blocks instead of a vertical one between the two columns.
   Same element, same --rule/--rule-width tokens; only the axis
   changes at the >=640px breakpoint below. */
.office-directory-divider {
  display: block;
  inline-size: 100%;
  block-size: var(--rule-width);
  background-color: var(--rule);
}

@media (min-width: 640px) {
  .office-directory {
    grid-template-columns: 1fr auto 1fr;
    grid-template-rows: repeat(5, auto);
    column-gap: var(--space-9);
    row-gap: var(--space-6);
  }

  .office-directory-col {
    display: grid;
    grid-template-rows: subgrid;
    grid-row: 1 / span 5;
  }

  .office-directory-col:first-of-type {
    grid-column: 1;
  }

  .office-directory-col:last-of-type {
    grid-column: 3;
  }

  .office-directory-divider {
    grid-column: 2;
    grid-row: 1 / span 5;
    inline-size: var(--rule-width);
    /* auto overrides the mobile fixed block-size above so the grid's
       default stretch alignment can take over and fill the full row
       height again, matching every other row in the subgrid. */
    block-size: auto;
  }
}

.office-directory-col .office-identity {
  margin-block-end: var(--space-6);
}

.office-field + .office-field {
  margin-block-start: var(--space-5);
}

/* Owner task: city-identity block groups the new prominent city
   label with its illustration into a single subgrid row (see
   .office-directory above -- still 5 shared rows: identity, address,
   telephone, email, map), so the label-to-illustration gap can stay
   tight and independent of the row-gap used between the unrelated
   fields below, and the label/illustration still line up across both
   columns like every other row. */
.office-identity {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-4);
}

@media (min-width: 640px) {
  .office-identity {
    align-items: flex-start;
  }
}

/* Owner task (revised): at generous desktop widths, sit the label
   directly beside its illustration (row) instead of above it
   (column) -- "next to", not just "close above". Stays column below
   1200px: label+image+gap side by side doesn't fit the two-office
   column width once it narrows (1024px and 768px columns), so it
   falls back to the tight stacked arrangement there instead of
   squeezing the illustration down to nothing. */
@media (min-width: 1200px) {
  .office-identity {
    flex-direction: row;
    align-items: center;
    gap: var(--space-5);
  }
}

/* City label: reuses the homepage Capabilities section's Practice-
   title band (.practice-label -- var(--surface-raised) warm-paper
   background, no border/shadow/radius) and .overline's microtype
   (var(--accent) navy text, uppercase, var(--tracking-overline)) --
   same tokens as both, not a new color or a new label language --
   sized up (--size-h4 instead of --size-overline, more padding) since
   here it identifies an entire office column rather than sitting
   inside a card. Still clearly smaller than "Our offices" (--size-h2)
   above it. */
.office-city-label {
  display: inline-block;
  font-family: var(--font-text);
  font-size: var(--size-h4);
  line-height: var(--leading-overline);
  letter-spacing: var(--tracking-overline);
  text-transform: uppercase;
  font-weight: 500;
  color: var(--accent);
  background-color: var(--surface-raised);
  padding-block: var(--space-3);
  padding-inline: var(--space-5);
}

/* Shared visual stage (owner task, revised twice: bigger, and now a
   fixed SQUARE rather than a shared height only) -- Beirut's source
   PNG is portrait (clock tower, 2:3) and Houston's is landscape
   (skyline, 3:2), so a fixed width/height pair would either crop or
   distort one of them. A square stage plus object-fit: contain keeps
   each image's natural aspect ratio (no crop/stretch) while making
   both occupy the exact same rendered area: 2:3 and 3:2 are
   reciprocal ratios, so contain-fitting each into an identical square
   letterboxes them to the same visible width x height, not just the
   same bounding box. Bigger than the previous height-only version
   (160-280px tall) at every breakpoint. */
.office-illustration {
  display: flex;
  justify-content: center;
  align-items: center;
  inline-size: clamp(180px, 22vw, 260px);
  block-size: clamp(180px, 22vw, 260px);
}

@media (min-width: 640px) {
  .office-illustration {
    justify-content: flex-start;
  }
}

@media (min-width: 1200px) {
  .office-illustration {
    inline-size: clamp(240px, 22vw, 320px);
    block-size: clamp(240px, 22vw, 320px);
    justify-content: center;
  }
}

.office-illustration img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: contain;
}

/* Owner task: the current Beirut source (Beirut-b&w-2.png, ~1024x1055,
   nearly square) fills almost the entire shared square stage, while
   Houston's source (1536x1024, 3:2 landscape) only fills it
   width-first and gets letterboxed top/bottom -- so at the same
   bounding box, Beirut's visible illustration reads noticeably
   larger than Houston's. Scaling Beirut's own box down to ~83% (both
   axes, so object-fit: contain still centers it and preserves its
   aspect ratio) equalizes the two images' rendered area within the
   stage: sqrt((1/1.5) / (1024/1055)) = ~0.829. Houston is untouched
   at 100%. */
.office-illustration img[src*="Beirut"] {
  inline-size: 83%;
  block-size: 83%;
}

/* Same microtype as .overline / #beirut-office-table's dt (base.css
   token set) -- the site's established small-uppercase-label
   language -- so ADDRESS/TELEPHONE/EMAIL read as clearly subordinate
   to the values beneath them without introducing a new label style. */
.office-label {
  display: block;
  font-size: var(--size-overline);
  line-height: var(--leading-overline);
  letter-spacing: var(--tracking-overline);
  text-transform: uppercase;
  font-weight: 500;
  color: var(--accent);
  margin-block-end: var(--space-2);
}

/* Office location maps (owner task, revised twice): a real
   navigable/zoomable map rather than a static illustration.
   Switched from the OpenStreetMap embed to Google Maps' free classic
   iframe embed (maps.google.com/maps?q=...&output=embed -- no API
   key, no billing, same mechanism as Google's own "Share > Embed a
   map" UI) because the OSM embed's own page chrome (attribution
   paragraph, "report a problem", donation prompt) is baked into that
   cross-origin iframe's content and cannot be hidden or restyled
   from here. Google's basic embed doesn't surface that same visible
   text, so the separate attribution line this page previously showed
   underneath the OSM maps no longer applies and was removed. The
   grayscale/contrast filter is what gives the restrained monochrome
   look without a paid map-styling API; no JS map library is added.
   No card/border/shadow: border:0 on the iframe itself. */
.office-map {
  margin-block-start: var(--space-6);
}

/* Row-gap supplies all vertical spacing between the shared subgrid
   rows at >=640px; the per-field margins above (needed for the
   <640px stacked layout) must be zeroed here, AFTER their base
   rules above, so this override actually wins the cascade. */
@media (min-width: 640px) {
  .office-directory-col .office-identity,
  .office-field + .office-field,
  .office-map {
    margin-block-start: 0;
  }
}

.office-map iframe {
  display: block;
  inline-size: 100%;
  aspect-ratio: 4 / 3;
  border: 0;
  filter: grayscale(1) contrast(1.1) brightness(1.02);
}

/* Owner task: maps read as a bit large on desktop -- cap their
   width below the full column so both shrink (height follows via
   the fixed aspect-ratio) without touching the mobile layout, where
   the column is already narrow. Owner task: center the capped map
   within its column instead of leaving it flush against the column's
   start edge (margin-inline: auto is a no-op below this breakpoint,
   since the iframe is 100% of the column there and has no spare
   width to center within). */
@media (min-width: 640px) {
  .office-map iframe {
    max-inline-size: 380px;
    margin-inline: auto;
  }
}

/* Caption reuses .office-label's exact microtype but sits centered
   under the map rather than left of a value. */
.office-map-caption {
  margin-block-start: var(--space-3);
  margin-block-end: 0;
  text-align: center;
}

/* Single-office pages (Beirut/Houston §"The Office"): same
   office-field/office-map language as the Contact page's directory,
   without that component's two-column subgrid (only one office per
   page here). Flex gap supplies field-to-field and field-to-map
   spacing directly, since the >=640px rule above zeroes
   .office-field's own margin in favor of .office-directory's
   row-gap -- which doesn't exist in this single-column context.
   Stacked (fields, then map) below 900px; from 900px up, the map
   sits beside the fields on the right -- the site's established
   two-column breakpoint (see .split in layout.css). */
.office-details {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}

.office-fields {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}

@media (min-width: 900px) {
  .office-details {
    flex-direction: row;
    align-items: flex-start;
    gap: var(--space-9);
  }

  .office-fields {
    flex: 1 1 auto;
    min-inline-size: 0;
  }

  .office-map {
    flex: 0 0 auto;
    inline-size: 380px;
  }
}

/* Houston's admissions disclaimer sits directly after .office-details.
   Below 900px the map is the last stacked item and butts straight
   against it with no default paragraph margin; from 900px the row
   layout's map height already clears space above the paragraph, so
   this stays zeroed there to leave that (already fine) spacing
   untouched. */
.office-details + p {
  margin-block-start: var(--space-6);
}

@media (min-width: 900px) {
  .office-details + p {
    margin-block-start: 0;
  }
}

/* Carl Attieh's Profile section (owner task): the Admission(s)/
   Languages rail sat too close to the narrative text at the
   .split default column-gap (var(--gutter)) -- widened for this
   section only, not the generic .split rule other pages share. */
@media (min-width: 900px) {
  #carl-profile .split {
    column-gap: var(--space-8);
  }
}

/* Admission(s)/Language(s) rail fields (owner task): .maguy-section-
   head's own margin-block-end (var(--space-7), sized for a full
   section heading) read as too loose above a single value line here
   -- tightened so the value sits close to its title. Between the two
   fields, the opposite problem: .office-field + .office-field's
   margin is zeroed sitewide at >=900px (see the office-details rule
   above, which relies on flex gap instead) -- restored here with
   deliberate space, since .split-rail isn't that flex container. */
.split-rail .office-field .maguy-section-head,
.split-rail .office-field .maguy-section-head .rule-accent {
  margin-block-end: var(--space-3);
}

@media (min-width: 900px) {
  .split-rail .office-field + .office-field {
    margin-block-start: var(--space-7);
  }
}

/* Carl Attieh's rail Practice Focus (owner task): reuses Maguy's
   .maguy-practice-list, but this rail column stays narrow at every
   width (it's the .split-rail 8/13 track, not a full section) -- the
   generic list's own >=1200px 2-column rule would cramp two columns
   into that narrow track, so it's overridden back to one column
   here regardless of viewport. */
.split-rail .maguy-practice-list {
  grid-template-columns: 1fr;
}

.card:hover {
  transform: translateY(-2px);
  border-block-start-color: var(--accent-detail);
}

.card:hover .card-title {
  color: var(--accent);
}

.card-filled {
  background-color: var(--surface-raised);
  border-block-start: var(--rule-width) solid var(--rule);
  padding: var(--space-5);
}

/* Attorney card: 3:4 duotone portrait */
.card-attorney .portrait {
  margin-block-end: var(--space-4);
}

.portrait {
  aspect-ratio: 3 / 4;
  overflow: hidden;
  background-color: var(--surface-raised);
}

.portrait img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  filter: var(--img-grade);
}

/* Leadership page (owner task) — a compact circular-portrait +
   header pattern shared by all three profile sections (Maguy Chebli,
   Carl Jose Sami Attieh, Cynthia-Clara Attieh), replacing Carl's
   former large 3:4 .portrait/.split layout so no single profile
   dominates the page. New class names (not a change to the existing
   .portrait rule above), so people/carl-attieh/'s own identity block
   — the only other .portrait consumer — is unaffected.

   The portrait is a FIXED pixel square (not vw-based), so it is
   always a true circle regardless of container width; the <img>
   fills that square at 100%/100% with object-fit: cover, which is
   the safe way to crop into a circle without the aspect-ratio
   distortion this codebase has hit before when a bare <img> had both
   its width and height independently constrained. A section without
   a verified portrait asset simply omits the .leadership-profile-
   portrait element — flex handles the header alone taking full
   width, no empty circle placeholder is rendered. */
.leadership-profile {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  margin-block-end: var(--space-5);
}

.leadership-profile-portrait {
  flex: 0 0 auto;
  inline-size: 6.5rem;
  block-size: 6.5rem;
  border-radius: 50%;
  overflow: hidden;
  border: 1.5px solid var(--accent-detail);
}

.leadership-profile-portrait img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  /* Maguy's and Cynthia-Clara's source photos are portrait-oriented
     (taller than the square crop), so object-fit: cover crops
     vertically; biasing 35% from the top instead of the default
     centered 50% keeps hair fully in frame rather than trimming it.
     No-op for Carl's photo, which is already a 1:1 square (no
     vertical cropping occurs regardless of this value). */
  object-position: center 35%;
  filter: var(--img-grade);
}

/* Maguy's face sits lower in her source photo than Cynthia-Clara's
   (more headroom above her hair), so the shared center-35% crop left
   her face noticeably below the circle's true center. Overriding to
   center-top for her specifically pulls the crop window down to
   include (almost) the full frame from the very top, which centers
   her eye-to-chin line in the circle instead of the hair. */
.leadership-profile-portrait--maguy img {
  object-position: center top;
}

/* Cynthia-Clara's face, like Maguy's, sits low enough in its source
   photo (measured: eye-to-chin center at ~37% of image height, hair
   top at ~10%) that only center-top (0%) lands the crop window's
   midpoint on her face -- confirmed by rendering the actual
   object-fit:cover crop and checking it, not by guessing a
   percentage. The intermediate 35%/45% values tried first still
   read as too high. */
.leadership-profile-portrait--cynthia img {
  object-position: center top;
}

/* Carl's overline ("Houston · International Practice & Business
   Development") is long enough that "Houston" and "International
   Practice" can't always share a line-break unit safely. Below
   430px, forcing them together (e.g. via nbsp) overflows the
   container outright -- measured: the phrase needs ~300px there,
   the mobile column (portrait + gap eaten out of it) only has
   ~250px. >=430px it fits with room to spare. white-space:nowrap
   only at >=430px gets the requested "Houston next to International
   Practice" grouping wherever it actually fits, and lets it wrap
   naturally (never overflow) below that -- "International" and
   "Practice" stay joined by their own &nbsp; regardless of tier. */
/* Carl's overline ("Houston · International Practice & Business
   Development") is long enough that "Houston" and "International
   Practice" can't always share a line safely. Empirically probed
   pixel-by-pixel (not guessed): true minimum fit is 425px -- 420px
   still overflows by 3px, 430px fit with zero margin (my first pass
   used 430 as the threshold, which is why it still failed: 428px,
   the CSS width of iPhone 12/13/14 Pro Max -- a common real device,
   not an edge case -- falls between 420 and 430 and was landing on
   the wrong side of that cutoff). 425px is the earliest point that
   measured safe, so it's used here rather than a rounder but
   incorrect number. Below 425px it wraps naturally (never overflows)
   -- "International" and "Practice" stay joined by their own &nbsp;
   regardless of tier. */
@media (min-width: 425px) {
  .carl-overline-lead {
    white-space: nowrap;
  }
}

.leadership-profile-header .rule-accent {
  margin-block-end: var(--space-3);
}

.leadership-profile-header .lead {
  margin-block-start: var(--space-2);
}

/* Desktop-only correction (owner task, revised twice): the first cut
   used a 1200px breakpoint for this split while the Continuity
   section directly above switches to its own two-column .split at
   900px. That mismatch left a bad zone from 900-1199px: the
   container is already at (near-)full desktop width there -- same
   as Continuity, already two columns above it -- but these profile
   sections hadn't switched yet, so the single-column stacked
   paragraph (capped at the sitewide 68ch measure) sat inside a
   nearly-1100px-wide container with a large empty gap to its right.
   Moved to 900px to match .split's own breakpoint exactly, so the
   whole page transitions at one consistent width. Below 900px each
   profile stays the narrow flex row + full-width paragraph -- the
   adapted tablet/mobile layout. At >=900px: portrait+name/role on
   the LEFT, paragraph+link on the RIGHT -- the same left-intro/
   right-body shape as Continuity's .split-intro/.split-body.
   .leadership-profile and .stack-5 are ALREADY direct siblings
   inside .leadership-section (see the HTML), so this needs no DOM
   change and no display:contents promotion -- they simply become the
   grid's two column items via normal auto-placement. 5fr/6fr
   approximates .split's own 5/12 vs 6/12 intro/body ratio. No
   .flow-measure override: column 2 at this ratio is already close to
   the sitewide 68ch measure, so the paragraph reads at a normal,
   comfortable line length without a separate widening rule. */
@media (min-width: 900px) {
  .leadership-section {
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    column-gap: var(--space-7);
    align-items: center; /* owner correction, 2026-08-23: was start -- the portrait+header column and the paragraph column are rarely the same height, so pinning both tops together left the shorter column's own vertical center noticeably off from the taller one's; centering both columns keeps their centers aligned instead */
  }

  /* .container also carries .stack-7 (site-wide "space children
     48px apart" rule), which is what supplies the vertical gap
     between .leadership-profile and .stack-5 in the stacked
     tablet/mobile layout. In the grid above they're side-by-side
     siblings instead, so that inherited top margin would just shove
     the right column down out of alignment with the left one. */
  .leadership-section > .stack-5 {
    margin-block-start: 0;
  }

  /* .leadership-profile's own margin-block-end (space-5) exists to
     separate it from the paragraph below in the stacked tablet/
     mobile layout; at this grid layout the two are side-by-side
     siblings instead (column-gap handles their spacing), and grid's
     align-items: center centers each item's MARGIN box -- a bottom-
     only margin on just the left column shifts its perceived (border-
     box) center down by half that margin, undoing the centering
     above. Zeroed here, matching how .stack-5's own margin-block-start
     is neutralised just above for the same reason. */
  .leadership-section > .leadership-profile {
    margin-block-end: 0;
  }

  /* Owner correction: below 1200px .leadership-profile is a flex ROW
     (portrait beside the eyebrow/name/role text, vertically
     centered) -- kept as-is, that's the adapted tablet/mobile layout.
     At >=1200px the owner asked for the picture, location, title,
     and name to sit ABOVE the detailed role line instead of beside
     it, now that the left column has its own real estate. Switching
     to a plain block stack keeps DOM order (portrait, then the
     eyebrow/rule/h2/lead header) as the visual order -- no reordering
     needed, just no longer laying them out side-by-side. */
  .leadership-section .leadership-profile {
    display: block;
  }

  .leadership-section .leadership-profile-portrait {
    margin-block-end: var(--space-4);
  }
}

@media (max-width: 639.98px) {
  .leadership-profile-portrait {
    inline-size: 5rem;
    block-size: 5rem;
  }
}

/* Office card: the city as typographic hero */
.card-city {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--size-h1);
  line-height: var(--leading-h1);
}

/* Homepage Offices section (owner task, 2026-08-23): promoted
   verbatim from the offices-calibrator tool and its mock
   (site/dev/offices-calibrator/, site/preview/offices-config-mock/)
   -- this IS that system, not a re-approximation of it. Full
   mode-by-mode reasoning (why mobile uses a grid and tablet/desktop
   use a float, the overlap fix, the equal-gap city centering) is
   documented once, in calibrator.js's own comments; kept brief here
   to avoid duplicating it out of sync.

   <img> is FIRST in source order (see calibrator.js buildCards():
   "a float only wraps the content that follows it") -- required for
   the tablet/desktop float to start at the top of the card.

   Breakpoints: <480px mobile (grid, "city-image-row" -- eyebrow
   alone above, city+image share a row, paragraph always below both),
   480-1199px tablet and >=1200px desktop (both float/"wrap" -- image
   floats right from the top, text wraps around it; only the pixel
   values differ between the two).

   .card supplies the shared top-rule/hover-transition every other
   card on the site has; .card > * + *'s automatic spacing is
   neutralised below since this layout's gaps are all explicit. */
#offices .oc {
  position: relative;
  z-index: 0; /* stacking context so .oc-img's z-index: -1 only reaches back to here, never behind the section's own background */
}

#offices .card-city a {
  color: inherit;
  text-decoration: none;
}

#offices .card-city a::after {
  content: "";
  position: absolute;
  inset: 0;
}

/* No lift/gold-border on hover here (the generic .card:hover
   elsewhere on the site) -- owner asked for a calmer, non-commercial
   interaction: just the city name's color and the illustration's
   opacity responding slightly. :focus-within mirrors the same cue
   for keyboard users tabbing to the stretched link. */
#offices .oc:hover,
#offices .oc:focus-within {
  transform: none;
}

#offices .oc:hover .card-city,
#offices .oc:focus-within .card-city {
  color: var(--accent);
}

#offices .oc:hover .oc-img,
#offices .oc:focus-within .oc-img {
  opacity: 0.8;
}

/* office-tablet-break: an owner-requested manual line break inside
   each office's paragraph, scoped to the tablet float layout only --
   hidden everywhere else so mobile/desktop keep their own natural
   wrapping. display: none suppresses a <br>'s forced break entirely;
   any other display value restores it. */
.office-tablet-break { display: none; }

/* ---- MOBILE (<480px): grid, "city-image-row" mode. gapCityText's
   pull is absorbed into .card-city's own margin-block-end (floored
   at 0 -- both offices' calibrated offsets exceed the available
   gap), and the city name is vertically centered in its row so the
   leftover space above/below it (from the taller image) splits
   evenly, keeping it equidistant from the eyebrow above and the
   paragraph below. ---- */
#offices .oc-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: 20px;
  margin-block-start: 48px;
  margin-block-end: 0;
}
#offices .oc {
  padding-block-start: 28px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, auto);
  grid-template-areas: "eyebrow eyebrow" "city image" "text text";
}
#offices .oc > * { margin-block-start: 0; margin-block-end: 0; }
#offices .oc > .overline  { grid-area: eyebrow; margin-block-end: 0; }
#offices .oc > .card-city { grid-area: city; align-self: center; }
#offices .oc > .card-text { grid-area: text; }
#offices .oc-img {
  grid-area: image;
  justify-self: end;
  block-size: auto;
  opacity: 0.65;
  position: relative;
  z-index: -1;
  margin-block-start: 0; /* grid mode: pull absorbed into .card-city's gap instead */
  margin-inline-start: 4px;
  transition: opacity var(--motion-base) var(--ease-standard);
}
#ocBeirut .card-city  { margin-block-end: 0; }
#ocHouston .card-city { margin-block-end: 0; }
#ocBeirut .oc-img  { inline-size: 101px; align-self: center; margin-inline-end: 20px; }
#ocHouston .oc-img { inline-size: 149px; align-self: start;  margin-inline-end: 4px; }

/* ---- TABLET+DESKTOP (>=480px): float/"wrap" mode. The image is the
   first child, floats right, and the eyebrow/city/paragraph flow in
   normal document flow around it -- genuine text wrap, not a
   two-column grid. display: flow-root contains the float. imageTop
   is floored at 0 (both offices' calibrated offsets are negative --
   a first-child float's negative margin-block-start is NOT
   auto-clamped at its containing block's edge in this engine,
   verified directly).

   Deliberately NO upper bound here (owner correction, 2026-08-23):
   an earlier pass added "and (max-width: 1199.98px)" while porting
   this from the mock, which never had one -- that cut the float
   structure off at 1200px, leaving desktop stuck on the mobile grid
   rules below with only its sizes overridden on top, not its
   structure. This block now stays active through desktop; the
   >=1200px block further down only layers size differences on top
   of it, exactly like the mock/calibrator do. ---- */
@media (min-width: 480px) {
  #offices .oc-row { gap: 27px; margin-block-start: 33px; margin-block-end: 19px; }
  #offices .oc { display: flow-root; padding-block-start: 20px; }
  #offices .oc > .overline,
  #offices .oc > .card-city,
  #offices .oc > .card-text { grid-area: auto; }
  #offices .oc > .overline  { margin-block-end: 8px; }
  #offices .oc > .card-city { margin-block-end: 13px; align-self: auto; }
  #offices .oc-img {
    grid-area: auto;
    justify-self: auto;
    float: right;
    margin-block-start: 0;
    margin-block-end: 8px;
  }
  #ocBeirut .oc-img  { inline-size: 111px; align-self: auto; margin-inline-start: 2px; margin-inline-end: 26px; }
  #ocHouston .oc-img { inline-size: 164px; align-self: auto; margin-inline-start: 2px; margin-inline-end: 5px; }
  #ocHouston .card-city { inline-size: 43px; }

  .office-tablet-break { display: inline; }
}

/* ---- DESKTOP (>=1200px): float/"wrap" mode continues, wider
   values, both office cards side by side. Houston's imageTop (+14)
   is a genuinely positive offset, so it's one of two cases left
   unclamped here.

   Owner correction, 2026-08-23: Beirut's image (floored to 0, per
   the overlap fix) still read as sitting low next to Houston's --
   not a positioning bug so much as the two source images' different
   proportions: Beirut is tall/narrow (192px tall at this width),
   Houston short/wide (126px), so Beirut's visual center sits lower
   even though its top edge doesn't. Raised, in three owner-requested
   passes the same day: -14px, then -24px ("a bit more" -- slightly
   overshot, centers flipped to Beirut sitting a touch high), settled
   at -20px ("lower it a tiny bit"). Comfortably inside the
   proven-safe range throughout: Beirut's full calibrated pull here
   was -37px, already verified not to touch the eyebrow/city text at
   this width during the original
   overlap-fix investigation. */
@media (min-width: 1200px) {
  #offices .oc-row { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 32px; margin-block-start: 48px; margin-block-end: 0; }
  #offices .oc { padding-block-start: 24px; }
  #offices .oc > .overline  { margin-block-end: 12px; }
  #offices .oc > .card-city { margin-block-end: 12px; }
  #ocHouston .card-city  { inline-size: auto; }
  #ocBeirut .card-text  { max-inline-size: 440px; }
  #ocHouston .card-text { max-inline-size: 389px; }
  .office-tablet-break { display: none; } /* the forced break is a tablet-only fix for its tighter float squeeze; desktop's roomier text columns don't need it -- restores the original pre-1200px-bug scoping */
  #ocBeirut .oc-img  { inline-size: 128px; margin-inline-start: 8px; margin-inline-end: 2px; margin-block-start: -20px; margin-block-end: 0; }
  #ocHouston .oc-img { inline-size: 189px; margin-inline-start: 4px; margin-inline-end: 0; margin-block-start: 14px; margin-block-end: 0; }
}

/* ============================================================
   STATISTICS BAND — display-serif gold numerals, overline
   labels, hairline separators. One band per page max.
   ============================================================ */

.stats {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-6) 0;
}

@media (min-width: 900px) {
  .stats { grid-template-columns: repeat(4, 1fr); }
}

.stat {
  padding-inline: var(--space-6);
  border-inline-start: var(--rule-width) solid var(--rule);
}

/* First stat in each row starts flush with the section's own
   content edge, where a separator has nothing to divide —
   matches every other section's flush-left start. Below 900px
   the grid is 2 columns, so the 3rd stat also starts a row. */
.stat:first-child {
  border-inline-start: 0;
  padding-inline-start: 0;
}

@media (max-width: 899px) {
  .stat:nth-child(2n+1) {
    border-inline-start: 0;
    padding-inline-start: 0;
  }
}

.stat-number {
  display: block;
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--size-display);
  line-height: var(--leading-display);
  color: var(--accent-display);
}

.stat-label {
  display: block;
  margin-block-start: var(--space-3);
  font-size: var(--size-overline);
  line-height: var(--leading-overline);
  letter-spacing: var(--tracking-overline);
  text-transform: uppercase;
  color: var(--text-muted);
}

/* ============================================================
   AC STAT ANIMATION — TasteLab experimental component.
   Digit reel (odometer) clipped in its own fixed-height window,
   plus a staggered letter-tile flip for the label. Geometry and
   timing match the owner-supplied reference exactly; only fonts
   and colors are mapped to existing A&C tokens.
   ============================================================ */
.ac-stat-animation__number {
  display: flex;
  flex-flow: row nowrap;
  justify-content: center;
  align-items: flex-start;
  white-space: nowrap;
  line-height: 1;
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--size-display);
  color: var(--accent-display);
  /* Cormorant Garamond's numerals are old-style (descending)
     figures; a bare 1em cell clips too tight and lets a sliver
     of the outgoing digit's descender show past the seam. */
  --digit-cell: 1.1em;
}

.ac-stat-animation__digit-window {
  display: block;
  flex: 0 0 0.63em;
  width: 0.63em;
  height: var(--digit-cell);
  overflow: hidden;
  line-height: 1;
}

.ac-stat-animation__digit-reel {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: calc(var(--digit-cell) * 2);
  transform: translate3d(0, 0, 0);
  transition: transform 1.8s cubic-bezier(0.22, 1, 0.36, 1);
}

.ac-stat-animation__digit {
  display: block;
  flex: 0 0 var(--digit-cell);
  width: 100%;
  height: var(--digit-cell);
  line-height: 1;
}

.ac-stat-animation.is-second .ac-stat-animation__digit-reel {
  transform: translate3d(0, calc(var(--digit-cell) * -1), 0);
}

.ac-stat-animation__static-char {
  display: block;
}

.ac-stat-animation__label {
  display: flex;
  justify-content: center;
  gap: 2px;
  margin-block-start: var(--space-6);
  perspective: 40rem;
}

.ac-stat-animation__tile {
  position: relative;
  /* 21 fixed-width tiles overflow narrow phones; scale down below
     the point where the row no longer fits the container. */
  inline-size: clamp(0.7rem, 2.5vw, 1.125rem);
  block-size: 1.75rem;
  transform-style: preserve-3d;
  transition: transform 900ms var(--ease-standard);
}

.ac-stat-animation.is-second .ac-stat-animation__tile {
  transform: rotateX(180deg);
}

.ac-stat-animation__face {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  backface-visibility: hidden;
  background-color: color-mix(in srgb, var(--text) 6%, transparent);
  border-radius: 1px;
  font-family: var(--font-text);
  font-size: var(--size-overline);
  text-transform: uppercase;
  color: var(--text);
}

.ac-stat-animation__face[data-face="back"] {
  transform: rotateX(180deg);
}

@media (prefers-reduced-motion: reduce) {
  .ac-stat-animation__digit-reel,
  .ac-stat-animation__tile {
    transition: none;
  }
}

/* Homepage Counsel paragraph: sized to match the adjacent For Law
   Firms .lead paragraph (owner request — the two read as
   consecutive statements). Scoped to this one instance only;
   .flow-measure itself (used on 14 other pages) is untouched. */
.counsel-lede {
  font-size: var(--size-lead);
  line-height: var(--leading-lead);
}

/* ============================================================
   ENGAGEMENT STATEMENTS — the testimonial replacement
   (anonymized representative matters in pull-quote form)
   ============================================================ */

.engagement {
  max-inline-size: var(--measure-body);
}

.engagement-quote {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--size-h3);
  line-height: var(--leading-h3);
}

.engagement-meta {
  display: block;
  margin-block-start: var(--space-4);
  font-size: var(--size-overline);
  letter-spacing: var(--tracking-overline);
  text-transform: uppercase;
  color: var(--text-muted);
}

/* ============================================================
   TIMELINE — hairline spine, 6px sharp gold nodes.
   One per site (About).
   ============================================================ */

.timeline {
  list-style: none;
  padding-inline-start: var(--space-5);
  border-inline-start: var(--rule-width) solid var(--rule);
}

.timeline > li {
  position: relative;
  padding-block-end: var(--space-6);
}

.timeline > li:last-child {
  padding-block-end: 0;
}

.timeline > li::before {
  content: "";
  position: absolute;
  inset-inline-start: calc(-1 * var(--space-5) - 3px);
  inset-block-start: 0.5em;
  inline-size: 6px;
  block-size: 6px;
  background-color: var(--accent-detail);
}

/* ============================================================
   FORMS — underline-only fields, label above, max 6 visible
   fields, in-place confirmation (no toasts).
   ============================================================ */

.form {
  max-inline-size: var(--measure-lead);
}

.form > * + * {
  margin-block-start: var(--space-6);
}

.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.field label {
  font-size: var(--size-small);
  font-weight: 500;
}

.field input,
.field select,
.field textarea {
  inline-size: 100%;
  padding-block: var(--space-2);
  background: transparent;
  border: 0;
  border-block-end: var(--rule-width) solid var(--rule);
  border-radius: var(--radius-input);
  border-start-start-radius: 0;
  border-start-end-radius: 0;
  transition: border-color var(--motion-fast) var(--ease-standard),
              box-shadow var(--motion-fast) var(--ease-standard);
}

/* Focus: 2px gold underline + gold label */
.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-block-end-color: var(--accent);
  box-shadow: 0 1px 0 0 var(--accent);
}

.field:focus-within label {
  color: var(--accent);
}

.field textarea {
  min-block-size: 6rem;
  resize: vertical;
}

/* Native select + custom chevron.
   DOCUMENTED EXCEPTION (§7.2): the URL-encoded stroke color in
   this inline SVG data URI is the one raw hex value outside
   tokens.css (data URIs cannot read custom properties).
   Value = --text-on-light-muted (#5A6474). */
.field select {
  appearance: none;
  padding-inline-end: var(--space-6);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%235A6474' stroke-width='1.25'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-1) center;
}

/* Error state: terracotta + "!" prefix text via aria-describedby —
   never color alone. */
.field.has-error input,
.field.has-error select,
.field.has-error textarea {
  border-block-end-color: var(--color-error);
}

.field.has-error label {
  color: var(--color-error);
}

.field-error {
  font-size: var(--size-small);
  color: var(--color-error);
}

.form-actions {
  display: flex;
  gap: var(--space-4);
}

.form-confirmation {
  padding-block-start: var(--space-5);
  border-block-start: var(--rule-width) solid var(--rule);
  max-inline-size: var(--measure-lead);
}

/* ============================================================
   CTA BLOCK — dark band, the one sanctioned gradient
   (ink-900 → ink-950). Centered. Never stacked with another
   dark band.
   ============================================================ */

.cta-block {
  background-image: linear-gradient(var(--navy-900), var(--navy-950));
  text-align: center;
}

.cta-inner {
  max-inline-size: var(--measure-lead);
  margin-inline: auto;
}

.cta-inner > * {
  margin-inline: auto;
}

.cta-inner .rule-accent {
  margin-block-end: var(--space-5);
}

.cta-inner .btn,
.cta-inner p {
  margin-block-start: var(--space-6);
}

/* Owner task: switched from surface-dark (navy gradient) to
   surface-light-alt -- the site's existing warm-paper surface
   (--paper-100, the same "yellowish" token used for the homepage
   Practice labels and the Contact page Offices city labels), not a
   new color. surface-light-alt's own flat --surface color is enough
   on its own, no gradient needed, so .error-404 no longer carries a
   background rule -- kept only as the shared prefix for the
   page-specific rules below (.error-404-grid, .error-404-intro,
   etc.), still present on the <section> in 404.html. */

/* Owner task (revised twice): "Not Found" centers at every
   breakpoint now -- originally desktop-only, but the owner has since
   asked for mobile/tablet text to center too, so this is no longer
   scoped to >=900px. Width-capping to match .error-404-grid's 820px
   column is still a >=900px-only concern (mobile has no such column
   to match). */
.error-404-intro {
  text-align: center;
}

.error-404-intro .rule-accent {
  margin-inline: auto;
}

@media (min-width: 900px) {
  .error-404-intro {
    max-inline-size: 820px;
    margin-inline: auto;
  }
}

/* Owner task: below the >=900px 2-column grid, center the *text*
   content (h1/p/.btn all respond to text-align; the judge/lawyer
   <img>s are block-level with no auto margin, so they're
   deliberately unaffected and stay where the "image left" DOM order
   naturally places them -- "center all texts" was scoped to text,
   not the illustrations). .error-404-sep is a fixed-width div, not
   inline content, so it needs its own margin-inline: auto to center
   alongside the now-centered text above/below it. */
@media (max-width: 899.98px) {
  .error-404-grid {
    text-align: center;
  }

  .error-404-sep {
    margin-inline: auto;
  }

  /* Owner task: images now center too, alongside the text/separator
     above -- block-level with no auto margin by default (global img
     rule), so text-align on the parent doesn't reach them; each needs
     its own margin-inline: auto. */
  .error-404-grid img {
    margin-inline: auto;
  }
}

/* Owner task (revised composition): mobile is a single flowing
   column in DOM order (judge -> error -> trespass -> separator ->
   lawyer -> message -> cta), each gap set explicitly since these
   items no longer share a wrapper to inherit spacing from. Images
   capped at 240px (down from the previous 320px) -- "modestly
   smaller" per the owner's request, and a narrower rendered width is
   also what gives the (still 1:1, undistorted) judge more of a
   vertical, upright feel next to the tall standing lawyer beneath it. */
.error-404-grid img {
  max-inline-size: 240px;
}

/* Owner task: lawyer read too large next to the judge/reassurance
   text -- narrowed further than the shared 240px cap above (matched
   specificity to ".error-404-grid img" so this override actually
   wins). Portrait source, so height still follows automatically
   (global img rule's block-size: auto) with no distortion. */
.error-404-grid img.error-404-lawyer {
  max-inline-size: 190px;
}

/* Owner task: sized by matching FACE height, not overall image
   footprint. Measured via pixel-cropped analysis of each source: the
   judge's face (hairline to chin) is ~15.4% of his square 1254x1254
   canvas; the lawyer's face is ~12.4% of his taller 1024x1536
   canvas. At the old 200px/285px render sizes that put the lawyer's
   face (~35px) visibly larger than the judge's (~31px) despite
   similar overall footprints -- because the judge's canvas has much
   more bench/desk below the head, the face is a smaller share of his
   total rendered height for a given max-inline-size. 230px brings
   the judge's face back up to ~35px, matching the lawyer's. */
.error-404-grid img.error-404-judge {
  max-inline-size: 230px;
}

/* Owner task (revised): inline-block so this wrapper shrink-wraps to
   h1's own rendered text width, instead of stretching to the grid
   cell/container. That's what makes the underline below track
   "Error 404" correctly at any size or alignment -- it's sized to
   100% of THIS box, and this box is never wider than the heading
   text itself, whether left-aligned (desktop) or centered (mobile/
   tablet, via text-align on the ancestor .error-404-grid, which an
   inline-block box responds to same as any other inline content). */
.error-404-error {
  display: inline-block;
  margin-block-start: var(--space-6);
}

/* Owner task: hand-drawn double underline beneath "Error 404" -- two
   parallel curved strokes (a shallow upward bow, not straight lines),
   roughened by an SVG feTurbulence/feDisplacementMap filter for a
   graphite-pencil texture rather than a clean vector line. Red is a
   deliberate one-off per the owner's explicit request, not pulled
   from the brand token set (no red exists in tokens.css) -- scoped
   entirely to this decorative accent, nothing else on the page uses
   it. Normal flow (not absolutely positioned) at 100% of
   .error-404-error's shrink-wrapped width -- so it's always exactly
   as wide as "Error 404" itself and moves with it automatically as
   the heading's size/position changes across breakpoints, no
   estimated width or manual offset to keep in sync. Its own
   margin-block-start is the "not touching" gap below the text. */
.error-404-underline {
  display: block;
  inline-size: 100%;
  block-size: 20px;
  margin-block-start: var(--space-2);
}

.error-404-trespass {
  margin-block-start: var(--space-4);
}

.error-404-sep {
  margin-block-start: var(--space-7);
}

.error-404-lawyer {
  margin-block-start: var(--space-7);
}

.error-404-message {
  margin-block-start: var(--space-6);
}

/* Owner task (revised three times): "Attieh & Chebli" matches the
   header wordmark's font-family (.brand-wordmark in this file), but
   bigger and bolder than the surrounding .lead text -- back down to
   --size-h3 (26px, vs. the paragraph's 20px) after --size-h2
   (28-36px) read too big -- and weight 600, the heaviest Cormorant
   Garamond weight actually loaded (see the Google Fonts link in
   <head>: wght@500;600, no 700), so this is a real loaded weight
   rather than a synthetic/faked bold. */
.error-404-brand {
  font-family: var(--font-display);
  font-size: var(--size-h3);
  font-weight: 600;
  letter-spacing: 0.01em;
}

.error-404-grid .btn {
  margin-block-start: var(--space-6);
}

/* Owner task (revised composition): at >=900px the same 7 items
   above are repositioned into a real 2-column grid via named areas
   -- judge spans rows 1-2 opposite "Error 404"/"Trespass", lawyer
   spans the later rows opposite the reassurance message/button. The
   empty cell in the image column (the "." row, opposite the
   separator) is what makes the lawyer land directly under the judge
   with no manual offset -- its vertical position is driven entirely
   by the image column's own row-track sizing, inherited for free
   from column 2's content height in that row. Column width (240px)
   and gap (var(--space-7), down from the previous ~48-138px
   .split-derived gap) are both noticeably tighter than the earlier
   composition, and the whole grid is capped to the same 820px
   central column as .error-404-intro above, rather than spreading
   across the full .container width. */
@media (min-width: 900px) {
  .error-404-grid {
    display: grid;
    /* 250px (was 240px) to hold the judge's 230px box plus its 19px
       visible-axis offset without spilling into the column gap. */
    grid-template-columns: 250px minmax(0, 1fr);
    grid-template-areas:
      "judge   error"
      "judge   trespass"
      ".       sep"
      "lawyer  copy";
    /* The reassurance copy and its button now share ONE grid area
       (.error-404-copy) opposite the lawyer. Previously they sat in two
       rows that the taller lawyer spanned, so its surplus height
       inflated the row between them and pushed the button 83px clear of
       the text it belongs to. In one area the button's gap is its own
       margin and nothing else. */
    column-gap: var(--space-7);
    row-gap: 0;
    align-items: start;
    max-inline-size: 820px;
    margin-inline: auto;
  }

  /* Owner task (composition pass): the two illustrations are centred
     inside their own canvases but carry DIFFERENT transparent side
     padding -- at their rendered widths the judge's artwork starts
     19.1px into its box and the lawyer's 37.7px. Aligning the boxes
     therefore left the drawn figures ~19px out of true, which is what
     made the column read as assembled rather than composed. Nudging
     the judge's box in by 19px puts both figures' visible left edges
     on one axis (38.1px vs 37.7px from the block edge). The image
     column is 250px so the offset box still fits inside its cell. */
  .error-404-judge  { grid-area: judge; margin-block-start: 0; margin-inline-start: 19px; }
  /* Lawyer and message share a top edge, so the second group reads as
     one unit instead of the lawyer floating above its own copy. */
  .error-404-lawyer { grid-area: lawyer; margin-block-start: var(--space-6); }
  .error-404-error  { grid-area: error; margin-block-start: 0; justify-self: start; }
  /* Owner task: tighter than the mobile/tablet var(--space-4) gap --
     desktop-only per the owner's request. */
  .error-404-trespass { grid-area: trespass; margin-block-start: var(--space-2); }
  /* The gold rule now lands exactly on the judge's baseline, so the
     divider is an alignment in the composition rather than a floating
     ornament, and the 96px dead band above it closes. */
  .error-404-sep    { grid-area: sep; margin-block-start: 0; }
  .error-404-copy   { grid-area: copy; margin-block-start: var(--space-6); }
  .error-404-message { margin-block-start: 0; }

  /* Owner task: grid items blockify to fill their cell by default
     (justify-self: stretch), which was stretching .btn's border to
     the full text-column width instead of hugging its own text.
     start restores the button's normal shrink-to-fit size. */
  .error-404-cta {
    /* Inside .error-404-copy now, so this is the real, only gap between
       the reassurance line and the button. */
    margin-block-start: var(--space-5);
  }
}

/* ============================================================
   TABLES — hairline rows only, overline headers,
   stack to label/value below 640.
   ============================================================ */

.table {
  inline-size: 100%;
  border-collapse: collapse;
  text-align: start;
}

.table th,
.table td {
  padding-block: var(--space-3);
  padding-inline-end: var(--space-5);
  border-block-end: var(--rule-width) solid var(--rule);
  text-align: start;
  vertical-align: top;
}

.table thead th,
.table th[scope="row"] {
  font-size: var(--size-overline);
  line-height: var(--leading-overline);
  letter-spacing: var(--tracking-overline);
  text-transform: uppercase;
  font-weight: 500;
  color: var(--text-muted);
}

@media (max-width: 639px) {
  .table-stack thead { display: none; }

  .table-stack tr,
  .table-stack th,
  .table-stack td {
    display: block;
    padding-inline-end: 0;
  }

  .table-stack th[scope="row"] {
    border-block-end: 0;
    padding-block-end: 0;
  }

  .table-stack td {
    padding-block-start: var(--space-1);
  }
}

/* Beirut Office details (#beirut-office-table). An "invisible table"
   deliberately built as a <dl> (dt = label, dd = value — a more
   accurate semantic fit for label:value pairs than a <table>, whose
   scope="row"/scope="col" machinery implies relational/tabular data
   this content never had) laid out as a native 2-column CSS grid,
   rather than reusing the shared .table/.table-stack component
   (kept intact for the Houston Office, United States Practice, and
   Contact pages, which this id never touches). dt/dd are direct grid
   children with no wrapper div, so the browser auto-flows each
   label/value pair into its own grid row while keeping every label
   on one shared column and every value on another — table-like
   column alignment, without table markup or borders-on-every-cell
   spreadsheet chrome. */
#beirut-office-table {
  display: grid;
  grid-template-columns: max-content 1fr;
  column-gap: var(--space-5);
}

#beirut-office-table dt,
#beirut-office-table dd {
  padding-block: var(--space-4);
  border-block-end: var(--rule-width) solid var(--rule);
}

/* Same microtype as .overline (base.css) — small uppercase, restrained
   tracking, the established accent color — so these labels read as
   the same "small label" language used site-wide, clearly
   subordinate to the normal-body-text values beside them. */
#beirut-office-table dt {
  font-size: var(--size-overline);
  line-height: var(--leading-overline);
  letter-spacing: var(--tracking-overline);
  text-transform: uppercase;
  font-weight: 500;
  color: var(--accent);
}

#beirut-office-table .value-group {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
}

/* Below 640px: collapse to a single column, matching the sitewide
   .table-stack convention this replaces (label loses its row-end
   border/padding so it sits directly above its value; the value
   keeps a small top gap instead). */
@media (max-width: 639px) {
  #beirut-office-table {
    grid-template-columns: 1fr;
  }

  #beirut-office-table dt {
    border-block-end: 0;
    padding-block-end: 0;
  }

  #beirut-office-table dd {
    padding-block-start: var(--space-2);
  }
}

/* ============================================================
   RULED LISTS — replace bullets site-wide.
   Hairline rows, 4px gold square marker.
   ============================================================ */

.list-ruled {
  list-style: none;
  padding-inline-start: 0;
  max-inline-size: var(--measure-body);
}

.list-ruled > li {
  position: relative;
  padding-block: var(--space-4);
  padding-inline-start: var(--space-5);
  border-block-end: var(--rule-width) solid var(--rule);
}

.list-ruled > li::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: calc(var(--space-4) + 0.55em);
  inline-size: var(--space-1);
  block-size: var(--space-1);
  background-color: var(--accent-detail);
}

/* Numbered variant — <ol class="list-ruled">. Only targets the
   ordered-list case, so existing <ul class="list-ruled"> usages
   (dot marker) are unaffected. */
ol.list-ruled {
  counter-reset: list-ruled-count;
}

ol.list-ruled > li {
  counter-increment: list-ruled-count;
  padding-inline-start: var(--space-6);
}

ol.list-ruled > li::before {
  content: counter(list-ruled-count) ".";
  inset-block-start: var(--space-4);
  inline-size: auto;
  block-size: auto;
  background-color: transparent;
  color: var(--accent);
  font-weight: 600;
}

/* ============================================================
   BREADCRUMB — small, "/" separators, interior pages
   ============================================================ */

.breadcrumb ol {
  list-style: none;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  font-size: var(--size-small);
  color: var(--text-muted);
}

.breadcrumb li + li::before {
  content: "/";
  margin-inline-end: var(--space-2);
  color: var(--text-muted);
}

.breadcrumb a {
  color: var(--text-muted);
  text-decoration: none;
}

.breadcrumb a:hover {
  color: var(--accent);
}

/* ============================================================
   ACCORDION — +/− glyph rotating 45°, one open per group
   ============================================================ */

.accordion {
  border-block-start: var(--rule-width) solid var(--rule);
}

.accordion-item {
  border-block-end: var(--rule-width) solid var(--rule);
}

.accordion-trigger {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-4);
  inline-size: 100%;
  padding-block: var(--space-4);
  background: none;
  border: 0;
  text-align: start;
  font-size: var(--size-body);
  font-weight: 500;
  cursor: pointer;
}

.accordion-trigger:hover {
  color: var(--accent);
}

.accordion-panel {
  padding-block-end: var(--space-5);
  color: var(--text-muted);
}

/* Sharp-terminal glyph; rotates + into × when open */
.glyph {
  flex-shrink: 0;
  display: inline-flex;
  transition: transform var(--motion-base) var(--ease-standard);
}

.accordion-trigger[aria-expanded="true"] .glyph {
  transform: rotate(45deg);
}

/* ============================================================
   TABS — office pages only; accordion below 900
   ============================================================ */

.tabs-list {
  display: flex;
  gap: var(--space-6);
  border-block-end: var(--rule-width) solid var(--rule);
}

.tab {
  position: relative;
  padding-block: var(--space-3);
  background: none;
  border: 0;
  font-size: var(--size-nav);
  font-weight: 500;
  color: var(--text-muted);
  cursor: pointer;
}

.tab::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: calc(-1 * var(--rule-width));
  block-size: var(--rule-width);
  background-color: var(--accent);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform var(--motion-base) var(--ease-standard);
}

.tab[aria-selected="true"] {
  color: var(--text);
}

.tab[aria-selected="true"]::after,
.tab:hover::after {
  transform: scaleX(1);
}

/* ============================================================
   HERO — the sanctioned gradient seats hero photography
   ============================================================ */

.hero {
  position: relative;
  display: grid;
  align-items: end;
  min-block-size: 80vh;
  background-image: linear-gradient(var(--navy-900), var(--navy-950));
  overflow: hidden;
}

.hero-media {
  position: absolute;
  inset: 0;
}

.hero-media img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  object-position: center 70%;
  filter: var(--img-grade);
  opacity: var(--hero-img-opacity);
}

/* Leadership hero (owner task) — .page-header doesn't establish a
   positioning context or clip overflow the way .hero does, so both
   are added here, scoped to this page only; every other .page-header
   consumer (31 pages) is untouched. .hero-media itself and its ::after
   scrim are the same shared rules the homepage/Beirut-office heroes
   use — only this video-specific sizing rule is new. No --hero-scrim
   override: the shared default (28%, tokens.css) already reads as the
   "very subtle" navy layer the brief asked for; the video is left at
   full opacity (no --hero-img-opacity dimming, no --img-grade filter)
   since it's a supplied brand loop, not a photograph needing grading.
   .container gets position:relative (bare, no z-index — the same
   mechanism .hero-content already uses elsewhere) so the text paints
   above the absolutely-positioned .hero-media layer. */
#leadership-hero {
  position: relative;
  overflow: hidden;
}

#leadership-hero > .container {
  position: relative;
}

#leadership-hero .hero-media video {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  object-position: center center;
}

/* The source loop is 16:9 with its gold filament confined to the
   right ~30% of frame (verified by sampling frames across the whole
   loop). At desktop/tablet the hero is wider than 16:9, so cover
   scales to match width and the full frame -- filament included --
   is already visible with no horizontal cropping; below 900px the
   hero's aspect narrows enough that cover starts cropping
   horizontally, which at a centered position would cut into the
   filament long before it touches the empty left two-thirds. Biasing
   right keeps the filament in frame, matching the brief's "a
   right-biased object-position is likely necessary on mobile." */
@media (max-width: 899.98px) {
  #leadership-hero .hero-media video {
    object-position: right center;
  }
}

/* At mobile widths the crop window is narrower than the filament is
   wide (verified by measuring the actual rendered line boxes against
   the filament's source-pixel extent), so the H1/lead's widest lines
   and the filament's left edge genuinely overlap there -- no single
   object-position both keeps the filament fully in frame AND clears
   an ~87%-wide text column. Rather than sacrifice the filament (or
   the text width), reusing the exact text-shadow already established
   for this situation elsewhere (.hero--deep-scrim, above): legibility
   stops depending on the scrim/background alone. The linework is
   thin and sparse, not a solid mass, so this is sufficient without
   darkening the video further. */
#leadership-hero .overline,
#leadership-hero h1,
#leadership-hero .lead {
  text-shadow: 0 1px 4px color-mix(in srgb, var(--navy-950) 70%, transparent);
}

/* Subtle navy overlay: unifies the photograph with the brand
   and secures text readability while keeping the building
   clearly visible ("global headquarters", not cinema).
   Weighted toward the base, where the text sits. */
.hero-media::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: linear-gradient(
    to bottom,
    color-mix(in srgb, var(--navy-900) calc(var(--hero-scrim) * 0.75), transparent),
    color-mix(in srgb, var(--navy-900) calc(var(--hero-scrim) * 2.4), transparent)
  );
}

/* Same overlay mechanism used everywhere (identical gradient, color,
   and direction) — just calibrated stronger via the existing
   --hero-scrim/--hero-img-opacity tokens for a busier photograph
   (Beirut office). Scoped to this modifier only. Owner feedback: the
   first pass (42%/0.85) still wasn't quiet/readable enough, so this
   raises both further while keeping the photo's detail visible (not
   a full block-out). The homepage hero now reuses these exact same
   token values via .hero--blue-fade below, on owner request — same
   strength, without this modifier's overline-size/text-shadow
   additions (those were specific to Beirut's request, not asked for
   on the homepage). */
.hero--deep-scrim {
  --hero-scrim: 58%;
  --hero-img-opacity: 0.72;
}

/* Homepage hero: reuses the exact same --hero-scrim/--hero-img-opacity
   values as .hero--deep-scrim above (same gradient mechanism, same
   colors, same direction, same strength) so the two heroes' overlays
   match. Kept as a separate modifier rather than reusing the
   .hero--deep-scrim class name directly so this stays scoped to only
   the fade itself — Beirut's additional overline-size and text-shadow
   rules are not pulled in here, since those weren't requested for the
   homepage hero. */
.hero--blue-fade {
  --hero-scrim: 58%;
  --hero-img-opacity: 0.72;
}

/* Extra crispness on the text itself (independent of the photo
   darkening above) so legibility doesn't depend solely on how dark
   the scrim gets — a soft drop shadow, not a redesign. */
.hero--deep-scrim .hero-content .overline,
.hero--deep-scrim .hero-content .type-display,
.hero--deep-scrim .hero-content .lead {
  text-shadow: 0 1px 4px color-mix(in srgb, var(--navy-950) 70%, transparent);
}

/* Owner request: the overline should read with the same prominence
   as the homepage hero's — increased beyond the shared base .overline
   size specifically for this busier photograph. */
.hero--deep-scrim .hero-content .overline {
  font-size: 1rem;
  font-weight: 600;
}

/* Originally United States Practice hub hero only; now shared with
   International Practice's hero too (2026-08-20, owner request),
   whose photo has a similarly bright vanishing point needing the
   stronger tier. Still a plain class, not ID-scoped, so any future
   hero can opt in the same way. Owner request: make the photograph
   less visually distracting behind the
   copy without blurring or replacing it. Strengthened a further step
   beyond the site's existing "strong" tier (.hero--deep-scrim/
   .hero--blue-fade, 58%/0.72) now that the supporting line reads in
   the standardized muted light-blue rather than full white, so the
   overlay carries more of the contrast job on its own. Layers an
   additional left-to-right navy gradient on top of the existing
   vertical one — darkest behind the left-aligned copy, fading toward
   the right, using the same color-mix/token formula as the base
   vertical gradient for visual consistency. Does not touch the
   shared .hero-media::after rule itself.

   Lightened slightly (owner request, 2026-08-20, both pages this
   class is used on): 68%/0.6 -> 58%/0.7. The left-to-right gradient's
   own leading-edge strength (separate from --hero-scrim, only the
   vertical gradient below reads that token) was reduced by the same
   proportion, 62% -> 52%, so it doesn't stay disproportionately dark
   relative to the rest of the lightened overlay. */
.hero--us-scrim {
  --hero-scrim: 58%;
  --hero-img-opacity: 0.7;
}

.hero--us-scrim .hero-media::after {
  background-image:
    linear-gradient(
      to right,
      color-mix(in srgb, var(--navy-900) 52%, transparent),
      transparent 65%
    ),
    linear-gradient(
      to bottom,
      color-mix(in srgb, var(--navy-900) calc(var(--hero-scrim) * 0.75), transparent),
      color-mix(in srgb, var(--navy-900) calc(var(--hero-scrim) * 2.4), transparent)
    );
}

/* International, Lebanon, and US Practice heroes: all matched to the
   same height (owner request, 2026-08-21 -- "same dimensions as US
   Practice"). International's own hero went through several earlier
   nudges (80vh base -> 60vh -> 74vh -> 70vh) before this; Lebanon
   previously had no override at all and sat at the base .hero's 80vh;
   US Practice landed on 68vh first (74vh -> 68vh, "a little bit
   shorter") and is now the shared value all three use. */
#international-hero,
#lebanon-hero,
#us-hero {
  min-block-size: 68vh;
}

/* Beirut office hero (owner request, 2026-08-20): shorter, and the
   background photo (Beirut-Clock.jpg, 5325x7101 -- a very tall
   portrait crop of the clock tower) should show more of its upper
   part on desktop. The shared .hero-media img rule's
   object-position: center 70% biases toward the BOTTOM of the frame
   (higher Y% = more cropped off the top, per object-position
   semantics), which was cropping the tower's upper portion away --
   lowering it toward the top reveals more of that. Desktop-only
   (>=900px): mobile/tablet keep the shared 70% default, unchanged,
   since the ask was specifically about "the desktop version".

   Two follow-up corrections, same day: 65vh read as too short --
   raised to 72vh. And 35% overshot past the middle toward the top --
   the owner's actual ask was the vertical middle of the photo, so
   this is now a plain 50%, not a tuned-to-taste value. */
#beirut-hero {
  min-block-size: 72vh;
}

@media (min-width: 900px) {
  #beirut-hero .hero-media img {
    object-position: center 50%;
  }
}

/* Houston office hero (owner task, 2026-08-24): height matched to the
   Beirut office hero (#beirut-hero, 72vh — was the shared base .hero's
   80vh). */
#houston-hero {
  min-block-size: 72vh;
}

/* Navy overlay for the Houston office hero, same gradient mechanism as
   Beirut's .hero--deep-scrim (58%/0.72) but calibrated lighter, per
   owner request. Halfway between the shared base default (28%/0.96,
   tokens.css) and Beirut's strong tier. */
.hero--houston-scrim {
  --hero-scrim: 43%;
  --hero-img-opacity: 0.84;
}

/* International Practice's "The Mandate" section -- owner request,
   2026-08-20: "some excessive blank space above the title". The
   shared .section rule (layout.css, sitewide) sets padding-block to
   --space-10 (128px) at this width; scoped down to --space-9 (96px)
   for just the top edge here, a modest 32px reduction ("a little bit
   up", not a drastic cut). padding-block-end is left alone (only
   overriding -start, not the whole shorthand) so spacing into §3
   below is unaffected. */
#international-mandate {
  padding-block-start: var(--space-9);
}

/* Beirut office's "The Headquarters" section -- same fix as
   International Practice's Mandate section above (owner request,
   2026-08-20): "excessive blank space above the title". */
#beirut-headquarters {
  padding-block-start: var(--space-9);
}

/* Lebanon Practice hero only (#lebanon-hero). The shared
   .hero-media img rule biases object-position toward center 70%
   (tuned for the very tall 5325x7101/5163x3442-class portrait
   photography used by the other image heroes, where cropping the
   sky rather than the street kept the subject framed). This hero's
   source is landscape (1536x1024) and symmetrical — center left/
   right, clock tower roughly centered vertically too — so centering
   both axes keeps the architecture on both sides and the tower
   itself in frame at every breakpoint instead of biasing toward the
   ground. Does not touch the shared default used elsewhere. */
#lebanon-hero .hero-media img {
  object-position: center center;
}

.hero-content {
  position: relative;
  padding-block: var(--space-9);
}

.hero-content .rule-accent {
  margin-block-end: var(--space-5);
}

/* Over photography the overline reads in text color;
   the bronze monogram rule beneath carries the accent. */
.hero-content .overline {
  color: var(--text);
}

/* Standardized hero supporting-line color (owner task): every
   photographic hero's lead paragraph reads in this one muted
   light-blue (--text-on-dark-muted, resolved via --text-muted on
   dark surfaces) — no page-specific white override remains. Matches
   .page-header .lead, which already used this same token, so every
   hero pattern on the site now shares one color. */
.hero-content .lead {
  margin-block-start: var(--space-5);
  color: var(--text-muted);
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-5);
  margin-block-start: var(--space-6);
}

/* ============================================================
   FOOTER — ink-950, gold top rule, signature-register office
   blocks, --space-10 padding
   ============================================================ */

.site-footer {
  background-color: var(--navy-950);
}

.footer-main {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-7);
  padding-block: var(--space-8);
}

/* <640px only: brand full width, The Firm + Capabilities side by side,
   People & Insights and Contact each span the full width below. The
   640-899px (tablet) and >=900px (desktop) tiers are untouched below -
   this tier is scoped by max-width so it can never overlap them. Direct
   nth-child targeting addresses footer-main's 5 fixed children
   [brand, Firm, Capabilities, People & Insights, Contact] regardless of
   element type. */
@media (max-width: 639px) {
  .footer-main {
    grid-template-columns: repeat(2, 1fr);
    column-gap: var(--space-5);
    row-gap: var(--space-6);
    padding-block: var(--space-7);
  }

  .footer-main > *:nth-child(1),
  .footer-main > *:nth-child(4),
  .footer-main > *:nth-child(5) {
    grid-column: 1 / -1;
  }
}

@media (min-width: 640px) {
  .footer-main {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 900px) {
  .footer-main {
    grid-template-columns: 2fr repeat(4, 1fr);
    column-gap: var(--space-5);
    padding-block: var(--space-9);
  }
}

/* The Capabilities column holds the longest link text ("United States
   Practice"); prevent it from breaking mid-name. nowrap gives the link
   a min-content floor, which the 1fr grid track honors automatically
   (the same mechanism already widens the Contact column for its long
   email addresses), so the column grows only as much as this text
   actually needs without a hand-tuned fr ratio disturbing siblings.
   nth-of-type(3) counts the 3rd <div> sibling overall (.footer-brand is
   the 1st div, "The Firm" the 2nd), which is the Capabilities column. */
.footer-col:nth-of-type(3) a {
  white-space: nowrap;
}

.footer-brand .brand-wordmark {
  font-size: var(--size-h4);
}

.footer-descriptor {
  margin-block-start: var(--space-4);
  font-size: var(--size-small);
  line-height: var(--leading-small);
  color: var(--text-muted);
  max-inline-size: 32ch;
}

.footer-col .overline {
  margin-block-end: var(--space-4);
}

.footer-col ul {
  list-style: none;
  padding: 0;
}

.footer-col li + li {
  margin-block-start: var(--space-2);
}

.footer-col a {
  font-size: var(--size-small);
  color: var(--text-muted);
  text-decoration: none;
}

.footer-col a:hover {
  color: var(--accent);
}

.footer-office {
  font-size: var(--size-small);
  line-height: var(--leading-small);
  color: var(--text-muted);
}

.footer-office + .footer-office {
  margin-block-start: var(--space-5);
}

.footer-office strong {
  display: block;
  color: var(--text);
  font-weight: 500;
}

.footer-legal {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-5);
  padding-block: var(--space-5);
  border-block-start: var(--rule-width) solid var(--rule);
  font-size: var(--size-overline);
  color: var(--text-muted);
}

.footer-legal a {
  color: var(--text-muted);
}

.footer-ad-line {
  inline-size: 100%;
}

/* ============================================================
   MOTION — the complete locked vocabulary (§3.2, §7.4)
   ============================================================ */

.reveal-hero {
  opacity: 0;
  translate: 0 var(--space-3);
  transition: opacity var(--motion-reveal) var(--ease-out),
              translate var(--motion-reveal) var(--ease-out);
  transition-delay: calc(var(--hero-i, 0) * 60ms);
}

.reveal-hero.is-visible {
  opacity: 1;
  translate: 0 0;
}

/* Opacity-only below 900 */
@media (max-width: 899px) {
  .reveal-hero {
    translate: 0 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .reveal-hero {
    translate: 0 0;
    transition-delay: 0s;
  }

  .card:hover {
    transform: none;
  }
}
