/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */

@font-face {
  font-family: Inter;
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../fonts/inter-latin.woff2") format("woff2");
  unicode-range: U+??, U+131, U+152-153, U+2BB-2BC, U+2C6, U+2DA, U+2DC, U+304, U+308, U+329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: Inter;
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../fonts/inter-latin-ext.woff2") format("woff2");
  unicode-range: U+100-2BA, U+2BD-2C5, U+2C7-2CC, U+2CE-2D7, U+2DD-2FF, U+304, U+308, U+329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: Manrope;
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url("../fonts/manrope-latin.woff2") format("woff2");
  unicode-range: U+??, U+131, U+152-153, U+2BB-2BC, U+2C6, U+2DA, U+2DC, U+304, U+308, U+329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: Manrope;
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url("../fonts/manrope-latin-ext.woff2") format("woff2");
  unicode-range: U+100-2BA, U+2BD-2C5, U+2C7-2CC, U+2CE-2D7, U+2DD-2FF, U+304, U+308, U+329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  --color-charcoal: #17191b;
  --color-warm-white: #f5f4f0;
  --color-concrete: #d9d8d4;
  --color-softone-red: #e94b50;
  --color-sand: #b9aa95;
  --color-charcoal-800: #212426;
  --color-charcoal-600: #3a3e41;
  --color-charcoal-500: #595e62;
  --color-charcoal-400: #6b7074;
  --color-charcoal-200: #a4aaae;
  --color-concrete-light: #e8e7e4;
  /* Concrete darkened at constant hue for text that must clear the 3:1
     large-text bar on white. #d9d8d4 is 1.43:1 there; this is 3.04:1.
     No existing neutral token lands between 3 and 3.5 on white — the
     nearest are charcoal-200 at 2.35 and charcoal-400 at 5.01, one too
     faint and one heavy enough to read as body text. */
  --color-concrete-dark: #979489;
  --color-sand-light: #d3c9ba;
  --color-softone-red-light: #ee5c61;
  --color-softone-red-dark: #c73b40;
  --color-softone-red-deep: #b8353a;
  --color-softone-red-deeper: #9e2c31;
  --color-bg: var(--color-warm-white);
  --color-bg-inverse: var(--color-charcoal);
  --color-surface: #fff;
  --color-surface-muted: var(--color-concrete-light);
  --color-text: var(--color-charcoal);
  --color-text-muted: var(--color-charcoal-500);
  --color-text-inverse: var(--color-warm-white);
  --color-text-muted-inverse: var(--color-charcoal-200);
  --color-border: var(--color-concrete);
  --color-border-strong: var(--color-charcoal-600);
  --color-accent: var(--color-softone-red);
  --color-accent-hover: var(--color-softone-red-dark);
  --color-accent-text: var(--color-softone-red-deep);
  --color-accent-text-hover: var(--color-softone-red-deeper);
  --color-accent-on-dark: var(--color-softone-red-light);
  --color-accent-surface: var(--color-softone-red-dark);
  --color-accent-surface-hover: var(--color-softone-red-deep);
  --color-on-accent-surface: #fff;
  --font-display: "Manrope", "Inter", ui-sans-serif, system-ui, -apple-system,
    "Segoe UI", sans-serif;
  --font-body: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI",
    sans-serif;
  --font-mono: ui-monospace, "SFMono-Regular", "SF Mono", Menlo, Consolas,
    monospace;
  --font-size-display-min: 64px;
  --font-size-display-max: 78px;
  --font-size-display: clamp(2.25rem, 1.75rem + 3.9vw, 4.875rem);
  --font-size-heading-min: 48px;
  --font-size-heading-max: 60px;
  --font-size-heading: clamp(2.25rem, 1.5rem + 3.4vw, 3.75rem);
  --font-size-subhead-min: 22px;
  --font-size-subhead-max: 30px;
  --font-size-subhead: clamp(1.375rem, 1.15rem + 1vw, 1.875rem);
  --font-size-body-min: 16px;
  --font-size-body-max: 18px;
  --font-size-body: clamp(1rem, .95rem + .25vw, 1.125rem);
  --font-size-body-sm: 14px;
  --font-size-label-min: 10px;
  --font-size-label-max: 12px;
  --font-size-label: clamp(.625rem, .575rem + .16vw, .75rem);
  --font-weight-light: 300;
  --font-weight-regular: 400;
  --font-weight-medium: 500;
  --font-weight-semibold: 600;
  --font-weight-bold: 700;
  --font-weight-extrabold: 800;
  --line-height-display: .98;
  --line-height-heading: 1.06;
  --line-height-subhead: 1.25;
  --line-height-body: 1.6;
  --line-height-label: 1.2;
  --letter-spacing-display: -.03em;
  --letter-spacing-heading: -.02em;
  --letter-spacing-subhead: -.01em;
  --letter-spacing-body: 0em;
  --letter-spacing-label: .16em;
  --space-3xs: .25rem;
  --space-2xs: .5rem;
  --space-xs: .75rem;
  --space-sm: 1rem;
  --space-md: 1.5rem;
  --space-lg: 2rem;
  --space-xl: 3rem;
  --space-2xl: 4rem;
  --space-3xl: 6rem;
  --space-4xl: 8rem;
  --layout-max-width: 100rem;
  --layout-gutter: clamp(1rem, .5rem + 2vw, 3rem);
  --layout-columns: 12;
  --border-hairline: 1px;
  --radius-none: 0;
  --radius-sm: 2px;
  --radius-md: 4px;
  --radius-lg: 8px;
  --duration-fast: .12s;
  --duration-base: .2s;
  --ease-standard: cubic-bezier(.2, 0, .2, 1);
  --brand-mark-gradient-start: #e94b50;
  --brand-mark-gradient-mid: #3f6fd8;
  --brand-mark-gradient-end: #7b4de0;
}

@layer theme {
  :root, :host {
    --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
      "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
      "Segoe UI Symbol", "Noto Color Emoji";
    --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
      "Courier New", monospace;
    --font-weight-light: 300;
    --font-weight-medium: 500;
    --font-weight-semibold: 600;
    --font-weight-bold: 700;
    --font-weight-extrabold: 800;
    --radius-sm: .25rem;
    --radius-md: .375rem;
    --radius-lg: .5rem;
    --default-transition-duration: .15s;
    --default-transition-timing-function: cubic-bezier(.4, 0, .2, 1);
    --default-font-family: var(--font-sans);
    --default-mono-font-family: var(--font-mono);
  }
}

@layer base {
  *, :after, :before, ::backdrop {
    box-sizing: border-box;
    border: 0 solid;
    margin: 0;
    padding: 0;
  }

  ::file-selector-button {
    box-sizing: border-box;
    border: 0 solid;
    margin: 0;
    padding: 0;
  }

  html, :host {
    -webkit-text-size-adjust: 100%;
    tab-size: 4;
    line-height: 1.5;
    font-family: var(--default-font-family, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");
    font-feature-settings: var(--default-font-feature-settings, normal);
    font-variation-settings: var(--default-font-variation-settings, normal);
    -webkit-tap-highlight-color: transparent;
  }

  hr {
    height: 0;
    color: inherit;
    border-top-width: 1px;
  }

  abbr:where([title]) {
    -webkit-text-decoration: underline dotted;
    text-decoration: underline dotted;
  }

  h1, h2, h3, h4, h5, h6 {
    font-size: inherit;
    font-weight: inherit;
  }

  a {
    color: inherit;
    -webkit-text-decoration: inherit;
    -webkit-text-decoration: inherit;
    -webkit-text-decoration: inherit;
    text-decoration: inherit;
  }

  b, strong {
    font-weight: bolder;
  }

  code, kbd, samp, pre {
    font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);
    font-feature-settings: var(--default-mono-font-feature-settings, normal);
    font-variation-settings: var(--default-mono-font-variation-settings, normal);
    font-size: 1em;
  }

  small {
    font-size: 80%;
  }

  sub, sup {
    vertical-align: baseline;
    font-size: 75%;
    line-height: 0;
    position: relative;
  }

  sub {
    bottom: -.25em;
  }

  sup {
    top: -.5em;
  }

  table {
    text-indent: 0;
    border-color: inherit;
    border-collapse: collapse;
  }

  :-moz-focusring:where(:not(iframe)) {
    outline: auto;
  }

  progress {
    vertical-align: baseline;
  }

  summary {
    display: list-item;
  }

  ol, ul, menu {
    list-style: none;
  }

  img, svg, video, canvas, audio, iframe, embed, object {
    vertical-align: middle;
    display: block;
  }

  img, video {
    max-width: 100%;
    height: auto;
  }

  button, input, select, optgroup, textarea {
    font: inherit;
    font-feature-settings: inherit;
    font-variation-settings: inherit;
    letter-spacing: inherit;
    color: inherit;
    opacity: 1;
    background-color: #0000;
    border-radius: 0;
  }

  ::file-selector-button {
    font: inherit;
    font-feature-settings: inherit;
    font-variation-settings: inherit;
    letter-spacing: inherit;
    color: inherit;
    opacity: 1;
    background-color: #0000;
    border-radius: 0;
  }

  :where(select:is([multiple], [size])) optgroup {
    font-weight: bolder;
  }

  :where(select:is([multiple], [size])) optgroup option {
    padding-inline-start: 20px;
  }

  ::file-selector-button {
    margin-inline-end: 4px;
  }

  ::placeholder {
    opacity: 1;
  }

  @supports (not ((-webkit-appearance: -apple-pay-button))) or (contain-intrinsic-size: 1px) {
    ::placeholder {
      color: currentColor;
    }

    @supports (color: color-mix(in lab, red, red)) {
      ::placeholder {
        color: color-mix(in oklab, currentcolor 50%, transparent);
      }
    }
  }

  textarea {
    resize: vertical;
  }

  ::-webkit-search-decoration {
    -webkit-appearance: none;
  }

  ::-webkit-date-and-time-value {
    min-height: 1lh;
    text-align: inherit;
  }

  ::-webkit-datetime-edit {
    display: inline-flex;
  }

  ::-webkit-datetime-edit-fields-wrapper {
    padding: 0;
  }

  ::-webkit-datetime-edit {
    padding-block: 0;
  }

  ::-webkit-datetime-edit-year-field {
    padding-block: 0;
  }

  ::-webkit-datetime-edit-month-field {
    padding-block: 0;
  }

  ::-webkit-datetime-edit-day-field {
    padding-block: 0;
  }

  ::-webkit-datetime-edit-hour-field {
    padding-block: 0;
  }

  ::-webkit-datetime-edit-minute-field {
    padding-block: 0;
  }

  ::-webkit-datetime-edit-second-field {
    padding-block: 0;
  }

  ::-webkit-datetime-edit-millisecond-field {
    padding-block: 0;
  }

  ::-webkit-datetime-edit-meridiem-field {
    padding-block: 0;
  }

  ::-webkit-calendar-picker-indicator {
    line-height: 1;
  }

  :-moz-ui-invalid {
    box-shadow: none;
  }

  button, input:where([type="button"], [type="reset"], [type="submit"]) {
    appearance: button;
  }

  ::file-selector-button {
    appearance: button;
  }

  ::-webkit-inner-spin-button {
    height: auto;
  }

  ::-webkit-outer-spin-button {
    height: auto;
  }

  [hidden]:where(:not([hidden="until-found"])) {
    display: none !important;
  }

  html {
    -webkit-text-size-adjust: 100%;
    scroll-behavior: smooth;
  }

  body {
    background: var(--color-bg);
    color: var(--color-text);
    font-family: var(--font-body);
    font-size: var(--font-size-body);
    line-height: var(--line-height-body);
    letter-spacing: var(--letter-spacing-body);
    -webkit-font-smoothing: antialiased;
  }

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

@layer components;

/* The mark is a fixed box the artwork fills; the box's size comes from the
   `size` prop, so a consumer still asks for one number. */
.brand-mark__mark {
  display: block;
  flex: none;
}

.brand-mark__mark img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.brand__brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  text-decoration: none;
  color: var(--color-text);
}

.brand__dark {
  color: var(--color-text-inverse);
}

.brand__mark {
  display: block;
  flex: none;
}

.brand__wordmark {
  font-family: var(--font-display);
  font-size: 1.125rem;
  font-weight: var(--font-weight-extrabold);
  letter-spacing: -0.02em;
  line-height: 1;
}

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

.footer__footer {
  background: var(--color-bg-inverse);
  color: var(--color-text-muted-inverse);
}

.footer__inner {
  display: grid;
  /* Two columns even at 360px. A single stacked column turns the footer into
     ~1900px of scrolling, which is exactly the "desktop stacked vertically"
     outcome CLAUDE.md §10 rules out — mobile may be denser, not emptier. */
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-md);
  padding-block: var(--space-xl) var(--space-lg);
}

.footer__identity {
  grid-column: 1 / -1;
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  align-items: flex-start;
}

.footer__description {
  margin: 0;
  max-width: 34ch;
  font-size: var(--font-size-body-sm);
  line-height: var(--line-height-body);
}

.footer__column {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

/* Technical labels — small, uppercase, wide tracking. Red here is the
   lighter step that clears AA on charcoal (5.32:1), and these label real
   column contents rather than decorating them (CLAUDE.md §3.7). */
.footer__column-title {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--font-size-label);
  line-height: var(--line-height-label);
  letter-spacing: var(--letter-spacing-label);
  text-transform: uppercase;
  font-weight: var(--font-weight-semibold);
  color: var(--color-accent-on-dark);
}

/* No gap: each row carries its own 2.75rem height, so a gap on top of that
   would space the columns twice.

   DO NOT "tighten the spacing between these rows" — measured, the visual gap
   between consecutive footer links is already 0px. The rows sit flush and
   their height IS the 2.75rem touch target (CLAUDE.md §10), so the only way
   to close them further is to break that target. When the footer reads as too
   tall, the space is in the inner padding, the grid gaps, the baseline bar and
   unused column height — not between the rows. That is what the five-column
   arrangement below reclaims. */
.footer__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
}

/* Six services in two sub-columns from 1440. One <ul> under one heading, so
   nothing changes semantically or for a screen reader — only the visual flow.
   This is what stops the Services column setting the whole footer's height:
   seven 44px rows is 308px, four is 176px. Below 1280 the sub-columns would be
   narrower than the longest label ("Hospitality Services", 131.5px), so the
   list stays single-column there.

   grid-template-rows MUST equal ceil(services / 2). It was repeat(3, auto) for
   six services; a seventh with that value overflows into an implicit THIRD
   column, because grid-template-columns only declares two. Any change to the
   number of services changes this number too. */
@media (min-width: 1280px) {
  .footer__list--split {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-auto-flow: column;
    grid-template-rows: repeat(4, auto);
    column-gap: var(--space-md);
  }
}

/* Office (the postal address) and Contact (phone + the two mailboxes) are two
   columns, not one. Splitting them is what lets them sit side by side in the
   last mobile row instead of stacking — 87px saved at 390 — and it gives the
   contact links the same flush 2.75rem rows as every other footer list. */

/* 2.75rem rows. Measured at 390 these links were 17px tall — eleven of them,
   on every route, and the footer is the only place several routes are linked
   from on a phone. The type size is unchanged; only the row grew, and the
   footer had the room (CLAUDE.md §10: every CTA within natural thumb reach).
   width: fit-content keeps the hit area to the text's own width rather than
   the whole column, so neighbouring rows cannot be hit by accident. */
.footer__link {
  display: flex;
  align-items: center;
  width: fit-content;
  min-height: 2.75rem;
  color: var(--color-text-muted-inverse);
  text-decoration: none;
  font-size: var(--font-size-body-sm);
  line-height: var(--line-height-body);
  transition: color var(--duration-fast) var(--ease-standard);
}

.footer__link:hover {
  color: var(--color-text-inverse);
  text-decoration: underline;
  text-underline-offset: 0.25em;
}

.footer__link:focus-visible {
  outline: 2px solid var(--color-accent-on-dark);
  outline-offset: 3px;
}

.footer__address {
  display: flex;
  flex-direction: column;
  gap: var(--space-3xs);
  align-items: flex-start;
  font-style: normal;
  font-size: var(--font-size-body-sm);
  line-height: var(--line-height-body);
}

.footer__baseline {
  border-block-start: var(--border-hairline) solid var(--color-charcoal-600);
}

.footer__copyright {
  margin: 0;
  padding-block: var(--space-sm);
  font-size: var(--font-size-label);
  letter-spacing: var(--letter-spacing-label);
  text-transform: uppercase;
}

/* Tablet: four columns, every block placed explicitly.

   The identity block used to span the full width here and sit in a row of its
   own, which cost the footer a whole row for one short paragraph — measured,
   613px at 768, the tallest the footer got at any width. Giving it a column
   and stacking Office over Contact in the fourth puts all five blocks in one
   band. The row is then set by the Services list's six 2.75rem rows, which is
   the real floor at this width: four columns of 162px are too narrow to split
   that list in two (see .footer__list--split). */
@media (min-width: 768px) {
  .footer__inner {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    align-items: start;
  }

  .footer__identity {
    grid-column: 1;
    grid-row: 1 / span 2;
  }

  .footer__inner > nav.footer__column {
    grid-column: 2;
    grid-row: 1 / span 2;
  }

  .footer__services {
    grid-column: 3;
    grid-row: 1 / span 2;
  }

  .footer__office {
    grid-column: 4;
    grid-row: 1;
  }

  .footer__contact {
    grid-column: 4;
    grid-row: 2;
  }
}

/* Full five-column band. The shares are set by the widest thing each column
   has to hold rather than by an even split: Office needs 136px for "Fereej
   Bin Mahmoud" and Contact 111px for the phone number, so neither can take an
   equal fifth at 1024 without wrapping. The identity column is sized to its
   description rather than given a share it cannot fill — an unfillable column
   reads as an accident, not as composed asymmetry. */
@media (min-width: 1024px) {
  .footer__inner {
    grid-template-columns: 2.5fr 2fr 4fr 2.5fr 2.5fr;
    gap: var(--space-lg) var(--space-lg);
    padding-block: var(--space-2xl) var(--space-xl);
  }

  /* Undo the tablet placement above — five columns, one row, source order. */
  .footer__identity,
  .footer__inner > nav.footer__column,
  .footer__services,
  .footer__office,
  .footer__contact {
    grid-column: auto;
    grid-row: auto;
  }
}

@media (prefers-reduced-motion: reduce) {
  .footer__link {
    transition: none;
  }
}
.navigation__list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.navigation__link {
  position: relative;
  display: inline-block;
  text-decoration: none;
  color: var(--color-text-muted);
  font-family: var(--font-body);
  font-weight: var(--font-weight-medium);
  transition: color var(--duration-fast) var(--ease-standard);
}

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

/* The red indicator: a short rule under the label, not a full underline.
   2px of --color-accent on warm white is 3.42:1 — above the 3:1 bar for a
   non-text indicator, and it is never the only cue: active items also shift
   to the darker text colour. */
.navigation__link::after {
  content: '';
  position: absolute;
  inset-inline-start: 0;
  inset-block-end: -0.375rem;
  width: 1rem;
  height: 2px;
  background: var(--color-accent);
  opacity: 0;
}

.navigation__active {
  color: var(--color-text);
}

.navigation__active::after {
  opacity: 1;
}

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

/* --- Desktop -------------------------------------------------------------- */

.navigation__desktop .navigation__list {
  display: flex;
  align-items: center;
  gap: var(--space-md);
}

/* Uppercase at desktop, matching docs/reference/. The mobile panel keeps
   sentence case: those rows are set at subhead size, and 22-30px uppercase
   would be shouty — CLAUDE.md §3.3 warns against excessive uppercase. */
.navigation__desktop .navigation__link {
  font-size: 0.8125rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: var(--font-weight-semibold);
  padding-block: var(--space-3xs);
}

/* --- Mobile panel --------------------------------------------------------- */

.navigation__mobile .navigation__list {
  display: flex;
  flex-direction: column;
}

.navigation__mobile .navigation__item {
  border-block-end: var(--border-hairline) solid var(--color-charcoal-600);
}

.navigation__mobile .navigation__link {
  display: block;
  /* Full-width row: the whole strip is the target, comfortably past 44px. */
  padding-block: var(--space-sm);
  padding-inline: 0;
  font-family: var(--font-display);
  font-size: var(--font-size-subhead);
  font-weight: var(--font-weight-semibold);
  letter-spacing: var(--letter-spacing-subhead);
  color: var(--color-text-muted-inverse);
}

