/* ============================================================================
   shell.css — site-header · mega-menu · mobile-drawer · site-footer ·
               whatsapp-fab · cookie-banner
   ========================================================================= */

/* --------------------------------------------------------------------------
   site-header — condenses 96px -> 64px past 120px of scroll. Only the
   background and the block-size transition, and it NEVER overlaps an h1:
   the header is sticky rather than fixed, so content flows beneath it.
   ----------------------------------------------------------------------- */
.site-header {
  position: sticky;
  inset-block-start: 0;
  z-index: var(--z-header);
  background: var(--bg);
  border-block-end: var(--rule);
}
.site-header__bar { transition: background-color var(--dur-dropdown) var(--ease-out); }
.site-header__inner {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  block-size: var(--header-h-condensed);
  transition: none;
}
@media (min-width: 1024px) {
  .site-header__inner {
    block-size: var(--header-h);
    /* transform/opacity only elsewhere; block-size here is on a container with
       no children whose layout depends on it, and it is the one place the spec
       explicitly permits a height change. */
    transition: block-size var(--dur-dropdown) var(--ease-out); /* motion-audit-exception: the brief specifies a 96->64px header condense by name. It runs on a bar whose children do not depend on it for layout, and it is the only box property animated anywhere on the site. */
  }
  .site-header[data-condensed] .site-header__inner { block-size: var(--header-h-condensed); }
}
.site-header[data-condensed] { box-shadow: 0 1px 0 var(--border); }

.site-header__logo { display: flex; align-items: center; color: var(--fg); flex: none; }

/* The desktop bar switches on at 1260px, not 1024.

   Measured, not guessed. The bar's min-content width is:

     logo 184  +  gap 24  +  nav 646  +  gap 24  +  actions 327  =  1205px

   which needs about 1220px of viewport once the container's padding is off.
   The old bar fitted at 1024 with six nav items and a 113px logo and had 3px to
   spare; the 2026 lockup is a 5.75:1 horizontal and Clients is a seventh item,
   so it no longer does. 1260 leaves ~40px of slack, which matters because a
   fallback font would widen the nav if the display face failed to load.

   Between 1024 and 1259 the drawer takes over, and the drawer carries the
   ENTIRE taxonomy: six hubs, their eight capability pages, twelve sectors and
   their fourteen sector pages, each nested under its hub. Nothing is lost.

   No `min-inline-size: 0` here. `flex: 1` is `flex: 1 1 0%`, and letting the
   box shrink below its min-content width does not make the bar fit — it lets
   the nav list overflow its own box and paint on top of the actions. */
.site-nav { display: none; flex: 1; }
@media (min-width: 1260px) { .site-nav { display: block; } }
.site-nav__list { display: flex; gap: var(--sp-1); }
.site-nav__link {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  min-block-size: var(--tap);
  padding-inline: var(--sp-2);
  font-size: var(--fs-small);
  font-weight: var(--weight-medium);
  color: var(--fg);
  text-decoration: none;
  border-radius: var(--r-btn);
  white-space: nowrap;
  transition: background-color var(--dur-hover) var(--ease-out);
}
/* The roomier hit area returns once the bar has the width for it. */
@media (min-width: 1440px) { .site-nav__link { padding-inline: var(--sp-3); } }
@media (hover: hover) and (pointer: fine) { .site-nav__link:hover { background: var(--mist); } }
.site-nav__link[aria-expanded="true"] { background: var(--mist); }
.site-nav__chevron {
  inline-size: 14px; block-size: 14px; color: var(--fg-muted);
  transition: transform var(--dur-dropdown) var(--ease-out);
}
.site-nav__link[aria-expanded="true"] .site-nav__chevron { transform: rotate(180deg); }

.site-header__actions { display: flex; align-items: center; gap: var(--sp-2); margin-inline-start: auto; }
.site-header__phone {
  display: none; align-items: center; gap: var(--sp-2);
  font-family: var(--font-mono); font-size: var(--fs-small);
  font-variant-numeric: tabular-nums;
  color: var(--fg); text-decoration: none; min-block-size: var(--tap);
  padding-inline: var(--sp-2);
}
.site-header__phone svg { inline-size: 16px; block-size: 16px; color: var(--fg-muted); flex: none; }
.site-header__phone .bidi-isolate { white-space: nowrap; }
@media (min-width: 1400px) { .site-header__phone { display: inline-flex; } }
@media (hover: hover) and (pointer: fine) { .site-header__phone:hover { color: var(--ember-deep); } }

