/* ============================================================
   LEVRG v3 — THE HEADER, AS A COMPONENT

   ⚠️ EXTRACTED FROM herofloat.css. Every rule below was written for the home
   hero's bar and is unchanged; only its address moved.

   WHY IT MOVED. The header markup is shared by every page on the site
   (`website/v3/_shell/nav.html`, spliced in by `scripts/build_pages.py`), but
   its STYLESHEET was inside the hero's, which only the home page loads. So the
   first inner page rendered the whole nav unstyled — a full-width block of
   links where the pill should be — and the sweep read it as fourteen failing
   tap targets. Shared markup needs a shared stylesheet or it is not shared.

   The split rule: a selector naming `.hf__bar`, `.mnav` or `.wm` lives here;
   everything else stayed with the hero. It was done mechanically and the
   remainder re-verified, because a rule left behind can only under-style an
   inner page — never change the founder-locked hero.

   ⚠️ LOAD ORDER: this file comes BEFORE herofloat.css on the home page, which
   preserves the order these rules had when they were one file.
   ============================================================ */


/* ---- the header, inside the panel, inverted ------------------- */
.hf__bar { display: flex; align-items: center; justify-content: center;
  gap: var(--s5); padding: 16px var(--s5); position: relative; z-index: 4; }
/* ⚠️ 44px TALL, 19px PAINTED. The wordmark became the home link (D-142.2 said
   it always should have been), and the moment it did, the sweep read it as a
   66x19 tap target at every width. The mask is `center/contain`, so a taller
   box scales the artwork to FIT — 66 wide, 19 tall, vertically centred, pixel
   for pixel what it was. The box grows; the wordmark does not. The bar's other
   children are already 44-50px tall, so the row height is unchanged. */
.hf__bar .wm { width: 66px; min-height: 44px; background: var(--ink); display: block;
  -webkit-mask: url('../logos/levrg-wordmark.png') no-repeat center/contain;
  mask: url('../logos/levrg-wordmark.png') no-repeat center/contain; }
.hf__bar .grp { display: flex; align-items: center; gap: 4px;
  background: rgba(15,15,15,0.06); border-radius: var(--r-pill); padding: 5px; }
.hf__bar .grp a { font-size: var(--t-xs); font-weight: 600; padding: 9px 16px;
  border-radius: var(--r-pill); color: var(--ink-3); }
.hf__bar .grp a:hover { color: var(--ink); }
/* ⚠️ TEXT, NOT AN OUTLINE. Founder-directed. It was a bordered button sitting
   next to the filled one, which gave the bar two things claiming to be actions
   and made "Book a call" compete with a link to a dashboard only existing
   customers can use. A text link is the correct weight for a returning-user
   affordance — and it leaves exactly one button in the header, which is the
   point of having one. */
/* ⚠️ A BUTTON AGAIN, founder-directed, and it no longer competes with the
   primary: "Book a call" moved INTO the pill as a white segment, so the outline
   out here is the only bordered thing in the bar rather than a second one
   arguing with a black slab. Pill radius to match the group it sits beside. */
.hf__bar .g { font-size: var(--t-xs); font-weight: 600; padding: 9px 18px;
  border-radius: var(--r-pill); color: var(--ink-2);
  border: 1px solid rgba(15,15,15,0.18);
  transition: border-color var(--fast) var(--ease), color var(--fast) var(--ease); }
.hf__bar .g:hover { color: var(--ink); border-color: rgba(15,15,15,0.42); }
/* The caret marks the one item that opens a panel — without it the dropdown is
   a link that behaves differently from its neighbour for no visible reason.
   ⚠️ DRAWN, NOT TYPED. It was a '⌄' glyph, and a glyph sits on the font's
   baseline with the font's own side bearings — so it rendered low and adrift
   from the word, and every attempt to fix it is a magic `top` value that is
   wrong at the next font size. Two borders rotated 45° is a shape this
   stylesheet controls: it centres with `align-items` like anything else, scales
   with the text, and inherits `currentColor` so it dims and brightens with the
   link instead of needing its own hover rule. */
.hf__bar .grp .has-sub { gap: 8px; display: inline-flex; align-items: center;
  font-size: var(--t-xs); font-weight: 600; padding: 9px 16px;
  border-radius: var(--r-pill); color: var(--ink-3); min-height: 40px; }