.navigation__mobile .navigation__link:hover {
  color: var(--color-text-inverse);
}

.navigation__mobile .navigation__active {
  color: var(--color-text-inverse);
}

/* On charcoal the indicator moves beside the label and uses the lighter red
   that clears AA on dark (--color-accent-on-dark). */
.navigation__mobile .navigation__link::after {
  inset-block-end: auto;
  inset-block-start: 50%;
  inset-inline-start: auto;
  inset-inline-end: 0;
  transform: translateY(-50%);
  width: 1.25rem;
  background: var(--color-accent-on-dark);
}

.navigation__mobile .navigation__link:focus-visible {
  outline: 2px solid var(--color-accent-on-dark);
  outline-offset: -2px;
}

@media (prefers-reduced-motion: reduce) {
  .navigation__link {
    transition: none;
  }
}

.header__header {
  --header-height: 3.75rem;

  position: sticky;
  inset-block-start: 0;
  z-index: 100;
  background: var(--color-bg);
  border-block-end: var(--border-hairline) solid var(--color-border);
}

.header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  min-height: var(--header-height);
}

/* Nav + action travel together at the right edge. */
.header__desktop-cluster {
  display: none;
  align-items: center;
  gap: var(--space-lg);
}

/* Primary action. Solid red, square corners — see the §3.2 flag in
   DEVELOPMENT_PLAN.md. White on --color-accent-surface is 5.09:1. */
.header__action {
  display: inline-flex;
  align-items: center;
  min-height: 2.5rem;
  padding-inline: var(--space-md);
  border-radius: var(--radius-none);
  background: var(--color-accent-surface);
  color: var(--color-on-accent-surface);
  text-decoration: none;
  font-family: var(--font-body);
  font-size: var(--font-size-body-sm);
  font-weight: var(--font-weight-semibold);
  letter-spacing: 0.02em;
  transition: background-color var(--duration-fast) var(--ease-standard);
}

.header__action:hover {
  background: var(--color-accent-surface-hover);
}

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

/* --- Mobile toggle -------------------------------------------------------- */

.header__toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  /* 44px minimum target (CLAUDE.md §10 / QA checklist). */
  min-height: 44px;
  min-width: 44px;
  padding: 0;
  margin-inline-end: calc(var(--space-2xs) * -1);
  padding-inline: var(--space-2xs);
  background: none;
  border: 0;
  border-radius: var(--radius-none);
  color: var(--color-text);
  cursor: pointer;
  font-family: var(--font-body);
}

.header__toggle-bars {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  width: 20px;
  height: 14px;
}

.header__bar,
.header__bar-top-open,
.header__bar-hidden,
.header__bar-bottom-open {
  display: block;
  height: 2px;
  width: 100%;
  background: currentColor;
}

/* Open state becomes an X. No transition — the brief rules out heavy motion,
   and an instant state change reads as precise rather than animated. */
.header__bar-top-open {
  transform: translateY(6px) rotate(45deg);
}

.header__bar-hidden {
  opacity: 0;
}

.header__bar-bottom-open {
  transform: translateY(-6px) rotate(-45deg);
}

.header__toggle-label {
  font-size: var(--font-size-label);
  letter-spacing: var(--letter-spacing-label);
  text-transform: uppercase;
  font-weight: var(--font-weight-semibold);
}

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

/* --- Mobile panel --------------------------------------------------------- */

/* Absolute inside the sticky header, so it tracks the header on scroll
   without any viewport maths. */
.header__panel {
  position: absolute;
  inset-inline: 0;
  inset-block-start: 100%;
  background: var(--color-bg-inverse);
  border-block-end: var(--border-hairline) solid var(--color-charcoal-600);
  /* Fills the screen below the header. Without this the panel ends wherever
     the links do and the page behind shows through underneath, which reads
     as a rendering fault rather than an open menu. */
  min-height: calc(100dvh - var(--header-height));
  max-height: calc(100dvh - var(--header-height));
  overflow-y: auto;
  overscroll-behavior: contain;
  display: flex;
  flex-direction: column;
}

.header__panel-inner {
  padding-block: var(--space-sm) var(--space-lg);
  flex: 1;
  display: flex;
  flex-direction: column;
}

/* Sits in the space between the links and the action, pushed down so the
   action stays at the foot of the panel. */
.header__panel-meta {
  margin-block-start: auto;
  padding-block-start: var(--space-xl);
  color: var(--color-text-muted-inverse);
}

.header__panel-meta-label {
  margin: 0 0 var(--space-2xs);
  font-size: var(--font-size-label);
  letter-spacing: var(--letter-spacing-label);
  text-transform: uppercase;
  font-weight: var(--font-weight-semibold);
  color: var(--color-accent-on-dark);
}

.header__panel-address {
  display: flex;
  flex-direction: column;
  gap: var(--space-3xs);
  align-items: flex-start;
  font-style: normal;
  font-size: var(--font-size-body-sm);
  line-height: var(--line-height-body);
}

/* 2.75rem rows (CLAUDE.md §10): the phone and both email links sit in a
   stack, and 22px text-height targets that close together are easy to
   mis-tap on a phone. */
.header__panel-phone {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  color: var(--color-text-inverse);
  text-decoration: none;
}

.header__panel-address span + .header__panel-phone {
  margin-block-start: var(--space-2xs);
}

.header__panel-phone:hover {
  text-decoration: underline;
  text-underline-offset: 0.25em;
}

.header__panel-phone:focus-visible {
  outline: 2px solid var(--color-accent-on-dark);
  outline-offset: 3px;
}

.header__panel-action {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 3rem;
  /* At the foot of the panel — within thumb reach (CLAUDE.md §10). */
  margin-block-start: var(--space-lg);
  border-radius: var(--radius-none);
  background: var(--color-accent-surface);
  color: var(--color-on-accent-surface);
  text-decoration: none;
  font-family: var(--font-body);
  font-size: var(--font-size-body-sm);
  font-weight: var(--font-weight-semibold);
  letter-spacing: 0.02em;
}

.header__panel-action:focus-visible {
  outline: 2px solid var(--color-accent-on-dark);
  outline-offset: 3px;
}

/* --- Breakpoint ----------------------------------------------------------- */

@media (min-width: 768px) {
  .header__header {
    --header-height: 4.5rem;
  }

  .header__desktop-cluster {
    display: flex;
  }

  .header__toggle,
  .header__panel {
    display: none;
  }
}

/* Between 768 and 1023 the desktop nav is tight: six labels plus the
   action. With Home added (2026-09-18) the header overflowed by 12px at
   exactly 768 — the latent risk CLAUDE.md §3.3 recorded. Narrower gaps in
   this band only give it ~36px of slack; wider screens keep their spacing. */
@media (min-width: 768px) and (max-width: 1023px) {
  .header__desktop-cluster {
    gap: var(--space-md);
  }

  .navigation__desktop .navigation__list {
    gap: var(--space-sm);
  }

  .navigation__desktop .navigation__link {
    letter-spacing: 0.04em;
  }
}

/* --- Touch on the desktop navigation -------------------------------------
   Keyed to the input, not the width. The desktop nav turns on at 768 and a
   tablet reaches it at every width above that too — iPad landscape is
   1024-1366 — so a width-based fix would leave the larger tablets behind.
   `any-pointer: coarse` matches a device that has a coarse pointer at all,
   including a touchscreen laptop; a mouse-only machine matches nothing here
   and renders exactly as before.

   Measured before: the nav rows were 28.8-29.8px and the Services chevron
   24x24 — the tablet case the "768 is a tablet" rule was written to catch and
   never had. The rows carry the height themselves rather than an overlay,
   because an absolutely-positioned hit area over a link was tried once and
   reached only 35px (docs/DESIGN_AND_CONTENT.md #touch-targets).

   Nothing visible moves. The label keeps its type and position, the chevron
   glyph keeps its exact x (the gap it used to sit after is folded into the
   button's own padding), and only the invisible box around each grows. The
   nav row is 20px wider for the chevron, against 108px of header slack at
   768 and 297px at 1024. */
@media (any-pointer: coarse) {
  .navigation__desktop .navigation__link {
    /* The line box is 20.784px, not the 20.8 it rounds to, so 0.475rem of
       extra padding landed the row on 43.984 — a hair under, and a measured
       sweep is right to fail it. 0.5rem clears 44 by 0.78px instead of
       missing it by 0.016. The value is held in a variable because the
       indicator below has to move by exactly the same amount, and min-height
       is a floor for whatever a future type change does to the line box. */
    --nav-touch-grow: 0.5rem;

    min-height: 2.75rem;
    padding-block: calc(var(--space-3xs) + var(--nav-touch-grow));
  }

  /* The red active indicator belongs under the label, not under the padding
     box: it moves up by exactly what was added below it. */
  .navigation__desktop .navigation__link::after {
    inset-block-end: calc(-0.375rem + var(--nav-touch-grow));
  }

  /* The chevron's 2px gap becomes the button's own leading padding, so the
     glyph does not move while the box grows 24 -> 44. */
  .navigation__desktop .navigation__item--menu {
    gap: 0;
  }

  .navigation__desktop .navigation__menu-toggle {
    width: 2.75rem;
    height: 2.75rem;
    justify-content: flex-start;
    padding-inline-start: 0.5rem;
  }

  .header__action {
    min-height: 2.75rem;
  }

  /* The brand links and the skip link. Flagged by a sweep on 2026-10-05 as the
     last three interactive elements under 44px once the nav was fixed: the
     header brand measured 94.6x30, the footer brand 93.6x28 and the skip-link
     chip 149.7x38.4, at every touch width.

     The row carries the height itself (min-height), not a pseudo-element band
     over it -- an overlay reached only 35px when that was tried, and its
     height is invisible to every measurement the sweep makes
     (docs/DESIGN_AND_CONTENT.md #touch-targets).

     Nothing visible moves, and the two cases are different:

       header   .header__inner is a flex row with align-items: center and a
                72px min-height (60px below 768), so a 44px brand is absorbed
                whole. The brand's own align-items: center keeps the mark and
                the wordmark on the same baseline they had at 30px.
       footer   .footer__identity is a flex COLUMN, so the extra 16px would
                push the address and everything under it down. It is given
                back with a negative block margin of exactly half the growth
                on each side, from the same custom property -- the pattern the
                nav's active indicator already uses. The link occupies the
                28px it always did and its hit area overhangs 8px into the
                footer's top padding above and into the 16px column gap below,
                reaching neither neighbour's box. */
  .brand__brand {
    /* 44 - 28 = 16, half each side. The footer brand is the shorter of the
       two, so this is the larger of the two corrections and it is the one the
       cancel below has to match. */
    --brand-touch-grow: 0.5rem;

    min-height: 2.75rem;
  }

  .footer__identity .brand__brand {
    margin-block: calc(-1 * var(--brand-touch-grow));
  }

  /* Off-screen until focused, so this grows the focused chip from 38.4 to 44
     and nothing else. It needs the flex centring because a min-height on a
     block box leaves the text at the top of it. */
  .site-layout__skip-link {
    display: inline-flex;
    align-items: center;
    min-height: 2.75rem;
  }
}

/* The action never wraps or shrinks: squeezed, the button label broke onto two
   lines at 768 while technically still fitting. */
.header__action {
  flex: none;
  white-space: nowrap;
}

@media (prefers-reduced-motion: reduce) {
  .header__action {
    transition: none;
  }
}
.site-layout__shell {
  display: flex;
  flex-direction: column;
  min-height: 100dvh;
}

/* Grows so the footer sits at the bottom on short pages. */
.site-layout__main {
  flex: 1 0 auto;
}

.site-layout__main:focus {
  outline: none;
}

.site-layout__skip-link {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;
  z-index: 200;
  /* Off-screen until focused, rather than display:none — a hidden link is
     not reachable by keyboard at all. */
  transform: translateY(-120%);
  padding: var(--space-2xs) var(--space-md);
  background: var(--color-bg-inverse);
  color: var(--color-text-inverse);
  font-size: var(--font-size-body-sm);
  font-weight: var(--font-weight-semibold);
  text-decoration: none;
}

.site-layout__skip-link:focus-visible {
  transform: translateY(0);
  outline: 2px solid var(--color-accent-on-dark);
  outline-offset: -4px;
}

.about-closing-cta__section {
  position: relative;
  isolation: isolate;
  background: var(--color-bg-inverse);
  color: var(--color-text-inverse);
}

/* The backdrop is now a <picture> wrapper, so the positioning sits on the
   box and the cover behaviour on the image inside it. */
.about-closing-cta__backdrop {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.about-closing-cta__backdrop picture {
  display: block;
  width: 100%;
  height: 100%;
}

.about-closing-cta__backdrop-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 60%;
}

/* Flat, not a gradient. A gradient would leave some part of the photograph
   under-covered, and the bright dusk sky sits on the same side as the
   outlined button — see the note in the component. The alpha here is the
   measured value, not an eyeballed one. */
.about-closing-cta__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: rgb(23 25 27 / 0.82);
}

.about-closing-cta__inner {
  position: relative;
  z-index: 2;
  display: grid;
  gap: var(--space-xl);
  padding-block: var(--space-3xl);
}

.about-closing-cta__statement {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.about-closing-cta__heading {
  margin: 0;
  max-width: 18ch;
  font-family: var(--font-display);
  font-size: var(--font-size-heading);
  line-height: var(--line-height-heading);
  letter-spacing: var(--letter-spacing-heading);
  font-weight: var(--font-weight-extrabold);
  text-transform: uppercase;
  text-wrap: balance;
}

.about-closing-cta__lead {
  margin: 0;
  max-width: 44ch;
  font-size: var(--font-size-body);
  line-height: var(--line-height-body);
  color: var(--color-text-muted-inverse);
}

.about-closing-cta__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-sm);
}

.about-closing-cta__primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2xs);
  min-height: 3rem;
  padding-inline: var(--space-lg);
  background: var(--color-accent-surface);
  color: var(--color-on-accent-surface);
  border: var(--border-hairline) solid var(--color-accent-surface);
  border-radius: var(--radius-none);
  text-decoration: none;
  font-size: var(--font-size-body-sm);
  font-weight: var(--font-weight-semibold);
  letter-spacing: 0.02em;
  transition: background-color var(--duration-fast) var(--ease-standard);
}

.about-closing-cta__primary:hover {
  background: var(--color-accent-surface-hover);
  border-color: var(--color-accent-surface-hover);
}

/* Outlined and neutral on dark — one red fill per group (CLAUDE.md §3.2). */
.about-closing-cta__secondary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 3rem;
  padding-inline: var(--space-lg);
  background: transparent;
  color: var(--color-text-inverse);
  /* 7.50:1 against the charcoal ground — the same value the shared
     PageClosing uses. The previous --color-charcoal-600 was about 1.6:1
     against the scrimmed photograph behind it, which is not a visible
     boundary (WCAG 1.4.11). */
  border: var(--border-hairline) solid var(--color-charcoal-200);
  border-radius: var(--radius-none);
  text-decoration: none;
  font-size: var(--font-size-body-sm);
  font-weight: var(--font-weight-semibold);
  letter-spacing: 0.02em;
  transition: background-color var(--duration-fast) var(--ease-standard),
    color var(--duration-fast) var(--ease-standard),
    border-color var(--duration-fast) var(--ease-standard);
}

.about-closing-cta__secondary:hover {
  background: var(--color-text-inverse);
  color: var(--color-text);
  border-color: var(--color-text-inverse);
}

.about-closing-cta__primary:focus-visible,
.about-closing-cta__secondary:focus-visible {
  outline: 2px solid var(--color-accent-on-dark);
  outline-offset: 3px;
}

.about-closing-cta__arrow {
}

@media (max-width: 559px) {
  .about-closing-cta__actions {
    flex-direction: column;
    align-items: stretch;
  }
}

@media (min-width: 900px) {
  .about-closing-cta__inner {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: end;
    gap: var(--space-2xl);
  }

  .about-closing-cta__actions {
    justify-content: flex-end;
  }
}

@media (prefers-reduced-motion: reduce) {
  .about-closing-cta__primary,
  .about-closing-cta__secondary,
  .about-closing-cta__arrow {
    transition: none;
  }
}

.about-hero__section {
  background: var(--color-bg-inverse);
  color: var(--color-text-inverse);
}

/* Phones get a tighter foot than head: the headline is the last thing in the
   section, and 96px of empty charcoal under it read as a gap rather than a
   composition. CLAUDE.md §10 — mobile can be denser than desktop, and
   decorative whitespace is a desktop luxury. */
.about-hero__inner {
  padding-block: var(--space-2xl) var(--space-xl);
}

.about-hero__eyebrow {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  margin: 0 0 var(--space-lg);
  font-size: var(--font-size-label);
  line-height: var(--line-height-label);
  letter-spacing: var(--letter-spacing-label);
  text-transform: uppercase;
  font-weight: var(--font-weight-semibold);
  color: var(--color-accent-on-dark);
}

.about-hero__rule {
  display: block;
  width: var(--space-xl);
  height: 1px;
  flex: none;
  background: var(--color-accent-on-dark);
}

.about-hero__headline {
  margin: 0;
  max-width: 16ch;
  font-family: var(--font-display);
  font-size: var(--font-size-display);
  line-height: var(--line-height-display);
  letter-spacing: var(--letter-spacing-display);
  font-weight: var(--font-weight-extrabold);
  text-transform: uppercase;
}

@media (min-width: 768px) {
  .about-hero__inner {
    padding-block: var(--space-2xl) var(--space-3xl);
  }
}

@media (min-width: 1024px) {
  /* Single column again. This was a 7fr/5fr grid holding the headline against
     the lead out to its right; with the lead gone the grid had one occupied
     track and pinned the headline to 7/12 of the measure for no reason. The
     foot also comes in from --space-4xl: that much empty charcoal under a
     headline with nothing after it reads as a gap, which is the same thing the
     mobile rule above already guards against. */
  .about-hero__inner {
    padding-block: var(--space-3xl);
  }
}
.photo__figure {
  margin: 0;
  width: 100%;
  max-width: 100%;
  /* Sections opt into fill by setting --illustration-height: 100%. */
  height: var(--illustration-height, auto);
  display: flex;
  flex-direction: column;
}

/* Carries the ratio, so a caption placed below sits outside it and the image
   keeps the shape the section asked for. */
.photo__box {
  position: relative;
  width: 100%;
  aspect-ratio: var(--illustration-ratio, 16 / 9);
  height: var(--illustration-height, auto);
  flex: 1 1 auto;
  overflow: hidden;
  background: var(--color-surface-muted);
  border: var(--border-hairline) solid var(--color-border);
  border-radius: var(--radius-none);
}

/* The generated <picture> is an inline wrapper with no box of its own; the
   image inside it keeps the absolute fill the frame has always used. */
.photo__box picture {
  display: contents;
}

.photo__image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.section-label__wrap {
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
  margin: 0;
  font-size: var(--font-size-label);
  line-height: var(--line-height-label);
  letter-spacing: var(--letter-spacing-label);
  text-transform: uppercase;
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-muted);
}

.section-label__index {
  color: var(--color-accent-text);
}

.section-label__rule {
  width: var(--space-md);
  height: 1px;
  background: var(--color-accent);
}

.section-label__dark {
  color: var(--color-text-muted-inverse);
}

.section-label__dark .section-label__index {
  color: var(--color-accent-on-dark);
}

.section-label__dark .section-label__rule {
  background: var(--color-accent-on-dark);
}
.about-who-we-are__section {
  background: var(--color-surface);
  overflow: hidden;
}

.about-who-we-are__inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
}

.about-who-we-are__media {
  display: flex;
  min-width: 0;
}

.about-who-we-are__image {
  --illustration-ratio: 3 / 2;
}

.about-who-we-are__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  padding-inline: var(--layout-gutter);
  padding-block: var(--space-2xl);
}

.about-who-we-are__opening {
  margin: 0;
  max-width: 32ch;
  font-family: var(--font-display);
  font-size: var(--font-size-subhead);
  line-height: var(--line-height-subhead);
  letter-spacing: var(--letter-spacing-subhead);
  font-weight: var(--font-weight-medium);
  color: var(--color-text);
  text-wrap: balance;
}