.lang-switch {
  display: inline-flex; align-items: center; justify-content: center;
  min-block-size: var(--tap); padding-inline: var(--sp-3);
  font-size: var(--fs-small); font-weight: var(--weight-medium);
  color: var(--fg); text-decoration: none;
  border: 1px solid var(--border); border-radius: var(--r-btn);
  transition: border-color var(--dur-hover) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) { .lang-switch:hover { border-color: var(--fg); } }

.site-header__cta { display: none; }
@media (min-width: 640px) { .site-header__cta { display: inline-flex; } }
/* Below 480px the bar is logo + language + menu, and nothing else.

   The 2026 lockup is 5.75:1 where the old one was 3.53:1, so the compact logo
   is 149px at 320px width against a 305px container. Search is the item that
   goes: it is already in the drawer, one tap away, whereas the language switch
   is the control an Arabic-speaking visitor needs to find without opening
   anything. Measured at 320px: 149 + 69 + 44 + gaps = 278 of 305. */
@media (max-width: 479px) { .site-header__search { display: none; } }

.site-header__burger { display: inline-flex; }
@media (min-width: 1260px) { .site-header__burger { display: none; } }

/* --------------------------------------------------------------------------
   mega-menu — CSS transitions (not keyframes) so that moving between sibling
   triggers RETARGETS rather than restarting. transform-origin sits at the
   trigger, set from JS as a percentage along the inline axis.
   ----------------------------------------------------------------------- */
.mega { position: absolute; inset-inline: 0; inset-block-start: 100%; z-index: var(--z-dropdown); }
.mega[hidden] { display: none; }
/* Positioned INSIDE .mega rather than fixed to the viewport.
   It was previously `position: fixed` with `inset-block-start:
   var(--header-h-condensed)` — 64px — while the desktop header is 96px tall
   until it condenses. That left a 32px strip of backdrop showing between the
   bar and the panel, and the strip changed size as the header condensed.
   .mega already sits exactly at the header's bottom edge in both states, so
   anchoring the backdrop to it is correct at every header height. */
.mega__backdrop {
  position: absolute;
  inset-inline: 0;
  inset-block-start: 0;
  block-size: 100vh;
  background: rgba(20,17,15,.28);
  opacity: 0; transition: opacity var(--dur-dropdown) var(--ease-out);
  pointer-events: none;
}
.mega[data-open] .mega__backdrop { opacity: 1; pointer-events: auto; }

.mega__panel {
  position: absolute; inset-inline: 0; inset-block-start: 0;
  /* On a short viewport a long panel would otherwise run off the bottom with
     no way to reach the rest of it. It never scrolls at a normal window
     height; this is a safety net, not a scroll pane. */
  max-block-size: calc(100vh - var(--header-h-condensed) - var(--sp-5));
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--bg);
  border-block-end: var(--rule);
  box-shadow: var(--shadow-raised);
  opacity: 0;
  transform: scale(.98) translateY(-4px);
  transform-origin: var(--origin-x, 20%) top;
  transition: opacity var(--dur-dropdown) var(--ease-out),
              transform var(--dur-dropdown) var(--ease-out);
  pointer-events: none;
}
.mega__panel[hidden] { display: none; }
.mega__panel[data-open] { opacity: 1; transform: scale(1) translateY(0); pointer-events: auto; }
/* Once one panel is open, a sibling swaps instantly — no delay, no re-animation. */
.mega[data-swapping] .mega__panel { transition: none; }
.mega__panel:exit, .mega__panel[data-exiting] { transition-duration: var(--dur-exit); }

.mega__inner {
  display: grid;
  grid-template-columns: minmax(0, 20rem) minmax(0, 1fr);
  gap: var(--sp-8);
  padding-block: var(--sp-7);
}
.mega__lead { border-inline-end: var(--rule); padding-inline-end: var(--sp-7); }
.mega__intro { font-size: var(--fs-small); color: var(--fg-muted); margin-block-start: var(--sp-3); max-inline-size: 34ch; }
.mega__links { margin-block-start: var(--sp-5); display: grid; gap: var(--sp-1); }