.hf__bar .grp .has-sub:hover { color: var(--ink); }
.hf__bar .grp .has-sub::after { content: ''; width: 5px; height: 5px;
  border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  border-radius: 0 0 1px 0; opacity: 0.55;
  /* ⚠️ TRANSLATE BEFORE ROTATE. In `rotate() translate()` the translate happens
     in the ROTATED frame, so a -2px "up" nudge moves the chevron diagonally.
     Screen-space first, then turn it. The 2px lift is optical: a V built from
     two borders carries its mass low, so box-centred looks like it has dropped. */
  transform: translateY(-2px) rotate(45deg);
  transition: transform var(--base) var(--ease), opacity var(--fast) var(--ease); }
/* it points at the panel when the panel is open */
.hf__bar .sub:hover .has-sub::after,
.hf__bar .sub__t:checked ~ .has-sub::after,
.hf__bar .sub__t:focus-visible ~ .has-sub::after {
  transform: translateY(1px) rotate(225deg); opacity: 0.85; }@media (prefers-reduced-motion: reduce) {
  .hf__bar .grp .has-sub::after { transition: none; }}

/* ⚠️ INSIDE THE PILL NOW, founder-directed, and it stops being the black slab.
   A filled black button sitting IN a grey pill group is two containers arguing:
   the group already says "these belong together", and a heavy fill inside it
   reads as a foreign object rather than as emphasis. A white segment on the
   group's own grey is the subtle version — it is the same move a segmented
   control makes to show which one is live, so the affordance is already
   familiar and it needs no border to exist.
   The lift is `--lift-1`, the shallowest on the scale: enough to sit above the
   group, not enough to detach from it. */
.hf__bar .grp .p { background: var(--white); color: var(--ink);
  box-shadow: var(--lift-1); border-radius: var(--r-pill);
  transition: box-shadow var(--fast) var(--ease); }
.hf__bar .grp .p:hover { box-shadow: var(--lift-2); color: var(--ink); }
.hf__bar .p { font-size: var(--t-xs); font-weight: 600; padding: 9px 16px;
  border-radius: var(--r-btn); background: var(--ink); color: #fff; }@media (max-width: 760px) {
  /* full width on a phone too — no inset, no radius */
  /* ONE ROW, NOT TWO. `flex-wrap: wrap` put the buttons on a second line and
     the header cost 128px of a 390-wide screen before the headline started.
     "My dashboard" comes out of the bar rather than being shrunk — it is
     already in the nav sheet, and a returning customer opens the menu; a first
     visitor needs "Book a call" to be the only button in the bar. */
  .hf__bar { flex-wrap: nowrap; justify-content: space-between; gap: var(--s2);
    padding: 12px var(--s3); }
  .hf__bar .grp { display: none; }
  /* ⚠️ LOG IN STAYS IN THE BAR, AND STAYS THERE WITH THE MENU OPEN.
     Founder-directed. It was `display: none` below 760 and lived only in the
     sheet's action row — so the one control a RETURNING customer wants was
     three taps deep behind a menu built for first visitors. In the bar it is
     one tap from anywhere, and it is lifted above the sheet (below) so opening
     the menu does not take it away again.
     DOM order is wordmark → sheet → Log in, so `order` puts it before the
     burger without moving the markup; the sheet itself is `position: fixed`
     and out of flow, so it is not in this ordering at all. */
  .hf__bar .g { display: inline-flex; order: 1; margin-left: auto;
    padding: 9px 14px; }
  .mnav__b { order: 2; margin-left: 0; }}


/* ============================================================
   TAP TARGETS.  A Playwright sweep across ten widths found the header buttons
   at 39px and 41px — under the 44px touch minimum on every phone width, which
   is exactly where it matters and nowhere it is visible.

   They are sized by padding, so they came out at whatever the font and padding
   happened to produce. `min-height` states the requirement instead of hoping
   the padding adds up to it, and it survives a font-size change.
   ============================================================ */