.about-who-we-are__paragraph {
  margin: 0;
  max-width: 58ch;
  font-size: var(--font-size-body);
  line-height: var(--line-height-body);
  color: var(--color-text-muted);
}

@media (min-width: 1024px) {
  /* Image bleeds off the LEFT edge — the mirror of the homepage hero, and a
     device used nowhere else on the site. */
  .about-who-we-are__inner {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.28fr);
    align-items: stretch;
  }

  .about-who-we-are__image {
    --illustration-ratio: auto;
    --illustration-height: 100%;
  }

  .about-who-we-are__body {
    justify-content: center;
    padding-inline: var(--space-2xl)
      max(
        var(--layout-gutter),
        calc((100vw - var(--layout-max-width)) / 2 + var(--layout-gutter))
      );
    padding-block: var(--space-3xl);
  }
}

.about-why-soft-one__section {
  background: var(--color-surface);
}

.about-why-soft-one__inner {
  padding-block: var(--space-2xl);
}

.about-why-soft-one__head {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  margin-block-end: var(--space-xl);
}

.about-why-soft-one__heading {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--font-size-subhead);
  line-height: var(--line-height-subhead);
  letter-spacing: var(--letter-spacing-subhead);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
}

.about-why-soft-one__grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-lg) var(--space-md);
}

/* Numeral above the name, not beside it — the homepage puts the number
   inline at label size, so stacking it changes the silhouette. */
.about-why-soft-one__item {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  padding-block-start: var(--space-sm);
  border-block-start: 2px solid var(--color-accent);
}

.about-why-soft-one__number {
  font-family: var(--font-display);
  font-size: var(--font-size-subhead);
  line-height: 1;
  letter-spacing: var(--letter-spacing-subhead);
  font-weight: var(--font-weight-extrabold);
  /* Was --color-concrete: 1.43:1 on this white ground at 60px/800, against
     a 3:1 large-text bar. Still the faintest thing in the section. */
  color: var(--color-concrete-dark);
}

.about-why-soft-one__name {
  font-family: var(--font-display);
  font-size: var(--font-size-body);
  line-height: var(--line-height-subhead);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
}

@media (min-width: 768px) {
  .about-why-soft-one__inner {
    padding-block: var(--space-3xl);
  }

  .about-why-soft-one__head {
    flex-direction: row;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-lg);
  }

  /* min-content, not 0, as the track floor. At 768 six equal columns are
     100.2px and "Professionals" is 111 — the word cannot break, so it
     overflowed its cell and ran into the neighbour. A min-content floor lets
     the tracks go unequal only where a name needs it (768-839, measured);
     from 840 up there is room for six equal columns and nothing changes. */
  .about-why-soft-one__grid {
    grid-template-columns: repeat(6, minmax(min-content, 1fr));
    gap: var(--space-lg) var(--space-md);
  }

  .about-why-soft-one__number {
    font-size: var(--font-size-heading);
  }
}

.company-introduction__section {
  background: var(--color-bg);
}

.company-introduction__inner {
  padding-block: var(--space-2xl);
}

.company-introduction__head {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  margin-block-end: var(--space-xl);
}

.company-introduction__statement {
  margin: 0;
  max-width: 34ch;
  font-family: var(--font-display);
  font-size: var(--font-size-subhead);
  line-height: var(--line-height-subhead);
  letter-spacing: var(--letter-spacing-subhead);
  font-weight: var(--font-weight-medium);
  color: var(--color-text);
  text-wrap: balance;
}

.company-introduction__areas {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 var(--space-lg);
  border-block-start: var(--border-hairline) solid var(--color-border);
}

.company-introduction__area {
  display: flex;
  align-items: baseline;
  gap: var(--space-sm);
  padding-block: var(--space-md);
  border-block-end: var(--border-hairline) solid var(--color-border);
}

.company-introduction__number {
  flex: none;
  font-size: var(--font-size-label);
  letter-spacing: var(--letter-spacing-label);
  font-weight: var(--font-weight-semibold);
  color: var(--color-accent-text);
}

.company-introduction__name {
  font-family: var(--font-display);
  font-size: var(--font-size-subhead);
  line-height: 1.2;
  letter-spacing: var(--letter-spacing-subhead);
  font-weight: var(--font-weight-medium);
  color: var(--color-text);
}

@media (min-width: 768px) {
  .company-introduction__inner {
    padding-block: var(--space-3xl);
  }

  .company-introduction__head {
    flex-direction: row;
    align-items: baseline;
    gap: var(--space-2xl);
  }

  .company-introduction__statement {
    max-width: 40ch;
  }

  .company-introduction__areas {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    column-gap: var(--space-2xl);
  }
}

.core-values__section {
  background: var(--color-surface-muted);
}

.core-values__inner {
  padding-block: var(--space-2xl);
}

.core-values__head {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.core-values__heading {
  margin: 0;
  max-width: 18ch;
  font-family: var(--font-display);
  font-size: var(--font-size-heading);
  line-height: var(--line-height-heading);
  letter-spacing: var(--letter-spacing-heading);
  font-weight: var(--font-weight-bold);
  color: var(--color-text);
  text-wrap: balance;
}

.core-values__list {
  list-style: none;
  margin: var(--space-xl) 0 0;
  padding: 0;
  display: grid;
  gap: var(--space-md);
}

/* Framed cells, not cards: a hairline box with square corners and no fill or
   shadow (CLAUDE.md §3.5, §11). */
/* The card held a number, a name and a sub-line pinned to the bottom by
   margin-block-start: auto. The client removed the sub-line from all four on
   2026-10-05, which left the pair at the top of an 8rem box with up to 28px
   of hole under it. The floor comes down to 7rem instead, which closes the
   hole to 2-12.5px depending on width.

   Centring the pair vertically was tried first and is wrong: two of the four
   names wrap at most widths, so centring put the four red numbers on two
   different baselines -- 241 and 259 at 1440 -- and the row read as
   misaligned rather than composed. Top alignment keeps all four numbers and
   all four names on one line each. The cards are grid items, so they still
   stretch to a common height within the row whatever the longest name does. */
.core-values__value {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  padding: var(--space-md);
  border: var(--border-hairline) solid var(--color-border);
  border-radius: var(--radius-none);
  min-height: 7rem;
}

.core-values__number {
  font-size: var(--font-size-label);
  letter-spacing: var(--letter-spacing-label);
  font-weight: var(--font-weight-semibold);
  color: var(--color-accent-text);
}

.core-values__name {
  font-family: var(--font-display);
  font-size: var(--font-size-subhead);
  line-height: var(--line-height-subhead);
  letter-spacing: var(--letter-spacing-subhead);
  font-weight: var(--font-weight-medium);
  color: var(--color-text);
}

@media (min-width: 600px) {
  .core-values__list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1024px) {
  .core-values__inner {
    padding-block: var(--space-3xl);
  }

  .core-values__head {
    flex-direction: row;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-2xl);
  }

  .core-values__list {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--space-lg);
  }
}

.health-safety__section {
  background: var(--color-bg);
}

.health-safety__inner {
  display: grid;
  gap: var(--space-xl);
  padding-block: var(--space-2xl);
}

/* The column held a label, a heading, the statement and a note under it. The
   client removed the note on 2026-10-05, which dropped the column from 77.2%
   of the photograph's height to 67.0% at 1440. The gap goes up one step --
   --space-md to --space-xl -- to put it back to 74.1%, measured, which is as
   close as the existing tokens get without inventing a value. At 1024 the
   column is the taller of the two: 148.8% before, 134.2% after the removal,
   144.4% now. */
.health-safety__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-xl);
}

.health-safety__heading {
  margin: 0;
  max-width: 20ch;
  font-family: var(--font-display);
  font-size: var(--font-size-subhead);
  line-height: var(--line-height-subhead);
  letter-spacing: var(--letter-spacing-subhead);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
  text-wrap: balance;
}

/* The one verified sentence, given the weight of the section. */
.health-safety__statement {
  margin: 0;
  padding-inline-start: var(--space-md);
  border-inline-start: 2px solid var(--color-accent);
}

.health-safety__statement p {
  margin: 0;
  max-width: 30ch;
  font-family: var(--font-display);
  font-size: var(--font-size-heading);
  line-height: var(--line-height-heading);
  letter-spacing: var(--letter-spacing-heading);
  font-weight: var(--font-weight-bold);
  color: var(--color-text);
  text-wrap: balance;
}

.health-safety__image {
  --illustration-ratio: 3 / 2;
}

@media (min-width: 900px) {
  .health-safety__inner {
    /* Text leads, photograph to the right and narrower — the reverse weight
       of Who We Are further up the page. */
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    gap: var(--space-2xl);
    padding-block: var(--space-3xl);
    align-items: center;
  }

  .health-safety__image {
    --illustration-ratio: 4 / 5;
  }
}

.our-approach__section {
  background: var(--color-bg-inverse);
  color: var(--color-text-inverse);
}

.our-approach__inner {
  padding-block: var(--space-2xl);
}

.our-approach__intro {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  margin-block-end: var(--space-xl);
}

.our-approach__heading {
  margin: 0;
  max-width: 20ch;
  font-family: var(--font-display);
  font-size: var(--font-size-heading);
  line-height: var(--line-height-heading);
  letter-spacing: var(--letter-spacing-heading);
  font-weight: var(--font-weight-bold);
  text-wrap: balance;
}

/* Stages run as columns, not stacked rows — the homepage's dark section is a
   two-column row list, so this reads differently at a glance. */
.our-approach__stages {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-lg);
}

.our-approach__stage {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  padding-block-start: var(--space-md);
  border-block-start: var(--border-hairline) solid var(--color-charcoal-600);
}

.our-approach__number {
  font-size: var(--font-size-label);
  letter-spacing: var(--letter-spacing-label);
  font-weight: var(--font-weight-semibold);
  color: var(--color-accent-on-dark);
}

.our-approach__name {
  font-family: var(--font-display);
  font-size: var(--font-size-subhead);
  line-height: var(--line-height-subhead);
  letter-spacing: var(--letter-spacing-subhead);
  font-weight: var(--font-weight-medium);
}

.our-approach__description {
  max-width: 34ch;
  font-size: var(--font-size-body-sm);
  line-height: var(--line-height-body);
  color: var(--color-text-muted-inverse);
}

.our-approach__plate {
  --illustration-ratio: 16 / 9;
  margin-block-start: var(--space-xl);
}

@media (min-width: 768px) {
  .our-approach__inner {
    padding-block: var(--space-3xl);
  }

  .our-approach__stages {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--space-xl);
  }

  .our-approach__plate {
    /* The photograph is 2.5:1; holding close to its own ratio avoids cropping
       the two figures out of frame. */
    --illustration-ratio: 5 / 2;
    margin-block-start: var(--space-2xl);
  }
}

.contact-strip__section {
  background: var(--color-bg-inverse);
  color: var(--color-text-inverse);
}

.contact-strip__inner {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-lg);
  padding-block: var(--space-2xl);
}

.contact-strip__body {
  display: grid;
  gap: var(--space-sm);
}

.contact-strip__heading {
  margin: 0;
  max-width: 26ch;
  font-family: var(--font-display);
  font-size: var(--font-size-subhead);
  line-height: var(--line-height-subhead);
  letter-spacing: var(--letter-spacing-subhead);
  font-weight: var(--font-weight-semibold);
}

.contact-strip__details {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2xs) var(--space-md);
  margin: 0;
  font-size: var(--font-size-label);
  line-height: var(--line-height-label);
  letter-spacing: var(--letter-spacing-label);
  text-transform: uppercase;
  font-weight: var(--font-weight-semibold);
}

.contact-strip__place {
  color: var(--color-text-muted-inverse);
}

/* A real target, not just a tinted word: the strip exists so a visitor can
   call from here, and a 13px line of text is not something a thumb can hit
   (CLAUDE.md §10). */
.contact-strip__phone {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  color: var(--color-accent-on-dark);
  text-decoration: none;
  border-block-end: var(--border-hairline) solid transparent;
  font-variant-numeric: tabular-nums;
  transition: border-color var(--duration-fast) var(--ease-standard);
}

.contact-strip__phone:hover {
  border-block-end-color: var(--color-accent-on-dark);
}

.contact-strip__phone:focus-visible {
  outline: 2px solid var(--color-accent-on-dark);
  outline-offset: 3px;
}

/* The one red-filled control on the page (CLAUDE.md §3.2). */
.contact-strip__action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2xs);
  min-height: 3rem;
  padding-inline: var(--space-lg);
  background: var(--color-accent-surface);
  color: var(--color-on-accent-surface);
  border-radius: var(--radius-none);
  text-decoration: none;
  font-size: var(--font-size-body-sm);
  font-weight: var(--font-weight-semibold);
  letter-spacing: 0.02em;
  transition: background-color var(--duration-fast) var(--ease-standard);
}

.contact-strip__action:hover {
  background: var(--color-accent-surface-hover);
}

.contact-strip__action:focus-visible {
  outline: 2px solid var(--color-accent-on-dark);
  outline-offset: 3px;
}

.contact-strip__arrow {
}

/* Full-width target on a phone, matched to the hero button treatment. */
@media (max-width: 559px) {
  .contact-strip__action {
    align-self: stretch;
  }
}

@media (min-width: 768px) {
  .contact-strip__inner {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2xl);
    padding-block: var(--space-2xl);
  }

  .contact-strip__heading {
    font-size: var(--font-size-subhead);
  }

  .contact-strip__action {
    flex: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .contact-strip__action,
  .contact-strip__arrow,
  .contact-strip__phone {
    transition: none;
  }
}
/* Tone is inherited, not branched: the consuming section overrides these two
   on .mark where it sits on charcoal. */
.section-mark__mark {
  --mark-accent: var(--color-accent-text);
  --mark-text: var(--color-text-muted);

  display: flex;
  align-items: baseline;
  gap: var(--space-sm);
  margin: 0;
  padding-block-end: var(--space-2xs);
  border-block-end: var(--border-hairline) solid var(--color-border);
  font-size: var(--font-size-label);
  line-height: var(--line-height-label);
  letter-spacing: var(--letter-spacing-label);
  text-transform: uppercase;
  font-weight: var(--font-weight-semibold);
}

.section-mark__number {
  color: var(--mark-accent);
  font-variant-numeric: tabular-nums;
}

.section-mark__label {
  color: var(--mark-text);
}
/* The pager sits on the page ground, not in the dark block — it is
   navigation between siblings, not part of the call to action. */
.page-closing__pager {
  background: var(--color-bg);
}

/* Two blocks sharing the measure, each with enough height to read as a
   destination rather than a footnote (CLAUDE.md §16.6). A hairline above each,
   so the division survives the stack rather than depending on the columns. */
.page-closing__pager-inner {
  display: grid;
  padding-block: 0;
}

.page-closing__step {
  display: grid;
  /* A service name set at display scale has a wide max-content, and an
     auto-sized track would take it — "Hospitality Services" pushed its label
     10px past the viewport at 768 before this. */
  grid-template-columns: minmax(0, 1fr);
  min-width: 0;
  gap: var(--space-2xs);
  padding-block: var(--space-xl);
  border-block-start: var(--border-hairline) solid var(--color-border);
  align-content: center;
  text-decoration: none;
  color: var(--color-text);
}

.page-closing__step-label {
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
  font-size: var(--font-size-label);
  line-height: var(--line-height-label);
  letter-spacing: var(--letter-spacing-label);
  text-transform: uppercase;
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-muted);
}

/* Sized against the half-measure this block actually gets, not the full page.
   At --font-size-heading the word "Hospitality" alone measured 297px inside a
   264px column at 768 and overflowed the viewport: a single word cannot wrap,
   so the ceiling has to come down rather than the box grow. Still large — 33px
   at 768, 48px at 1440. break-word is the guard for any future name longer
   than the ones that exist today. */
.page-closing__step-name {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 1rem + 2.2vw, 3rem);
  line-height: 1.1;
  letter-spacing: var(--letter-spacing-heading);
  font-weight: var(--font-weight-semibold);
  overflow-wrap: break-word;
}

.page-closing__step:hover .page-closing__step-name,
.page-closing__step:focus-visible .page-closing__step-name {
  color: var(--color-accent-text);
}

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

/* The back step travels the other way. */
.page-closing__prev {
}

.page-closing__arrow {
}

.page-closing__section {
  background: var(--color-bg-inverse);
  color: var(--color-text-inverse);
}

.page-closing__inner {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-lg);
  padding-block: var(--space-2xl);
}

/* `balance` evens the lines of a short heading. Nine of the ten pages using
   this component set a heading that fits on one line, or on two that already
   break well, and balance leaves a single line untouched — only /clients was
   breaking to "… IN / MIND?". */
.page-closing__heading {
  margin: 0;
  max-width: 22ch;
  text-wrap: balance;
  font-family: var(--font-display);
  font-size: var(--font-size-subhead);
  line-height: var(--line-height-subhead);
  letter-spacing: var(--letter-spacing-subhead);
  font-weight: var(--font-weight-semibold);
}

/* Optional parts, added for /clients. The other nine pages that use this
   component pass a heading alone and render neither of these; grouping the
   three into a statement keeps the desktop flex row splitting statement from
   actions rather than spreading four children across it. */
.page-closing__statement {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
}

/* The dark-ground eyebrow, as .home-page__eyebrow and .service-page__eyebrow
   already set it: a 48px hairline in the on-dark red before the label, drawn
   with ::before because the markup carries no rule element. The light-ground
   eyebrows on the same page use a <span class="__rule"> instead — that is the
   older of the two spellings and the one the hero and Our Approach use; this
   component's markup came later and has no span to reach. */
.page-closing__eyebrow {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  margin: 0;
  font-size: var(--font-size-label);
  line-height: var(--line-height-label);
  letter-spacing: var(--letter-spacing-label);
  text-transform: uppercase;
  font-weight: var(--font-weight-semibold);
  /* On charcoal the light red is the sanctioned accent; the deep red used on
     warm white does not carry here. */
  color: var(--color-accent-on-dark);
}

.page-closing__eyebrow::before {
  content: '';
  display: block;
  width: var(--space-xl);
  height: 1px;
  flex: none;
  background: var(--color-accent-on-dark);
}

.page-closing__lead {
  margin: 0;
  max-width: 46ch;
  font-size: var(--font-size-body);
  line-height: var(--line-height-body);
  color: var(--color-text-muted-inverse);
}

.page-closing__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
}

/* One red-filled button in the group; the second stays outlined
   (CLAUDE.md §3.2). */
.page-closing__primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2xs);
  min-height: 3rem;
  padding-inline: var(--space-lg);
  background: var(--color-accent-surface);
  color: var(--color-on-accent-surface);
  border: var(--border-hairline) solid var(--color-accent-surface);
  border-radius: var(--radius-none);
  text-decoration: none;
  font-size: var(--font-size-body-sm);
  font-weight: var(--font-weight-semibold);
  letter-spacing: 0.02em;
  transition: background-color var(--duration-fast) var(--ease-standard);
}

.page-closing__primary:hover {
  background: var(--color-accent-surface-hover);
  border-color: var(--color-accent-surface-hover);
}

.page-closing__secondary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 3rem;
  padding-inline: var(--space-lg);
  background: transparent;
  color: var(--color-text-inverse);
  /* 7.50:1 against the charcoal ground, so the outline is a visible
     boundary rather than a hint (docs/DESIGN_SYSTEM.md §2.5 records the same
     hex as --color-text-muted-inverse). */
  border: var(--border-hairline) solid var(--color-charcoal-200);
  border-radius: var(--radius-none);
  text-decoration: none;
  font-size: var(--font-size-body-sm);
  font-weight: var(--font-weight-semibold);
  letter-spacing: 0.02em;
  transition: background-color var(--duration-fast) var(--ease-standard),
    color var(--duration-fast) var(--ease-standard);
}

.page-closing__secondary:hover {
  background: var(--color-text-inverse);
  color: var(--color-text);
  border-color: var(--color-text-inverse);
}

.page-closing__primary:focus-visible,
.page-closing__secondary:focus-visible {
  outline: 2px solid var(--color-accent-on-dark);
  outline-offset: 3px;
}

.page-closing__action-arrow {
}

@media (max-width: 559px) {
  .page-closing__primary,
  .page-closing__secondary {
    flex: 1 1 100%;
  }
}

