/* ============================================================
   SITE HEADER — the one header.

   Source of truth: _local/partials/site-header.html (markup) + this file
   (style). Both are written into every page by _local/build/sync_header.py.
   Do not hand-edit the nav or the menu panel inside a page; the next sync
   overwrites it. Change it here, run the script, commit the result.

   TWO GROUNDS, ONE HEADER.
   The bar is transparent by default and assumes a DARK section beneath it,
   so its ink is cream. `body.nav-on-light` is the other half: a frosted
   cream bar with olive ink, for whenever a light section is under the strip.

   Pages that are light the whole way down ship `class="nav-on-light"` on
   <body> and never change it. Pages with a dark hero ship `nav-on-dark`
   and let their own observer toggle `nav-on-light` on scroll.

   THE WORDMARK. Both files are the same lockup — solid letters plus an
   offset shadow in the opposite colour — so each one only reads on the
   ground it was drawn for, and on the other it hollows out into an
   outline. That hollow mark was showing on the blog, on every case study,
   and on eight other pages before this file existed.

     wordmark-olive.svg  olive letters, cream shadow  -> LIGHT ground
     wordmark-cream.svg  cream letters, olive shadow  -> DARK ground

   Class names follow the ink, not the ground: .wm-olive is the olive-ink
   mark and shows under nav-on-light. assets/js/theme.js swaps both by
   filename for the denim and rust schemes, so the src attributes in the
   partial are load-bearing — keep them in step with the map in that file.
   ============================================================ */

nav.site {
  position: fixed; top: 0; left: 0; right: 0; z-index: 50;
  background: transparent;
  backdrop-filter: none;
  padding: 18px var(--pad-x, clamp(16px, 3vw, 36px));
  display: flex; align-items: center; justify-content: space-between;
  gap: 20px;
  border-bottom: 0;
}

/* Over a light section, fade in a backdrop so the olive ink has something
   to sit on and the section under it still reads through. */
body.nav-on-light nav.site {
  background: color-mix(in oklab, var(--cream) 75%, transparent);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-bottom: 1px solid color-mix(in oklab, var(--olive) 14%, transparent);
}
body.nav-on-light .brand-lock,
body.nav-on-light .nav-cta,
body.nav-on-light .menu-btn { color: var(--olive); }
body.nav-on-light .nav-cta  { border-color: var(--olive); }
body.nav-on-light .menu-btn { border-color: var(--olive); }
body.nav-on-light .nav-cta:hover  { background: var(--olive); color: var(--cream); }
body.nav-on-light .menu-btn:hover { background: var(--olive); color: var(--cream); }
/* The selected theme dot wears a cream ring, which is invisible on the
   cream bar. Same swap as everything else in here. */
body.nav-on-light .theme-dot[aria-pressed="true"],
body.nav-on-light .theme-dot:focus-visible { outline-color: var(--olive); }

/* ── Brand lock ─────────────────────────────────────────────────────── */
.brand-lock {
  display: inline-flex; align-items: center;
  height: 24px; line-height: 0;
  position: relative;
}
.brand-lock img {
  height: 22px; width: auto; display: block;
  transition: opacity .2s ease;
}
/* The dark-ground mark is the one taken out of flow, so the lock keeps a
   single stable width and the swap costs no layout. */
.brand-lock .wm-cream { position: absolute; top: 50%; left: 0; transform: translateY(-50%); opacity: 1; }
.brand-lock .wm-olive { opacity: 0; }
body.nav-on-light .brand-lock .wm-olive { opacity: 1; }
body.nav-on-light .brand-lock .wm-cream { opacity: 0; }

/* ── Right-hand cluster ─────────────────────────────────────────────── */
.nav-right { display: flex; align-items: center; gap: 10px; }
.nav-cta {
  display: inline-flex; align-items: center;
  padding: 12px 22px; border-radius: 999px;
  color: var(--cream);
  border: 1px solid var(--cream);
  font-family: var(--ff-mono, ui-monospace, Menlo, monospace); font-size: 11px;
  letter-spacing: 0.14em; text-transform: uppercase;
  text-decoration: none;
  transition: background .2s, color .2s;
  white-space: nowrap;
}
.nav-cta:hover { background: var(--cream); color: var(--olive); }
.menu-btn {
  width: 44px; height: 44px; border-radius: 50%;
  border: 1px solid var(--cream); color: var(--cream);
  background: transparent; cursor: pointer; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  transition: all .2s;
}
.menu-btn:hover { background: var(--cream); color: var(--olive); }