.hf__bar .g,
.hf__bar .p { min-height: 44px; display: inline-flex; align-items: center; }
.hf__bar .grp a { min-height: 40px; display: inline-flex; align-items: center; }/* 44px on a coarse pointer. The header's nav pills are 40px from their 9px
   padding, which is fine for a mouse (24px) and short for a finger. */
@media (pointer: coarse) {
  /* `.has-sub` is a LABEL, not an <a>, so the anchor rule above missed it — and
     it is the one item in the bar that opens something, which makes it the most
     important 44px in the header rather than the least. */
  .hf__bar .grp a, .hf__bar .grp .has-sub, .hf__bar .g, .hf__bar .p { min-height: 44px; }}


/* ============================================================
   THE "WHAT WE BUILD" PANEL.

   A HIERARCHY, NOT A LIST — the IA is explicit about this and it is the whole
   commercial position in a menu: the platform is the base and is never sold
   alone; everything else ATTACHES to it. A flat list of six products would say
   the opposite, which is why the first group gets a sentence and the others get
   names.

   ⚠️ NO SCRIPT. `:hover` opens it and `:focus-within` keeps it open for the
   keyboard, so tabbing through the six links does not dismiss the thing they
   are inside. A JS dropdown here would be a second state machine on a page that
   has none.

   ⚠️ TOUCH GETS THE PAGE, NOT THE PANEL, and that is deliberate: a hover panel
   on a touch device either needs a tap-to-open state machine or it traps the
   first tap. The trigger is a real link to /what-we-build/, so a tap navigates
   to the hub — the same content, one level down. Below 760px the whole group is
   display:none anyway (the nav sheet takes over).

   ⚠️ IT OPENS INTO THE HERO, which is `overflow: hidden`. The panel is ~300px
   under an ~80px bar inside a 950px panel, so it clears — but anything taller
   would be silently cut, and there would be no error to say so. Measure before
   adding a group. */
/* ⚠️ STATIC, so the panel positions against `.hf__bar` — the full-width header
   — and not against the trigger. Anchored to the trigger it was centred on a
   word sitting left of centre, so at 1100px a 940px panel ran off the right of
   the viewport. Centring on the bar keeps it on screen at every width without
   a collision check. */
.hf__bar .sub { position: static; }
.hf__bar .sub__p { position: absolute; top: calc(100% + 4px); left: 50%;
  transform: translateX(-50%) translateY(-6px);
  width: min(940px, 86vw); display: grid;
  grid-template-columns: 1.5fr 1fr 1fr 1fr; gap: var(--s5);
  padding: var(--s5); border-radius: var(--r-lg);
  background: var(--white); border: 1px solid var(--line);
  box-shadow: 0 1px 2px rgba(31,26,22,0.10), 0 34px 70px -28px rgba(31,26,22,0.42);
  opacity: 0; visibility: hidden; text-align: left;
  transition: opacity var(--base) var(--ease), transform var(--base) var(--ease),
              visibility 0s linear var(--base); }
/* the visually hidden toggle. NOT display:none — it has to stay focusable, or
   the panel becomes unreachable by keyboard */
.hf__bar .sub__t { position: absolute; opacity: 0; width: 1px; height: 1px;
  margin: 0; pointer-events: none; }
.hf__bar .sub .has-sub { cursor: pointer; user-select: none; }
.hf__bar .sub__t:focus-visible + .has-sub { outline: 2px solid var(--ink);
  outline-offset: 2px; border-radius: var(--r-pill); }
/* ⚠️ NOT `.sub:focus-within`. That kept the panel open after a click had just
   UNCHECKED it — the checkbox still held focus, so the toggle appeared not to
   work on the second tap. Three precise conditions instead: the pointer is over
   it, the box is checked, or focus is genuinely inside the panel. Keyboard
   reaches it through `:focus-visible` on the toggle, which a mouse click does
   not trigger — so a click closes it and Tab still opens it. */
.hf__bar .sub:hover .sub__p,
.hf__bar .sub__t:checked ~ .sub__p,
.hf__bar .sub__t:focus-visible ~ .sub__p,
.hf__bar .sub__p:focus-within {
  opacity: 1; visibility: visible; transform: translateX(-50%) translateY(0);
  transition-delay: 0s, 0s, 0s; }