@media (min-width: 768px) {
  .page-closing__pager-inner {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: var(--space-2xl);
    /* Stretch, not centre: the two blocks must share one height or the
       shorter one floats and its hairline stops lining up with the other's.
       "Hospitality Services" wraps where "Dental Materials" does not, so the
       pair came out 185px against 251px with a 33px offset between them. */
    align-items: stretch;
  }

  /* The forward step reads right-aligned, so the pair frames the page. Its
     child fills the column rather than shrink-wrapping — shrink-wrapped, a
     long name pushed its label past the viewport edge at 768. */
  .page-closing__next {
    padding-inline-start: var(--space-2xl);
    border-inline-start: var(--border-hairline) solid var(--color-border);
    justify-items: stretch;
    text-align: end;
  }

  .page-closing__next .page-closing__step-label {
    justify-content: end;
  }

  .page-closing__inner {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2xl);
  }
}

@media (prefers-reduced-motion: reduce) {
  .page-closing__arrow,
  .page-closing__action-arrow,
  .page-closing__primary,
  .page-closing__secondary {
    transition: none;
  }
}

/* Only the pages that pass a spine number render this (CLAUDE.md §16.2).
   The closing block is charcoal, so the mark takes the on-dark red and a
   hairline visible against it. */
.page-closing__mark {
  --mark-accent: var(--color-accent-on-dark);
  --mark-text: var(--color-text-muted-inverse);

  border-block-end-color: var(--color-border-inverse);
  margin-block-end: var(--space-lg);
}

.contact-page-hero__section {
  background: var(--color-bg-inverse);
  color: var(--color-text-inverse);
}

.contact-page-hero__inner {
  padding-block: var(--space-2xl) var(--space-xl);
}

.contact-page-hero__eyebrow {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  margin: 0 0 var(--space-lg);
  font-size: var(--font-size-label);
  line-height: var(--line-height-label);
  letter-spacing: var(--letter-spacing-label);
  text-transform: uppercase;
  font-weight: var(--font-weight-semibold);
  color: var(--color-accent-on-dark);
}

.contact-page-hero__rule {
  display: block;
  width: var(--space-xl);
  height: 1px;
  flex: none;
  background: var(--color-accent-on-dark);
}

.contact-page-hero__headline {
  margin: 0;
  max-width: 14ch;
  font-family: var(--font-display);
  font-size: var(--font-size-display);
  line-height: var(--line-height-display);
  letter-spacing: var(--letter-spacing-display);
  font-weight: var(--font-weight-extrabold);
  text-transform: uppercase;
}

.contact-page-hero__lead {
  margin: var(--space-lg) 0 0;
  max-width: 52ch;
  font-size: var(--font-size-body);
  line-height: var(--line-height-body);
  color: var(--color-text-muted-inverse);
}

@media (min-width: 1024px) {
  .contact-page-hero__inner {
    display: grid;
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    column-gap: var(--space-2xl);
    align-items: end;
    padding-block: var(--space-3xl) var(--space-2xl);
  }

  .contact-page-hero__eyebrow {
    grid-column: 1 / -1;
  }

  .contact-page-hero__lead {
    margin: 0;
    padding-block-end: var(--space-2xs);
  }
}

.industries-hero__section {
  background: var(--color-surface-muted);
}

.industries-hero__inner {
  padding-block: var(--space-2xl) var(--space-xl);
}

.industries-hero__eyebrow {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  margin: 0 0 var(--space-lg);
  font-size: var(--font-size-label);
  line-height: var(--line-height-label);
  letter-spacing: var(--letter-spacing-label);
  text-transform: uppercase;
  font-weight: var(--font-weight-semibold);
  color: var(--color-accent-text);
}

.industries-hero__rule {
  display: block;
  width: var(--space-xl);
  height: 1px;
  flex: none;
  background: var(--color-accent);
}

.industries-hero__headline {
  margin: 0;
  max-width: 15ch;
  font-family: var(--font-display);
  font-size: var(--font-size-display);
  line-height: var(--line-height-display);
  letter-spacing: var(--letter-spacing-display);
  font-weight: var(--font-weight-extrabold);
  text-transform: uppercase;
}

.industries-hero__lead {
  margin: var(--space-lg) 0 0;
  max-width: 50ch;
  font-size: var(--font-size-body);
  line-height: var(--line-height-body);
  color: var(--color-text-muted);
}

/* The index: five destinations, divided. Stacked below 768 it reads as a
   jump list with a hairline between entries; from 768 it becomes one row of
   five cells with vertical rules between them (CLAUDE.md §15.5). Either way
   every cell is a link, and the rules separate links, not labels. */
.industries-hero__index {
  margin-block-start: var(--space-xl);
}

.industries-hero__rail {
  list-style: none;
  display: grid;
  margin: 0;
  padding: 0;
  border-block-start: var(--border-hairline) solid var(--color-border);
}

.industries-hero__rail-item + .industries-hero__rail-item {
  border-block-start: var(--border-hairline) solid var(--color-border);
}

.industries-hero__rail-link {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2xs);
  min-height: 2.75rem;
  padding-block: var(--space-2xs);
  font-size: var(--font-size-label);
  line-height: var(--line-height-label);
  letter-spacing: var(--letter-spacing-label);
  text-transform: uppercase;
  font-weight: var(--font-weight-semibold);
  text-decoration: none;
  color: var(--color-text);
}

.industries-hero__rail-number {
  color: var(--color-accent-text);
  font-variant-numeric: tabular-nums;
}

.industries-hero__rail-name {
  color: var(--color-text);
}

/* Points at the chapter the link opens, and travels a little towards it. */
.industries-hero__rail-arrow {
  margin-inline-start: auto;
}

.industries-hero__rail-link:hover .industries-hero__rail-name,
.industries-hero__rail-link:focus-visible .industries-hero__rail-name {
  color: var(--color-accent-text);
}

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

/* Three across, then two. Five cells in one row do not fit between 768 and
   1023: measured there, the cell is 143px and "02 HOSPITALITY ↓" needs about
   140 before its rule and padding, so the indicator dropped onto a second
   line in four cells out of five. Three columns give the cell 240px and the
   row stays one line. */
@media (min-width: 768px) {
  .industries-hero__rail {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .industries-hero__rail-item + .industries-hero__rail-item {
    border-block-start: 0;
    border-inline-start: var(--border-hairline) solid var(--color-border);
  }

  /* 04 opens the second row: it takes the row's rule, not a column rule. */
  .industries-hero__rail-item:nth-child(4) {
    border-block-start: var(--border-hairline) solid var(--color-border);
    border-inline-start: 0;
  }

  .industries-hero__rail-link {
    padding-inline: var(--space-sm) 0;
  }

  .industries-hero__rail-item:first-child .industries-hero__rail-link,
  .industries-hero__rail-item:nth-child(4) .industries-hero__rail-link {
    padding-inline-start: 0;
  }

  .industries-hero__rail-arrow {
    margin-inline-start: 0;
  }
}

/* Five across: the cell reaches 192px and the whole index is one row. */
@media (min-width: 1024px) {
  .industries-hero__rail {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }

  .industries-hero__rail-item:nth-child(4) {
    border-block-start: 0;
    border-inline-start: var(--border-hairline) solid var(--color-border);
  }

  .industries-hero__rail-item:nth-child(4) .industries-hero__rail-link {
    padding-inline-start: var(--space-sm);
  }
}

@media (min-width: 1024px) {
  .industries-hero__inner {
    display: grid;
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    column-gap: var(--space-2xl);
    align-items: end;
    padding-block: var(--space-3xl) var(--space-2xl);
  }

  .industries-hero__lead {
    max-width: 42ch;
  }

  /* Copy left, source note right, rail across the foot of both. */
  .industries-hero__copy {
    grid-column: 1;
  }

  .industries-hero__index {
    grid-column: 1 / -1;
  }
}

/* The hero's contact link (CLAUDE.md §20). An index page is never a dead end —
   every entry links onward — but nothing on it reaches /contact until the
   closing block four screens down, and a visitor who wants to talk decides
   early. One text link at the top, in the page's own travel verb, rather than
   a block bolted into the middle of a list. */
.industries-hero__contact {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  min-height: 2.75rem;
  margin-block-start: var(--space-md);
  text-decoration: none;
  font-size: var(--font-size-body-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
}

.industries-hero__contact-label {
  border-block-end: var(--border-hairline) solid var(--color-border-strong);
  padding-block-end: 2px;
  transition: border-color var(--duration-fast) var(--ease-standard);
}

.industries-hero__contact:hover,
.industries-hero__contact:focus-visible {
  color: var(--color-accent-text);
}

.industries-hero__contact:hover .industries-hero__contact-label,
.industries-hero__contact:focus-visible .industries-hero__contact-label {
  border-block-end-color: var(--color-accent);
}

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

.industries-hero__contact-arrow {
}

@media (prefers-reduced-motion: reduce) {
  .industries-hero__contact-label {
    transition: none;
  }
}

.industries-list__section {
  background: var(--color-bg);
}

.industries-list__inner {
  padding-block: var(--space-2xl);
}

.industries-list__visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.industries-list__chapter {
  padding-block: var(--space-xl);
  border-block-start: var(--border-hairline) solid var(--color-border);
  /* The hero index jumps here; clear the sticky header (4.5rem at its
     tallest) plus a little air so the title line is not welded to it. */
  scroll-margin-block-start: calc(4.5rem + var(--space-lg));
}

.industries-list__chapter:last-child {
  border-block-end: var(--border-hairline) solid var(--color-border);
}

/* The title line runs the full measure — that is the move this page makes
   and the other two treatments of these five do not. */
.industries-list__title {
  display: flex;
  align-items: baseline;
  gap: var(--space-sm);
  margin-block-end: var(--space-lg);
}

.industries-list__number {
  font-family: var(--font-display);
  font-size: var(--font-size-subhead);
  line-height: 1;
  font-weight: var(--font-weight-extrabold);
  color: var(--color-accent-text);
  font-variant-numeric: tabular-nums;
}

.industries-list__name {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--font-size-heading);
  line-height: var(--line-height-heading);
  letter-spacing: var(--letter-spacing-heading);
  font-weight: var(--font-weight-extrabold);
  text-transform: uppercase;
  color: var(--color-text);
}

.industries-list__body {
  display: grid;
  gap: var(--space-lg);
}

/* Stacked, the figure is the full measure, so the ratio alone fixes the box
   and object-fit does the rest — the source's orientation cannot set the
   height. From 768 up the figure shares a row with the text column, and
   there a defined height is what keeps the rows even (CLAUDE.md §15.3). */
.industries-list__figure {
  --illustration-ratio: 3 / 2;
}

.industries-list__detail {
  display: grid;
  gap: var(--space-lg);
  align-content: start;
}

.industries-list__services-label {
  margin: 0 0 var(--space-2xs);
  font-size: var(--font-size-label);
  line-height: var(--line-height-label);
  letter-spacing: var(--letter-spacing-label);
  text-transform: uppercase;
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-muted);
}

.industries-list__service-list {
  list-style: none;
  margin: 0;
  padding: 0;
  border-block-start: var(--border-hairline) solid var(--color-border);
}

.industries-list__service-link {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-sm);
  min-height: 2.75rem;
  padding-block: var(--space-2xs);
  border-block-end: var(--border-hairline) solid var(--color-border);
  text-decoration: none;
  color: var(--color-text);
}

.industries-list__service-number {
  font-size: var(--font-size-label);
  letter-spacing: var(--letter-spacing-label);
  font-weight: var(--font-weight-semibold);
  color: var(--color-accent-text);
  font-variant-numeric: tabular-nums;
}

.industries-list__service-name {
  font-family: var(--font-display);
  font-size: var(--font-size-body);
  font-weight: var(--font-weight-medium);
}

.industries-list__arrow {
}

.industries-list__service-link:hover .industries-list__service-name,
.industries-list__service-link:focus-visible .industries-list__service-name {
  color: var(--color-accent-text);
}

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

@media (min-width: 768px) {
  .industries-list__inner {
    padding-block: var(--space-3xl);
  }

  .industries-list__chapter {
    padding-block: var(--space-2xl);
  }

  /* The text column sizes to its content and registers its top edge with the
     photograph's (CLAUDE.md §15.3). It is deliberately not stretched: an
     earlier version filled the column height and pushed Related Services to
     the foot, which opened 350-600px between the description and the services
     block in every chapter. Top alignment keeps those two a single spacing
     token apart and moves the leftover space outside the text, where the
     chapter hairline bounds it. */
  .industries-list__body {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    column-gap: var(--space-2xl);
    align-items: start;
  }

  /* Both items are placed by column, so both must name the row as well:
     auto-placement only moves forward, and a figure explicitly put in the
     second column sends an unpinned text column to a second row. */
  .industries-list__figure {
    grid-column: 1;
    grid-row: 1;
    --illustration-height: 18rem;
  }

  .industries-list__detail {
    grid-column: 2;
    grid-row: 1;
  }

  /* 02 Hospitality and 04 Residential take the mirrored composition: text
     left, image right (CLAUDE.md §15.2). The number rail and the 01-05
     reading order are untouched — only the side the picture sits on. */
  .industries-list__chapter:nth-of-type(even) .industries-list__body {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  }

  .industries-list__chapter:nth-of-type(even) .industries-list__figure {
    grid-column: 2;
  }

  .industries-list__chapter:nth-of-type(even) .industries-list__detail {
    grid-column: 1;
  }

}

@media (min-width: 1024px) {
  /* The number steps out into its own rail, so the names line up down the
     page and the rail reads as the index the hero set up. */
  .industries-list__title {
    display: grid;
    grid-template-columns: 4rem minmax(0, 1fr);
    gap: var(--space-lg);
    align-items: baseline;
  }

  .industries-list__body {
    grid-template-columns: 4rem minmax(0, 7fr) minmax(0, 5fr);
    column-gap: var(--space-lg);
  }

  /* The picture carries the chapter: seven twelfths of the measure and a
     height band that lands near the photographs' own 3:2 at each width,
     so the crop stays light and the page reads editorially rather than as
     a list with thumbnails (CLAUDE.md §15.3). */
  .industries-list__figure {
    grid-column: 2;
    grid-row: 1;
    --illustration-height: 21rem;
  }

  .industries-list__detail {
    grid-column: 3;
    grid-row: 1;
  }

  .industries-list__chapter:nth-of-type(even) .industries-list__body {
    grid-template-columns: 4rem minmax(0, 5fr) minmax(0, 7fr);
  }

  .industries-list__chapter:nth-of-type(even) .industries-list__figure {
    grid-column: 3;
  }

  .industries-list__chapter:nth-of-type(even) .industries-list__detail {
    grid-column: 2;
  }

  .industries-list__name {
    font-size: var(--font-size-display);
    line-height: 1.02;
    letter-spacing: var(--letter-spacing-display);
  }

  .industries-list__number {
    font-size: var(--font-size-subhead);
  }
}

@media (min-width: 1280px) {
  .industries-list__body {
    grid-template-columns: 4rem minmax(0, 8fr) minmax(0, 4fr);
  }

  .industries-list__chapter:nth-of-type(even) .industries-list__body {
    grid-template-columns: 4rem minmax(0, 4fr) minmax(0, 8fr);
  }

  .industries-list__figure {
    --illustration-height: 28rem;
  }
}

@media (min-width: 1440px) {
  .industries-list__figure {
    --illustration-height: 32rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .industries-list__arrow {
    transition: none;
  }
}

.services-hero__section {
  background: var(--color-bg);
  border-block-end: var(--border-hairline) solid var(--color-border);
}

.services-hero__inner {
  padding-block: var(--space-2xl) var(--space-xl);
}

.services-hero__eyebrow {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  margin: 0 0 var(--space-lg);
  font-size: var(--font-size-label);
  line-height: var(--line-height-label);
  letter-spacing: var(--letter-spacing-label);
  text-transform: uppercase;
  font-weight: var(--font-weight-semibold);
  color: var(--color-accent-text);
}

.services-hero__rule {
  display: block;
  width: var(--space-xl);
  height: 1px;
  flex: none;
  background: var(--color-accent);
}

.services-hero__headline {
  margin: 0;
  max-width: 17ch;
  font-family: var(--font-display);
  font-size: var(--font-size-display);
  line-height: var(--line-height-display);
  letter-spacing: var(--letter-spacing-display);
  font-weight: var(--font-weight-extrabold);
  text-transform: uppercase;
}

.services-hero__lead {
  margin: var(--space-lg) 0 0;
  max-width: 46ch;
  font-size: var(--font-size-body);
  line-height: var(--line-height-body);
  color: var(--color-text-muted);
}

/* The register. A contents list, not a nav bar: hairline rules, numbers in
   red at label size, names at body size. */
.services-hero__register {
  margin-block-start: var(--space-xl);
}

.services-hero__register-label {
  margin: 0 0 var(--space-xs);
  font-size: var(--font-size-label);
  line-height: var(--line-height-label);
  letter-spacing: var(--letter-spacing-label);
  text-transform: uppercase;
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-muted);
}

.services-hero__register-list {
  list-style: none;
  display: grid;
  margin: 0;
  padding: 0;
  border-block-start: var(--border-hairline) solid var(--color-border);
}

.services-hero__register-item {
  border-block-end: var(--border-hairline) solid var(--color-border);
}

/* Below 768 the register is one full-width column and the hero section draws
   its own rule 49px under the last item, so the list's closing rule doubled
   it. From 768 the register is two columns and its rules are half width, so
   the two never read as a pair and the closing rule stays. Same defect and
   same fix as /clients' client rosters. */
@media (max-width: 767px) {
  .services-hero__register-item:last-child {
    border-block-end: 0;
  }
}

.services-hero__register-link {
  display: flex;
  align-items: baseline;
  gap: var(--space-sm);
  padding-block: var(--space-xs);
  min-height: 2.75rem;
  align-content: center;
  flex-wrap: wrap;
  text-decoration: none;
  color: var(--color-text);
  transition: color var(--duration-fast) var(--ease-standard);
}

.services-hero__register-link:hover {
  color: var(--color-accent-text);
}

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

.services-hero__register-number {
  flex: none;
  font-size: var(--font-size-label);
  letter-spacing: var(--letter-spacing-label);
  font-weight: var(--font-weight-semibold);
  color: var(--color-accent-text);
  font-variant-numeric: tabular-nums;
}

.services-hero__register-name {
  font-size: var(--font-size-body);
  font-weight: var(--font-weight-medium);
}

/* Two columns of three as soon as there is room — the register reads as a
   block rather than a tall ladder. */
@media (min-width: 560px) {
  .services-hero__register-list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: var(--space-xl);
  }

  /* Each column keeps its own top rule. */
  .services-hero__register-item:nth-child(2) {
    border-block-start: var(--border-hairline) solid var(--color-border);
  }

  .services-hero__register-list {
    border-block-start: none;
  }

  .services-hero__register-item:first-child {
    border-block-start: var(--border-hairline) solid var(--color-border);
  }
}

@media (min-width: 1024px) {
  .services-hero__inner {
    display: grid;
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    column-gap: var(--space-2xl);
    align-items: start;
    padding-block: var(--space-3xl) var(--space-2xl);
  }

  .services-hero__eyebrow,
  .services-hero__headline,
  .services-hero__lead {
    grid-column: 1;
  }

  /* The register sits beside the headline, top-aligned with it, and takes
     the right five columns for all six rows. */
  .services-hero__register {
    grid-column: 2;
    grid-row: 1 / span 3;
    margin-block-start: 0;
  }

  .services-hero__register-list {
    grid-template-columns: minmax(0, 1fr);
    border-block-start: var(--border-hairline) solid var(--color-border);
  }

  .services-hero__register-item:nth-child(2) {
    border-block-start: none;
  }

  .services-hero__register-link {
    padding-block: var(--space-sm);
  }

  .services-hero__register-name {
    font-family: var(--font-display);
    font-size: var(--font-size-subhead);
    line-height: var(--line-height-subhead);
    letter-spacing: var(--letter-spacing-subhead);
    font-weight: var(--font-weight-medium);
  }
}

@media (prefers-reduced-motion: reduce) {
  .services-hero__register-link {
    transition: none;
  }
}

/* The hero's contact link (CLAUDE.md §20). An index page is never a dead end —
   every entry links onward — but nothing on it reaches /contact until the
   closing block four screens down, and a visitor who wants to talk decides
   early. One text link at the top, in the page's own travel verb, rather than
   a block bolted into the middle of a list. */