/* ── Menu panel ─────────────────────────────────────────────────────────
   Full-screen overlay at z 40, under the nav's 50, so the wordmark and the
   close button stay on top of it. Three columns, mascot above, contact
   pinned bottom-right. */
.menu-panel {
  position: fixed; inset: 0; z-index: 40;
  background: var(--olive); color: var(--cream);
  opacity: 0; visibility: hidden;
  transition: opacity .3s ease, visibility .3s ease;
  overflow-y: auto; overscroll-behavior: contain;
  scrollbar-width: none; -ms-overflow-style: none;
}
.menu-panel::-webkit-scrollbar { width: 0; height: 0; display: none; }
.menu-panel.open { opacity: 1; visibility: visible; }

.menu-inner {
  min-height: 100%;
  display: grid;
  grid-template-rows: auto 1fr auto;
  gap: clamp(28px, 5vh, 56px);
  padding: clamp(92px, 12vh, 132px) var(--pad-x, clamp(16px, 3vw, 36px)) clamp(28px, 5vh, 48px);
  box-sizing: border-box;
}

/* Mascot. The reveal lives on the wrapper so it doesn't fight the float. */
.menu-dog-wrap {
  width: clamp(104px, 12vw, 160px);
  opacity: 0; transform: translateY(14px);
}
.menu-panel.open .menu-dog-wrap {
  opacity: 1; transform: translateY(0);
  transition: opacity .55s ease .05s, transform .55s ease .05s;
}
.menu-dog {
  width: 100%; height: auto; display: block;
  aspect-ratio: 3 / 4; object-fit: contain;
  pointer-events: none; -webkit-user-select: none; user-select: none;
  animation: menuDogFloat 5.5s ease-in-out infinite;
}
@keyframes menuDogFloat {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-8px); }
}
@media (prefers-reduced-motion: reduce) { .menu-dog { animation: none; } }

.menu-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(24px, 4vw, 72px);
  align-content: start;
  opacity: 0; transform: translateY(16px);
}
.menu-panel.open .menu-grid {
  opacity: 1; transform: translateY(0);
  transition: opacity .55s ease .12s, transform .55s ease .12s;
}
.menu-panel .menu-section + .menu-section { margin: 0; padding: 0; border: 0; }
.menu-panel .menu-eyebrow {
  font-family: var(--ff-mono, ui-monospace, Menlo, monospace); font-size: 11px;
  letter-spacing: 0.2em; text-transform: uppercase;
  opacity: 0.5; margin: 0 0 14px;
}
.menu-grid a {
  display: flex; align-items: baseline; gap: 10px;
  padding: 5px 0; text-decoration: none;
  color: var(--cream);
  font-family: var(--ff-display, 'Fraunces', 'Fraunces Fallback', ui-serif, Georgia, serif); font-weight: 400;
  font-size: clamp(22px, 2.4vw, 32px); line-height: 1.18;
  transition: color .18s ease, opacity .18s ease, transform .18s ease;
}
.menu-grid a:hover { opacity: 0.62; transform: translateX(4px); }
.menu-grid a .menu-meta {
  font-family: var(--ff-mono, ui-monospace, Menlo, monospace); font-size: 10px; font-weight: 400;
  letter-spacing: 0.12em; text-transform: uppercase;
  opacity: 0.5; white-space: nowrap;
}
/* The page you are already on: still listed, so the crate reads the same
   everywhere, but dimmed and inert rather than quietly missing. */
.menu-grid a[aria-current="page"] { opacity: 0.42; pointer-events: none; }

.menu-contact {
  justify-self: end; text-align: right;
  font-family: var(--ff-mono, ui-monospace, Menlo, monospace); font-size: 12px;
  letter-spacing: 0.1em; text-transform: uppercase;
  line-height: 1.9;
  opacity: 0; transform: translateY(10px);
}
.menu-panel.open .menu-contact {
  opacity: 0.85; transform: translateY(0);
  transition: opacity .55s ease .2s, transform .55s ease .2s;
}
.menu-contact a { color: var(--cream); text-decoration: none; }
.menu-contact a:hover { opacity: 0.7; }

/* ── Open state ─────────────────────────────────────────────────────────
   The overlay is olive whatever the page under it was, so the bar goes
   back to its cream-ink state here even on a page that is permanently
   nav-on-light. These come after the nav-on-light block on purpose: the
   two carry equal specificity and this one has to win. */