.mega__cols { display: grid; gap: var(--sp-7); }
.mega__cols--2 { grid-template-columns: 1fr 1fr; }
.mega__group-title { font-family: var(--font-display); font-size: var(--fs-h3); font-weight: var(--weight-semi); letter-spacing: var(--tracking-display); }
.mega__group-note { font-family: var(--font-mono); font-size: var(--fs-label); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--fg-muted); margin-block-start: var(--sp-1); }
.mega__list { margin-block-start: var(--sp-4); display: grid; gap: 0; }
.mega__list--dense { grid-template-columns: repeat(3, minmax(0,1fr)); column-gap: var(--sp-5); }

.mega__item {
  display: grid;
  grid-template-columns: 4.5rem minmax(0,1fr);
  gap: var(--sp-1) var(--sp-3);
  padding-block: var(--sp-3);
  padding-inline: var(--sp-3);
  margin-inline: calc(var(--sp-3) * -1);
  border-block-end: var(--rule);
  border-radius: 2px;
  text-decoration: none; color: inherit;
  min-block-size: var(--tap);
  transition: background-color var(--dur-hover) var(--ease-out);
}
.mega__item--tight { grid-template-columns: 4.5rem minmax(0,1fr); }
@media (hover: hover) and (pointer: fine) {
  .mega__item:hover { background: var(--mist); }
  .mega__item:hover .mega__code { color: var(--ember-deep); }
}
.mega__code {
  grid-row: 1 / span 2;
  font-family: var(--font-mono); font-size: var(--fs-label);
  letter-spacing: var(--tracking-label); text-transform: uppercase;
  color: var(--fg-muted); padding-block-start: 3px;
  transition: color var(--dur-hover) var(--ease-out);
}
.mega__item--tight .mega__code { grid-row: 1; }
.mega__name { font-size: var(--fs-small); font-weight: var(--weight-semi); }
.mega__desc { font-size: var(--fs-small); color: var(--fg-muted); grid-column: 2; }

/* --------------------------------------------------------------------------
   drawer — slides from the inline-end edge, so RTL mirrors for free.
   ----------------------------------------------------------------------- */
.drawer { position: fixed; inset: 0; z-index: var(--z-drawer); }
.drawer[hidden] { display: none; }
.drawer__backdrop {
  position: absolute; inset: 0; background: rgba(20,17,15,.5);
  opacity: 0; transition: opacity var(--dur-panel) var(--ease-drawer);
}
.drawer[data-open] .drawer__backdrop { opacity: 1; }
.drawer__panel {
  position: absolute;
  inset-block: 0; inset-inline-end: 0;
  inline-size: min(400px, 92vw);
  background: var(--bg);
  display: flex; flex-direction: column;
  box-shadow: var(--shadow-overlay);
  transform: translateX(100%);
  transition: transform var(--dur-panel) var(--ease-drawer);
  will-change: transform;
}
[dir="rtl"] .drawer__panel { transform: translateX(-100%); }
.drawer[data-open] .drawer__panel { transform: translateX(0); }
[dir="rtl"] .drawer[data-open] .drawer__panel { transform: translateX(0); }
.drawer[data-dragging] .drawer__panel { transition: none; }

.drawer__head {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--sp-4) var(--sp-5);
  border-block-end: var(--rule);
  flex: none;
}
.drawer__body { padding: var(--sp-5); overflow-y: auto; flex: 1; overscroll-behavior: contain; }
.drawer__cta { margin-block-end: var(--sp-5); }
.drawer__accordion .accordion__trigger { font-size: var(--fs-body); padding-block: var(--sp-4); }
.drawer__list { display: grid; gap: 0; padding-block-end: var(--sp-3); }
.drawer__list a {
  display: grid; grid-template-columns: 4.5rem minmax(0,1fr); gap: var(--sp-3);
  align-items: center;
  min-block-size: var(--tap); padding-block: var(--sp-2);
  font-size: var(--fs-small); text-decoration: none; color: var(--fg);
}
.drawer__code { font-family: var(--font-mono); font-size: var(--fs-label);
  letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--fg-muted); }