.services-hero__contact {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  min-height: 2.75rem;
  margin-block-start: var(--space-md);
  text-decoration: none;
  font-size: var(--font-size-body-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
}

.services-hero__contact-label {
  border-block-end: var(--border-hairline) solid var(--color-border-strong);
  padding-block-end: 2px;
  transition: border-color var(--duration-fast) var(--ease-standard);
}

.services-hero__contact:hover,
.services-hero__contact:focus-visible {
  color: var(--color-accent-text);
}

.services-hero__contact:hover .services-hero__contact-label,
.services-hero__contact:focus-visible .services-hero__contact-label {
  border-block-end-color: var(--color-accent);
}

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

.services-hero__contact-arrow {
}

@media (prefers-reduced-motion: reduce) {
  .services-hero__contact-label {
    transition: none;
  }
}
/* Shared page container. Composed by the layout modules so the gutter and
   max width are defined once (CLAUDE.md §3.4). */.container__container {
  width: 100%;
  max-width: var(--layout-max-width);
  margin-inline: auto;
  padding-inline: var(--layout-gutter);
}/**
 * The site's interaction vocabulary — three verbs, defined once.
 *
 * Phase 11 did not add a layer; it extracted one. There were 37 hover rules
 * across 23 files saying three things in slightly different ways, and 12 of
 * them had no keyboard equivalent because pairing hover with focus depended on
 * somebody remembering. Eleven of those twelve were the same arrow rule written
 * out eleven times.
 *
 *   travel  — an arrow shifts toward where the link goes, and the label takes
 *             the accent. Navigation: "this goes somewhere, and that way."
 *   reveal  — a picture scales slightly inside a fixed box. Used only where the
 *             picture is itself the link.
 *   state   — the focus ring. Never animated, never conditional.
 *
 * Rules here are written `:hover, :focus-visible` from the start rather than
 * paired afterwards, which is the whole point: a consumer cannot compose the
 * hover half and forget the keyboard half, because they are one rule.
 *
 * The motion budget is unchanged from what the site already used — 120ms and
 * 200ms, one easing, transform and colour only. Nothing here animates layout
 * (CLAUDE.md §3.1, §11).
 *//* ---- travel ------------------------------------------------------------ *//* On the link. The arrow inside it is .travelArrow. */.interaction__travel {
  --travel-shift: 4px;
}.interaction__travel-arrow {
  display: inline-block;
  color: var(--color-text-muted);
  transition: transform var(--duration-base) var(--ease-standard),
    color var(--duration-fast) var(--ease-standard);
}.interaction__travel:hover .interaction__travel-arrow,
.interaction__travel:focus-visible .interaction__travel-arrow {
  transform: translateX(var(--travel-shift));
  color: var(--color-accent-text);
}/* Inside a filled button the arrow is part of the label, so it inherits the
   button's ink and only moves. Composing the standard travelArrow here put
   --color-accent-text on --color-accent-surface: dark red on red. */.interaction__travel-arrow-plain {
  display: inline-block;
  color: inherit;
  transition: transform var(--duration-base) var(--ease-standard);
}.interaction__travel:hover .interaction__travel-arrow-plain,
.interaction__travel:focus-visible .interaction__travel-arrow-plain {
  transform: translateX(var(--travel-shift));
}/* Backwards, for a "previous" step. */.interaction__travel-back {
  --travel-shift: -4px;
}/* Downwards, for an in-page jump: the arrow points at the section it opens,
   which is what earns it under §3.7 — it marks a real destination. */.interaction__travel-down {
  --travel-shift: 3px;
}.interaction__travel-down:hover .interaction__travel-arrow,
.interaction__travel-down:focus-visible .interaction__travel-arrow {
  transform: translateY(var(--travel-shift));
}/* ---- reduced motion ----------------------------------------------------- *//* index.css already clamps every duration globally for anyone who asks for
   less motion. This states the intent per verb rather than relying on a
   0.01ms transition to be imperceptible: the movement goes, the information
   stays. Every verb still says what it said — in colour, or as a mark that is
   simply there — so nothing becomes ambiguous. The focus ring is untouched
   because a focus ring must never depend on motion. */@media (prefers-reduced-motion: reduce) {
  .interaction__travel-arrow,
  .interaction__travel-arrow-plain {
    transition: none;
  }

  .interaction__travel:hover .interaction__travel-arrow,
  .interaction__travel:focus-visible .interaction__travel-arrow,
  .interaction__travel:hover .interaction__travel-arrow-plain,
  .interaction__travel:focus-visible .interaction__travel-arrow-plain,
  .interaction__travel-down:hover .interaction__travel-arrow,
  .interaction__travel-down:focus-visible .interaction__travel-arrow {
    transform: none;
  }
}
/* Warm white, the same ground as the hero above it — the locked reference
   in docs/reference/service-1..4.png runs one tone from the masthead to the
   closing strip, and CLAUDE.md §6 makes the reference authoritative over
   prose. The photographs now carry the variation that an earlier white
   ground was compensating for. */
.services-overview__section {
  background: var(--color-bg);
}

.services-overview__inner {
  padding-block: var(--space-2xl) var(--space-xl);
}

.services-overview__head {
  margin-block-end: var(--space-lg);
}

.services-overview__heading {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--font-size-subhead);
  line-height: var(--line-height-subhead);
  letter-spacing: var(--letter-spacing-subhead);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
}

.services-overview__entries {
  border-block-start: var(--border-hairline) solid var(--color-border);
}

.services-overview__entry {
  display: grid;
  gap: var(--space-md);
  padding-block: var(--space-lg);
  border-block-end: var(--border-hairline) solid var(--color-border);
  /* The register in the hero links straight to these, and the header is
     sticky — without this the heading lands underneath it. */
  scroll-margin-block-start: 6rem;
}

/* One height band for all six, not each photograph's native shape.
   CLAUDE.md §13's correction: at native proportions the two portraits ran
   621px tall against 311px for the landscapes, which left a tall picture
   beside three lines of text and stretched the page. Every entry now holds
   the same ratio and the photographs crop into it (object-fit: cover), with
   object-position steering the crop where the subject is off-centre.

   Measured note kept for whoever reads this next: the reference screenshots
   themselves show the portraits at full native height — 497x621 against
   497x311 — so this is a deliberate departure from them, made on the
   client's instruction, not a correction toward them. See
   docs/DEVELOPMENT_PLAN.md.

   Two values, because a 3:2 band at 360px is a thin strip: the stacked
   range takes the deeper 4:3 (CLAUDE.md §10). */
.services-overview__entry {
  --visual-ratio: 4 / 3;
  --visual-ratio-wide: 3 / 2;
}

.services-overview__frame {
  --illustration-ratio: var(--visual-ratio);
}

.services-overview__body {
  display: grid;
  gap: var(--space-2xs);
  align-content: start;
}

/* Large by design, and red is sanctioned for section numbering (CLAUDE.md
   §3.2). It never drops below 2rem, which keeps it inside the large-text
   contrast allowance for #e94b50 on the warm white ground — 3.42:1 against a
   3:1 requirement (docs/DESIGN_SYSTEM.md §2.5). */
.services-overview__number {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(2rem, 1.4rem + 2.4vw, 3.5rem);
  line-height: 1;
  letter-spacing: var(--letter-spacing-heading);
  font-weight: var(--font-weight-extrabold);
  color: var(--color-accent);
  font-variant-numeric: tabular-nums;
}

.services-overview__name {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--font-size-subhead);
  line-height: var(--line-height-subhead);
  letter-spacing: var(--letter-spacing-subhead);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
  text-wrap: balance;
}

.services-overview__description {
  margin: var(--space-2xs) 0 0;
  max-width: 46ch;
  font-size: var(--font-size-body);
  line-height: var(--line-height-body);
  color: var(--color-text-muted);
}

.services-overview__link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  justify-self: start;
  margin-block-start: var(--space-2xs);
  min-height: 2.75rem;
  text-decoration: none;
  font-size: var(--font-size-body-sm);
  font-weight: var(--font-weight-semibold);
  letter-spacing: 0.02em;
  color: var(--color-text);
}

.services-overview__link-label {
  border-block-end: var(--border-hairline) solid var(--color-border-strong);
  padding-block-end: 2px;
  transition: border-color var(--duration-fast) var(--ease-standard),
    color var(--duration-fast) var(--ease-standard);
}

.services-overview__link:hover {
  color: var(--color-accent-text);
}

.services-overview__link:hover .services-overview__link-label,
.services-overview__link:focus-visible .services-overview__link-label {
  border-block-end-color: var(--color-accent);
}

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

.services-overview__arrow {
}

/* Tablet and large phone: still stacked, but a photograph spanning the full
   768px column is enormous — the page ran 7 000px deep before this cap. The
   photograph takes a fraction of the measure instead, and shifts side to
   side down the page so the stacked run keeps the alternation the wide
   layout has (CLAUDE.md §10: redesign for the breakpoint, don't let the
   desktop composition inflate). */
@media (min-width: 560px) and (max-width: 1023px) {
  /* Capped on the figure, not on its wrapper: an auto margin on the grid
     item makes the item shrink-to-fit, and the figure inside it is sized in
     percentages, so the whole photograph collapsed to 2px wide. */
  .services-overview__frame {
    max-width: min(100%, 26rem);
  }

  .services-overview__entry:nth-child(even) .services-overview__frame {
    margin-inline-start: auto;
  }
}

@media (min-width: 768px) {
  .services-overview__inner {
    padding-block: var(--space-3xl) var(--space-2xl);
  }

  .services-overview__head {
    margin-block-end: var(--space-xl);
  }
}

@media (min-width: 1024px) {
  /* Equal columns, as the reference shows — the photograph and the text hold
     the same measure and the gap between them is the only asymmetry. */
  .services-overview__entry {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: center;
    column-gap: var(--space-2xl);
    padding-block: var(--space-xl);
  }

  .services-overview__frame {
    --illustration-ratio: var(--visual-ratio-wide);
  }

  /* The photograph changes sides down the page. The text stays left-aligned
     on both sides: the reference sets it that way, and a right-ragged
     paragraph would be the worse reading of the two. */
  .services-overview__entry:nth-child(even) .services-overview__visual {
    order: 2;
  }

  .services-overview__entry:nth-child(even) .services-overview__body {
    order: 1;
  }

  .services-overview__name {
    font-size: var(--font-size-heading);
    line-height: 1.08;
    letter-spacing: var(--letter-spacing-heading);
  }

  .services-overview__body {
    gap: var(--space-xs);
  }
}

@media (prefers-reduced-motion: reduce) {
  .services-overview__arrow,
  .services-overview__link-label {
    transition: none;
  }
}

/* ==========================================================================
   Service detail page — compact layout (2026-09, owner request)
   --------------------------------------------------------------------------
   The owner found the service pages too spacious: a text-only charcoal hero,
   then a full-measure photograph, then the overview alone at display scale,
   then three more full-width sections, each with a mostly empty label
   column. This layout keeps every piece of content, the 01–05 spine
   (CLAUDE.md §16.2) and the caption rail (§16.3), and packs them into three
   bands:

     hero    — title and 01 Overview beside the service photograph
     detail  — 02 photograph beside 03 Scope of work and 04 Sectors
     closing — pager and 05, both tightened

   Scoped by `.service-page` on <main> and the `service-page__` prefix, so a
   service page not yet moved over keeps its old rules untouched.
   ========================================================================== */

/* --- Hero: the service photograph as a full-bleed ground ------------------ */

/* The photograph fills the band; a charcoal scrim sits between it and the
   text. The scrim is functional, not decorative. Across the zone where text
   sits it is near-opaque, because small red labels need the full charcoal
   ground to hold 4.5:1 (measured over the real pixels; lighter scrims
   failed at 1.3–3.5:1 on the bright sky). The photograph shows through
   the clear band at the top (--hero-clear). The only text up there is the
   breadcrumb, and a second, shallow layer darkens just the strip it sits
   on, fading out below it, so the picture stays clear under that. */
.service-page__hero {
  --hero-clear: 13rem;

  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: var(--color-bg-inverse);
  color: var(--color-text-inverse);
}

.service-page__backdrop {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.service-page__backdrop picture {
  display: block;
  width: 100%;
  height: 100%;
}

.service-page__backdrop-image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 55%;
}

.service-page__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    linear-gradient(
      to bottom,
      rgb(23 25 27 / 0.9) 0,
      rgb(23 25 27 / 0.85) 3.5rem,
      rgb(23 25 27 / 0) 7rem
    ),
    linear-gradient(
    to bottom,
    rgb(23 25 27 / 0.3) 0,
    rgb(23 25 27 / 0.55) calc(var(--hero-clear) * 0.55),
    rgb(23 25 27 / 0.95) var(--hero-clear),
    rgb(23 25 27 / 0.96) 100%
  );
}

.service-page__hero-inner {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  min-height: clamp(34rem, 30rem + 20vw, 44rem);
  padding-block: var(--space-sm) var(--space-md);
}

/* Title and overview sit on the bottom of the band, over the densest part
   of the scrim. */
.service-page__hero-body {
  display: grid;
  gap: var(--space-xl);
  margin-block-start: auto;
  /* Never let text rise into the clear band: the crumb row is ~3.25rem, so
     the body starts at least --hero-clear from the top of the band. */
  padding-block: calc(var(--hero-clear) - 3.25rem) var(--space-xl);
}

.service-page__intro {
  min-width: 0;
}

.service-page__crumbs {
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
  font-size: var(--font-size-label);
  line-height: var(--line-height-label);
  letter-spacing: var(--letter-spacing-label);
  text-transform: uppercase;
  font-weight: var(--font-weight-semibold);
}

/* 2.75rem row: the crumb is a real link and keeps a full touch target
   (CLAUDE.md §10). */
.service-page__crumb {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  /* Warm white, not red: over the photograph the red label measured
     3.7–4.0:1 with the top shade kept light, and darkening the shade enough
     for red brought back a black band. The red stays on the hover/focus
     underline. */
  color: var(--color-text-inverse);
  text-decoration: none;
  border-block-end: var(--border-hairline) solid transparent;
  transition: border-color var(--duration-fast) var(--ease-standard);
}

.service-page__crumb:hover,
.service-page__crumb:focus-visible {
  border-block-end-color: var(--color-accent-on-dark);
}

.service-page__crumb:focus-visible {
  outline: 2px solid var(--color-accent-on-dark);
  outline-offset: 3px;
}

.service-page__divider,
.service-page__current {
  color: var(--color-text-muted-inverse);
}

.service-page__eyebrow {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  margin: 0;
  font-size: var(--font-size-label);
  line-height: var(--line-height-label);
  letter-spacing: var(--letter-spacing-label);
  text-transform: uppercase;
  font-weight: var(--font-weight-semibold);
  color: var(--color-accent-on-dark);
}

.service-page__eyebrow::before {
  content: '';
  display: block;
  width: var(--space-xl);
  height: 1px;
  flex: none;
  background: var(--color-accent-on-dark);
}

/* Big again: in a full-bleed hero the name is the headline of the band. */
/* Number fixed on the left, name wrapping beside it: two-word names
   ("Hospitality Services") wrap to two lines instead of dropping the number
   onto a line of its own. Baseline-aligned to the name's first line. */
.service-page__title {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: baseline;
  column-gap: var(--space-md);
  margin-block-start: var(--space-md);
}

.service-page__number {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--font-size-display);
  line-height: var(--line-height-display);
  letter-spacing: var(--letter-spacing-display);
  font-weight: var(--font-weight-extrabold);
  color: var(--color-accent-on-dark);
  font-variant-numeric: tabular-nums;
}

.service-page__name {
  margin: 0;
  min-width: 0;
  font-family: var(--font-display);
  font-size: var(--font-size-display);
  line-height: var(--line-height-display);
  letter-spacing: var(--letter-spacing-display);
  font-weight: var(--font-weight-extrabold);
  text-transform: uppercase;
  overflow-wrap: break-word;
}

.service-page__overview {
  display: grid;
  gap: var(--space-sm);
  min-width: 0;
}

.service-page__lead {
  margin: 0;
  max-width: 40ch;
  font-family: var(--font-display);
  font-size: var(--font-size-subhead);
  line-height: var(--line-height-subhead);
  letter-spacing: var(--letter-spacing-subhead);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-inverse);
}

/* Section marks sit at the top of each block; the dark variant is for the
   charcoal hero (same colours as the page-closing mark). */
.service-page__mark {
  justify-self: start;
  align-self: flex-start;
  min-width: 12rem;
}

.service-page__mark--dark {
  --mark-accent: var(--color-accent-on-dark);
  --mark-text: var(--color-text-muted-inverse);

  border-block-end-color: var(--color-charcoal-500);
}

/* Caption rail: service name (left) · position in the set of six (right),
   along the foot of the band.

   The centre element used to be a "Doha / Qatar" place stamp. It was removed
   in the repetition pass: it mirrored the homepage hero's location caption,
   and that caption no longer exists, so it was repeating a fact the page
   states above it and pointing at nothing. Removing it left the desktop rule
   below as a three-track grid with an empty third column, which pushed the
   position stamp to the middle — hence two tracks here and at desktop. */
.service-page__rail {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--space-2xs) var(--space-md);
  padding-block-start: var(--space-sm);
  border-block-start: var(--border-hairline) solid var(--color-charcoal-500);
  font-size: var(--font-size-label);
  line-height: var(--line-height-label);
  letter-spacing: var(--letter-spacing-label);
  text-transform: uppercase;
  font-weight: var(--font-weight-semibold);
}

.service-page__rail-name {
  color: var(--color-text-inverse);
}

.service-page__rail-position {
  color: var(--color-accent-on-dark);
  font-variant-numeric: tabular-nums;
  text-align: end;
}

/* --- Shared section parts --------------------------------------------------- */

.service-page__section-head {
  display: grid;
  gap: var(--space-md);
  justify-items: start;
  max-width: 48rem;
}

.service-page__section-heading {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 1.3rem + 1.6vw, 2.75rem);
  line-height: var(--line-height-heading);
  letter-spacing: var(--letter-spacing-heading);
  font-weight: var(--font-weight-semibold);
}

.service-page__section-lead,
.service-page__body {
  margin: 0;
  max-width: 62ch;
  font-size: var(--font-size-body);
  line-height: var(--line-height-body);
  color: var(--color-text-muted);
}

.service-page__body {
  color: var(--color-text);
}

/* Line icons: 24-unit grid, hairline strokes, one red stroke each — the
   redline language (CLAUDE.md §3.7) at icon scale, never a red fill. */
.service-page__icon {
  width: 2.5rem;
  height: 2.5rem;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: square;
  stroke-linejoin: miter;
}

.service-page__icon-accent {
  stroke: var(--color-accent);
}

.service-page__link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  justify-self: start;
  min-height: 2.75rem;
  text-decoration: none;
  font-size: var(--font-size-body-sm);
  font-weight: var(--font-weight-semibold);
  letter-spacing: 0.02em;
  color: var(--color-text);
}

.service-page__link-label {
  border-block-end: var(--border-hairline) solid var(--color-border-strong);
  padding-block-end: 2px;
  transition: border-color var(--duration-fast) var(--ease-standard);
}

.service-page__link:hover .service-page__link-label,
.service-page__link:focus-visible .service-page__link-label {
  border-block-end-color: var(--color-accent);
}

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

/* --- 02 Service detail: intro copy beside the photograph ------------------- */

.service-page__intro-band {
  background: var(--color-bg);
}

.service-page__intro-inner {
  display: grid;
  gap: var(--space-xl);
  padding-block: var(--space-2xl);
}

.service-page__intro-text {
  display: grid;
  gap: var(--space-md);
  align-content: start;
  justify-items: start;
}

.service-page__intro-photo {
  --illustration-ratio: 4 / 3;
}

/* `pretty` only bans the orphan; it leaves the earlier lines alone. On the
   seven slug pages the caption already ends on a full phrase and is
   unchanged — measured at all nine widths. On /clients, where the sentence
   is shorter, it was dropping "project." onto a line of its own from 1280
   up. */
/* --- 03 Scope of work: service boxes ---------------------------------------- */

.service-page__scope {
  background: var(--color-surface-muted);
}

.service-page__scope-inner {
  display: grid;
  gap: var(--space-xl);
  padding-block: var(--space-2xl);
}