/* the gap between trigger and panel would drop the hover halfway across it */
.hf__bar .sub__p::before { content: ''; position: absolute; left: 0; right: 0;
  top: -14px; height: 14px; }
.hf__bar .sub__k { font-family: var(--mono); font-size: 9px; letter-spacing: 0.11em;
  text-transform: uppercase; color: var(--ink-4); margin-bottom: 12px; }
.hf__bar .sub__g { display: grid; align-content: start; gap: 2px; }
/* ⚠️ `display: block` and `min-height: 0` UNDO the header pill's own rule.
   `.hf__bar .grp a` is `inline-flex; align-items: center; min-height: 40px` for
   the top-level items — inherited here it laid the lead item's heading and its
   sentence out SIDE BY SIDE, and gave every menu link a 40px box. Repurposing a
   component means undoing its geometry; this is the fourth time on this site
   that the forgotten property was the bug. */
.hf__bar .sub__g a { display: block; font-size: var(--t-sm); font-weight: 500;
  color: var(--ink-2); padding: 7px 0; min-height: 0; border-radius: 0;
  transition: color var(--fast) var(--ease); }
.hf__bar .sub__g a:hover { color: var(--ink); }
.hf__bar .sub__lead { font-size: var(--t-body) !important; font-weight: 600 !important;
  color: var(--ink) !important; line-height: 1.3; }
.hf__bar .sub__lead span { display: block; font-size: var(--t-xs); font-weight: 400;
  color: var(--ink-3); line-height: 1.5; margin-top: 7px; }
.hf__bar .sub__g--base { padding-right: var(--s4); border-right: 1px solid var(--line); }
.hf__bar .sub__g--line { padding-left: var(--s4); border-left: 1px solid var(--line); }
/* nowrap: the number broke across two lines at 1440, which reads as two numbers */
.hf__bar .sub__tel { font-family: var(--display); font-weight: var(--w-display);
  font-size: 21px !important; letter-spacing: -0.02em; color: var(--ink) !important;
  white-space: nowrap; }
.hf__bar .sub__note { display: block; font-size: var(--t-xs); color: var(--ink-3);
  line-height: 1.5; margin-top: 6px; }@media (prefers-reduced-motion: reduce) {
  .hf__bar .sub__p { transition: none; transform: translateX(-50%); }}
@media (max-width: 1100px) {
  .hf__bar .sub__p { grid-template-columns: 1.4fr 1fr 1fr; }
  .hf__bar .sub__g--line { grid-column: 1 / -1; padding-left: 0; padding-top: var(--s3);
    border-left: 0; border-top: 1px solid var(--line); }}


/* ============================================================
   THE MOBILE MENU.

   ⚠️ THE PHONE HAD NO NAVIGATION. `.hf__bar .grp` and `.g` are display:none
   below 760 and nothing replaced them — Home, Solutions, Contact, Log in and
   the PRIMARY CTA were all simply absent, with no toggle to reach any of them.
   The parity check found it: nineteen items visible at 1920 and gone at 600.
   "No overflow and no contrast failures" is not "the content is there".

   No script, same mechanism as the Solutions panel: a checkbox drives it, the
   label is the burger, and the sheet is a sibling. The burger is two bars that
   become an X on :checked — drawn, not a glyph, for the reason the caret was.
   ============================================================ */