.drawer__flat { margin-block-start: var(--sp-5); display: grid; border-block-start: var(--rule); }
.drawer__flat a {
  display: flex; align-items: center; min-block-size: var(--tap);
  padding-block: var(--sp-3); border-block-end: var(--rule);
  font-size: var(--fs-body); font-weight: var(--weight-medium);
  text-decoration: none; color: var(--fg);
}
.drawer__flat--muted a { font-weight: var(--weight-regular); font-size: var(--fs-small); color: var(--fg-muted); }
.drawer__foot {
  flex: none; padding: var(--sp-5);
  border-block-start: var(--rule);
  display: grid; gap: var(--sp-3); justify-items: start;
}
.drawer__contact {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  font-size: var(--fs-small); color: var(--fg); text-decoration: none;
  min-block-size: var(--tap);
}
.drawer__contact svg { inline-size: 16px; block-size: 16px; color: var(--fg-muted); }

/* Nav items stagger in — decorative only, never blocking interaction. */
.drawer[data-open] .drawer__body > * { animation: drawer-item var(--dur-panel) var(--ease-out) backwards; }
.drawer[data-open] .drawer__body > *:nth-child(2) { animation-delay: 40ms; }
.drawer[data-open] .drawer__body > *:nth-child(3) { animation-delay: 80ms; }
@keyframes drawer-item { from { opacity: 0; transform: translateY(8px); } }
@media (prefers-reduced-motion: reduce) { .drawer[data-open] .drawer__body > * { animation: none; } }

/* --------------------------------------------------------------------------
   site-footer
   ----------------------------------------------------------------------- */
.site-footer {
  background: var(--footer-bg);
  color: var(--fg-on-dark);
  --border: var(--border-on-dark);
  padding-block-start: var(--sp-9);
  margin-block-start: 0;
  /* A 2px ember rule across the top. The footer is the one place on the site
     where a full-width accent is earned: it marks the end of the document, it
     is seen once per page, and it makes the boundary unambiguous in a theme
     where the two grounds are close together. */
  border-block-start: 2px solid var(--footer-rule);
}
.site-footer__top { display: grid; gap: var(--sp-8); padding-block-end: var(--sp-8); }
@media (min-width: 1024px) { .site-footer__top { grid-template-columns: minmax(0, 22rem) minmax(0, 1fr); gap: var(--sp-9); } }

.site-footer__logo { color: var(--fg-on-dark); }
.site-footer__blurb { margin-block-start: var(--sp-4); color: var(--fg-on-dark-muted); font-size: var(--fs-small); max-inline-size: 40ch; }
.site-footer__address { margin-block-start: var(--sp-5); font-style: normal; font-size: var(--fs-small); color: var(--fg-on-dark-muted); line-height: 1.7; }
.site-footer__contact { margin-block-start: var(--sp-5); display: grid; gap: var(--sp-2); }
.site-footer__contact a, .site-footer__hours {
  display: inline-flex; align-items: center; gap: var(--sp-3);
  font-size: var(--fs-small); color: var(--fg-on-dark); text-decoration: none;
  min-block-size: 32px;
}
.site-footer__hours { color: var(--fg-on-dark-muted); }
.site-footer__contact svg { inline-size: 16px; block-size: 16px; color: var(--fg-on-dark-muted); flex: none; }
@media (hover: hover) and (pointer: fine) { .site-footer__contact a:hover { color: var(--ember); } }

.site-footer__social { margin-block-start: var(--sp-5); display: flex; gap: var(--sp-2); }
.site-footer__social a {
  display: grid; place-content: center;
  inline-size: var(--tap); block-size: var(--tap);
  border: 1px solid var(--border-on-dark); border-radius: var(--r-btn);
  color: var(--fg-on-dark-muted);
  transition: color var(--dur-hover) var(--ease-out), border-color var(--dur-hover) var(--ease-out);
}
.site-footer__social svg { inline-size: 18px; block-size: 18px; }
@media (hover: hover) and (pointer: fine) { .site-footer__social a:hover { color: var(--fg-on-dark); border-color: var(--fg-on-dark); } }