/* Hairline boxes on a shared grid: 1px gaps over a border-coloured ground
   draw every divider once, so adjacent boxes never double their borders. */
/* The hairlines between the scope cards used to be the container's own
   background showing through a 1px gap. That works only while every cell is
   filled. Measured 2026-09-26 with a card removed: at three columns a
   five-card grid left 17.7% of the container uncovered and a four-card grid
   34.1%, and that uncovered area painted as a solid rectangle of border grey
   beside the last card -- not as a gap. The client is about to review the
   scope lists and any page may lose a card, so each card now draws its own
   hairline instead.

   Geometry is deliberately untouched: the 1px gap and the container's 1px
   border both stay -- the border is simply transparent now -- so the cards
   sit exactly where they did. The ring is a box-shadow, which paints outside
   the border box without taking layout space, so it lands precisely in the
   gap and over the transparent border. Adjacent rings meet in the middle of
   the 1px gap and are the same colour, and the outer edge is drawn by the
   edge cards' own rings. Proven: all seven service pages at 1780 / 1440 /
   1024 / 768 / 390 are pixel-identical before and after, 0 differing pixels
   in 35 comparisons. An empty cell now shows the section ground behind it,
   with no outline around it, which is what a missing card should look
   like. */
.service-page__cards {
  list-style: none;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--border-hairline);
  margin: 0;
  padding: 0;
  background: transparent;
  border: var(--border-hairline) solid transparent;
}

.service-page__card {
  display: grid;
  align-content: start;
  gap: var(--space-xs);
  padding: var(--space-md);
  background: var(--color-surface);
  box-shadow: 0 0 0 var(--border-hairline) var(--color-border);
}

.service-page__card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-block-end: var(--space-xs);
  color: var(--color-text);
}

.service-page__card-number {
  font-size: var(--font-size-label);
  letter-spacing: var(--letter-spacing-label);
  font-weight: var(--font-weight-semibold);
  color: var(--color-accent-text);
  font-variant-numeric: tabular-nums;
}

.service-page__card-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(1.125rem, 1.05rem + 0.3vw, 1.3rem);
  line-height: var(--line-height-subhead);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
}

.service-page__card-text {
  margin: 0;
  font-size: var(--font-size-body-sm);
  line-height: var(--line-height-body);
  color: var(--color-text-muted);
}

/* --- 04 Why SoftOne: strengths on charcoal ---------------------------------- */

.service-page__why {
  background: var(--color-bg-inverse);
  color: var(--color-text-inverse);
}

.service-page__why-inner {
  display: grid;
  gap: var(--space-xl);
  padding-block: var(--space-2xl);
}

.service-page__why .service-page__section-heading {
  color: var(--color-text-inverse);
}

.service-page__strengths {
  list-style: none;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-lg);
  margin: 0;
  padding: 0;
}

.service-page__strength {
  display: grid;
  align-content: start;
  gap: var(--space-xs);
  padding-block-start: var(--space-md);
  border-block-start: var(--border-hairline) solid var(--color-charcoal-500);
}

.service-page__strength .service-page__icon {
  color: var(--color-text-inverse);
  margin-block-end: var(--space-2xs);
}

.service-page__strength .service-page__icon-accent {
  stroke: var(--color-accent-on-dark);
}

.service-page__strength-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(1.125rem, 1.05rem + 0.3vw, 1.3rem);
  line-height: var(--line-height-subhead);
  font-weight: var(--font-weight-semibold);
}

.service-page__strength-text {
  margin: 0;
  font-size: var(--font-size-body-sm);
  line-height: var(--line-height-body);
  color: var(--color-text-muted-inverse);
}

/* --- 05 Sectors: compact tiles ---------------------------------------------- */

.service-page__sectors-band {
  background: var(--color-bg);
}

.service-page__sectors-inner {
  display: grid;
  gap: var(--space-lg);
  padding-block: var(--space-2xl);
}

/* A service's own description names one, three or five sectors
   (CLAUDE.md §15.6). Fixed tracks keep every tile the same size on every
   page — one sector is one tile, not a stretched bar — and each tile draws
   its own hairline (overlapping by 1px) so an unfilled track shows nothing. */
.service-page__sector-tiles {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin: 0;
  padding: 0 var(--border-hairline) var(--border-hairline) 0;
}

.service-page__sector-tile {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto auto;
  column-gap: var(--space-sm);
  align-items: center;
  padding: var(--space-md);
  background: var(--color-surface);
  color: var(--color-text);
  border: var(--border-hairline) solid var(--color-border);
  margin: 0 calc(var(--border-hairline) * -1) calc(var(--border-hairline) * -1) 0;
}

.service-page__sector-tile .service-page__icon {
  grid-row: 1 / 3;
}

.service-page__sector-number {
  font-size: var(--font-size-label);
  letter-spacing: var(--letter-spacing-label);
  font-weight: var(--font-weight-semibold);
  color: var(--color-accent-text);
  font-variant-numeric: tabular-nums;
}

.service-page__sector-name {
  font-family: var(--font-display);
  font-size: var(--font-size-body);
  font-weight: var(--font-weight-medium);
  color: var(--color-text);
}

/* --- Closing: pager and 05, tightened ------------------------------------- */

.service-page .page-closing__step {
  padding-block: var(--space-lg);
}

.service-page .page-closing__step-name {
  font-size: var(--font-size-subhead);
  line-height: var(--line-height-subhead);
}

.service-page .page-closing__inner {
  padding-block: var(--space-xl);
}

.service-page .page-closing__mark {
  margin-block-end: 0;
}

/* --- Wider screens --------------------------------------------------------- */

@media (min-width: 640px) {
  .service-page__cards,
  .service-page__strengths {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .service-page__card {
    gap: var(--space-sm);
    padding: var(--space-lg);
  }
}

@media (min-width: 1024px) {
  .service-page__hero {
    --hero-clear: 17rem;
  }

  /* Title left, overview right, both on the foot of the band. */
  .service-page__hero-body {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    gap: var(--space-2xl);
    align-items: end;
  }

  .service-page__intro-inner {
    grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    gap: var(--space-3xl);
    align-items: center;
  }

  .service-page__strengths {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--space-xl);
  }

  .service-page__sector-tiles {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }

  .service-page__cards {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* Two across, but not below 360. Measured at 320 (the WCAG 1.4.10 reflow
   width, which this project's sweep list did not previously reach): the
   second column starts at x=241 and "Residential" needs 84px, so the row
   reached 325 against a 320 viewport and five of the seven slug pages
   scrolled sideways. */
@media (max-width: 359px) {
  .service-page__sector-tiles {
    grid-template-columns: minmax(0, 1fr);
  }

  /* Same width, a different symptom. The display clamp resolves to 40.48px
     at 320, where the single word "CONTRACTING," measures 306px against a
     288px content box: the line pushed 4px into the 16px gutter (element
     overflow only — the page itself never scrolled). Below 360 the display
     type drops to the clamp's own floor, which puts that word at 272px. */
  .services-hero__headline {
    font-size: 2.25rem;
  }
}

/* ==========================================================================
   Home page — redesigned with the owner, 2026-09-18 (CLAUDE.md §6)
   --------------------------------------------------------------------------
   Full-bleed photo hero with a fact rail, then the six services as the
   page's main block, then Who We Are, Why SoftOne, Industries, Selected Work
   (unchanged), a photo CTA and Contact (unchanged). Same visual language as
   the service pages (§16.0): hairline boxes, line icons with one red
   stroke, measured scrims over photographs. Scoped by `main.home-page`.
   ========================================================================== */

/* --- Shared parts ---------------------------------------------------------- */

.home-page__icon {
  width: 2.5rem;
  height: 2.5rem;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: square;
  stroke-linejoin: miter;
}

.home-page__icon--large {
  width: 3rem;
  height: 3rem;
}

.home-page__icon--small {
  width: 1.5rem;
  height: 1.5rem;
}

.home-page__mark {
  justify-self: start;
  align-self: flex-start;
  min-width: 12rem;
}

.home-page__mark--dark {
  --mark-accent: var(--color-accent-on-dark);
  --mark-text: var(--color-text-muted-inverse);

  border-block-end-color: var(--color-charcoal-500);
}

.home-page__section-head {
  display: grid;
  gap: var(--space-md);
  justify-items: start;
  max-width: 48rem;
}

.home-page__section-head--split {
  max-width: none;
  width: 100%;
  gap: var(--space-lg);
}

.home-page__section-title,
.home-page__section-aside {
  display: grid;
  gap: var(--space-md);
  justify-items: start;
}

.home-page__section-heading {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 1.3rem + 1.6vw, 2.75rem);
  line-height: var(--line-height-heading);
  letter-spacing: var(--letter-spacing-heading);
  font-weight: var(--font-weight-semibold);
}

.home-page__section-lead,
.home-page__body {
  margin: 0;
  max-width: 62ch;
  font-size: var(--font-size-body);
  line-height: var(--line-height-body);
  color: var(--color-text-muted);
}

.home-page__body {
  color: var(--color-text);
}

.home-page__link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  min-height: 2.75rem;
  text-decoration: none;
  font-size: var(--font-size-body-sm);
  font-weight: var(--font-weight-semibold);
  letter-spacing: 0.02em;
  color: var(--color-text);
}

.home-page__link-label {
  border-block-end: var(--border-hairline) solid var(--color-border-strong);
  padding-block-end: 2px;
  transition: border-color var(--duration-fast) var(--ease-standard);
}

.home-page__link:hover .home-page__link-label,
.home-page__link:focus-visible .home-page__link-label {
  border-block-end-color: var(--color-accent);
}

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

/* Buttons: one red primary per group (CLAUDE.md §3.2), outlined secondary. */
.home-page__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
}

.home-page__actions--center {
  justify-content: center;
}

.home-page__primary,
.home-page__secondary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2xs);
  min-height: 3rem;
  padding-inline: var(--space-lg);
  border-radius: var(--radius-none);
  text-decoration: none;
  font-size: var(--font-size-body-sm);
  font-weight: var(--font-weight-semibold);
  letter-spacing: 0.02em;
  transition: background-color var(--duration-fast) var(--ease-standard),
    color var(--duration-fast) var(--ease-standard);
}

.home-page__primary {
  background: var(--color-accent-surface);
  color: var(--color-on-accent-surface);
  border: var(--border-hairline) solid var(--color-accent-surface);
}

.home-page__primary:hover,
.home-page__primary:focus-visible {
  background: var(--color-accent-surface-hover);
  border-color: var(--color-accent-surface-hover);
}

.home-page__secondary {
  background: transparent;
  color: var(--color-text-inverse);
  border: var(--border-hairline) solid var(--color-charcoal-200);
}

.home-page__secondary:hover,
.home-page__secondary:focus-visible {
  background: var(--color-text-inverse);
  color: var(--color-text);
  border-color: var(--color-text-inverse);
}

.home-page__primary:focus-visible,
.home-page__secondary:focus-visible {
  outline: 2px solid var(--color-accent-on-dark);
  outline-offset: 3px;
}

/* --- Hero: full-bleed photograph --------------------------------------------- */

/* Hero and CTA: a photograph behind a measured overlay (see each scrim). */
.home-page__hero,
.home-page__cta {
  --hero-clear: 12rem;

  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: var(--color-bg-inverse);
  color: var(--color-text-inverse);
}

.home-page__backdrop {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.home-page__backdrop picture {
  display: block;
  width: 100%;
  height: 100%;
}

.home-page__backdrop-image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* A single even overlay across the whole photograph (owner request,
   2026-09-18) instead of the dark foot. 0.6 is the lightest value that keeps
   every hero line legible against the brightest pixel behind it: measured
   >= 5.30:1 at 1440/1024/768/390/360, where 0.55 dipped to 4.38:1. The
   eyebrow is warm white for the same reason — in red it measured 1–2:1 over
   the pale stone at any light overlay; its short red rule stays. */
.home-page__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: rgb(0 0 0 / 0.6);
}

.home-page__hero-inner {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  min-height: clamp(38rem, 30rem + 22vw, 48rem);
  padding-block-end: var(--space-md);
}

.home-page__hero-body {
  display: grid;
  gap: var(--space-md);
  justify-items: start;
  margin-block-start: auto;
  padding-block: var(--hero-clear) var(--space-xl);
}

.home-page__eyebrow {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  margin: 0;
  font-size: var(--font-size-label);
  line-height: var(--line-height-label);
  letter-spacing: var(--letter-spacing-label);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-inverse);
}

.home-page__eyebrow::before {
  content: '';
  display: block;
  width: var(--space-xl);
  height: 1px;
  flex: none;
  background: var(--color-accent-on-dark);
}

.home-page__headline {
  margin: 0;
  max-width: 16ch;
  font-family: var(--font-display);
  font-size: var(--font-size-display);
  line-height: var(--line-height-display);
  letter-spacing: var(--letter-spacing-display);
  font-weight: var(--font-weight-extrabold);
}

.home-page__lead {
  margin: 0 0 var(--space-xs);
  max-width: 46ch;
  font-size: clamp(1.0625rem, 1rem + 0.35vw, 1.25rem);
  line-height: var(--line-height-body);
  color: var(--color-text-inverse);
}

/* Fact rail: true counts only (6 services, 5 sectors, Doha, Qatar) —
   CLAUDE.md §1 rules out invented statistics. The coordinate stamp that
   used to sit at its right end was removed at the owner's request. */
.home-page__rail {
  display: grid;
  gap: var(--space-sm) var(--space-lg);
  padding-block-start: var(--space-md);
  border-block-start: var(--border-hairline) solid var(--color-charcoal-500);
}

.home-page__facts {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-sm) var(--space-md);
  margin: 0;
  padding: 0;
}

.home-page__fact {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  font-size: var(--font-size-body-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-inverse);
}

.home-page__hero .service-page__icon-accent,
.home-page__why .service-page__icon-accent {
  stroke: var(--color-accent-on-dark);
}

/* --- 01 Services: the page's main block ------------------------------------ */

.home-page__services {
  background: var(--color-surface-muted);
}

.home-page__services-inner {
  display: grid;
  gap: var(--space-xl);
  padding-block: var(--space-2xl);
}

/* 1px gaps over a border-coloured ground: every divider drawn once. */
.home-page__service-grid {
  list-style: none;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--border-hairline);
  margin: 0;
  padding: 0;
  background: var(--color-border);
  border: var(--border-hairline) solid var(--color-border);
}

.home-page__service-item {
  display: flex;
}

/* The whole box is the link: a large target, and one clear destination. */
.home-page__service {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  width: 100%;
  padding: var(--space-lg) var(--space-md);
  background: var(--color-surface);
  color: var(--color-text);
  text-decoration: none;
  transition: background-color var(--duration-fast) var(--ease-standard);
}

.home-page__service-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-block-end: var(--space-xs);
}

.home-page__service-number {
  font-size: var(--font-size-label);
  letter-spacing: var(--letter-spacing-label);
  font-weight: var(--font-weight-semibold);
  color: var(--color-accent-text);
  font-variant-numeric: tabular-nums;
}

.home-page__service-name {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(1.25rem, 1.1rem + 0.5vw, 1.5rem);
  line-height: var(--line-height-subhead);
  letter-spacing: var(--letter-spacing-subhead);
  font-weight: var(--font-weight-semibold);
  transition: color var(--duration-fast) var(--ease-standard);
}

.home-page__service-text {
  margin: 0;
  font-size: var(--font-size-body-sm);
  line-height: var(--line-height-body);
  color: var(--color-text-muted);
}

.home-page__service-more {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  margin-block-start: auto;
  padding-block-start: var(--space-sm);
  font-size: var(--font-size-body-sm);
  font-weight: var(--font-weight-semibold);
  letter-spacing: 0.02em;
  color: var(--color-text);
}

.home-page__service:hover,
.home-page__service:focus-visible {
  background: var(--color-bg);
}

.home-page__service:hover .home-page__service-name,
.home-page__service:focus-visible .home-page__service-name {
  color: var(--color-accent-text);
}

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

/* --- 02 Who We Are ------------------------------------------------------------ */

.home-page__who {
  background: var(--color-bg);
}

.home-page__who-inner {
  display: grid;
  gap: var(--space-xl);
  padding-block: var(--space-2xl);
}

.home-page__who-photo {
  --illustration-ratio: 4 / 3;
}

.home-page__who-text {
  display: grid;
  gap: var(--space-md);
  align-content: start;
  justify-items: start;
}

.home-page__who-lead {
  margin: 0;
  max-width: 40ch;
  font-family: var(--font-display);
  font-size: var(--font-size-subhead);
  line-height: var(--line-height-subhead);
  letter-spacing: var(--letter-spacing-subhead);
  font-weight: var(--font-weight-medium);
  color: var(--color-text);
}

.home-page__who-facts {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm) var(--space-lg);
  width: 100%;
  margin: var(--space-2xs) 0 0;
  padding: var(--space-md) 0 0;
  border-block-start: var(--border-hairline) solid var(--color-border);
}

.home-page__who-fact {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  font-size: var(--font-size-body-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
}

/* --- 03 Why SoftOne ------------------------------------------------------------ */

.home-page__why {
  background: var(--color-bg-inverse);
  color: var(--color-text-inverse);
}

.home-page__why-inner {
  display: grid;
  gap: var(--space-xl);
  padding-block: var(--space-2xl);
}

.home-page__strengths {
  list-style: none;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-lg) var(--space-xl);
  margin: 0;
  padding: 0;
}

.home-page__strength {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-areas:
    'icon number'
    'title title'
    'text text';
  align-items: start;
  align-content: start;
  gap: var(--space-xs);
  padding-block-start: var(--space-md);
  border-block-start: var(--border-hairline) solid var(--color-charcoal-500);
}

.home-page__strength .home-page__icon {
  grid-area: icon;
  color: var(--color-text-inverse);
}

.home-page__strength-number {
  grid-area: number;
  justify-self: end;
  font-size: var(--font-size-label);
  letter-spacing: var(--letter-spacing-label);
  font-weight: var(--font-weight-semibold);
  color: var(--color-accent-on-dark);
  font-variant-numeric: tabular-nums;
}

.home-page__strength-title {
  grid-area: title;
  margin: var(--space-2xs) 0 0;
  font-family: var(--font-display);
  font-size: clamp(1.125rem, 1.05rem + 0.3vw, 1.3rem);
  line-height: var(--line-height-subhead);
  font-weight: var(--font-weight-semibold);
}

.home-page__strength-text {
  grid-area: text;
  margin: 0;
  font-size: var(--font-size-body-sm);
  line-height: var(--line-height-body);
  color: var(--color-text-muted-inverse);
}

/* --- 04 Industries --------------------------------------------------------------- */

.home-page__industries {
  background: var(--color-bg);
}

.home-page__industries-inner {
  display: grid;
  gap: var(--space-xl);
  padding-block: var(--space-2xl);
}

.home-page__industries-photo {
  --illustration-ratio: 16 / 9;
}

.home-page__sectors {
  list-style: none;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--border-hairline);
  margin: calc(var(--space-xl) * -1 + var(--space-md)) 0 0;
  padding: 0;
  background: var(--color-border);
  border: var(--border-hairline) solid var(--color-border);
}

.home-page__sectors li {
  display: flex;
}

.home-page__sector {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-rows: auto auto;
  column-gap: var(--space-sm);
  align-items: center;
  width: 100%;
  min-height: 4.5rem;
  padding: var(--space-md);
  background: var(--color-surface);
  color: var(--color-text);
  text-decoration: none;
  transition: background-color var(--duration-fast) var(--ease-standard);
}

.home-page__sector .home-page__icon {
  grid-row: 1 / 3;
}

.home-page__sector .home-page__link-arrow {
  grid-row: 1 / 3;
  grid-column: 3;
  color: var(--color-text-muted);
}

.home-page__sector-number {
  font-size: var(--font-size-label);
  letter-spacing: var(--letter-spacing-label);
  font-weight: var(--font-weight-semibold);
  color: var(--color-accent-text);
  font-variant-numeric: tabular-nums;
}

.home-page__sector-name {
  font-family: var(--font-display);
  font-size: var(--font-size-body);
  font-weight: var(--font-weight-medium);
}

.home-page__sector:hover,
.home-page__sector:focus-visible {
  background: var(--color-bg);
}