.mnav__t, .mnav__b, .mnav, .mnav__lv { display: none; }@media (max-width: 760px) {
  .mnav__t { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0;
    pointer-events: none; }
  /* ⚠️ NO `margin-left: auto` HERE ANY MORE, and it has to come off rather than
     be overridden earlier: this rule is later in the file than the bar block,
     so it wins on order. With Log in also carrying an auto margin the free
     space was SPLIT between the two, leaving a 47px hole between them at 320.
     One auto margin, on the first of the two — the pair is pushed right
     together and the bar's own `gap` sets the space between them. */
  .mnav__b { display: inline-flex; flex-direction: column; justify-content: center;
    gap: 5px; width: 44px; height: 44px; align-items: center; cursor: pointer; }
  .mnav__b i { display: block; width: 20px; height: 1.5px; background: var(--ink);
    border-radius: 2px; transition: transform var(--base) var(--ease); }
  .mnav__t:checked + .mnav__b i:first-child { transform: translateY(3.25px) rotate(45deg); }
  .mnav__t:checked + .mnav__b i:last-child  { transform: translateY(-3.25px) rotate(-45deg); }
  .mnav__t:focus-visible + .mnav__b { outline: 2px solid var(--ink); outline-offset: 2px;
    border-radius: 8px; }

  /* ⚠️ FIXED, FULL SCREEN — and that is a CORRECTNESS fix, not a restyle.
     As a dropdown it was `position: absolute` inside `.hf`, which is
     `overflow: hidden`, so the hero CLIPPED it: at 360 the last two items
     ("Contact" and "Book a call" — the primary CTA) were cut, and adding one
     more menu item moved the cut up to "Construction" at 390. The panel was
     560px tall inside a hero that was 630. Capping the height only decides
     WHICH items get eaten; the item count is not something the stylesheet
     gets to know.
     A `position: fixed` box is laid out against the VIEWPORT and is not
     clipped by an overflow ancestor (no ancestor here has a transform, which
     is the one thing that would re-parent it) → [[fixed-escapes-overflow-clip]].
     Full screen rather than a floating card so the height can never be wrong
     again: however many items the menu grows to, it scrolls inside itself.
     The bar's wordmark and burger are lifted above it (below), so the brand
     and the close control stay where they were. */
  /* ⚠️ THE OPACITY IS NOT ON `--ease`, AND THAT WAS THE "HARSH" PART. `--ease`
     is cubic-bezier(0.22, 1, 0.30, 1) — an expo-out, built for MOVEMENT, where
     a thing should leap and settle. Applied to opacity it put the sheet at 77%
     within 79ms and 96% by 147ms: technically a 280ms fade, over before the eye
     registers one, which reads as a pop. Measured, not guessed. The transform
     keeps the expo (that is what it is for); the fade gets a near-even curve
     over a longer window, so it is actually seen. */
  .mnav { display: grid; grid-template-rows: minmax(0,1fr) auto; position: fixed; inset: 0;
    z-index: 100; background: var(--white); padding: 68px 0 0;
    opacity: 0; visibility: hidden; transform: translateY(-8px);
    transition: opacity 240ms cubic-bezier(0.4, 0.05, 0.35, 1) ,
                transform 380ms var(--ease),
                visibility 0s linear 380ms; text-align: left; }
  .mnav__t:checked ~ .mnav { opacity: 1; visibility: visible; transform: none;
    transition-delay: 0s, 0s, 0s; }

  /* ⚠️ THE ROWS ARRIVE AFTER THE SHEET, AND THAT IS WHAT SELLS IT. Fading a
     white box onto a white-ish page is nearly invisible whatever the curve —
     the only thing the reader actually sees change is the type. Staggering it
     gives the open a direction and a duration; without it four headlines
     simply exist, which is the pop again one layer down.
     Keyed off `:checked` so it runs on OPEN only. A pane switch does not
     re-trigger it — those animations have already finished and `both` holds
     them at their end state, which is why the pane transition below can own
     the drill without the two fighting. */
  /* ⚠️ THE DELAY IS A CUSTOM PROPERTY, NOT `animation-delay`, and that is not a
     style choice. The `animation` SHORTHAND below resets every longhand it does
     not name — including `animation-delay` — and its selector (0,3,0) outranks
     a per-child `.mnav__pane > :nth-child(n)` (0,2,0). Written the obvious way
     the delays were silently discarded and all four rows animated in unison,
     which is the pop this was meant to fix. Measured, and it looked correct in
     the stylesheet. A custom property is read by the shorthand instead of being
     overwritten by it, so the cascade cannot lose it. */
  .mnav__t:checked ~ .mnav .mnav__pane > *,
  .mnav__t:checked ~ .mnav .mnav__foot > * {
    animation: mrow 420ms var(--ease) var(--d, 0ms) both; }
  .mnav__pane > :nth-child(1) { --d: 60ms; }
  .mnav__pane > :nth-child(2) { --d: 105ms; }
  .mnav__pane > :nth-child(3) { --d: 150ms; }
  .mnav__pane > :nth-child(4) { --d: 195ms; }
  .mnav__pane > :nth-child(5) { --d: 240ms; }
  .mnav__pane > :nth-child(6) { --d: 285ms; }
  .mnav__pane > :nth-child(7) { --d: 330ms; }
  .mnav__pane > :nth-child(8) { --d: 375ms; }
  .mnav__foot > * { --d: 180ms; }
  .mnav a { display: block; padding: 11px 0; min-height: 44px; font-size: var(--t-body);
    font-weight: 500; color: var(--ink-2); }
  .mnav a:hover { color: var(--ink); }
  /* same reason as the accordion row: the OS flash is gone site-wide, so every
     full-width tappable row needs a state of its own */
  .mnav a:active { color: var(--brand); }

  /* ── THE TWO LEVELS ────────────────────────────────────────────────────
     ⚠️ EVERY ROW RULE BELOW IS SCOPED `.mnav .mnav__x`, AND THAT IS LOAD-
     BEARING. The rule directly above — `.mnav a` — is (0,1,1). A bare
     `.mnav__row` would be (0,1,0) and LOSE, and two of these four rows are
     <a> (Home, Contact) while two are <label> (the groups, because a label is
     what drives a radio). The anchors would silently take body size and weight
     500 while the labels took the headline size, so Home and Contact would read
     as captions between two destinations. This exact defect shipped on the
     options page and the founder caught it by eye. `.mnav .mnav__row` is
     (0,2,0) and wins for both: a row's size must not depend on which element
     happens to implement it. */
  .mnav__lv { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0;
    pointer-events: none; }
  /* one grid cell for all three panes, so the sheet is the same height at both
     levels and does not resize under the finger that just opened it */
  /* ⚠️ THE TOP PADDING IS ON THE STACK, NOT ON `.mnav`. The sheet's own
     `padding-top: 68px` is BAR CLEARANCE — it is the height of the header the
     wordmark and the close X sit in, and changing it would slide the rows under
     the control that closes them. The gap below is the separate, editable
     thing: the space between the bar and the first row, which was zero, so
     "Home" sat hard against the X while the sheet had 400px of nothing below. */
  .mnav__stack { display: grid; overflow-y: auto; -webkit-overflow-scrolling: touch;
    padding: 0 var(--s4) var(--s4); }
  /* ⚠️ THE DRILL HAS A DIRECTION, AND IT IS NOT DECORATION. Going deeper enters
     from the RIGHT; coming back enters from the LEFT. Because the panes are
     fixed in their roles — 0 is always the top level, 1 and 2 are always
     children — one rule per pane gives the correct direction in BOTH directions
     with no need to know which pane was showing before, which is the thing CSS
     cannot know. Without it the two levels swapped instantly and the reader had
     to re-read the screen to work out what had happened.
     ⚠️ `pointer-events: none` has NO transition delay while `visibility` does:
     the outgoing pane stays painted for 260ms so it can fade, and for those
     260ms it is stacked on top of the incoming one in the same grid cell. Left
     alone it would swallow the first tap after a switch. */
  .mnav__pane { grid-area: 1 / 1; visibility: hidden; opacity: 0;
    pointer-events: none;
    transition: opacity 200ms cubic-bezier(0.4, 0.05, 0.35, 1),
                transform 260ms var(--ease),
                visibility 0s linear 260ms; }
  .mnav__pane[data-i="0"] { transform: translateX(-16px); }
  .mnav__pane[data-i="1"], .mnav__pane[data-i="2"] { transform: translateX(16px); }
  #mnav-l0:checked ~ .mnav__stack [data-i="0"],
  #mnav-l1:checked ~ .mnav__stack [data-i="1"],
  #mnav-l2:checked ~ .mnav__stack [data-i="2"] {
    visibility: visible; opacity: 1; transform: none; pointer-events: auto;
    transition-delay: 0s, 0s, 0s; }
  .mnav .mnav__row {
    display: flex; align-items: center; justify-content: space-between; gap: var(--s3);
    padding: 10px 0; min-height: 56px; cursor: pointer;
    font-family: var(--display); font-weight: var(--w-display);
    font-size: clamp(29px, 8.2vw, 40px); letter-spacing: -0.04em; line-height: 1.1;
    color: var(--ink); }
  .mnav .mnav__row:active { color: var(--brand); }
  /* the chevron is sized in `em` so it scales with the row rather than sitting
     as a fixed 8px mark beside 40px type */
  .mnav .mnav__row--go span { flex: 0 0 auto; width: 0.32em; height: 0.32em;
    border-top: 2px solid var(--ink-4); border-right: 2px solid var(--ink-4);
    transform: rotate(45deg); }
  .mnav__back { display: inline-flex; align-items: center; min-height: 44px;
    font-size: var(--t-xs); font-weight: 600; color: var(--ink-4); cursor: pointer; }
  .mnav .mnav__sub { font-family: var(--display); font-weight: var(--w-display);
    font-size: clamp(22px, 6vw, 27px); letter-spacing: -0.03em; line-height: 1.15;
    color: var(--ink); padding: 9px 0; }
  /* `minmax(0,1fr)` on the sheet's first row, not `1fr`: a grid track's
     automatic minimum is its content, so a `1fr` row refuses to shrink below
     its links and the pinned bar is pushed off the bottom of the viewport —
     the exact failure the pinned bar was added to fix, wearing a different
     hat. It still matters: level two is seven rows of display type. */
  .mnav__foot { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s3);
    padding: var(--s3) var(--s4) calc(var(--s4) + env(safe-area-inset-bottom));
    border-top: 1px solid var(--line); background: var(--white); }
  .mnav__foot a { padding: 8px 0; }
  /* ⚠️ THE ONE ACTION IS FULL WIDTH — `justify-content: center` and not
     `text-align`, because this is a flex item: `display: block` from `.mnav a`
     makes it fill the row, but its own contents would still sit hard left. */
  .mnav__p { background: var(--ink); color: var(--white) !important;
    padding: 14px 18px !important; border-radius: var(--r-btn); font-weight: 600;
    flex: 1 1 100%; justify-content: center; text-align: center;
    font-size: var(--t-body); }
  .mnav__tel { font-family: var(--display); font-weight: var(--w-display);
    font-size: var(--t-md); color: var(--ink) !important; margin-left: auto; }
  /* the bar becomes wordmark + burger only */
  .hf__bar { justify-content: space-between; position: relative; }
  /* ⚠️ ABOVE THE SHEET, and inside the SAME stacking context as it — both are
     children of `.hf__bar`, so these z-indexes are comparable and a context on
     the bar itself would put the sheet above them again. Without this the
     full-screen white covers its own close control. */
  .hf__bar .wm, .hf__bar .g, .mnav__b { position: relative; z-index: 110; }}

