/* ═══════════════════════════════════════════════════════════════════════════
   RivCut mobile/tablet shell — loaded on every in-scope page (~16,400)
   Ported from the RivCut Mobile App prototype.

   ── CASCADE RULE (read before editing) ───────────────────────────────────
   css/mobile.css is NOT reliably last: 16,122 pages carry a <style> block
   AFTER </head>, so document order cannot be used as a tie-breaker.

   Therefore:
     • New .rc-* class names        → plain selectors, NO !important.
       Nothing else in the codebase uses this namespace, and a page-level
       element selector (e.g. `nav {}` at 0,0,1) loses to `.rc-tabbar` (0,1,0).

     • Overrides of EXISTING classes → prefix with `body` AND use !important.
       Specificity (0,1,1) beats css/mobile.css's `.x{...!important}` (0,1,0),
       and specificity is evaluated BEFORE source order, so this wins from
       anywhere in the document. Verified: no body-qualified or ID-qualified
       !important competitors exist in css/, and only 95 of 16,122 in-body
       <style> blocks use !important at all (none on classes touched here).

   Do NOT use @layer. Specificity escalation wins in every browser and does
   not depend on the reversed !important-layer ordering, which is easy to
   get wrong later.

   ── BREAKPOINTS ──────────────────────────────────────────────────────────
     ≤1023px           "phone-style"    tab bar, 44pt targets, nav fix,
                                        single-column page, applied as ONE
                                        block so the previously unhandled
                                        769–1023px window is covered by
                                        construction rather than by a third
                                        rule set
       ↳ ≤600px        phone portrait   1-up card grids
       ↳ 601–1023px    tablet/landscape 2-up card grids
     1024–1279px       compact desktop  two-column preserved, nav restored
                                        (1024 is exactly iPad Pro portrait)
     ≥1280px           desktop          untouched — any diff here is a bug
   ═══════════════════════════════════════════════════════════════════════ */


/* ─────────────────────────────────────────────────────────────────────────
   A. Tokens
   The site already defines --blue/--dark/--gray-* in css/index.css and
   css/quote.css, matching the prototype exactly. Only the two the prototype
   uses that the site lacks are added here. All uses carry literal fallbacks
   so the 4,172 pages that load no site stylesheet still render correctly.
   ───────────────────────────────────────────────────────────────────────── */
:root {
  --rc-line:    #DFE3E8;  /* prototype hairline (site --gray-200 is #DDE1E7) */
  --rc-muted:   #A8AEB7;  /* inactive tab */
  --rc-ease:    cubic-bezier(.2, .8, .2, 1);

  /* Runtime contract. js/rc-shell.js measures and overwrites these as inline
     styles on <body> — NOT <html>. The pre-JS defaults below are declared on
     body too, and a declaration on body shadows anything inherited from html
     for body and all its descendants, so writing to html would leave the
     measured value invisible to every element on the page. */
  --rc-tabbar-h: 0px;   /* measured tab-bar height, 0 above 1023px */
  --rc-promo-h:  0px;   /* measured promo-bar height, 0 when absent/closed */
  --rc-cta-h:    0px;   /* measured sticky-CTA height, set by app pages */
}

/* Structural defaults so first paint is close and JS only nudges it.
   :has() is baseline (Safari 15.4 / Chrome 105 / Firefox 121); browsers
   without it start at 0px and JS corrects within the same paint.
   The promo bar is ~38px on desktop but wraps to ~70px at phone widths
   (css/mobile.css:34-36 shrinks the type and forces the CTA to display:block),
   which is precisely why css/mobile.css:40's hardcoded 58px overlaps it. */
body:has(> .promo-bar) { --rc-promo-h: 38px; }
@media screen and (max-width: 768px) {
  body:has(> .promo-bar) { --rc-promo-h: 70px; }
}

@media screen and (max-width: 1023px) {
  body.rc-has-tabbar { --rc-tabbar-h: 64px; }
}

/* Prototype keyframes (RivCut Mobile App.dc.html:19-24). rc-in and rc-sheet
   are used by the app sheets; the rest are here so the sheet is complete. */
@keyframes rc-in     { from { opacity: 0; transform: translateY(10px); }
                       to   { opacity: 1; transform: none; } }