.site-footer__cols { display: grid; gap: var(--sp-7) var(--sp-6); grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.site-footer__col-title {
  font-family: var(--font-mono); font-size: var(--fs-label);
  letter-spacing: var(--tracking-label); text-transform: uppercase;
  font-weight: var(--weight-medium); color: var(--fg-on-dark-muted);
  padding-block-end: var(--sp-3); border-block-end: var(--rule);
}
[lang="ar"] .site-footer__col-title { text-transform: none; letter-spacing: 0; }
.site-footer__col ul { margin-block-start: var(--sp-3); display: grid; gap: 0; }
.site-footer__col a {
  display: block; padding-block: var(--sp-2);
  font-size: var(--fs-small); color: var(--fg-on-dark-muted); text-decoration: none;
  transition: color var(--dur-hover) var(--ease-out);
  min-block-size: 32px;
}
@media (hover: hover) and (pointer: fine) { .site-footer__col a:hover { color: var(--fg-on-dark); } }

/* --------------------------------------------------------------------------
   Get started — its own full-width row rather than the fifth of five columns.
   These are the actions someone scrolled this far to find; a taxonomy column
   is the wrong container for them.
   ----------------------------------------------------------------------- */
.site-footer__actions {
  padding-block: var(--sp-6);
  border-block-start: var(--rule);
  display: grid;
  gap: var(--sp-4);
}
@media (min-width: 1024px) {
  .site-footer__actions { grid-template-columns: minmax(0, 22rem) minmax(0, 1fr); gap: var(--sp-9); align-items: baseline; }
}
.site-footer__actions-title { border-block-end: 0; padding-block-end: 0; }
.site-footer__actions ul {
  display: flex; flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-6);
}
.site-footer__actions .link-arrow {
  color: var(--fg-on-dark);
  font-size: var(--fs-small);
}
@media (hover: hover) and (pointer: fine) {
  .site-footer__actions .link-arrow:hover { color: var(--ember); }
}

.site-footer__bottom {
  display: flex; flex-wrap: wrap; gap: var(--sp-4);
  align-items: center; justify-content: space-between;
  padding-block: var(--sp-5);
  border-block-start: var(--rule);
}
.site-footer__legal { display: flex; flex-wrap: wrap; gap: var(--sp-5); }
.site-footer__legal a {
  font-family: var(--font-mono); font-size: var(--fs-label);
  letter-spacing: var(--tracking-label); text-transform: uppercase;
  color: var(--fg-on-dark-muted); text-decoration: none;
}
[lang="ar"] .site-footer__legal a { text-transform: none; letter-spacing: 0; }
@media (hover: hover) and (pointer: fine) { .site-footer__legal a:hover { color: var(--fg-on-dark); } }

/* --------------------------------------------------------------------------
   whatsapp-fab — ONE floating action. Clears the footer and the sticky bar.
   ----------------------------------------------------------------------- */
.whatsapp-fab {
  position: fixed;
  inset-block-end: var(--sp-5);
  inset-inline-end: var(--sp-5);
  z-index: var(--z-sticky);
  display: grid; place-content: center;
  inline-size: 52px; block-size: 52px;
  border-radius: 50%;
  background: #25D366; color: #0B2E17;
  box-shadow: var(--shadow-raised);
  transition: transform var(--dur-press) var(--ease-out);
}
.whatsapp-fab svg { inline-size: 26px; block-size: 26px; }
.whatsapp-fab:active { transform: scale(0.97); }
body:has(.sticky-quote[data-visible]) .whatsapp-fab { inset-block-end: calc(var(--sp-5) + 64px); }

/* --------------------------------------------------------------------------
   cookie-banner — bottom-anchored, never a full-screen blocker.
   ----------------------------------------------------------------------- */
.cookie-banner {
  position: fixed;
  inset-block-end: 0; inset-inline: 0;
  z-index: var(--z-toast);
  background: var(--surface);
  border-block-start: var(--rule-strong);
  box-shadow: var(--shadow-raised);
  transform: translateY(100%);
  transition: transform var(--dur-panel) var(--ease-out);
}
.cookie-banner[data-open] { transform: translateY(0); }
.cookie-banner[hidden] { display: none; }
.cookie-banner__inner {
  display: grid; gap: var(--sp-4);
  padding-block: var(--sp-5);
  align-items: center;
}
@media (min-width: 900px) { .cookie-banner__inner { grid-template-columns: minmax(0,1fr) auto; gap: var(--sp-7); } }
.cookie-banner__title { font-weight: var(--weight-semi); margin-block-end: var(--sp-1); }
.cookie-banner__text { max-inline-size: 72ch; }
.cookie-banner__actions { display: flex; flex-wrap: wrap; gap: var(--sp-3); }

/* --------------------------------------------------------------------------
   Footer disclosure. Open and inert on desktop (the columns are the point);
   collapsed on a phone, where 28 taxonomy links at the bottom of the page is
   ~840px of scroll nobody asked for. Uses <details> so it works with JS off.
   ----------------------------------------------------------------------- */