.home-page__sector:hover .home-page__sector-name,
.home-page__sector:focus-visible .home-page__sector-name {
  color: var(--color-accent-text);
}

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

/* --- CTA: photograph behind a solid scrim ------------------------------------------ */

/* Centred text over a photograph, so the scrim is uniform rather than
   graded — the text sits in the middle, not on a dark foot. */
.home-page__cta-scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: rgb(23 25 27 / 0.86);
}

.home-page__cta .home-page__backdrop-image {
  object-position: 50% 55%;
}

.home-page__cta-inner {
  position: relative;
  z-index: 2;
  display: grid;
  justify-items: center;
  gap: var(--space-md);
  padding-block: var(--space-3xl);
  text-align: center;
}

.home-page__cta-heading {
  margin: 0;
  max-width: 18ch;
  font-family: var(--font-display);
  font-size: var(--font-size-heading);
  line-height: var(--line-height-heading);
  letter-spacing: var(--letter-spacing-heading);
  font-weight: var(--font-weight-extrabold);
}

.home-page__cta-lead {
  margin: 0 0 var(--space-xs);
  max-width: 46ch;
  font-size: var(--font-size-body);
  line-height: var(--line-height-body);
  color: var(--color-text-inverse);
}

/* Two sector tiles per row need ~150px each for icon, name and arrow;
   below 480 they would push the arrow off the screen, so one per row. */