.menu-btn .icon-close { display: none; }
body.menu-open .menu-btn { background: var(--cream); color: var(--olive); border-color: var(--cream); }
body.menu-open .menu-btn .icon-open  { display: none; }
body.menu-open .menu-btn .icon-close { display: block; }
body.menu-open nav.site { background: transparent; backdrop-filter: none; -webkit-backdrop-filter: none; border-bottom: 0; }
body.menu-open .brand-lock .wm-olive { opacity: 0; }
body.menu-open .brand-lock .wm-cream { opacity: 1; }
body.menu-open .brand-lock,
body.menu-open .nav-cta { color: var(--cream); }
body.menu-open .nav-cta { border-color: var(--cream); }
body.menu-open .theme-dot[aria-pressed="true"],
body.menu-open .theme-dot:focus-visible { outline-color: var(--cream); }

/* ── Responsive ─────────────────────────────────────────────────────── */
@media (max-width: 900px) {
  /* Tighten the bar so wordmark + CTA + menu still fit on one line. */
  nav.site { padding: 14px var(--pad-x, clamp(16px, 3vw, 36px)); gap: 12px; }
  .nav-right { gap: 8px; }
  .nav-cta { padding: 10px 16px; font-size: 10.5px; letter-spacing: 0.12em; }
  .menu-btn { width: 40px; height: 40px; }
  .brand-lock { height: 20px; }
  .brand-lock img { height: 18px; }
}
@media (max-width: 760px) {
  .menu-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 28px 24px; }
  .menu-contact { justify-self: start; text-align: left; }
}
@media (max-width: 460px) {
  .menu-grid { grid-template-columns: 1fr; }
  .menu-grid a { font-size: 20px; }
}