/* ⚠️ THE BREATHING SPACE IS GATED ON HAVING THE ROOM FOR IT. A flat 48px read
   well on a 14 Pro Max and cost 320x568 — the smallest phone still in use — a
   44px overflow on BOTH panes, turning a menu whose whole claim is "neither
   level scrolls" into one that does. Level two is seven rows of display type
   plus a back link, and its slack scales with viewport height: about 10px at
   568, about 80px at 640. 620 is where 48px fits with room over.
   This also catches a phone held LANDSCAPE, which is 360px tall and under 760
   wide, so it gets this menu and has never had room to spare. */
@media (max-width: 760px) and (min-height: 620px) {
  .mnav__stack { padding-top: var(--s5); }}

/* THE PAGE MUST NOT SCROLL BEHIND THE SHEET. The sheet is fixed and the bar is
   not, so a scroll with the menu open would carry the wordmark and the X off
   the top and leave a full-screen menu with no way out. Locking the root is
   the only close-control guarantee that does not need a script. */
html:has(.mnav__t:checked) { overflow: hidden; }
@keyframes mrow { from { opacity: 0; transform: translateY(12px); } }

/* Everything above comes off together. A stagger is the one piece here that is
   pure motion with no informational job — under reduced motion the rows are
   simply there, which is what this menu did last week. */
@media (prefers-reduced-motion: reduce) {
  .mnav { transition: none; }
  .mnav__b i { transition: none; }
  .mnav__pane { transition: none; transform: none; }
  .mnav__t:checked ~ .mnav .mnav__pane > *,
  .mnav__t:checked ~ .mnav .mnav__foot > * { animation: none; }}