@media (min-width: 480px) {
  .home-page__sectors {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 559px) {
  .home-page__hero .home-page__primary,
  .home-page__hero .home-page__secondary {
    flex: 1 1 100%;
  }

  .home-page__service {
    padding: var(--space-md);
  }

  .home-page__service .home-page__icon--large {
    width: 2.5rem;
    height: 2.5rem;
  }
}

/* --- Wider screens ----------------------------------------------------------------- */

@media (min-width: 640px) {
  .home-page__service-grid,
  .home-page__strengths {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .home-page__sectors {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .home-page__facts {
    grid-template-columns: repeat(4, auto);
    justify-content: start;
    column-gap: var(--space-xl);
  }

  .home-page__service {
    padding: var(--space-xl) var(--space-lg);
  }
}

@media (min-width: 1024px) {
  .home-page__hero,
  .home-page__cta {
    --hero-clear: 16rem;
  }

  .home-page__section-head--split {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    align-items: end;
    gap: var(--space-2xl);
  }

  .home-page__service-grid,
  .home-page__strengths {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .home-page__who-inner {
    grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    gap: var(--space-3xl);
    align-items: center;
  }

  .home-page__who-photo {
    --illustration-ratio: 4 / 5;
  }

  .home-page__industries-photo {
    --illustration-ratio: 21 / 7;
  }

  /* Five across moved from 1024 to 1280 on 2026-09-24. Measured at 1024:
     the tile is 192px, its chrome (48 padding + 40 icon + 2x16 gap + 15
     arrow) takes 135, and the name column was left 57px for "Commercial",
     which needs 101 — the word overflowed its own cell and painted through
     the arrow. The cell first holds the longest name at 1260; 1280 is the
     next width on the project's own list and leaves 5px of margin. */
}

/* Five across, once the tile is wide enough to hold the longest sector name
   without the word running into the arrow. */
@media (min-width: 1280px) {
  .home-page__sectors {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
}

/* Five tiles never divide evenly into two or three columns, so the grid's
   background showed through the leftover cell as a grey block. Widening the
   three-column band to 1279 would have made that block a fixture of ordinary
   laptop widths, so the last tile takes the remaining track instead. Not
   applied at five across, where the row is already full. */
@media (min-width: 480px) and (max-width: 1279px) {
  .home-page__sectors li:last-child {
    /* span, not a fixed line: the leftover cell is the second column at
       three across and the first at two, and span lands correctly in both. */
    grid-column: span 2;
  }
}

/* --- Home: Clients preview -------------------------------------------------
   Replaced the Selected work tiles when /projects was removed. Same band,
   same position, section 05 — but text only: four categories with the client
   names under each, and one link onward. No gallery, no images.

   Removed with the tiles: .home-page__works, .home-page__work,
   .home-page__work-figure, .home-page__work-caption, .home-page__work-number
   and the reveal transition on their photographs. Nothing else used them
   (grepped across html, css and js before deleting).
   -------------------------------------------------------------------------- */

/* Muted, not the white this band carried as Selected Work. The tiles filled
   it with four photographs; text-only, the white read as a hole between 04
   and 06. Warm white was the other candidate and was rejected: 04 and 06 are
   both warm white, so 05 would have merged the three into one continuous
   band. Muted is the token section 01 already uses, so the page reads
   muted / warm / charcoal / warm / muted / charcoal / warm. */
.home-page__clients-band {
  background: var(--color-surface-muted);
}

.home-page__clients-inner {
  display: grid;
  gap: var(--space-xl);
  padding-block: var(--space-2xl);
}

.home-page__client-groups {
  list-style: none;
  display: grid;
  margin: 0;
  padding: 0;
  border-block-start: var(--border-hairline) solid var(--color-border);
}

/* Two rows, two columns: the number holds the first column across both rows
   so the names line up under the category rather than under the number. */
.home-page__client-group {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: var(--space-sm);
  row-gap: var(--space-3xs);
  padding-block: var(--space-sm);
  border-block-end: var(--border-hairline) solid var(--color-border);
}

.home-page__client-number {
  grid-column: 1;
  grid-row: 1 / span 2;
  font-size: var(--font-size-label);
  line-height: var(--line-height-label);
  letter-spacing: var(--letter-spacing-label);
  font-weight: var(--font-weight-semibold);
  color: var(--color-accent-text);
  font-variant-numeric: tabular-nums;
}

.home-page__client-category {
  grid-column: 2;
  grid-row: 1;
  margin: 0;
  font-size: var(--font-size-body);
  line-height: var(--line-height-body);
  font-weight: var(--font-weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--color-text);
}

/* A client's name never breaks across lines — a name split over two lines
   reads as though there were more clients than there are. Lines may only
   break at the commas between names.

   The case that first showed it was "Dadawi Dental Clinic" wrapping between
   1024 and 1218; that client came off the site on 2026-10-05, so the rule was
   re-measured against what ships rather than left resting on a name that is
   gone. Lifting it now wraps "Aster Dental Clinics" at 320. Still earned. */
.home-page__client-name {
  white-space: nowrap;
}

/* Plain text, as on /clients: a client name is never a link here either. */
.home-page__client-names {
  grid-column: 2;
  grid-row: 2;
  margin: 0;
  font-size: var(--font-size-body-sm);
  line-height: var(--line-height-body);
  color: var(--color-text-muted);
}

@media (min-width: 768px) {
  .home-page__client-groups {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: var(--space-2xl);
  }
}

/* From 1024 the section head splits 7fr/5fr, and the content takes the same
   tracks so the second column starts on the head's aside rather than a
   column short of it. Content aligns to the head; the head is never moved to
   suit the content. Below 1024 the head is one stacked column, so there is
   nothing to align to and the two equal columns stay. */
@media (min-width: 1024px) {
  .home-page__client-groups {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  }
}

/* ==========================================================================
   Contact actions — call and email, no form (2026-09-18, owner request)
   --------------------------------------------------------------------------
   The enquiry forms were never connected to a mailbox; the owner asked for
   direct call and email actions instead. Used on the home page (06) and the
   contact page (01). Each card is one tel:/mailto: link — a large target,
   and on a phone a single tap starts the call or the email.
   ========================================================================== */

.contact-actions__section {
  background: var(--color-bg);
}

.contact-actions__inner {
  display: grid;
  gap: var(--space-xl);
  padding-block: var(--space-2xl);
}

.contact-actions__head {
  display: grid;
  gap: var(--space-md);
  justify-items: start;
  max-width: 44rem;
}

.contact-actions__mark {
  min-width: 12rem;
}

.contact-actions__heading {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 1.3rem + 1.6vw, 2.75rem);
  line-height: var(--line-height-heading);
  letter-spacing: var(--letter-spacing-heading);
  font-weight: var(--font-weight-semibold);
}

.contact-actions__lead {
  margin: 0;
  max-width: 56ch;
  font-size: var(--font-size-body);
  line-height: var(--line-height-body);
  color: var(--color-text-muted);
}

/* Hairline boxes on a shared grid (1px gaps over the border colour). */
.contact-actions__list {
  list-style: none;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--border-hairline);
  margin: 0;
  padding: 0;
  background: var(--color-border);
  border: var(--border-hairline) solid var(--color-border);
}

.contact-actions__list > li {
  display: flex;
}

.contact-actions__card {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  width: 100%;
  padding: var(--space-lg) var(--space-md);
  background: var(--color-surface);
  color: var(--color-text);
  text-decoration: none;
  transition: background-color var(--duration-fast) var(--ease-standard);
}

.contact-actions__icon {
  width: 2.5rem;
  height: 2.5rem;
  margin-block-end: var(--space-sm);
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: square;
  stroke-linejoin: miter;
}

.contact-actions__label {
  font-size: var(--font-size-label);
  line-height: var(--line-height-label);
  letter-spacing: var(--letter-spacing-label);
  text-transform: uppercase;
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-muted);
}

.contact-actions__value {
  font-family: var(--font-display);
  font-size: clamp(1.125rem, 1.05rem + 0.4vw, 1.375rem);
  line-height: var(--line-height-subhead);
  font-weight: var(--font-weight-semibold);
  font-style: normal;
  overflow-wrap: anywhere;
  transition: color var(--duration-fast) var(--ease-standard);
}

.contact-actions__cta {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  margin-block-start: auto;
  padding-block-start: var(--space-md);
  font-size: var(--font-size-body-sm);
  font-weight: var(--font-weight-semibold);
  letter-spacing: 0.02em;
  color: var(--color-accent-text);
}

.contact-actions__card:hover,
.contact-actions__card:focus-visible {
  background: var(--color-bg);
}

.contact-actions__card:hover .contact-actions__value,
.contact-actions__card:focus-visible .contact-actions__value {
  color: var(--color-accent-text);
}

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

.contact-actions__card--static {
  background: var(--color-surface-muted);
}

@media (min-width: 640px) {
  .contact-actions__list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1024px) {
  .contact-actions__list {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  .contact-actions__card {
    padding: var(--space-xl) var(--space-lg);
  }
}

/* ==========================================================================
   Header: glass background + scroll-driven hiding (2026-09-18, owner request)
   --------------------------------------------------------------------------
   Glass: warm white at 78% with a background blur, so content scrolling
   under the sticky header shows through softly. Where backdrop-filter is not
   supported the header stays solid, since a translucent header without the
   blur would put text straight over whatever is behind it.
   The desktop nav labels step one shade darker (charcoal-600) so they keep
   AA contrast over the darkest thing that can pass behind the glass (the
   charcoal bands and photo overlays) — measured, see CLAUDE.md §5.
   Hiding: js/main.js adds .header__header--hidden when the page scrolls
   down and removes it on any scroll up, near the top of the page, while
   the mobile menu is open, and whenever focus moves into the header.
   ========================================================================== */

/* The glass lives on a ::before layer, not on the header itself. An element
   with backdrop-filter becomes a "backdrop root": a descendant's own
   backdrop-filter can then only see that element, not the page. The mobile
   menu panel is a descendant and is glass too, so the header must not be
   the root. */
.header__header {
  background: transparent;
  isolation: isolate;
  transition: transform var(--duration-base) var(--ease-standard);
}

.header__header::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: rgb(245 244 240 / 0.78);
  -webkit-backdrop-filter: saturate(160%) blur(16px);
  backdrop-filter: saturate(160%) blur(16px);
  pointer-events: none;
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .header__header::before {
    background: var(--color-bg);
  }
}

/* Mobile menu panel: dark glass. 0.86 charcoal is measured, not guessed —
   the panel's grey labels must hold AA over the lightest page that can sit
   behind it (see CLAUDE.md §5). Solid where the blur is unsupported. */
.header__panel {
  background: rgb(23 25 27 / 0.86);
  -webkit-backdrop-filter: saturate(140%) blur(20px);
  backdrop-filter: saturate(140%) blur(20px);
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .header__panel {
    background: var(--color-bg-inverse);
  }
}

.header__header--hidden {
  transform: translateY(-100%);
}

.navigation__desktop .navigation__link {
  color: var(--color-charcoal-600);
}

.navigation__desktop .navigation__active {
  color: var(--color-text);
}

@media (prefers-reduced-motion: reduce) {
  .header__header {
    transition: none;
  }
}

/* ==========================================================================
   Services dropdown (2026-09-18, owner request)
   --------------------------------------------------------------------------
   Desktop: "Services" stays a real link to /services; the chevron beside it
   is a disclosure button (aria-expanded) that opens the list of the six
   services. A mouse can also just hover. The keyboard equivalent of the
   hover is that button — Enter/Space opens, Escape closes (js/main.js §7).
   Mobile panel: the six services are listed under Services, always open —
   there is no hover on a phone, and one tap should reach a service.
   ========================================================================== */

.navigation__item--menu {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.125rem;
}

.navigation__menu-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.5rem;
  height: 1.5rem;
  padding: 0;
  border: 0;
  border-radius: var(--radius-none);
  background: transparent;
  color: var(--color-charcoal-600);
  cursor: pointer;
}

.navigation__chevron {
  width: 0.75rem;
  height: 0.75rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  transition: transform var(--duration-fast) var(--ease-standard);
}

.navigation__menu-toggle[aria-expanded='true'] .navigation__chevron {
  transform: rotate(180deg);
}

.navigation__menu-toggle:hover,
.navigation__menu-toggle:focus-visible {
  color: var(--color-accent-text);
}

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

.navigation__submenu {
  position: absolute;
  inset-block-start: calc(100% + 0.9rem);
  inset-inline-start: -1rem;
  z-index: 110;
  display: none;
  min-width: 17rem;
  margin: 0;
  padding: var(--space-2xs) 0;
  list-style: none;
  background: var(--color-surface);
  border: var(--border-hairline) solid var(--color-border);
  box-shadow: 0 16px 40px rgb(23 25 27 / 0.12);
}

/* Invisible bridge across the gap, so the pointer can travel from the
   label to the list without the hover dropping. */
.navigation__submenu::before {
  content: '';
  position: absolute;
  inset-inline: 0;
  inset-block-end: 100%;
  height: 1rem;
}

.navigation__item--menu:hover > .navigation__submenu,
.navigation__item--menu.is-open > .navigation__submenu {
  display: block;
}

.navigation__sublink {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  min-height: 2.75rem;
  padding-inline: var(--space-md);
  font-family: var(--font-body);
  font-size: var(--font-size-body-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-text);
  text-decoration: none;
  white-space: nowrap;
  transition: background-color var(--duration-fast) var(--ease-standard),
    color var(--duration-fast) var(--ease-standard);
}

.navigation__subnumber {
  font-size: var(--font-size-label);
  letter-spacing: var(--letter-spacing-label);
  font-weight: var(--font-weight-semibold);
  color: var(--color-accent-text);
  font-variant-numeric: tabular-nums;
}

.navigation__sublink:hover,
.navigation__sublink:focus-visible,
.navigation__sublink[aria-current='page'] {
  background: var(--color-bg);
  color: var(--color-accent-text);
}

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

.navigation__submenu-all {
  margin-block-start: var(--space-2xs);
  border-block-start: var(--border-hairline) solid var(--color-border);
}

.navigation__sublink--all {
  justify-content: space-between;
  font-weight: var(--font-weight-semibold);
}

/* --- Mobile panel: always-open sub-list under Services ------------------- */

.navigation__sublist {
  margin: 0 0 var(--space-sm);
  padding: 0;
  list-style: none;
}

.navigation__sublink--mobile {
  padding-inline: var(--space-sm) 0;
  font-size: var(--font-size-body);
  color: var(--color-text-muted-inverse);
}

.navigation__sublink--mobile .navigation__subnumber {
  color: var(--color-accent-on-dark);
}

.navigation__sublink--mobile:hover,
.navigation__sublink--mobile:focus-visible,
.navigation__sublink--mobile[aria-current='page'] {
  background: transparent;
  color: var(--color-text-inverse);
}

.navigation__sublink--mobile:focus-visible {
  outline: 2px solid var(--color-accent-on-dark);
  outline-offset: -2px;
}

@media (prefers-reduced-motion: reduce) {
  .navigation__chevron {
    transition: none;
  }
}

/* Over the glass panel the small red "Office" label measured 3.5:1 against
   the lightest page behind it; warm white keeps it legible (same fix as the
   hero eyebrow and breadcrumb). */
.header__panel .header__panel-meta-label {
  color: var(--color-text-inverse);
}

/* --- Mobile: Services is a dropdown too (2026-09-18, owner request) --------
   The row is the Services link plus a 44px chevron button; the six services
   sit underneath, collapsed by default ([hidden] = display:none, so they are
   out of the tab order while closed). On a service page the list starts
   open, so the current service is visible. */
.navigation__mobile .navigation__item--submenu {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
}

.navigation__mobile .navigation__item--submenu > .navigation__link {
  flex: 1 1 auto;
  min-width: 0;
  margin-inline-end: var(--space-sm);
}

.navigation__menu-toggle--mobile {
  flex: none;
  width: 2.75rem;
  height: 2.75rem;
  color: var(--color-text-muted-inverse);
}

.navigation__menu-toggle--mobile .navigation__chevron {
  width: 1rem;
  height: 1rem;
}

.navigation__menu-toggle--mobile:hover,
.navigation__menu-toggle--mobile:focus-visible {
  color: var(--color-text-inverse);
}

.navigation__menu-toggle--mobile:focus-visible {
  outline: 2px solid var(--color-accent-on-dark);
  outline-offset: -2px;
}

.navigation__mobile .navigation__item--submenu > .navigation__sublist {
  flex: 1 0 100%;
}

/* ==========================================================================
   Clients — /clients
   Added in the Clients revision (the page that replaced /projects).

   Why this is its own module rather than a reuse of services-hero__ /
   services-overview__: those two are page-scoped to /services (the shared
   modules in this file are the ones used on many pages — photo__,
   page-closing__, interaction__, container__). Two things here also differ
   in behaviour, not only in name:

     1. The category index carries a descriptor and a client count beside
        each name. The services register carries a number and a name only,
        and its flex row has nowhere to put two more cells predictably, so
        the row here is a grid with named areas.
     2. The image alternation starts on the opposite foot. /services runs
        image-left on the odd entries; /clients was specified image-right on
        01 and 03. Same treatment, opposite phase.

   Every value below is copied from the corresponding services-* rule, so
   the two pages render the same measure, ratio band and hairline.
   ========================================================================== */

.clients-hero__section {
  background: var(--color-surface-muted);
}

.clients-hero__inner {
  padding-block: var(--space-2xl) var(--space-xl);
}

.clients-hero__eyebrow {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  margin: 0 0 var(--space-lg);
  font-size: var(--font-size-label);
  line-height: var(--line-height-label);
  letter-spacing: var(--letter-spacing-label);
  text-transform: uppercase;
  font-weight: var(--font-weight-semibold);
  color: var(--color-accent-text);
}

.clients-hero__rule {
  display: block;
  width: var(--space-xl);
  height: 1px;
  flex: none;
  background: var(--color-accent);
}

.clients-hero__headline {
  margin: 0;
  max-width: 17ch;
  font-family: var(--font-display);
  font-size: var(--font-size-display);
  line-height: var(--line-height-display);
  letter-spacing: var(--letter-spacing-display);
  font-weight: var(--font-weight-extrabold);
  text-transform: uppercase;
}

.clients-hero__lead {
  margin: var(--space-lg) 0 0;
  max-width: 50ch;
  font-size: var(--font-size-body);
  line-height: var(--line-height-body);
  color: var(--color-text-muted);
}

/* The hero's contact link (docs/DESIGN_AND_CONTENT.md #contact-affordances).
   /projects carried this and /clients takes its place, so the affordance
   moves with the slot: one text link at the top of an index page, in the
   page's own travel verb. */
.clients-hero__contact {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  min-height: 2.75rem;
  margin-block-start: var(--space-md);
  text-decoration: none;
  font-size: var(--font-size-body-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
}

.clients-hero__contact-label {
  border-block-end: var(--border-hairline) solid var(--color-border-strong);
  padding-block-end: 2px;
  transition: border-color var(--duration-fast) var(--ease-standard);
}

.clients-hero__contact:hover,
.clients-hero__contact:focus-visible {
  color: var(--color-accent-text);
}

.clients-hero__contact:hover .clients-hero__contact-label,
.clients-hero__contact:focus-visible .clients-hero__contact-label {
  border-block-end-color: var(--color-accent);
}

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

/* The category index. Hairline rows, no cards. */
.clients-hero__register {
  margin-block-start: var(--space-xl);
}

.clients-hero__register-label {
  margin: 0 0 var(--space-xs);
  font-size: var(--font-size-label);
  line-height: var(--line-height-label);
  letter-spacing: var(--letter-spacing-label);
  text-transform: uppercase;
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-muted);
}

.clients-hero__register-list {
  list-style: none;
  display: grid;
  margin: 0;
  padding: 0;
  border-block-start: var(--border-hairline) solid var(--color-border);
}

.clients-hero__register-item {
  border-block-end: var(--border-hairline) solid var(--color-border);
}

/* A grid, not a flex row: three cells whose wrap has to be the same at every
   width. The number holds its own column and the name and descriptor stack in
   the second, so both start on one left edge at every width.

   It was four cells until 2026-10-05, the fourth being a per-category client
   count ("03 CLIENTS" / "01 CLIENT") the client asked to remove. **Deleting
   the element is not enough**: a grid keeps the gap between two tracks even
   when one of them resolves to 0, and the descriptor spanned columns 2-3, so
   it would have run one --space-sm wider than the name above it. The track
   goes with the element. */
.clients-hero__register-link {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-areas:
    "number name"
    "number note";
  column-gap: var(--space-sm);
  row-gap: var(--space-3xs);
  align-items: baseline;
  min-height: 2.75rem;
  align-content: center;
  padding-block: var(--space-xs);
  text-decoration: none;
  color: var(--color-text);
  transition: color var(--duration-fast) var(--ease-standard);
}

.clients-hero__register-number {
  grid-area: number;
  font-size: var(--font-size-label);
  letter-spacing: var(--letter-spacing-label);
  font-weight: var(--font-weight-semibold);
  color: var(--color-accent-text);
  font-variant-numeric: tabular-nums;
}

.clients-hero__register-name {
  grid-area: name;
  font-size: var(--font-size-body);
  font-weight: var(--font-weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.clients-hero__register-note {
  grid-area: note;
  font-size: var(--font-size-body-sm);
  line-height: var(--line-height-body);
  color: var(--color-text-muted);
}

.clients-hero__register-link:hover,
.clients-hero__register-link:focus-visible {
  color: var(--color-accent-text);
}

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

@media (min-width: 768px) {
  .clients-hero__inner {
    padding-block: var(--space-3xl) var(--space-2xl);
  }

  .clients-hero__register-link {
    padding-block: var(--space-sm);
  }
}

/* Copy left, index right — the /services hero composition. Measured at 1024,
   the narrowest width this applies at: the right column is 376.3px and the
   longest row is still "03 CONTRACTING & BUILDING MATERIALS", measured here
   at two lines (115.2px against 86.8px for its three siblings), which is the
   shape the grid areas give every row anyway. The 351px this comment claimed
   until 2026-10-05 was stale — re-measured, not re-asserted.
   Every child is placed explicitly rather than left to auto-flow, because
   auto-placement puts the fifth child in the free cell beside the index. */
@media (min-width: 1024px) {
  .clients-hero__inner {
    display: grid;
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    column-gap: var(--space-2xl);
    align-items: start;
  }

  .clients-hero__eyebrow,
  .clients-hero__headline,
  .clients-hero__lead,
  .clients-hero__contact {
    grid-column: 1;
  }

  .clients-hero__register {
    grid-column: 2;
    /* span 4, not `1 / -1`: with no grid-template-rows the explicit grid has
       one row line, so -1 resolves to 1 and the index sits in row 1 alone,
       inflating it and dropping the headline half a screen down. Four is the
       number of children in column 1. */
    grid-row: 1 / span 4;
    align-self: start;
    margin-block-start: 0;
  }

  .clients-hero__lead {
    max-width: 46ch;
  }
}

@media (prefers-reduced-motion: reduce) {
  .clients-hero__contact-label,
  .clients-hero__register-link {
    transition: none;
  }
}

/* --- The four category sections ----------------------------------------- */

.clients-list__section {
  background: var(--color-bg);
}

.clients-list__inner {
  padding-block: var(--space-2xl) var(--space-xl);
}

.clients-list__entries {
  border-block-start: var(--border-hairline) solid var(--color-border);
}

.clients-list__entry {
  display: grid;
  gap: var(--space-md);
  padding-block: var(--space-lg);
  border-block-end: var(--border-hairline) solid var(--color-border);
  /* The index links straight to these and the header is sticky. */
  scroll-margin-block-start: 6rem;
}

/* One height band for all four, as /services holds one band for its six:
   the sources are 900-1260px wide at a common 1104px height, so without
   this the narrow one would stand taller than the rest. */
.clients-list__entry {
  --visual-ratio: 4 / 3;
  --visual-ratio-wide: 3 / 2;
}

.clients-list__frame {
  --illustration-ratio: var(--visual-ratio);
}

/* Mobile order is image, eyebrow, heading, description, client list — the
   DOM order, so nothing is reordered below 1024. */
.clients-list__body {
  display: grid;
  gap: var(--space-2xs);
  align-content: start;
}

.clients-list__eyebrow {
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
  margin: 0;
  font-size: var(--font-size-label);
  line-height: var(--line-height-label);
  letter-spacing: var(--letter-spacing-label);
  text-transform: uppercase;
  font-weight: var(--font-weight-semibold);
  color: var(--color-accent-text);
}

.clients-list__eyebrow-number {
  font-variant-numeric: tabular-nums;
}

.clients-list__name {
  margin: var(--space-2xs) 0 0;
  font-family: var(--font-display);
  font-size: var(--font-size-subhead);
  line-height: var(--line-height-subhead);
  letter-spacing: var(--letter-spacing-subhead);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
  text-wrap: balance;
}

.clients-list__description {
  margin: var(--space-2xs) 0 0;
  max-width: 46ch;
  font-size: var(--font-size-body);
  line-height: var(--line-height-body);
  color: var(--color-text-muted);
}

/* The roster. Plain text on hairlines — not links, no hover, no arrows:
   these are client names, and nothing on the site links out to a client. */
.clients-list__roster {
  margin-block-start: var(--space-md);
}

/* --- Client logo tiles (v1.1) --------------------------------------------
   PENDING THE CLIENT'S WRITTEN PERMISSION TO SHOW LOGOS. Until it arrives
   this must not go live -- see docs/DESIGN_AND_CONTENT.md #lock-clients.

   The hairline is the scope grid's, and for the same reason it was changed
   there on 2026-09-26: a per-tile ring survives a short last row where a
   container background paints a grey rectangle instead. This grid has short
   last rows by construction -- section 03 holds one client.

   Columns: 3 where a tile is at least ~170px wide, otherwise 2. Measured
   against the text column, which is full width below 1024 and half width
   above it: 2 across is the base (320 -> 143.5px tile, 390 -> 178.5,
   430 -> 197.9, 1024 -> 225.3); 3 across from 560 to 1023 (560 -> 173.2,
   768 -> 239.8) and again from 1280 (1280 -> 190.8, 1440 -> 216.4,
   1780 -> 240.8). One column is never needed: the narrowest tile still
   leaves 119.5px of content, and the widest logo box is 110. */
.clients-list__tiles {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--border-hairline);
  margin: 0;
  padding: 0;
  background: transparent;
  border: var(--border-hairline) solid transparent;
}

/* One row per section from 560 up, client's decision 2026-10-05. The band
   that ran 2 across between 1024 and 1279 left an empty cell in every
   three-client section, which the client did not want to see. */
@media (min-width: 560px) {
  .clients-list__tiles {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* Three fixed rows so every tile is the same height whether it holds a logo
   and a caption or a name on its own: the number, the 52px logo box, and one
   line for the caption. */
.clients-list__tile {
  display: grid;
  grid-template-rows: auto 3.25rem 1.25rem;
  justify-items: center;
  gap: var(--space-2xs);
  padding: var(--space-sm);
  background: var(--color-surface);
  box-shadow: 0 0 0 var(--border-hairline) var(--color-border);
}

/* At 320 the tile is 142.5px and the widest logo box is 110, which leaves
   half a pixel inside the default 16px padding. Twelve gives it 8.5px. */
@media (max-width: 359px) {
  .clients-list__tile {
    padding: var(--space-xs);
  }
}

/* The other tight band. Above 1024 the tiles sit in the half-width text
   column, which is at its narrowest right at 1024: a 149.2px tile, 117.2px of
   content, against a longest caption -- "Aster Dental Clinics" -- that needs
   129.3. It wrapped onto a second line and broke the fixed caption row. Eight
   pixels of side padding gives 133.2 and nothing else moves; the vertical
   padding stays at 16 so the number keeps its distance from the ring. By 1149
   the column has grown enough that 16 fits again. */
@media (min-width: 1024px) and (max-width: 1149px) {
  .clients-list__tile {
    padding-inline: var(--space-2xs);
  }
}

.clients-list__tile-number {
  justify-self: start;
  font-size: var(--font-size-label);
  letter-spacing: var(--letter-spacing-label);
  font-weight: var(--font-weight-semibold);
  color: var(--color-accent-text);
  font-variant-numeric: tabular-nums;
}

.clients-list__tile-mark {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-width: 0;
}

.clients-list__logo {
  display: block;
  max-width: 100%;
  height: auto;
}

/* Logo boxes, equalised by visual weight rather than by height. A logo's
   perceived weight is roughly its rendered area times the square root of its
   ink density -- the share of its own bounding box that is actually ink -- so
   solid shapes need less area than line marks to read as equally strong.
   Solving area = 1300 / sqrt(density) and clamping to 110 x 52 gives:

     logo             aspect  density  box (px)      perceived
     talabat           2.98    0.650   69.4 x 23.2     1300
     carrefour         4.03    0.325   95.8 x 23.8     1300
     ph-hospitality    1.00    0.178   52.0 x 52.0     1141  (height-capped)
     lexus-tailoring   3.88    0.176  109.7 x 28.3     1300
     banana-island     0.95    0.149   49.3 x 52.0      991  (height-capped)
     naseem            3.04    0.102  110.0 x 36.2     1270  (width-capped)
     aster             3.52    0.326   89.5 x 25.4     1300

   Without the density term Talabat -- a solid charcoal banner -- would sit at
   the same area as PH Hospitality's hairline circle and swamp it. */
.clients-list__logo--talabat { width: 69.4px; height: 23.2px; }
.clients-list__logo--carrefour { width: 95.8px; height: 23.8px; }
.clients-list__logo--ph-hospitality { width: 52px; height: 52px; }
.clients-list__logo--lexus-tailoring { width: 109.7px; height: 28.3px; }
.clients-list__logo--banana-island { width: 49.3px; height: 52px; }
.clients-list__logo--naseem { width: 110px; height: 36.2px; }
.clients-list__logo--aster { width: 89.5px; height: 25.4px; }

.clients-list__tile-name {
  align-self: center;
  font-size: var(--font-size-body-sm);
  line-height: 1.25;
  color: var(--color-text-muted);
  text-align: center;
}

/* --- The mobile client rows (v1.1, client's decision 2026-10-05) ----------
   Below 560 each section with two or more clients becomes one horizontal row
   that moves on its own. **This is the only continuous motion on the site**,
   and it exists because the client asked for it in the meeting on 2026-10-05;
   it overrides the motion lock for this component and nothing else.

   Three states, in the order a browser falls through them:

     no JS           a static swipe row. The track is a scroll container with
                     scroll snapping and the next tile peeking in, so the row
                     is still usable with nothing but a finger.
     reduced motion  the same static swipe row. js/main.js checks the query
                     and does not enhance, so there are no clones and no
                     pause button -- WCAG 2.2.2 wants a control for motion
                     that runs, and here none does.
     JS, motion ok   js/main.js clones the tiles once, marks the clones
                     aria-hidden and inert, and adds --moving. The track
                     translates by exactly one copy's width, so the loop is
                     seamless, and the shift and duration come from the
                     measured width rather than a guess.

   No fade mask and no gradient at the edges: the gradient lock still holds.
   Tiles slide in and out at the screen edges instead. */

.clients-list__roster-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  min-height: 2.75rem;
}

/* The button is injected by js/main.js, so this is the one place the head
   row has anything to align against. Above 560 nothing is injected and the
   head collapses back to the label's own height. */
@media (min-width: 560px) {
  .clients-list__roster-head {
    min-height: 0;
  }
}

@media (max-width: 559px) {
  /* The track below is `width: max-content` -- wider than the screen on
     purpose. Grid and flex items take an automatic minimum size of
     min-content, so without these two lines that width propagates back up
     through .clients-list__body's implicit column and the entry's column,
     and the whole page scrolls sideways (673px at 390 when the marquee is
     running, 174px without JS). minmax(0, 1fr) clamps the body's column to
     the space it actually has; min-width: 0 stops the rail asking for more.
     Measured 0 page overflow at 320 / 360 / 390 / 430 / 559 after this. */
  .clients-list__body {
    grid-template-columns: minmax(0, 1fr);
    min-width: 0;
  }

  /* Full bleed: the rail escapes the container's gutter so tiles enter and
     leave at the screen edges rather than at the text margin. */
  .clients-list__rail {
    min-width: 0;
    margin-inline: calc(-1 * var(--layout-gutter));
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-padding-inline-start: var(--layout-gutter);
    padding-inline: var(--layout-gutter);
    scrollbar-width: none;
  }

  .clients-list__rail::-webkit-scrollbar {
    display: none;
  }

  /* The static row is a scroll container a keyboard has to be able to reach
     (axe: scrollable-region-focusable), so it carries tabindex="0" and needs
     the `state` verb like anything else focusable. The offset is negative
     because the row is full-bleed: an outside ring would be clipped by the
     viewport on both edges. */
  .clients-list__rail:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: -2px;
  }

  /* One row, tiles at a fixed width so the next one peeks in. 11rem is close
     to the 2-column tile this replaces (177.5px at 390), and at 320 it still
     leaves 1.8 tiles in view. */
  .clients-list__tiles {
    grid-auto-flow: column;
    grid-auto-columns: 11rem;
    grid-template-columns: none;
    width: max-content;
  }

  .clients-list__tile {
    scroll-snap-align: start;
  }

  /* Moving. The track no longer scrolls or snaps -- it is driven by the
     animation -- and the gutter padding goes so the loop maths is exactly
     one copy's width. */
  .clients-list__rail--moving {
    overflow-x: hidden;
    scroll-snap-type: none;
    padding-inline: 0;
  }

  .clients-list__rail--moving .clients-list__tiles {
    animation: clients-marquee var(--marquee-duration, 20s) linear infinite;
    will-change: transform;
  }

  .clients-list__rail--moving .clients-list__tile {
    scroll-snap-align: none;
  }

  /* Paused by the button, by a finger held on the row, or because the
     section is off-screen. */
  .clients-list__rail--paused .clients-list__tiles {
    animation-play-state: paused;
  }
}

@keyframes clients-marquee {
  from {
    transform: translateX(0);
  }

  to {
    transform: translateX(calc(-1 * var(--marquee-shift, 0px)));
  }
}

/* Belt and braces: even if the enhancement ran before the query changed, a
   reader who prefers reduced motion gets no animation. */
@media (prefers-reduced-motion: reduce) {
  .clients-list__rail--moving .clients-list__tiles {
    animation: none;
  }
}

/* The pause control. 44x44 is the floor the rest of the site holds to, and
   the glyph inside it is 16px so it reads as a control rather than an icon
   button pretending to be a logo. */
.clients-list__marquee-toggle {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  margin-inline-end: calc(-1 * var(--space-2xs));
  padding: 0;
  border: 0;
  background: none;
  color: var(--color-text);
  cursor: pointer;
}

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

.clients-list__marquee-icon {
  width: 1rem;
  height: 1rem;
  fill: currentColor;
}

.clients-list__roster-label {
  margin: 0 0 var(--space-2xs);
  font-size: var(--font-size-label);
  line-height: var(--line-height-label);
  letter-spacing: var(--letter-spacing-label);
  text-transform: uppercase;
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-muted);
}

/* Between 560 and 1023 the entry is still stacked, and an image spanning the
   whole column is enormous — the same cap /services takes, and the same
   side-to-side shift so the stacked run keeps the alternation. */
@media (min-width: 560px) and (max-width: 1023px) {
  .clients-list__frame {
    max-width: min(100%, 26rem);
  }

  .clients-list__entry:nth-child(odd) .clients-list__frame {
    margin-inline-start: auto;
  }
}

@media (min-width: 768px) {
  .clients-list__inner {
    padding-block: var(--space-3xl) var(--space-2xl);
  }
}

@media (min-width: 1024px) {
  .clients-list__entry {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: center;
    column-gap: var(--space-2xl);
    padding-block: var(--space-xl);
  }

  .clients-list__frame {
    --illustration-ratio: var(--visual-ratio-wide);
  }

  /* The opposite phase to /services: 01 and 03 put the image on the right,
     02 and 04 on the left. The text stays left-aligned on both sides. */
  .clients-list__entry:nth-child(odd) .clients-list__visual {
    order: 2;
  }

  .clients-list__entry:nth-child(odd) .clients-list__body {
    order: 1;
  }

  .clients-list__name {
    font-size: var(--font-size-heading);
    line-height: 1.08;
    letter-spacing: var(--letter-spacing-heading);
  }

  .clients-list__body {
    gap: var(--space-xs);
  }
}

/* --- Our Approach -------------------------------------------------------- */

.clients-approach__section {
  background: var(--color-surface-muted);
}

.clients-approach__inner {
  padding-block: var(--space-2xl);
}

.clients-approach__eyebrow {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  margin: 0 0 var(--space-md);
  font-size: var(--font-size-label);
  line-height: var(--line-height-label);
  letter-spacing: var(--letter-spacing-label);
  text-transform: uppercase;
  font-weight: var(--font-weight-semibold);
  color: var(--color-accent-text);
}

.clients-approach__rule {
  display: block;
  width: var(--space-xl);
  height: 1px;
  flex: none;
  background: var(--color-accent);
}

.clients-approach__heading {
  margin: 0;
  max-width: 24ch;
  font-family: var(--font-display);
  font-size: var(--font-size-subhead);
  line-height: var(--line-height-subhead);
  letter-spacing: var(--letter-spacing-subhead);
  font-weight: var(--font-weight-semibold);
  text-transform: uppercase;
  color: var(--color-text);
}

.clients-approach__body {
  margin: var(--space-md) 0 0;
  max-width: 62ch;
  font-size: var(--font-size-body);
  line-height: var(--line-height-body);
  color: var(--color-text-muted);
}

/* Three labels, not links — there is no page behind "Trading" as a heading,
   and a row that looks like a link but is not is worse than plain text. No
   hover state for the same reason. */
.clients-approach__index {
  list-style: none;
  display: grid;
  margin: var(--space-lg) 0 0;
  padding: 0;
  border-block-start: var(--border-hairline) solid var(--color-border);
}

.clients-approach__index-item {
  display: flex;
  align-items: baseline;
  gap: var(--space-sm);
  padding-block: var(--space-xs);
  border-block-end: var(--border-hairline) solid var(--color-border);
  font-size: var(--font-size-label);
  line-height: var(--line-height-label);
  letter-spacing: var(--letter-spacing-label);
  text-transform: uppercase;
  font-weight: var(--font-weight-semibold);
}

.clients-approach__index-number {
  flex: none;
  color: var(--color-accent-text);
  font-variant-numeric: tabular-nums;
}

.clients-approach__index-name {
  color: var(--color-text);
}

@media (min-width: 768px) {
  .clients-approach__inner {
    padding-block: var(--space-3xl);
  }

  .clients-approach__index {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .clients-approach__index-item + .clients-approach__index-item {
    border-inline-start: var(--border-hairline) solid var(--color-border);
    padding-inline-start: var(--space-sm);
  }
}

@media (min-width: 1024px) {
  .clients-approach__heading {
    font-size: var(--font-size-heading);
    line-height: 1.08;
    letter-spacing: var(--letter-spacing-heading);
  }
}