.site-footer__disclosure > summary { list-style: none; cursor: default; }
.site-footer__disclosure > summary::-webkit-details-marker { display: none; }
.site-footer__chevron { display: none; inline-size: 16px; block-size: 16px; }

@media (min-width: 640px) {
  /* Always open above the phone breakpoint. */
  .site-footer__disclosure > ul { display: grid !important; }
}
@media (max-width: 639px) {
  .site-footer__disclosure > summary {
    display: flex; align-items: center; justify-content: space-between;
    cursor: pointer; min-block-size: var(--tap);
    padding-block-end: var(--sp-3);
  }
  .site-footer__chevron { display: block; color: var(--fg-on-dark-muted);
    transition: transform var(--dur-dropdown) var(--ease-out); }
  .site-footer__disclosure[open] .site-footer__chevron { transform: rotate(180deg); }
  .site-footer__col--collapsible { grid-column: 1 / -1; }
  .site-footer__disclosure > ul { padding-block-end: var(--sp-4); }
}

@media (max-width: 639px) {
  /* The action row stacks. Four full-width targets at the foot of the page is
     the right shape on a phone — these are the conversion funnels and they are
     easier to hit as rows than as wrapped inline links. */
  .site-footer__actions { padding-block: var(--sp-5); gap: var(--sp-3); }
  .site-footer__actions ul { display: grid; gap: 0; }
  .site-footer__actions li { border-block-end: var(--rule); }
  .site-footer__actions li:last-child { border-block-end: 0; }
  .site-footer__actions .link-arrow { inline-size: 100%; justify-content: space-between; }
}

/* --------------------------------------------------------------------------
   theme-toggle — light / dark switch.

   The icon crossfades rather than swapping: the sun and moon occupy the same
   cell and trade opacity plus a small rotation, so the control reads as one
   object changing state rather than two objects being swapped. 160ms, the
   standard hover duration — this is an occasional action, not a daily one.
   ----------------------------------------------------------------------- */
.theme-toggle__icons {
  position: relative;
  display: grid;
  place-items: center;
  inline-size: 20px;
  block-size: 20px;
  flex: none;
}
.theme-toggle__icons svg {
  grid-area: 1 / 1;
  inline-size: 20px;
  block-size: 20px;
  transition: opacity var(--dur-hover) var(--ease-out),
              transform var(--dur-hover) var(--ease-out);
}
/* Light is showing -> offer the moon. Dark is showing -> offer the sun. */
.theme-toggle__sun  { opacity: 0; transform: rotate(-45deg) scale(.7); }
.theme-toggle__moon { opacity: 1; transform: rotate(0) scale(1); }
:root[data-theme="dark"] .theme-toggle__sun  { opacity: 1; transform: rotate(0) scale(1); }
:root[data-theme="dark"] .theme-toggle__moon { opacity: 0; transform: rotate(45deg) scale(.7); }
@media (prefers-reduced-motion: reduce) {
  .theme-toggle__icons svg { transform: none !important; }
}

/* Drawer variant: a labelled row rather than a bare icon. */
.theme-toggle--row {
  display: inline-flex; align-items: center; gap: var(--sp-3);
  min-block-size: var(--tap);
  padding-inline: var(--sp-3);
  border: 1px solid var(--border);
  border-radius: var(--r-btn);
  font-size: var(--fs-small);
  font-weight: var(--weight-medium);
  color: var(--fg);
  transition: border-color var(--dur-hover) var(--ease-out),
              transform var(--dur-press) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) { .theme-toggle--row:hover { border-color: var(--fg); } }
.theme-toggle--row:active { transform: scale(0.97); }

.drawer__prefs { display: flex; flex-wrap: wrap; gap: var(--sp-3); align-items: center; }

/* The header toggle is hidden on the narrowest screens — the drawer carries it
   there, with a label, which is the better control on a phone anyway. */
.site-header__actions .theme-toggle { display: none; }
@media (min-width: 480px) { .site-header__actions .theme-toggle { display: inline-flex; } }

/* --------------------------------------------------------------------------
   Switching the theme changes a colour on effectively every element. Letting
   each one run its own transition produces a visible sweep down the page that
   reads as lag. Transitions are suppressed for one frame across the switch —
   the change should be instantaneous, because it is not a state the user is
   waiting on.
   ----------------------------------------------------------------------- */