@keyframes rc-sheet  { from { transform: translateY(100%); }
                       to   { transform: none; } }
@keyframes rc-pulse  { 0%,100% { opacity: 1; } 50% { opacity: .35; } }
@keyframes rc-bounce { 0%,100% { transform: none; } 50% { transform: translateY(-3px); } }
@keyframes rc-bar    { from { width: 0; } }

@media (prefers-reduced-motion: reduce) {
  .rc-tabbar, .rc-tab, .rc-drawer, .rc-scrim { animation: none !important; transition: none !important; }
}


/* ─────────────────────────────────────────────────────────────────────────
   B. Bottom tab bar          (new namespace — no !important needed)
   Ported from prototype lines 1354-1366.

   z-index 995 is deliberate: BELOW .mobile-overlay (999) so the drawer scrim
   covers the bar and you cannot tap through it, and below .chat-panel (1045)
   so full-screen chat covers it. Existing budget:
     #rvStickyCta 998 · .mobile-overlay 999 · .nav 1000 · .mobile-menu 1001
     · .promo-bar 1002 · .mobile-toggle 1002 · .chat-fab 1040
     · .rv-teaser 1044 · .chat-panel 1045 · .email-fab-wrap 1050
   ───────────────────────────────────────────────────────────────────────── */
.rc-tabbar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 995;
  display: none;                       /* the media query below turns it on */
  align-items: stretch;
  background: rgba(255, 255, 255, .94);
  -webkit-backdrop-filter: blur(18px);
          backdrop-filter: blur(18px);
  border-top: 1px solid var(--rc-line, #DFE3E8);
  /* env() resolves to 0 today because no page sets viewport-fit=cover, and
     iOS already insets the layout viewport above the home indicator. The
     max() keeps the rule correct if viewport-fit is ever added. */
  padding: 9px 6px max(10px, env(safe-area-inset-bottom, 0px));
  font-family: 'IBM Plex Sans', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
}

@media screen and (max-width: 1023px) { .rc-tabbar { display: flex; } }
@media print               { .rc-tabbar { display: none !important; } }