/* ── Skip link ──────────────────────────────────────────────────────── */
.rw-skip {
  position: absolute; left: -9999px; top: 0; z-index: 9999;
  background: var(--olive, #3F4528); color: var(--cream, #E8E2CE);
  padding: 12px 20px; border-radius: 0 0 6px 0;
  font: 600 14px/1 Inter, system-ui, sans-serif; text-decoration: none;
}
.rw-skip:focus { left: 0; }

/* ── Footer ─────────────────────────────────────────────────────────────
   Three columns so the industry and case-study pages have a consistent
   route in from every page on the site. Style lives here with the header's
   because sync_header.py owns both partials. */
/* The footer's own ground. This lived in every page's inline CSS, which
   meant a page generated later — the five service pages — got a footer with
   no background at all: the two-tone emblem vanished into the cream and left
   a 400px hole above the copyright line. The partial owns its own colours
   now, the way the header does. */
footer.site{
  background: var(--olive); color: var(--cream);
  padding: 60px var(--pad-x, clamp(16px, 3vw, 36px)) 30px;
  text-align: center;
}

footer.site .footer-cols{
  display: grid; gap: clamp(28px, 4vw, 64px);
  grid-template-columns: repeat(3, minmax(0, 1fr)) 1.6fr;
  max-width: var(--maxw); margin: 0 auto;
  padding: 0 0 clamp(24px, 3.4vh, 40px);
  text-align: left;
}
footer.site .footer-col{ display: block; min-width: 0; }
/* The links live in their own box. A <details> puts its non-summary children
   into a UA slot, so flexing the <details> itself makes that whole slot ONE
   flex item and every link runs together on a line. */
footer.site .footer-links{ display: flex; flex-direction: column; gap: 9px; }
footer.site .footer-eyebrow{
  font-family: var(--ff-mono, ui-monospace, Menlo, monospace); font-size: 10.5px;
  letter-spacing: 0.2em; text-transform: uppercase;
  opacity: 0.5; margin: 0 0 6px; list-style: none;
}
footer.site .footer-eyebrow::-webkit-details-marker{ display: none; }
/* Open and inert on a wide screen: the disclosure exists for phones only, so
   nothing here should look or behave like a control. */
footer.site details.footer-col > summary{ cursor: default; pointer-events: none; }
footer.site .footer-col a{
  font-family: var(--ff-body, ui-sans-serif, system-ui, sans-serif);
  font-size: 14.5px; line-height: 1.45; text-decoration: none;
  color: inherit; opacity: 0.86; transition: opacity .15s ease;
  width: fit-content;
}
footer.site .footer-col a:hover, footer.site .footer-col a:focus-visible{ opacity: 1; text-decoration: underline; }
footer.site .footer-col--wide .footer-links{
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 9px clamp(16px, 2vw, 32px); align-content: start;
}
footer.site .footer-copy a{ color: inherit; text-decoration: none; }
footer.site .footer-copy a:hover{ text-decoration: underline; }

@media (max-width: 900px){
  footer.site .footer-cols{ grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 26px 24px; }
  footer.site .footer-col--wide{ grid-column: 1 / -1; }
}

/* ── The footer on a phone ──────────────────────────────────────────────
   Twenty-seven links stacked made this 1,178px tall against an 844px
   viewport — 1.4 screens of footer under every page. Below 760px each
   group becomes a real disclosure: one tappable row each, closed, with the
   links still in the HTML for anything that reads the markup. */
@media (max-width: 760px){
  footer.site .footer-cols{
    display: block; padding-bottom: 20px;
    border-top: 1px solid color-mix(in oklab, var(--cream) 22%, transparent);
  }
  footer.site .footer-col{
    display: block;
    border-bottom: 1px solid color-mix(in oklab, var(--cream) 18%, transparent);
  }
  footer.site details.footer-col > summary{
    pointer-events: auto; cursor: pointer;
    display: flex; align-items: center; justify-content: space-between;
    padding: 15px 2px; margin: 0; opacity: .8;
    font-size: 11.5px; letter-spacing: .16em;
  }
  footer.site details.footer-col > summary::after{
    content: ''; width: 8px; height: 8px; flex: none; margin-left: 12px;
    border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
    transform: rotate(45deg) translate(-2px, -2px);
    transition: transform .18s ease;
  }
  footer.site details.footer-col[open] > summary::after{
    transform: rotate(-135deg) translate(-3px, -3px);
  }
  footer.site .footer-col a{ padding: 7px 2px; font-size: 15px; opacity: .78; }
  footer.site .footer-col--wide .footer-links{ grid-template-columns: none; }
  footer.site details.footer-col[open]{ padding-bottom: 10px; }
  footer.site .footer-emblem{ width: clamp(180px, 46vw, 240px); }
  footer.site .footer-lock{ padding: 6px 0 2px; }
}
@media (prefers-reduced-motion: reduce){
  footer.site details.footer-col > summary::after{ transition: none; }
}

/* ── Narrow phones ──────────────────────────────────────────────────────
   The brand lock keeps TWO wordmarks now, one in flow and one absolute, and
   the in-flow one is the 394x41 file — wider at a given height than the
   single 237x24 image most pages used to carry. At 390px that pushed the
   whole bar to 457px and the menu button off the right edge, where it could
   not be tapped. Measured, not guessed: 173px lock + 222px right cluster +
   12px gap + 32px padding = 439 on a 390px screen.

   So below 430px the lock and the CTA both give ground. Nothing is hidden —
   the theme switcher and Reach Out are still reachable, just tighter. */
@media (max-width: 430px) {
  nav.site { gap: 8px; padding-inline: 14px; }
  .brand-lock { height: 16px; min-width: 0; flex: 0 1 auto; }
  .brand-lock img { height: 15px; }
  .nav-right { gap: 6px; flex: 0 0 auto; }
  .theme-switch { gap: 6px; }
  .theme-dot { width: 13px; height: 13px; }
  .nav-cta { padding: 9px 12px; font-size: 9.5px; letter-spacing: 0.08em; }
  .menu-btn { width: 36px; height: 36px; }
}

/* The emblem is a 457x247 SVG. Pages that already had a footer carried their
   own rule for it; the ones that did not inherited nothing and rendered it at
   its natural width, which overflowed the document on every phone. It lives
   here now, with the rest of the footer. */
footer.site .footer-lock{ display: flex; justify-content: center; }
footer.site .footer-emblem{
  /* The established size is clamp(420px, 56vw, 720px). That lower bound is
     wider than a phone, which is what pushed the document to 457px. Same
     look everywhere it mattered — 56vw and the 720px cap are unchanged — with
     a floor that fits a 320px screen. */
  width: clamp(280px, 56vw, 720px); max-width: 100%; height: auto;
  display: block;
}

/* ── Menu: service pages read as children ───────────────────────────────
   Five service pages listed flat next to Services looked like five more
   peers. Indented under All Services, with a rule down the left, they read
   as what they are. Industries is no longer in this panel at all — ten more
   rows made it a wall, and those pages have a homepage section and a footer
   column now. */
.menu-sub{
  display: flex; flex-direction: column;
  margin: 6px 0 0 2px; padding-left: 16px;
  border-left: 1px solid color-mix(in oklab, var(--cream) 26%, transparent);
}
.menu-grid .menu-sub a{
  font-size: clamp(16px, 1.35vw, 20px);
  opacity: .78; padding: 3px 0;
}
.menu-grid .menu-sub a:hover,
.menu-grid .menu-sub a:focus-visible{ opacity: 1; }
@media (max-width: 760px){
  .menu-sub{ padding-left: 13px; }
  .menu-grid .menu-sub a{ font-size: 15.5px; }
}
