/* ==========================================================================
   MBSG — mobile navigation (hamburger + full-screen overlay)

   LINK ORDER MATTERS. This file is linked on every page AFTER that page's
   inline <style>, not before it like a11y.css. Every page declares its own
   mobile nav rules — `@media (max-width: 760px) { .nav { flex-wrap: wrap;
   justify-content: center } .nav-links { width: 100% } }` — and this file has
   to beat them. Same specificity, later source order, no !important anywhere.
   Moving this <link> above the <style> block silently reverts the whole
   feature: the link row comes back and sits under the hamburger.

   Everything that moves a pixel lives inside a max-width media query. Above
   768px this file contributes exactly two `display: none` declarations, both
   on elements that did not exist before, so the desktop nav is the same
   layout it has always been.

   Colours come from each page's own :root tokens so the menu inherits any
   future palette change. Fallbacks are spelled out anyway — a missing token
   would otherwise fail silently to an invalid value and paint the overlay
   transparent, which reads as "the menu is broken" rather than "off-brand".
   ========================================================================== */

/* ── DESKTOP BASELINE ─────────────────────────────────────────────────────
   Both new elements are display:none by default at every width, and only the
   mobile block below turns them on. Stated outside any media query so that a
   page which somehow loads this file without the media queries applying still
   shows its normal desktop nav rather than a stray button. */
.nav-hamburger,
.nav-overlay { display: none; }

/* ── SCROLL LOCK ──────────────────────────────────────────────────────────
   On <html> as well as <body>. <html> is the scrolling element on these
   pages, so overflow:hidden on <body> alone leaves the page scrolling behind
   the overlay.

   Deliberately NOT `position: fixed` on <body>, the other common lock. That
   technique zeroes the scroll offset, and about-2.html drives its entire act
   system off scroll position through an IntersectionObserver — dropping to
   scrollTop 0 would rewind that page to act 0 every time the menu closed.
   overflow:hidden preserves the offset, so the observer resumes exactly where
   it left off.

   Left outside the media query on purpose: the class is only ever applied
   below 768px (JS closes the menu above that), and scoping the lock too would
   make "is the page locked?" depend on two conditions instead of one. */
html.nav-open,
body.nav-open { overflow: hidden; }

/* Locking removes the classic scrollbar, which WIDENS the layout viewport and
   reflows the entire page behind the overlay — measured on about-2.html at
   375px: clientWidth 360 -> 375, document height 3679 -> 3652. The overlay
   hides the settled result, but it fades in over 180ms and the sideways jump
   is visible through it for those frames.

   Re-reserve exactly the width the scrollbar gave up. --nav-sbw is measured
   and set by js/nav-mobile.js immediately before the lock goes on; phones use
   zero-width overlay scrollbars, so there it resolves to 0px and this rule
   does nothing. Padding on <html> does not move .nav or .nav-overlay — both
   are position:fixed, so their containing block is the viewport, not this
   padding box. */
html.nav-open { padding-right: var(--nav-sbw, 0px); }

/* ── OVERLAY ENTRANCE ─────────────────────────────────────────────────────
   An animation, not a transition. The overlay goes from display:none to
   display:flex, and transitions do not run on an element that was just
   displayed — a fade built with `transition` would land instantly and the
   reduced-motion guard below would be decorative. Keyframes do run, so the
   guard is real: without `prefers-reduced-motion: no-preference` there is no
   animation property at all and the menu simply appears.

   TRANSFORM ONLY — no opacity anywhere in these keyframes, deliberately.
   Nothing about whether the menu can be SEEN may depend on an animation
   making progress. An earlier version faded the overlay in from opacity 0
   and was invisible in any environment that holds animations at their first
   frame: display:flex, hit-testable, painting nothing. If this animation is
   frozen, throttled, or unsupported, the worst case now is a menu sitting
   10px high — still fully opaque and completely usable.

   Exit is intentionally instant in both modes. An exit animation needs the
   element kept alive past the click, which means a JS timer racing every
   navigation the menu can trigger. Not worth it for 200ms of polish. */
@keyframes navOverlayPanelIn {
  from { transform: translateY(-10px); }
  to   { transform: translateY(0); }
}

/* ==========================================================================
   MOBILE — <=768px
   ========================================================================== */