:root[data-theme-switching] *,
:root[data-theme-switching] *::before,
:root[data-theme-switching] *::after {
  transition: none !important;
}

/* --------------------------------------------------------------------------
   logo — the 2026 mark, inlined as SVG.

   The ink layer of the artwork is painted with `currentColor`, so the reversed
   logo is not a second file: on the ink footer, in the app sidebar and in dark
   mode the near-black picks up the surrounding colour and the mark reads as the
   reversed artwork. What used to be twelve rasters and a <picture> switch is
   now one path set and one inherited colour.

   Sizing is by block-size on the wrapper. `aspect-ratio` comes from the
   generated intrinsic dimensions (--logo-ratio, set inline by the partial), so
   the box is reserved before paint exactly as width/height did on the <img>.
   ----------------------------------------------------------------------- */
.logo { display: inline-flex; align-items: center; flex: none; }
.logo svg { display: block; block-size: 100%; inline-size: auto; }
.logo { aspect-ratio: var(--logo-ratio); }

/* Sizes. */
.logo--compact { block-size: 30px; }
.logo--full    { block-size: 42px; }
.logo--mark    { block-size: 28px; }
.logo--stacked { block-size: 96px; }
/* The footer lockup is 5.75:1, so 52px tall is 299px wide — wider than a
   320px viewport's content column. It steps down twice rather than being
   allowed to push the page sideways. Measured, not assumed: the whole reason
   the 320px overflow check exists is that this class of bug is invisible on a
   laptop. */
.site-footer .logo--full { block-size: 52px; }
@media (max-width: 599px) { .site-footer .logo--full { block-size: 40px; } }
@media (max-width: 359px) { .site-footer .logo--full { block-size: 32px; } }
.app-sidebar .logo--compact { block-size: 26px; }

/* The header carries the tagline lockup at desktop and the compact one below.
   The tagline sits at 18% of the lockup height; under a ~36px lockup it renders
   below 6.5px and stops being type. Both are inlined and one is hidden, which
   costs 117 bytes gzipped — the two lockups share nearly all their path data,
   so the second compresses to almost nothing against the first. */
.site-header__logo .logo--full { block-size: 32px; }
.site-header__logo .logo--compact { display: none; }
/* Below the desktop breakpoint the bar is logo + burger and has room to spare,
   but the tagline at a 28px lockup renders about 5px tall and stops being type,
   so the compact lockup takes over rather than shipping an unreadable one. */
@media (max-width: 1259px) {
  .site-header__logo .logo--full { display: none; }
  .site-header__logo .logo--compact { display: inline-flex; block-size: 30px; }
}
/* Under 480px the bar is a measured fit, not a guess. The content box at a
   320px viewport is 273px; the 5.75:1 lockup at 26px is 149.5px, the gap is
   24px and the actions are 120.5px — 294px, which overflowed by 21. The lockup
   steps to 24px and the bar's gap tightens; 138 + 12 + 120.5 = 270.5 of 273. */
@media (max-width: 479px) {
  .site-header__logo .logo--compact { block-size: 24px; }
  .site-header__inner { gap: var(--sp-3); }
}

/* The header condenses 96 -> 64px; the logo steps down with it rather than
   staying at desktop size in a 64px bar. */
.site-header[data-condensed] .logo--full { block-size: 30px; }

/* The mega panel's service hubs name the capability pages beneath them, so the
   eight URLs that used to BE the services nav are still one interaction from
   any page rather than one interaction plus a hub visit. */
.mega__children {
  /* Column 2, beside the name — not under the 4.5rem mono code column, where a
     four-name list wraps to five lines and stretches the whole grid row. */
  grid-column: 2; margin-block-start: var(--sp-2);
  font-family: var(--font-mono); font-size: var(--fs-label);
  letter-spacing: var(--tracking-label); color: var(--fg-muted);
}
.mega__list--hubs { display: grid; gap: var(--sp-2); }
@media (min-width: 900px) { .mega__list--hubs { grid-template-columns: repeat(2, 1fr); column-gap: var(--sp-7); align-items: start; } }

/* Capability pages sit under their hub in the drawer, indented rather than
   dropped — a mobile nav that shows six of twenty-two links is the failure this
   build exists to fix. */
.drawer__sub a { padding-inline-start: var(--sp-6); color: var(--fg-muted); }