.rc-tab {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-height: 44px;                    /* WCAG 2.5.8 target size */
  padding: 3px 0;
  position: relative;
  background: none;
  border: 0;
  cursor: pointer;
  text-decoration: none;
  color: var(--rc-muted, #A8AEB7);
  transition: color .18s var(--rc-ease, ease);
  -webkit-tap-highlight-color: transparent;
}
.rc-tab-icon { height: 22px; display: flex; align-items: center; }
.rc-tab svg  { width: 21px; height: 21px; display: block; }
.rc-tab span {
  font-size: 10px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: .1px;
}
.rc-tab.is-active { color: var(--blue, #0d4fb4); }
.rc-tab:active    { opacity: .6; }
.rc-tab:focus-visible {
  outline: 2px solid var(--blue, #0d4fb4);
  outline-offset: -3px;
  border-radius: 8px;
}

/* Unread-chat dot, mirrored from #chatFab's .chat-fab-badge by rc-shell.js */
.rc-tab[data-rc-badge]::after {
  content: '';
  position: absolute;
  top: 1px;
  left: calc(50% + 7px);
  width: 8px; height: 8px;
  border-radius: 50%;
  background: #e11d48;
  border: 2px solid #fff;
  box-sizing: content-box;
}

/* Landscape phone: 58px of a 375px-tall viewport is 15%. Drop to icons. */
@media screen and (max-width: 1023px) and (max-height: 450px) and (orientation: landscape) {
  .rc-tabbar { padding: 5px 6px 6px; }
  .rc-tab span { display: none; }
  body.rc-has-tabbar { --rc-tabbar-h: 56px; }
}


/* ─────────────────────────────────────────────────────────────────────────
   C. Mobile drawer fallback
   js/rc-shell.js synthesizes a drawer on the 7,641 pages that render a
   .mobile-toggle with no .mobile-menu. It reuses the existing global class
   names, which css/mobile.css:231-338 already styles — but 4,172 pages never
   load mobile.css. This block is that fallback.

   It is a strict SUPERSET of mobile.css: every shared declaration carries
   mobile.css's exact value (including its cubic-bezier(.4,0,.2,1) slide and
   the .2s link transition — deliberately NOT the --rc-ease curve used
   elsewhere in this file), so on the 12,229 pages that load both, this block
   changes nothing. The only additions are literal fallbacks inside var() and
   two scroll properties, which matter solely on the pages that lack
   mobile.css. Keep it that way: if you retune the drawer animation here you
   silently retune it for 12,229 pages that were not part of the change.
   ───────────────────────────────────────────────────────────────────────── */
.mobile-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(11, 31, 59, .5);
  -webkit-backdrop-filter: blur(4px);
          backdrop-filter: blur(4px);
  z-index: 999;
  opacity: 0;
  transition: opacity .3s ease;
}
.mobile-overlay.visible { display: block; opacity: 1; }

.mobile-menu {
  position: fixed;
  top: 0; right: 0;
  width: 300px;
  max-width: 85vw;
  height: 100%;
  background: var(--white, #fff);
  z-index: 1001;
  transform: translateX(100%);
  transition: transform .35s cubic-bezier(.4, 0, .2, 1);   /* mobile.css value, do not change */
  display: flex;
  flex-direction: column;
  box-shadow: -8px 0 30px rgba(11, 31, 59, .12);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}
.mobile-menu.open { transform: translateX(0); }
.mobile-menu-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 20px 24px;
  border-bottom: 1px solid var(--gray-100, #F4F6F8);
}
.mobile-menu-links { list-style: none; padding: 16px 0; margin: 0; flex: 1; }
.mobile-menu-links li { border-bottom: 1px solid var(--gray-100, #F4F6F8); }
.mobile-menu-links a {
  display: block;
  padding: 16px 24px;
  font-size: 16px;
  font-weight: 500;
  color: var(--gray-700, #4A4F57);
  text-decoration: none;
  transition: all .2s;                                   /* mobile.css value, do not change */
}
.mobile-menu-links a:hover { background: var(--gray-100, #F4F6F8); color: var(--blue, #0d4fb4); }
.mobile-menu-footer { padding: 20px 24px; border-top: 1px solid var(--gray-100, #F4F6F8); }
.mobile-menu-footer .btn { width: 100%; justify-content: center; margin-bottom: 12px; }

/* The synthesized drawer's own close button and section headers. */
.rc-drawer-close {
  width: 44px; height: 44px;
  display: flex; align-items: center; justify-content: center;
  margin: -10px -10px -10px 0;
  background: none; border: 0; cursor: pointer;
  font-size: 26px; line-height: 1;
  color: var(--gray-500, #6E7580);
}
.rc-drawer-brand {
  font-family: 'Geist', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  font-size: 17px; font-weight: 800; letter-spacing: -.3px;
  color: var(--dark, #0B1F3B);
}
.mobile-menu-links li.rc-drawer-head a {
  font-weight: 700;
  color: var(--dark, #0B1F3B);
  font-size: 15px;
}

/* The hamburger must be tappable wherever it exists. */
@media screen and (max-width: 1023px) {
  body .mobile-toggle {
    min-width: 44px !important;
    min-height: 44px !important;
    align-items: center !important;
    justify-content: center !important;
  }
}


/* ─────────────────────────────────────────────────────────────────────────
   D. Nav offset  —  one mechanism for every page family
   css/mobile.css:40 hardcodes `.nav{top:58px !important}` to clear the promo
   bar. That is wrong three ways:
     1. The app pages set <nav style="top:0"> with no promo bar; an inline
        style loses to !important, giving a 58px dead band with the nav
        floating over content.
     2. index.html:2491 hidePromo() also sets nav.style.top='0', so every
        promo-bar page hits the same bug the moment a visitor closes the bar.
     3. At 375px, mobile.css:34-36 wraps the promo bar to ~75px, so even when
        the bar IS open the nav overlaps it.
   Replaced by a measured variable owned by whatever is actually up there.
   ───────────────────────────────────────────────────────────────────────── */
@media screen and (max-width: 1023px) {
  body .nav {
    top: var(--rc-promo-h, 0px) !important;
    /* .nav carries `transition:all .3s` in css/index.css, which would
       visibly slide the bar when JS refines the measurement. */
    transition: background .3s ease, box-shadow .3s ease, padding .3s ease !important;
  }

  /* Both of these hardcoded the old promo+nav geometry. */
  body .hero      { padding-top: calc(72px + var(--rc-promo-h, 0px)) !important; }
  body .page-wrap { padding-top: calc(88px + var(--rc-promo-h, 0px)) !important; }
}

/* The hamburger is active to 1150px in css/index.css, css/global.css and
   css/quote.css, but 7,551 generated pages only hide .nav-links at ≤600px,
   leaving a squeezed desktop nav at 601-768px. Normalize the whole range. */
@media screen and (max-width: 1023px) {
  body .nav-links    { display: none !important; }
  body .mobile-toggle { display: flex !important; }
}


/* ─────────────────────────────────────────────────────────────────────────
   D2. iOS input zoom, site-wide
   Safari auto-zooms on focus for any field under 16px and never zooms back,
   leaving the rest of the page off-centre and horizontally scrolled.

   css/rc-app.css fixes this, but only for the six pages carrying .rc-app. The
   same problem exists everywhere else, on the highest-value forms the site has:
     - the chat lead-capture form and message box, injected on EVERY page by
       js/rv-chat.js (its .chat-input-row textarea is 14px at js/rv-chat.js:54)
     - the job application form on careers.html (14px)
     - contact and newsletter fields
   !important is required: `.chat-input-row textarea` is specificity (0,1,1),
   which outranks `body textarea` at (0,0,2).

   Excludes controls where a font-size has no text-entry meaning and where
   forcing 16px would only distort the control's box.
   ───────────────────────────────────────────────────────────────────────── */
@media screen and (max-width: 1023px) {
  body input:not([type='checkbox']):not([type='radio']):not([type='range']):not([type='color']):not([type='hidden']),
  body select,
  body textarea {
    font-size: 16px !important;
  }

  /* The chat panel is the one form that appears on all ~16,400 pages, so its
     targets are worth bringing up to size here rather than per-page. */
  body .chat-panel input,
  body .chat-panel textarea,
  body .chat-panel button {
    min-height: 44px !important;
  }
  body .chat-panel .chat-attach-btn,
  body .chat-panel .chat-send-btn {
    min-width: 44px !important;
  }
}


/* ─────────────────────────────────────────────────────────────────────────
   E. Bottom-of-screen collision
   At ≤1023px the bottom strip would otherwise hold the tab bar plus the chat
   FAB, the email FAB, the chat teaser and (on index.html) a sticky CTA.
   ───────────────────────────────────────────────────────────────────────── */
@media screen and (max-width: 1023px) {
  /* The Chat tab replaces the FAB. The element stays in the DOM because
     rc-shell.js drives it with #chatFab.click(), which works while hidden. */
  body .chat-fab       { display: none !important; }
  body .email-fab-wrap { display: none !important; }
  /* The Quote tab is a permanent CTA. Affects index.html only. */
  body #rvStickyCta    { display: none !important; }

  /* Anything else the site pins to the bottom of the viewport has to be
     accounted for, or it fights the tab bar. Two real cases:

     1. .geo-banner / #geoBanner (index.html:2628) is z-index 999 against the
        tab bar's 995, sits at bottom:12px and is ~97px tall at 390px. It
        covered all five tabs outright and left a 2px sliver, so every tab was
        dead while it showed. Lift it above the bar instead of hiding it, since
        it is a real routing prompt.
     2. .sticky-cta-bar (materials/*.html, rapid-prototyping-3d-printing.html,
        on-demand-cnc-machining.html — 12 conversion pages) is z-index 90 at
        bottom:0, so it was buried COMPLETELY beneath the tab bar with only its
        4px top border showing. */
  body .geo-banner,
  body #geoBanner {
    bottom: calc(12px + var(--rc-tabbar-h, 64px)) !important;
    z-index: 993 !important;
  }
  body .sticky-cta-bar,
  body #stickyCta {
    bottom: var(--rc-tabbar-h, 64px) !important;
    z-index: 993 !important;
  }

  body .rv-teaser {
    bottom: calc(12px + var(--rc-tabbar-h, 64px)) !important;
    right: 12px !important;
    left: auto !important;
  }

  /* iOS Safari's collapsing URL bar overflows 100vh.
     `bottom` MUST be pinned here too. Every chat variant only moves to
     bottom:0 inside its own max-width:768px block (js/rv-chat.js:60; the
     generated pages at :543), but this rule forces 100dvh across the whole
     ≤1023px tier. At 769-1023px the panel kept bottom:92px (rv-chat) or
     bottom:156px (generated pages), so a 100dvh box resolved its TOP to
     -92/-156px and pushed the panel header — and its only close button —
     off the top of the screen, with the chat FAB hidden as the sole exit. */
  body .chat-panel {
    bottom: 0 !important;
    right: 0 !important;
    left: 0 !important;
    width: 100% !important;
    max-width: 100% !important;
    border-radius: 0 !important;
    height: 100vh !important;
    height: 100dvh !important;
    max-height: 100vh !important;
    max-height: 100dvh !important;
  }

  /* Clear the bar so the footer is never covered. */
  body { padding-bottom: var(--rc-tabbar-h, 64px) !important; }
  html { scroll-padding-bottom: var(--rc-tabbar-h, 64px); }
}


/* ─────────────────────────────────────────────────────────────────────────
   F. Phone tier — shared geometry (≤1023px)
   Mirrors the GEOMETRY of css/mobile.css so the 4,172 pages that never load
   it still lay out correctly, and extends the same treatment up to 1023px so
   the previously unhandled 769-1023px window is covered.

   Deliberately carries NONE of mobile.css's content-hiding rules
   (`:nth-child(n+4){display:none}` and friends). Those stay exactly where
   they are, on exactly the pages that already have them: nothing existing is
   removed, and no content is newly hidden on the 4,172 SEO pages that would
   otherwise start hiding .eco-section, .certs-strip, .trust-grid and .wm-grid
   under mobile-first indexing.
   ───────────────────────────────────────────────────────────────────────── */
@media screen and (max-width: 1023px) {
  body .container      { max-width: 100% !important; padding-left: 20px !important; padding-right: 20px !important; }
  body .section        { padding: 56px 0 !important; }
  body .section-title  { font-size: 28px !important; margin-bottom: 12px !important; }
  body .section-label  { font-size: 11px !important; margin-bottom: 8px !important; letter-spacing: 1.5px !important; }

  body .hero           { min-height: auto !important; padding-bottom: 40px !important; }
  body .hero h1        { font-size: 34px !important; letter-spacing: -1px !important; }
  body .hero-text      { font-size: 16px !important; }
  /* css/index.css only hides these at ≤900px, so 901-1023 still shows them. */
  body .hero-img-left,
  body .hero-img-right { display: none !important; }

  body .proof-split    { grid-template-columns: 1fr !important; gap: 24px !important; }
  body .proof-specs    { grid-template-columns: 1fr !important; }
  body .footer         { padding: 48px 0 24px !important; }

  /* Buttons and other tap targets. */
  body .btn            { min-height: 44px !important; display: inline-flex !important;
                         align-items: center !important; justify-content: center !important; }

  /* Legacy mega-menu panels carry min-width:480px / 680px in css/index.css. */
  body #servicesDropdown,
  body #industriesDropdown { max-width: calc(100vw - 32px) !important; min-width: 0 !important; }
}

/* Phone portrait: 1-up card grids. Matches css/mobile.css for the pages that
   have it and supplies the same geometry to the 4,172 pages that do not.

   Bounded at 600px, not 768px. Real phones in portrait are 320-430px wide, so
   they all land here. Above 600px you are on a small tablet or a phone in
   landscape, where a 1-up grid produces ~713px-wide cards — measured at 768px,
   which is iPad portrait and one of the most common tablet viewports there is. */
@media screen and (max-width: 600px) {
  body .parts-grid,
  body .why-grid,
  body .reviews-grid,
  body .pillars-grid,
  body .wm-grid,
  body .showcase-grid,
  body .trust-grid,
  body .cs-section-grid,
  body .process-steps,
  body .faq-grid,
  body .footer-grid      { grid-template-columns: 1fr !important; gap: 12px !important; }

  body .stats-grid,
  body .industries-grid,
  body .subindustry-grid,
  body .eco-companies-grid { grid-template-columns: repeat(2, 1fr) !important; gap: 12px !important; }

  body .section          { padding: 48px 0 !important; }
  body .section-title    { font-size: 24px !important; }
  body .hero h1          { font-size: 28px !important; }
  body .hero-text        { font-size: 15px !important; }
  body .hero-buttons,
  body .cta-buttons      { flex-direction: column !important; align-items: stretch !important; }
  body .footer-grid      { gap: 24px !important; }
}

/* Small tablet, phone landscape and tablet portrait: 2-up card grids.
   The PAGE is single-column here (hero stacks, sidebars stack, no side-by-side
   splits) but the CARD GRIDS are not — a 1-up grid at these widths produces
   700-950px cards, which reads as broken rather than as mobile. */
@media screen and (min-width: 601px) and (max-width: 1023px) {
  body .parts-grid,
  body .why-grid,
  body .reviews-grid,
  body .pillars-grid,
  body .wm-grid,
  body .showcase-grid,
  body .trust-grid,
  body .cs-section-grid,
  body .process-steps,
  body .aeo-steps,
  body .faq-grid,
  body .industries-grid,
  body .subindustry-grid { grid-template-columns: repeat(2, 1fr) !important; gap: 16px !important; }

  body .stats-grid       { grid-template-columns: repeat(4, 1fr) !important; gap: 24px !important; }
  body .footer-grid      { grid-template-columns: repeat(2, 1fr) !important; gap: 28px !important; }
  body .content-grid,
  body .checkout-grid    { grid-template-columns: 1fr !important; }
}

@media screen and (max-width: 400px) {
  body .hero h1       { font-size: 24px !important; }
  body .hero-text     { font-size: 14px !important; }
  body .section-title { font-size: 20px !important; }
  body .stats-grid    { gap: 12px !important; }
  body .industries-grid { grid-template-columns: 1fr !important; }
}


/* ─────────────────────────────────────────────────────────────────────────
   G. Compact desktop (1024-1279px)
   Two-column layouts preserved — 1024px is exactly iPad Pro portrait and
   deserves them. The inline nav comes back, condensed.
   ───────────────────────────────────────────────────────────────────────── */
/* ─────────────────────────────────────────────────────────────────────────
   G0. Desktop safety net for the synthesized drawer
   js/rc-shell.js synthesizes a drawer at ALL widths so a desktop->mobile
   resize works without re-running. Two consequences had to be neutralised
   above 1023px:

   1. texas/houston/index.html is the ONE page of 16,422 with a .nav .nav-inner
      but no .mobile-toggle and no .mobile-menu, so the script APPENDS a
      hamburger there. No stylesheet on that page hides .mobile-toggle at
      >=1280 (css/mobile.css:42 only shows it inside max-width:768px), so a
      browser-default button rendered in the desktop nav and opened a 300px
      drawer. Every other page already hides its own toggle above 1150px, so
      this rule is a no-op for them.
   2. The synthesized drawer parks off-screen at translateX(100%), which hides
      it visually but leaves its ~24 links in the tab order — adding 24
      invisible focus stops after the footer on 7,641 pages. visibility:hidden
      removes them from sequential focus without affecting the slide-in, which
      only ever happens below 1024px.
   ───────────────────────────────────────────────────────────────────────── */
@media screen and (min-width: 1024px) {
  body .mobile-toggle { display: none !important; }
  body .mobile-menu:not(.open) { visibility: hidden !important; }
}


@media screen and (min-width: 1024px) and (max-width: 1279px) {
  body .container      { max-width: 100% !important; padding-left: 20px !important; padding-right: 20px !important; }
  body .section        { padding: 72px 0 !important; }

  /* Undo the ≤1150px hamburger switch in index.css / global.css / quote.css. */
  body .nav-links      { display: flex !important; gap: 10px !important; }
  body .nav-links a    { font-size: 13px !important; }
  body .nav-cta        { padding: 7px 14px !important; font-size: 12px !important; }
  body .mobile-toggle  { display: none !important; }

  /* #industriesDropdown is min-width:680px, which overflows once the nav
     is centred at 1024px. */
  body #servicesDropdown   { min-width: 0 !important; width: min(480px, calc(100vw - 40px)) !important; }
  body #industriesDropdown { min-width: 0 !important; width: min(600px, calc(100vw - 40px)) !important; }

  body .parts-grid,
  body .pillars-grid,
  body .industries-grid,
  body .process-steps  { gap: 16px !important; }
  body .footer-grid    { grid-template-columns: 2fr 1fr 1fr 1fr !important; gap: 32px !important; }
}