@media (max-width: 768px) {

  /* ── The header row becomes logo + hamburger ────────────────────────────
     `justify-content` and `flex-wrap` undo the pages' own <=760px rules,
     which centred a wrapping three-row bar. With the link row gone there is
     nothing left to wrap, and the logo belongs hard left. */
  .nav {
    flex-wrap: nowrap;
    justify-content: space-between;
    gap: 12px;
  }

  /* The whole reason this file exists. Five links plus ./contact, each held
     to 44x44 by a11y.css, cannot fit one row on a phone — they wrapped to
     three rows and still overflowed at 320px. */
  .nav-links { display: none; }

  /* Keeps the logo lockup from being squeezed by the button (AC2: the logo is
     visible in every state, and it is the only thing identifying the site). */
  .nav-logo { flex: 0 0 auto; }

  /* ── HAMBURGER ─────────────────────────────────────────────────────────── */
  .nav-hamburger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 44px;
    height: 44px;
    padding: 0;
    background: none;
    border: 1px solid var(--hairline, rgba(77,163,255,0.14));
    border-radius: 8px;
    color: var(--text, #EAF2FF);
    cursor: pointer;
    /* arcade.html sets `.nav { pointer-events: none }` and re-enables only
       `.nav a` so the game canvas stays clickable through the bar. A <button>
       is not an <a>, so without this the arcade hamburger would render
       perfectly and ignore every tap. */
    pointer-events: auto;
    -webkit-tap-highlight-color: transparent;
  }

  /* Three CSS-drawn bars: the span is the middle one, its two pseudo-elements
     are the outer pair. No image, no icon font, no extra markup. */
  .nav-hamburger-icon,
  .nav-hamburger-icon::before,
  .nav-hamburger-icon::after {
    display: block;
    width: 20px;
    height: 2px;
    border-radius: 2px;
    background: currentColor;
  }

  .nav-hamburger-icon {
    position: relative;
  }

  .nav-hamburger-icon::before,
  .nav-hamburger-icon::after {
    content: '';
    position: absolute;
    left: 0;
  }

  .nav-hamburger-icon::before { top: -6px; }
  .nav-hamburger-icon::after  { top: 6px; }

  .nav-hamburger:hover {
    border-color: var(--orange, #F08A24);
    color: var(--orange, #F08A24);
  }

  /* ── OVERLAY ───────────────────────────────────────────────────────────
     Driven entirely by body.nav-open — (0,2,0) beats the (0,1,0) display:none
     at the top of this file, so no !important and no inline style from JS. */
  body.nav-open .nav-overlay {
    display: flex;
    flex-direction: column;
    position: fixed;
    inset: 0;
    /* Above the MB-01 robot (40), the nav itself (60) and the sound toggle
       (80). Deliberately BELOW the cookie notice (9000), the skip link (9500)
       and the takeover/chat overlays (99999/100000): a consent banner that a
       nav menu could bury would be a compliance problem, and the two big
       overlays trap focus themselves. */
    z-index: 8000;
    /* Same ground and same 44px grid as <body> at this breakpoint, so the
       menu reads as the page's own surface rather than a panel dropped on it.
       background-color is separate from background-image on purpose — the
       grid lines are drawn ON the page background, not instead of it. */
    background-color: var(--bg, #070B14);
    background-image:
      linear-gradient(var(--grid, rgba(77,163,255,0.045)) 1px, transparent 1px),
      linear-gradient(90deg, var(--grid, rgba(77,163,255,0.045)) 1px, transparent 1px);
    background-size: 44px 44px;
    /* Landscape phones are ~375px tall. Six rows plus the header can exceed
       that, so the menu scrolls itself rather than clipping its last item —
       the page behind it is locked, so this is the only scroller left. */
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    padding-bottom: 32px;
  }

  /* Header row of the open menu. Repeats the logo at the same size and
     position the real nav uses, so opening the menu does not make the brand
     mark disappear or jump. */
  .nav-overlay-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex: 0 0 auto;
    padding: 9px 14px;
    border-bottom: 1px solid var(--hairline, rgba(77,163,255,0.14));
  }

  .nav-overlay-logo {
    height: 46px;
    width: auto;
    display: block;
    filter: drop-shadow(0 1px 2px rgba(0,0,0,0.85));
  }

  .nav-overlay-close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 44px;
    height: 44px;
    padding: 0;
    font-family: var(--mono, 'IBM Plex Mono', monospace);
    font-size: 20px;
    line-height: 1;
    background: none;
    border: 1px solid var(--hairline, rgba(77,163,255,0.14));
    border-radius: 8px;
    color: var(--text, #EAF2FF);
    cursor: pointer;
    pointer-events: auto;
    -webkit-tap-highlight-color: transparent;
  }

  .nav-overlay-close:hover {
    border-color: var(--orange, #F08A24);
    color: var(--orange, #F08A24);
  }

  /* Matches the site's `// millennium business solutions group` eyebrow
     convention. Decorative — the dialog already carries an accessible name,
     so this is aria-hidden in the markup and must not be relied on for one. */
  .nav-overlay-eyebrow {
    margin: 26px 22px 14px;
    font-family: var(--mono, 'IBM Plex Mono', monospace);
    font-size: 12px;
    letter-spacing: 0.28em;
    text-transform: uppercase;
    color: var(--blue, #4DA3FF);
  }

  .nav-overlay-links {
    display: flex;
    flex-direction: column;
    padding: 0 22px;
  }

  /* Reuses .nav-link / .nav-cta so the menu inherits the real nav's mono
     face and orange-underline active convention instead of re-declaring a
     parallel set that could drift. Only size and axis are restated here.
     These selectors are (0,2,0) — they beat both the pages' own .nav-link
     rules and a11y.css's 44px floor, which is why the rows can be 56px. */
  .nav-overlay .nav-link,
  .nav-overlay .nav-cta {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    min-height: 56px;
    padding: 8px 0;
    font-family: var(--mono, 'IBM Plex Mono', monospace);
    font-size: 19px;
    font-weight: 500;
    /* 11.7:1 on the page background. The real nav's --muted is 6.6:1, which
       passes AA but is doing a different job there — de-emphasising a row of
       chrome. Here these six rows ARE the page. */
    color: rgba(234,242,255,0.82);
    text-decoration: none;
    white-space: nowrap;
    border-bottom: 1px solid var(--hairline, rgba(77,163,255,0.14));
    border-radius: 0;
  }

  .nav-overlay .nav-link:hover {
    color: var(--text, #EAF2FF);
  }

  /* Active page indicator (AC8). The header nav marks the current page with
     aria-current="page" and a 2px orange underline; the overlay copy carries
     the same attribute, so the same convention drives the same treatment.
     Pages that are not in the nav at all (arcade, the assessments, the legal
     pages) have no aria-current anywhere and correctly show no indicator. */
  .nav-overlay .nav-link[aria-current="page"] {
    color: var(--text, #EAF2FF);
    border-bottom: 2px solid var(--orange, #F08A24);
  }

  /* ./contact keeps its outlined-button identity rather than becoming a
     seventh list row — it is the one call to action in the stack. */
  .nav-overlay .nav-cta {
    justify-content: center;
    margin-top: 28px;
    padding: 9px 20px;
    font-weight: 600;
    color: var(--orange, #F08A24);
    border: 1.5px solid var(--orange, #F08A24);
    border-radius: 8px;
  }

  .nav-overlay .nav-cta:hover {
    background: var(--orange, #F08A24);
    color: var(--bg, #070B14);
  }

  /* arcade.html keeps its own "Back to site" link in the bar; hold it to the
     same 44px target the rest of the bar uses now that it shares the row
     with a button. */
  .nav-back { flex: 0 1 auto; }
}

/* ── MOTION ───────────────────────────────────────────────────────────────
   Only under an explicit no-preference. A user who has asked for less motion
   gets the display toggle and nothing else (AC12).

   Only the inner column moves, and only by transform — see the note on the
   keyframes above for why nothing here touches opacity. No fill-mode either,
   so outside the 260ms the element uses its own settled transform rather than
   holding a keyframe. Visibility is declarative; motion is decoration. */
@media (max-width: 768px) and (prefers-reduced-motion: no-preference) {
  body.nav-open .nav-overlay .nav-overlay-links,
  body.nav-open .nav-overlay .nav-overlay-eyebrow {
    animation: navOverlayPanelIn 0.26s ease-out;
  }
}

/* ── NAV CLEARANCE ────────────────────────────────────────────────────────
   Consequence of the change above, not a separate feature.

   a11y.css pins `main .subhero`, `main .act-hero` and `main .robot-stage` to
   padding-top:186px at <=760px, and says why: sizing the nav links to 44x44
   wrapped the bar onto two rows and grew it to 174px, which put the first
   line of those heroes underneath it. Collapsing the links into the hamburger
   removes that cause — the bar is now a single 73px row (62px on index.html,
   whose logo is trimmed to 46px) — so the 186px floor is 113px of dead air
   above the content it was protecting, and on about-2.html it pushes the
   fixed robot layer 58px below where that page positions it.

   These restate each element's own pre-a11y intent rather than inventing a
   number: clamp(132px, 15vh, 170px) is exactly what estimator.html,
   health-check.html, gut-check.html, stress-test.html and diagnostic.html
   already use for their own hero clearance (they opted out of these class
   names precisely to avoid the 186px pin), and 128px is about-2.html's own
   <=760px value for .robot-stage.

   Scoped to <=760px to mirror a11y.css exactly. Between 761 and 768px that
   rule never applied, and the bar is the same height with the links hidden as
   with them shown (the 55px logo sets it either way), so there is nothing to
   correct in that band and this must not start padding it.

   `main …` matches a11y.css's specificity; later source order wins. */
@media (max-width: 760px) {
  main .subhero,
  main .act-hero { padding-top: clamp(132px, 15vh, 170px); }

  main .robot-stage { padding-top: 128px; }
}
