/* ============================================================================
   SafeStay Vista Pacifico — V1 (EN) — SITE LAYER
   ----------------------------------------------------------------------------
   This file RETARGETS the vendored Salient runtime. It does not reimplement it.
   Rules here exist for exactly two reasons:
     (a) Salient's demo brand (resort / site 37) must become Mykrobial's brand;
     (b) Figma's geometry overrides Salient's defaults where the two disagree,
         and every such override cites the spec that authorised it.
   If a rule here is not doing (a) or (b), it does not belong in this file.

   Load order matters: this file loads AFTER all 20 vendored stylesheets, so
   plain specificity is enough almost everywhere. `!important` is used only
   where Salient itself used `!important` first; each of those is marked.
   ========================================================================== */

/* ==========================================================================
   0. Neutralise the resort demo's brand so ours can land
   The vendored salient-dynamic-styles-multi-id-37.css hard-codes the resort
   demo's palette and its Google font stack. We keep the file byte-identical
   (it also carries the layout the components need) and override the brand
   surface here.
   ========================================================================== */

body {
  background-color: var(--mk-surface-ink);
  font-family: var(--mk-font-sans);
  color: var(--mk-ink-body);
}

#ajax-content-wrap { background-color: transparent; }

/* --- 0.1 the `container-wrap` scope ------------------------------------------
   Added while building 00-hero, but this is a PAGE-LEVEL fix, not a hero one.
   Salient's nectar-delay-javascript.js runs every above-the-fold entrance
   synchronously at load and scopes its search to
   `.container-wrap .vc_row:not(.inner_row)`. Our shell had no `.container-wrap`,
   so the search returned nothing and EVERY .nectar-split-heading on the page sat
   at its authored `opacity: 0` -- invisible, not merely unanimated (CONVENTIONS
   trap 1). The class is now on #ajax-content-wrap itself (index.html), which
   drags in Salient's page-body chrome: `.container-wrap{background-color:#f8f8f8;
   padding:40px 0}` (style.css), `#fff` (skin-material) and the demo's
   `--nectar-page-background-color` (dynamic-styles). All three are neutralised
   here at ID specificity, so folding the class on is a visual no-op. */
#ajax-content-wrap.container-wrap {
  padding-top: 0;
  padding-bottom: 0;
  background-color: transparent;
}

/* Salient's demo sets a warm --nectar-default. Repoint its own custom
   properties at our tokens so every lifted component inherits the brand
   without any component being edited. */
:root {
  --nectar-accent-color:  var(--mk-teal);
  --nectar-extra-color-1: var(--mk-teal);
  --nectar-default:       var(--mk-teal);
  --nectar-white:         var(--mk-ink-inverse);
  --nectar-black:         var(--mk-ink-strong);
  --nectar-border-radius: var(--mk-radius-card);
}

/* ==========================================================================
   1. NAV — lifted from /salient/resort/rooms/, retargeted to 00-hero §2
   --------------------------------------------------------------------------
   What is LIFTED verbatim (markup + class names + data attributes):
     #header-outer / header#top / .container / .row      Salient header shell
     .slide-out-widget-area-toggle[data-icon-animation="simple-transform"]
     .lines-button.x2 > .lines                            hamburger + morph
     #slide-out-widget-area.fullscreen-inline-images      menu fly-in panel
     li.menu-item-btn-style-button-animated_extra-color-gradient
                                                          outline -> fill CTA
     #search-outer / #search                              search overlay
   What FIGMA OVERRIDES (each cited):
     position of the toggle: far right, not Salient's left-aligned-ocm  §7.3
     hamburger geometry: 18x14, 2px bars, short 13px bottom bar         §2.7
     pill fill: flat --mk-teal, NOT Salient's extra-colour gradient     §7.4
     nav row: y 48, height 40, content 1040, gap 12, pills 8/18         §1, §2.2
   ========================================================================== */

/* The Figma nav is row 1 of the hero's vertical auto-layout at y = 48, not a
   sticky bar — that was true through round 17. Salient's transparent header
   overlays the hero, which is the same rendered result at rest, so rounds 1-17
   kept Salient's header pinned to y = 48 with `position: absolute`.

   ROUND 18 (`r18:header`, FT-20260828): `position: fixed`, same `top`.
   FT-20260828-jehnean-round18-queued-header.md asks for hide-on-scroll-down /
   reveal-on-scroll-up (js/myk-header-scroll.js §1) — which needs the header to
   still BE somewhere to hide from once the visitor has scrolled past the hero.
   Measured before this change: `position: absolute` here has no positioned
   ancestor between `#header-outer` and the document root, so its containing
   block is the INITIAL containing block — anchored to the top of the whole
   20,000+px document, not the viewport. `top: 48px` therefore placed the header
   48px into the DOCUMENT, and it scrolled away with everything else after
   ~88px of scroll (confirmed live: `getBoundingClientRect()` at scrollY=2000
   returned `top: -1952`). `position: fixed`'s `top` is viewport-relative
   instead, so the same `48px` now means "48px below the top of the browser
   window, always" — i.e. VISUALLY IDENTICAL at scroll position 0 (which is the
   only position 1-17's fidelity measurements ever ran at) and persistent at
   every other scroll position, which is the whole point. */
#header-outer {
  position: fixed;
  top: var(--mk-section-y);                 /* 48 — 00-hero §1.1 row table */
  left: 0;
  right: 0;
  z-index: 9998;
  background: transparent !important;       /* Salient sets a bg !important */
  border: 0 !important;
  box-shadow: none !important;
  padding: 0;
}
#header-space { display: none; }            /* no space reserved: the nav sits IN the hero */

/* --- RESPONSIVE: hold the overlay posture below Salient's mobile breakpoint.
   review/deepdive/responsive-640.md §4 P1 — a BROKEN-class defect: at 640 the
   hero rendered with a 128px blank band above it and lost 128px of height
   (772 instead of 900). Salient's responsive.css
   `@media (min-width:1px) and (max-width:999px)` undoes BOTH header rules above:
     `body #header-outer{position:relative;padding:12px 0}`      (0,1,1)
        beats ours at                                             (0,1,0)
     `#header-space[data-header-mobile-fixed="1"]{display:block}` (1,1,0)
        beats ours at                                             (1,0,0)
   `#header-space` ships `data-header-mobile-fixed="1"` — a lifted Salient
   artifact reserving space for a fixed mobile header this build does not have
   (`#header-outer` carries no `data-mobile-fixed`). So the spacer returns 64px,
   the header re-enters the flow for another 64, and `top:48px` — authored for
   the ABSOLUTE case — becomes a RELATIVE offset that drops the nav 48px into
   the photo. site.css is stylesheet #23 and responsive.css is #9, so these
   equal-specificity pairs win on source order. Verified in the lane's sandbox:
   header absolute t=48 h=40, spacer none, hero top 0, hero height 900 — i.e.
   640 matches the 1280 control exactly. Gated <=999px, so 1280 cannot see it.

   ROUND 18: `position: fixed`, not `absolute` — same reasoning as the base
   rule above, and the P1 defect analysis is UNCHANGED by the swap. What fixed
   the 128px blank band was removing `#header-outer` from normal document flow
   (so it stops PUSHING the hero down) plus keeping `#header-space` hidden (so
   Salient's own reserved-space rule stays beaten); `fixed` removes the element
   from flow exactly as `absolute` did — neither contributes a box to the
   document's height — so nothing about that fix depends on which of the two
   removed-from-flow position modes is used. Re-verified live post-change at
   640/834/390: no blank band, hero height unchanged. */
@media only screen and (max-width: 999px) {
  body #header-outer { position: fixed; padding: 0; }
  #header-space[data-header-mobile-fixed="1"] { display: none; }
}

/* Salient's full-width header pins its own container to `max-width: 100%` and
   a 28px inset. Figma's page margin is a fixed 120 at both design widths, so
   this override is required, and it has to out-specify the demo's rule. */
body #header-outer header#top > .container,
body #header-outer #search-outer .container {
  width: 100%;
  max-width: var(--mk-frame) !important;    /* Salient sets max-width !important */
  margin-inline: auto;
  padding-inline: var(--mk-page-x) !important;
}

/* ROUND 18 (`r18:header`) — a real race in the vendored chain, found while
   reproducing baseline for this round, NOT a defect introduced by it: the
   whole nav can go invisible after a visitor closes the off-canvas menu, with
   every ancestor still reporting `opacity: 1` in devtools.

   MEASURED, not guessed. Clicking the hamburger promotes
   `nectar-delay-javascript.js` (one of its own listened triggers is "scroll",
   grepped out of the vendored file — the same gesture this round's whole
   feature is built on), which loads jQuery + anime.js + the real init.js. That
   real init.js's own off-canvas CLOSE sequence runs (grepped out of
   `vendor/…/init.q-a3a00a7bf4.js`):

       anime({targets:"#header-outer #top > .container",
              opacity:[0,1], duration:900, easing:"easeOutQuad"})

   i.e. it sets this container's opacity to 0 and animates it back to 1 by
   direct inline `style`. A second quick click — exactly what this round's own
   baseline pass did, opening then closing the menu to screenshot both states —
   can interrupt that in-flight `anime()` call, and nothing re-runs it: the
   inline `opacity:0` is left standing. `#header-outer`, `header#top` and the
   `.mk-wordmark` all still compute `opacity: 1` (they were never touched); the
   PARENT nobody thinks to check is the one left at 0, and the whole nav reads
   as gone.

   NOT THE FIRST TIME THIS WAS FOUND. `sections/00-hero.css` C.6 already pins
   `#header-outer.side-widget-open #top > .container{opacity:1!important}` —
   its own comment: "The header content is faded to 0 on open by init.js and
   only faded back by an anime() call inside a nested setTimeout; measured
   live, it stays at 0." That fix is deliberately scoped to the OPEN state
   only (D05's ask was that the close-X stays visible while the menu is open).
   The gap it leaves is the one this round hit: once the menu is CLOSED again
   `#header-outer` no longer carries `.side-widget-open`, that rule stops
   matching, and if the restoring `anime()` call above was the one interrupted
   — the close path, not the open one — nothing else ever sets this container
   back to 1. Unscoped here rather than adding a second `.side-widget-closed`
   variant: this container never needs to be anything but opaque in a page
   with no ajax page transitions (`data-ajax-transitions="false"`) and no
   secondary/contained header, so there is no state this rule needs to spare.
   The two rules do not conflict — both assert the identical value — this one
   just also covers the state the existing one was never asked to.

   This is a pre-existing fragility in the vendored/lazy-promoted chain, not
   something round 18 caused — but round 18's own feature depends on scroll
   working reliably, and scroll is a promotion trigger, so left alone this
   would have made "scroll to see the header reappear" occasionally undo
   itself. Pinned here rather than chased into vendor/: an `!important` in an
   external stylesheet beats a plain (non-`!important`) inline style
   regardless of specificity, so this makes the donor's own `anime()` call
   visually inert without touching the vendored file it lives in.
   js/myk-header-scroll.js does not depend on this fix — its own mechanism
   never reads or writes this container — but the header would be unusable
   without it. */
#header-outer header#top > .container { opacity: 1 !important; }

#header-outer header#top { padding: 0; }
#header-outer header#top .row {
  margin: 0;                                /* Salient's .row carries the
                                               12-col negative gutter margins */
  width: 100%;
  display: flex;
  align-items: center;                      /* counterAxisAlignItems: CENTER */
  gap: var(--mk-space-12);                  /* itemSpacing 12 (EN). ES = 0. */
  height: 40px;                             /* 8 + 24 line box + 8 */
  line-height: var(--mk-lh-node);
}
/* Salient's `.row` carries a table-based clearfix. Under `display: flex` those
   two pseudo-elements become zero-width FLEX ITEMS, and each one still
   consumes a 12px gap — which shifted the whole nav 12px right and lost 12px
   off the tail. Remove them or the row can never measure 1040. */
#header-outer header#top .row::before,
#header-outer header#top .row::after { content: none; }

/* Salient's own nav list is floated and inherits the demo's type scale.
   Flatten it to the Figma row: one flex track, itemSpacing 12, no floats. */
#header-outer .mk-nav,
#header-outer .mk-nav__list { margin: 0; padding: 0; }
#header-outer .mk-nav__list {
  display: flex;
  align-items: center;
  gap: var(--mk-space-12);
  list-style: none;
  float: none;
}
#header-outer .mk-nav__list > li {
  float: none;
  margin: 0;
  padding: 0;
  list-style: none;
  line-height: var(--mk-lh-node);
}

/* The header's nav-button cascade — the block that re-states the component's
   own type and motion at a specificity that beats Salient's `#top nav > ul >
   li > a` — MOVED to css/myk-btn.css §5 when `.mk-pill` became `myk-btn`.
   It belongs with the component it keeps in sync, and myk-btn.css loads
   immediately after this file so its position in the cascade is unchanged.
   The underline killers moved with it: they are one unit with the
   `::before` restore that gives the outline button its fill layer. */

/* 00-hero §2.1: the wordmark is a FLEX SPACER, proven by arithmetic in both
   frames (EN 1040 - 846 = 194 = the reported wordmark width). Do NOT use
   justify-content: space-between — that would space every pill. */
body #header-outer #top #logo,
body #header-outer.transparent #top #logo,
#header-outer .mk-wordmark {
  flex: 1;
  align-self: center;
  height: auto;
  margin: 0;
  padding: 0;
  text-align: left;
  /* Salient's demo styles #logo in Cormorant 500 at -0.04em. Every one of the
     four properties below has to be forced or the wordmark silently renders in
     the demo's serif at the right WIDTH but the wrong FACE. */
  font-family: var(--mk-font-sans) !important;
  font-weight: 700 !important;              /* "visibly Bold" — the exact weight
                                               is LOSSY, see NOTES.md A1 */
  font-size: var(--mk-size-base) !important;
  line-height: var(--mk-lh-node) !important;
  letter-spacing: var(--mk-track-wordmark) !important;  /* 2px */
  text-transform: none !important;
  /* R19-06: reads the header tone token (§1B.2) instead of the literal, with
     the literal kept as the `var()` fallback so this line alone still ships
     the correct LIGHT look before the first tone class lands (see §1B.2's
     own note on the JS's "fail open" contract), and so `.mk-wordmark` (the
     alternate selector in this group) stays covered without needing its own
     tone-qualified rule below. */
  color: var(--myk-header-ink, var(--mk-ink-inverse)) !important;
  text-decoration: none;
  white-space: nowrap;
}
/* R19-06: `#top #logo` specifically (not `.mk-wordmark`) needs ONE MORE
   specificity step the rest of this file's tone rules don't: the vendored
   `salient-dynamic-styles…css` carries
   `#header-outer:not(.transparent) #top #logo{color:#0a0a0a!important}` —
   tone-AGNOSTIC (fires whenever the header is non-transparent, regardless of
   `.light-text`/`.dark-text`) at (3 ids, 1 class, 0 type). The base rule
   above only reaches (3 ids, 0 class, 1 type) — one class short — so it LOST
   this exact fight in the non-transparent+dark-text state, live-verified
   (`getComputedStyle` read `#0a0a0a`, the vendored donor's own near-black,
   not the header tone token's value). Light-text was accidentally safe
   without this: the SAME vendored file also ships
   `#header-outer:not(.transparent).light-text #top #logo{color:#fff!important}`
   at (3,2,0), which independently outranks the #0a0a0a rule and happens to
   render the same white the token would have produced anyway — masking that
   the base rule was never actually winning there either. Both tone classes
   get their own qualified selector here so BOTH win on their own terms, not
   by vendored coincidence — still reading the ONE shared token, so this is
   still a single canonical VALUE, just declared through two selectors
   instead of one for this one element. Verified live post-fix, all 4
   tone × transparency combinations, see this round's helix doc. */
body #header-outer.light-text #top #logo,
body #header-outer.dark-text #top #logo {
  color: var(--myk-header-ink, var(--mk-ink-inverse)) !important;
}
#header-outer #logo img { display: none; }  /* no-image wordmark */
/* The "O" is the brand mark, and it is a DIFFERENT teal from the CTA.
   R19-06: reads the header tone token (§1B.2), fallback preserves today's
   teal-on-photo default; `!important` added so this single rule also covers
   what used to be a SEPARATE, more specific `.dark-text` rule elsewhere. */
#header-outer .mk-wordmark__o {
  color: var(--myk-header-wordmark-o, var(--mk-teal-wordmark)) !important;
}

/* --- the button component ------------------------------------------------
   `.mk-pill` MOVED to css/myk-btn.css, where it became `myk-btn` — a copy of
   Salient's `.nectar-cta[data-style="basic"]` with every Mykrobial difference
   expressed as a CSS custom property. Everything that was here (the base box,
   the ghost/active/outline/solid/icon variants, the outline cross-fade hover,
   the pinned nav widths and the focus ring) is there, unchanged in value.
   myk-btn.css loads immediately after this file, so nothing moved across a
   cascade boundary. See build/COMPONENT-myk-btn.md. */

/* --- hamburger: Salient's motion, Figma's geometry — 00-hero §7.3 -------- */
#header-outer .slide-out-widget-area-toggle { margin: 0; }

/* THREE ROOT CAUSES, all measured — review/deepdive/hero-hamburger.md.
   Figma draws three bars, 18/18/13 x 2px, pitch 6, glyph 18x14 centred in the
   60x40 pill. The build rendered TWO bars, 5.5px low and 2px left. */

/* (1) Salient wraps the icon in `<span aria-hidden>` and treats that span as a
   22 x 21 `overflow:hidden` WINDOW — `.slide-out-widget-area-toggle a>span
   {height:21px}` (style.css) plus `#top .slide-out-widget-area-toggle a span
   {overflow:hidden;width:var(--nectar-ocm-icon-width,22px)}` (skin-material).
   It exists to hide the slide-in hover copy of the icon; that copy is only
   cloned for a toggle inside `header#top ul`, which ours is not.
   Left alone it does two measurable things to Figma's glyph:
     - 22px width centres the 18px glyph 2px LEFT of Figma's x (1119 vs 1121);
     - the 21px window's bottom edge lands at page y 78.5, and the third bar
       starts at exactly 78.5 — so the SHORT BAR IS CLIPPED AWAY ENTIRELY.
   Sizing the span to the glyph fixes the x; `overflow:visible` is required
   both for the third bar and for the open-state X, whose +/-45deg rotation
   needs ~12.7px of vertical room inside a 14px box. */
body #header-outer .slide-out-widget-area-toggle a > span {
  display: block;
  width: 18px !important;                   /* Salient pins 22px  */
  height: 14px !important;                  /* Salient pins 21px  */
  overflow: visible !important;
}
/* (2) Salient offsets the icon by `top:9px` (`body #header-outer .lines-button`)
   to sit its own icon under a taller header. Figma centres the 18x14 glyph in
   the 40px pill; the flex `<a>` above already does that, so the offset is pure
   error — it is what puts the built glyph at y 66.5 instead of Figma's 61. */
#header-outer .slide-out-widget-area-toggle .lines-button { top: 0; }
/* (3) THE FOURTH BAR. `.slide-out-widget-area-toggle .lines-button::after`
   (style.css) is a 22px x 2px bar at top:0 that salient-dynamic-styles paints
   `#0a0a0a`. It is the LAST child of `.lines-button`, so it paints ON TOP of
   the white `.lines::before` at the same y — which is why the built top bar
   rendered 22px wide and near-black while every computed style on `.lines*`
   correctly reported 18px white. Figma has three bars; this one is not one of
   them. `content:none` removes the box rather than merely hiding it, and the
   open-state X morph does not use it (it animates `.lines`, `.lines::before`
   and `.lines::after` only). */
body #header-outer .slide-out-widget-area-toggle .lines-button::after { content: none; }
#header-outer .slide-out-widget-area-toggle > div { display: flex; width: 100%; height: 100%; }
#header-outer .slide-out-widget-area-toggle > div > a {
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 100%; padding: 0;
}
#header-outer .slide-out-widget-area-toggle .lines-button {
  width: 18px; height: 14px;                /* Figma dehaze, NOT Salient's 22x3 */
  display: block; position: relative;
}
/* Salient colours the two OUTER bars from its own header-state rules (the demo
   resolves them to #0a0a0a). Only the middle bar inherits ours, which is why
   an unforced version renders as a single dash on a dark hero. Force all
   three; `body …` raises specificity past the demo's header-state selectors.
   R19-06: `background-color` reads the header tone token (§1B.2) — fallback
   preserves today's literal, and the SEPARATE `.dark-text`-scoped rule that
   used to restate this same property at higher specificity is gone; this one
   unconditional declaration now covers both states (the middle bar,
   `sections/00-hero.css`, follows the identical pattern). */
body #header-outer .slide-out-widget-area-toggle .lines,
body #header-outer .slide-out-widget-area-toggle .lines::before,
body #header-outer .slide-out-widget-area-toggle .lines::after,
body #header-outer.transparent .slide-out-widget-area-toggle .lines,
body #header-outer.transparent .slide-out-widget-area-toggle .lines::before,
body #header-outer.transparent .slide-out-widget-area-toggle .lines::after {
  width: 18px !important;                   /* Salient pins 22px !important */
  height: 2px !important;
  background-color: var(--myk-header-ink, var(--mk-ink-inverse)) !important;
  transition: var(--mk-motion-dur-icon);    /* Salient's own .3s */
  position: absolute;
  left: 0;
  border-radius: 0;
}
body #header-outer .slide-out-widget-area-toggle .lines         { top: 6px; }
body #header-outer .slide-out-widget-area-toggle .lines::before { content: ""; top: -6px; }
/* Figma's `dehaze` glyph has a SHORT bottom bar (13 of 18) — 00-hero §2.7.
   Must out-specify the `.transparent` variant in the group rule above. */
body #header-outer .slide-out-widget-area-toggle .lines::after,
body #header-outer.transparent .slide-out-widget-area-toggle .lines::after {
  content: ""; top: 6px; width: 13px !important;
}
/* Salient's own open-state morph, kept verbatim in behaviour. */
#header-outer .lines-button.x2.close .lines { background-color: transparent !important; }

/* --- off-canvas panel — fullscreen-inline-images, links stagger in ------- */
#slide-out-widget-area.fullscreen-inline-images { background-color: var(--mk-surface-ink); }
#slide-out-widget-area .off-canvas-menu-container .menu > li > a {
  font-family: var(--mk-font-serif);
  font-optical-sizing: auto;          /* opsz = font-size — tokens.css
                                         "MERRIWEATHER OPTICAL SIZE" */
  font-variation-settings: "wdth" 100;
  font-weight: var(--mk-w-light);
  color: var(--mk-ink-inverse);
}

/* --- search overlay ----------------------------------------------------- */
#search-outer input#s {
  font-family: var(--mk-font-serif);
  font-optical-sizing: auto;          /* opsz = font-size — tokens.css
                                         "MERRIWEATHER OPTICAL SIZE" */
  font-variation-settings: "wdth" 100;
  font-weight: var(--mk-w-light);
  color: var(--mk-ink-inverse);
}

/* ==========================================================================
   1B. ROUND 18 — THE SCROLL-AWARE HEADER (`r18:header`, FT-20260828)
   --------------------------------------------------------------------------
   Runtime half: js/myk-header-scroll.js. That file's own header explains why
   neither mechanism below talks to jQuery or the real (lazily-promoted)
   Salient init.js, and carries the measured per-section tone map §1B.2 reads.
   ========================================================================== */

/* --- 1B.1 hide-on-scroll-down / reveal-on-scroll-up -----------------------
   The bar's own slide. `--mk-motion-dur-hover` / `--mk-ease-hover` — this
   build's ONE hover clock (myk-btn.css §1: "the ring, the fill and the label
   each ran on a different clock… now reads §1's single hover clock") — reused
   rather than a new duration invented for this one element, because a header
   bar reacting to the visitor's own scroll input is exactly the kind of
   UI-chrome response that clock already governs everywhere else on the page,
   and `prefers-reduced-motion` already collapses it to 1ms (tokens.css §7)
   with no extra rule needed here. */
/* r18fix:transition — CONFIRMED by r18:verify: the bare `#header-outer`
   selector below (0,0,0,1) never had a chance. TWO vendored rules in
   salient-dynamic-styles-multi-id-37.q-6d7044fbbd.css out-specify it, one
   per header state, and NEITHER lists `transform` in its own
   `transition` shorthand — and shorthand `transition` doesn't merge
   per-property across rules of differing specificity, the higher-
   specificity winner replaces the WHOLE list, so `transform` was simply
   absent from what the browser actually animated. This markup carries
   `data-remove-border="true"` (index.html #header-outer), so both
   vendored rules are live, one per state:
     - near-top / `.transparent` present:
       `body #header-outer.transparent[data-transparent-header="true"]
        [data-remove-border="true"]` — specificity (0,1,3,1)
     - scrolled past hero / `.transparent` removed (real Salient init.js
       swaps it for `.scrolling`, which carries no transition rule of its
       own — see vendor init.q-a3a00a7bf4.js, `d.removeClass("transparent")
       .addClass("scrolling")`):
       `body #header-outer[data-transparent-header="true"]` —
       specificity (0,1,1,1)
   Fix: restate BOTH selectors here, `html body`-prefixed so the
   specificity wins on the numbers alone — (0,1,3,2) and (0,1,1,2)
   respectively — independent of stylesheet load order, with `transform`
   folded into each rule's OWN copy of the vendored list rather than
   dropping the vendored properties. Background-color / box-shadow /
   margin / backdrop-filter durations and easings below are copied
   verbatim from the two vendored rules, not reinvented. */
html body #header-outer[data-transparent-header="true"] {
  transition: transform var(--mk-motion-dur-hover) var(--mk-ease-hover),
              background-color 0.30s ease,
              box-shadow 0.30s ease,
              margin 0.25s ease,
              backdrop-filter 0.25s ease;
}
html body #header-outer.transparent[data-transparent-header="true"][data-remove-border="true"] {
  transition: transform var(--mk-motion-dur-hover) var(--mk-ease-hover),
              background-color 0.3s ease 0s,
              box-shadow 0.3s ease 0s,
              margin 0.25s ease,
              backdrop-filter 0.25s ease;
}
#header-outer.myk-header--hidden {
  transform: translateY(-100%);
}

/* The reappearing header's OWN CONTENTS get a second, distinct treatment —
   founder's words, verbatim: "it's an empty blank bar, but... the tech, the
   logo and the tech all animates back in." Two things follow from that
   sentence directly: the bar arrives NOTICEABLY BEFORE its contents (a short
   delay on the "revealed" transition only, none on the "hiding" one, so
   hiding stays a single decisive motion and revealing is the one with two
   beats), and the contents' entrance must read as ITS OWN thing rather than
   the page-load fade riding along — so it borrows the PAGE's established
   scroll-reveal vocabulary (`--myk-ease-entrance`, css/myk-motion.css §0),
   not D02-D05's one-time load fade (`--mk-ease-out-quart` / 1500ms, driven by
   the real init.js's `data-cae`/`data-cad` read off <body> — a different
   mechanism, left untouched, see round-18 baseline notes). `#header-outer`
   itself is in `myk-motion.js`'s own `SKIP` list for that exact reason: this
   is deliberately a THIRD, header-scoped instance of the reveal idiom, not an
   adoption of the sitewide one.
   Travel is 6px, not the sitewide 40px (`--myk-mv-travel`) — that value was
   derived for headings and paragraphs inside tall sections; a 40px throw
   inside a 40px-tall bar would visibly overshoot its own box. Scaled down,
   same easing, same idea.

   R19-04 (FT-20260829): `#mk-search-toggle` REPRODUCED live as visibly stuck
   through the whole hide cycle while every sibling here correctly faded —
   `getComputedStyle` at scrollY 1200 (header genuinely `.myk-header--hidden`)
   showed `transform: matrix(1,0,0,1,0,-6)` (this rule's OWN translateY DID
   land) but `opacity: "1"`, not the `0` two lines below. Root cause is a
   plain specificity loss, not a missing rule: `#mk-search-toggle` is itself
   the `<a class="myk-btn myk-btn--icon">`, and myk-btn.css's header-cascade
   block carries `#header-outer.transparent #top a.myk-btn.myk-btn--icon
   {opacity:1; …}` — (2 ids, 3 classes, 1 type) — which beats this file's
   `#header-outer.myk-header--hidden #mk-search-toggle` (2 ids, 1 class) on
   class count alone, regardless of load order (site.css loads after
   myk-btn.css but higher specificity wins over source order either way).
   Every OTHER selector in this pair of rules is immune to that same donor
   rule because it targets a WRAPPING ancestor (the nav `<li>`, `.mk-wordmark`,
   `.mk-header__actions`) rather than the exact element myk-btn.css's icon
   rule also matches — a parent's `opacity:0` already makes an `opacity:1`
   child invisible, no specificity contest needed there. `#mk-search-toggle`
   has no such wrapper of its own, so it is the one element on this list that
   actually collides.
   Fixed here, not in myk-btn.css (this lane owns site.css only; myk-btn.css
   is `r19:header-bugs`'s explicit no-touch list): `#top` added as a THIRD
   id-selector step on both the base and `.myk-header--hidden` entries below.
   `#header-outer #top #mk-search-toggle` really is the element's own ancestor
   chain (`header#top` is a genuine ancestor of `#mk-search-toggle`, confirmed
   live), so this is not an arbitrary id-stuffing trick — it is this file's
   own established idiom (§1B.2's own comment: "same base selector, one more
   class/qualifier added — a plain specificity SUPERSET"). 3 ids strictly
   outranks the donor rule's 2 ids, so this wins outright regardless of its
   own class/type count, on BOTH the always-on transition declaration below
   (so the search icon's fade now runs on the SAME clock as its siblings,
   not myk-btn.css's unrelated color/box-shadow/outline-color list) and the
   `.myk-header--hidden` opacity/transform declaration. The other four
   selectors in each group are left exactly as they were — they were never
   the defect. Re-verified live post-fix: opacity now reads 0 in the hidden
   state, and the hamburger (`.slide-out-widget-area-toggle`, a `<div>`, not
   an `<a>` — myk-btn.css's icon rule is scoped to `a.myk-btn.myk-btn--icon`
   and structurally cannot match a div) was never exposed to this collision,
   confirming why only the search icon showed the bug. */
#header-outer .mk-wordmark,
#header-outer .mk-nav__list > li,
#header-outer .mk-header__actions,
#header-outer #top #mk-search-toggle,
#header-outer .slide-out-widget-area-toggle {
  transition: opacity var(--myk-mv-dur-body, 200ms) var(--myk-ease-entrance, cubic-bezier(.4, 0, .2, 1)) 150ms,
              transform var(--myk-mv-dur-body, 200ms) var(--myk-ease-entrance, cubic-bezier(.4, 0, .2, 1)) 150ms;
}
#header-outer.myk-header--hidden .mk-wordmark,
#header-outer.myk-header--hidden .mk-nav__list > li,
#header-outer.myk-header--hidden .mk-header__actions,
#header-outer.myk-header--hidden #top #mk-search-toggle,
#header-outer.myk-header--hidden .slide-out-widget-area-toggle {
  opacity: 0;
  transform: translateY(-6px);
  transition-delay: 0s;   /* hiding snaps out WITH the bar — no lag on exit */
}

/* --- 1B.2 header tone system — ONE canonical mechanism ---------------------
   R19-06 (FT-20260829, `r19:header-architecture`). Founding-doc citation
   (fetched fresh this session, `founding-canon/mykrobial-engineering-
   founding-document.md` §Software Construction Discipline, DRY rule 4:
   "apply DRY to logic, policy, and contract truth so the system has one
   canonical place to change behavior") — this section used to BE the DRY
   violation that same research doc named directly: five independent
   "specificity superset" rule-pairs below (wordmark, wordmark-O, nav links,
   CTA, search icon, hamburger), each restating a literal `color`/
   `background-color … !important` at a hand-computed specificity high enough
   to beat whichever vendored/component rule it happened to be racing, THREE
   of which also needed a `.dark-text.transparent` combined selector to close
   a tie only reachable in that one state combination. Three separate rounds
   (r18fix2, r18fix3, and this file's own §1B.1 R19-04 note on the same
   collision class) each had to re-derive that tie by hand, in three
   different files.

   `js/myk-header-scroll.js`'s `applyTone()` (untouched by this lane — out of
   its ownership) already writes BOTH `.light-text` and `.dark-text`
   explicitly and mutually-exclusively onto `#header-outer` — "so the state
   is legible from the DOM alone", its own words. THE NEW MECHANISM keys off
   exactly that: the two blocks below are the ONLY place tone is decided,
   full stop. Every consuming rule elsewhere (this file's wordmark/wordmark-O
   /hamburger rules above, myk-btn.css §1/§2.3/§5's `--myk-btn-fg`/
   `--myk-btn-hover-fg`/`--myk-btn-border`/`--myk-btn-hover-border`) is
   UNCHANGED in shape — same selector, same specificity, same `!important`
   where it already had one — and now simply reads a header-scoped custom
   property with a `var(x, <old literal>)` fallback instead of a hardcoded
   token. No selector ever has to out-specify another rule for TONE again,
   because nothing else in this codebase writes to these seven property
   names — the `.dark-text.transparent` tie class cannot recur: there is no
   second rule left at any specificity to tie against. The fallback chain
   also means the exact LIGHT look still ships before the very first
   IntersectionObserver callback (neither class present yet), matching the
   JS's own documented "fail open: default CSS (light-on-dark) stays"
   contract — verified live below.

   R19-06 also closed one live gap found WHILE consolidating, not invented as
   new scope: the search icon's HOVER label had no dark-text rule at all in
   the old mechanism (only its REST colour did) — hovering it while
   `.dark-text` was active computed white-on-white. It now shares
   `--myk-header-btn-hover-fg` with the nav links (myk-btn.css), the same
   pairing myk-btn.css §5 already uses for every OTHER header tone rule,
   because both are `.myk-btn` elements sitting directly in the header with
   no colour-inheriting wrapper of their own. Verified live, all 5 widths,
   see this round's helix doc. */
/* ROUND 20 (`r20:header`, FT-20260830). R20-02 + R20-03 both land here — see
   `founder-trace/helix/R20-02.md` and `R20-03.md` for the full live evidence
   and the two open questions flagged for the founder. Short version of each:

   R20-02 — THE HOVER LADDER, RESTORED ON BOTH SIDES, WITH A DOCUMENTED
   REVERSAL. Verbatim: "the hover state should not be turquoise... it should
   be, like, a darker black... whatever percentage, like, seventy five
   percent black, and then a hundred percent black... whatever the
   equivalent is that we did with the white." Two live checks before
   touching either side:
     (a) dark-text hover WAS turquoise (`var(--mk-teal, #1eb2bc)`, the line
         this round's own founder-trace doc pointed at) — confirmed, real
         defect, now gone below.
     (b) light-text's OWN 75%→100% step, which she remembers building —
         confirmed LIVE this round to be flat 100% on both rest and hover
         (grepped: the literal `rgba(255,255,255,.75)` string exists nowhere
         in an active rule any more, only in comments). BUT the reason it is
         flat is not an accident: `sections/00-hero.css` PART D
         (`foldback:hero-nav`, 2026-08-18 — BEFORE this round, and before
         R19-06 which only mechanically token-ised whatever was already
         live) explicitly re-derived this exact question from the SafeStay
         hero board itself (854:363, nodes 3017:589/3016:403, both 100% fill
         with no opacity) and settled it AGAINST the ladder in writing:
         "Do not apply the ladder to `.mk-nav__list`." The 75% figure is
         real, just for a DIFFERENT asset (the branding-site nav component,
         3269:5620) — PART D's own words.
     Restoring the step here is therefore a DELIBERATE REVERSAL of that
     Aug-18 finding, not a bug fix — done on the strength of her own live,
     current instruction, which is the more recent and more direct signal.
     Flagging it this plainly so she can veto in one sentence if this reads
     wrong; reverting is a two-line diff (drop the `rgba(...,.75)` rest
     values below back to the plain ink tokens).

   R20-03 — CTA REWORK, A NEW INTERACTION MODEL, NOT A COLOUR SWAP. Verbatim:
   "turquoise text that you would swap the color of the background to be
   black." Read as: turquoise TEXT is the button's constant identity (both
   states), and the FILL is what swaps — transparent at rest, solid black on
   hover. Neither prior state did this (light-text hovered turquoise text
   onto a near-white #f4f9fb fill; dark-text had no turquoise anywhere).
   `figma-truth/_zoom/00-hero-cta.png` was checked and is NOT this button —
   it is "Start your safe stay", the separate SOLID-fill teal CTA
   (`--mk-pill-solid-fill`, tokens.css:159); "Begin recovery" is the
   OUTLINE-stroke CTA (`--mk-pill-outline-stroke`, tokens.css:158). No Figma
   reference for this exact fill-swap was found, so this is this round's own
   interpretation of her verbal description — the two new tokens below
   (`--myk-header-cta-fg`, `--myk-header-cta-hover-bg`) are the whole
   mechanism, consumed in `css/myk-btn.css`'s `.myk-btn--outline` block with
   a fallback chain that leaves the 04-ecology CTA (the only OTHER consumer
   of `.myk-btn--outline`, where these two tokens are unset) byte-identical.
   The pill's rest BORDER is left tone-adaptive (unchanged) so the pill
   shape stays legible against whatever photo sits behind it; only the fill
   and the label identity change. Hover border is now `transparent` on both
   sides — the solid black fill carries the shape once it lands, an outline
   ring on top of a solid fill was not asked for and reads as clutter.

   R21 CORRECTION (`r21:cta-rest-color`) — the "same value rest and hover"
   reading above was WRONG and is superseded below. Founder, verbatim: "you
   messed up the original states of the Begin recovery... the turquoise text
   is ONLY on the hover." R20-03 turned turquoise into the CTA's constant
   identity at both states; she is saying REST was never supposed to change —
   only HOVER. Left in place above as the historical record of how the
   mistake happened (a plausible-sounding misreading of "turquoise text that
   you would swap the color of the background to be black", taken to mean
   the text itself was the constant, when she meant the fill swap happens ON
   HOVER and TEXT ALSO GOES turquoise ON HOVER, not at rest). The light-text
   block below now reverts CTA REST to a non-turquoise value; HOVER
   (`--myk-header-cta-hover-fg` turquoise, `--myk-header-cta-hover-bg` black)
   is UNCHANGED — that half of R20-03's reasoning stands, confirmed correct
   by her own words. Dark-text's CTA block was NOT touched this round — she
   scoped the correction to "the white version" specifically; whether the
   same conceptual issue exists there is reported, not fixed, in this round's
   ledger/helix entry. */
#header-outer.light-text {
  --myk-header-ink:              var(--mk-ink-inverse);   /* wordmark text, hamburger bars — today's unconditional look */
  --myk-header-wordmark-o:       var(--mk-teal-wordmark);
  /* R20-02: REST 75% white, restored — was `var(--mk-ink-inverse)` (flat
     100%, indistinguishable from hover). See the round banner above for the
     full evidence trail and the deliberate-reversal flag. */
  --myk-header-btn-fg:           rgba(255, 255, 255, 0.75);
  --myk-header-btn-hover-fg:     var(--mk-ink-inverse);   /* nav links, search icon — hover, 100% white, UNCHANGED (N1 settled at 100%, figma-truth/00-hero.spec.md §4, OPEN-BTN-3) */
  --myk-header-cta-border:       var(--mk-pill-outline-stroke, #ffffff);
  --myk-header-cta-hover-border: transparent;
  /* R21 CORRECTION (`r21:cta-rest-color`) — R20-03 set REST to
     `var(--mk-teal, #1eb2bc)`, the same turquoise as HOVER. Founder,
     verbatim: "the turquoise text is ONLY on the hover" — REST must NOT be
     turquoise. Reverted to `var(--myk-header-btn-fg)`, matching the ACTUAL
     pre-round-20 treatment, confirmed by git history (`git show
     689d0d660^:build/v1-en/css/site.css`): before round 20 there was no
     separate `--myk-header-cta-fg` token at all — the CTA read
     `--myk-header-btn-fg` directly, the exact same token nav links/search
     use at rest, with the comment "nav links, search icon, CTA — rest" on
     that one declaration. This restores that shared-token relationship
     rather than inventing an independent hardcoded value; today that
     resolves to R20-02's `rgba(255,255,255,0.75)` (75% white), which the
     founder did NOT object to — only R20-03's turquoise-at-rest is being
     corrected. Live-measured 2026-08-30: composited 75% white over the
     hero's `--mk-hero-ground` #0b0f12 is ~10.9:1, comfortably clear of the
     4.5:1 AA floor `inv_header_contrast.py`'s `hero_light_text` case
     enforces (that check reads `getComputedStyle` live and does not
     hard-code an expected hex, so it needed no edit — it now simply
     measures the corrected REST color instead of the mistaken one).
     HOVER is UNCHANGED — turquoise text on a black fill remains correct
     per her own words ("ONLY on the hover" confirms hover SHOULD be
     turquoise); she did not object to the black-fill hover behavior. */
  /* R23 CORRECTION (`r23:cta-hover-figma`) — R21's "black fill on hover"
     reading above is WRONG for THIS tone (light-text / white-outline) and is
     superseded here. Founder, verbatim: "if it's the white outline, when I
     hover on it, I expect the button to stay white and the text on the
     button to be turquoise... the Figma file is the source of truth... it
     shows here that the white outline button, the hover state for that...
     is that it's white with the drop shadow with the turquoise text on it...
     the opposite version, if it's the dark outline, then... make it a black
     button with the turquoise text on it." Confirmed against
     `review/branding/buttons.md` §3.2 "SECONDARY — the white outline ghost"
     (node IDs 3269:5605/3269:5607, edge-pixel-scan proofs) rather than only
     her verbal description: hover fill is `#F4F9FB` solid, border drops to
     none, label goes turquoise, shadow `0 4px 4px rgba(0,0,0,.15)` — never
     black. Black-fill hover was this tone's `--myk-header-cta-hover-bg`
     value from R20-03 onward and was simply never re-examined against the
     Figma spec when R21 corrected the adjacent rest-color question; this is
     that missed check, done now. `--mk-surface-mist` (tokens.css:45,
     #f4f9fb) is reused rather than a bare literal — it is this exact value,
     already named, per this file's own convention of naming shared colors.
     The drop shadow needs no new rule: `.myk-btn`'s base
     `--myk-btn-hover-shadow: 0 4px 4px rgba(0,0,0,.149)` (myk-btn.css §1)
     is the DEFAULT hover-shadow for every button including
     `.myk-btn--outline` (the CTA's own class), which does not override it —
     so the shadow already renders on this CTA's hover and needs no change
     here. `--myk-header-cta-hover-border` (line 699, `transparent`) and
     `--myk-header-cta-hover-fg` (below, turquoise) were ALREADY correct per
     this same spec and are untouched. The dark-text block below (line ~776)
     is NOT touched by this correction — she scoped it to "the white
     outline" specifically; see that block's own comment for the open
     rest-state-family question this leaves for her to weigh in on. */
  --myk-header-cta-fg:           var(--myk-header-btn-fg);
  --myk-header-cta-hover-fg:     var(--mk-teal, #1eb2bc);
  --myk-header-cta-hover-bg:     var(--mk-surface-mist, #f4f9fb);
}
#header-outer.dark-text {
  /* MEASURED, not the naive default — real WCAG relative-luminance contrast
     of `--mk-teal-wordmark` (#01bfa5) against every light section surface in
     the tone map: mist #f4f9fb 2.20:1 · haze #e6eef2 1.99:1 · stone #cbd6dc
     1.58:1 · plain #f5f5f5 2.14:1 · white #ffffff 2.33:1 — all five fail
     WCAG AA (needs 4.5:1 normal text, 3:1 UI/large-text). This deepened
     value in the SAME hue clears 4.5:1 against the darkest surface (stone):
     5.35:1 there, 6.74-7.92:1 against the other four. Carried over unchanged
     from the block this replaces — still a NEW token, not yet in
     tokens.css, flagged here rather than silently promoted so the founder
     can confirm the exact hex or substitute her own; still this one
     declaration is its only consumer. */
  --myk-teal-wordmark-on-light: #015c51;
  --myk-header-ink:              var(--mk-ink-body);
  /* R24 RESTORED (2026-08-30, same day) — a background verification agent
     reverted this to the WCAG-deepened value below, on the grounds that no
     `founder-trace/*.md` document records the instruction and round 22's
     own resume doc says this question was left deferred. That agent had no
     visibility into the actual source: Jehnean gave this instruction
     directly, live, in chat, verbatim: "the o on the mykrobial logo, make
     that the bright green even when the text is dark." The contrast
     tradeoff (raw `--mk-teal-wordmark` scores 1.58:1-2.33:1 against this
     tone's light-section surfaces, below the 4.5:1 AA floor) was
     explicitly surfaced to her in that same conversation before applying
     it, and she did not object or walk it back. Restoring per her direct
     instruction. This repo evidently has a SEPARATE, more formal
     round-dispatch discipline (founder-trace/, _progress/LEDGER.jsonl) that
     a different process/session expects changes to flow through — this
     value was never filed into that system, which is why an agent
     reading only the repo's own files, with no memory of this
     conversation, concluded it was unauthorized. Surfaced to Jehnean;
     reconciling the two tracking systems is a follow-up, not something
     resolved by silently discarding her live instruction. */
  --myk-header-wordmark-o:       var(--mk-teal-wordmark);
  /* R20-02: REST 75% ink-body (mirrors the light-text step above, same
     literal-rgba style already used for this exact hex elsewhere —
     tokens.css:161 `--mk-pill-hairline-dark`, #1a2328 = rgb(26,35,40)).
     HOVER: was turquoise (`var(--mk-teal, #1eb2bc)`) — the confirmed,
     explicitly-rejected defect this item exists to fix — now 100% ink-body,
     zero turquoise anywhere in dark-text nav-link hover. */
  --myk-header-btn-fg:           rgba(26, 35, 40, 0.75);
  --myk-header-btn-hover-fg:     var(--mk-ink-body);
  --myk-header-cta-border:       var(--mk-ink-body);
  /* R20-03: was `var(--mk-ink-body)` (border held on hover) — now
     transparent, matching the light-text side; see the round banner. */
  --myk-header-cta-hover-border: transparent;
  /* R20-03 REST: raw `--mk-teal` measured 1.74:1 against
     `--mk-surface-stone` (`review/regression/invariants/
     inv_header_contrast.py`'s own `amenities_dark_text` case caught this
     LIVE, first pass — a real regression, not a hypothetical) — nowhere
     near the 4.5:1 AA floor that same gate enforces for every header text
     element including this one. `--myk-teal-wordmark-on-light`
     (declared two lines up, #015c51) already exists in this exact block
     for the identical problem on the wordmark-O, already measured against
     all five light-section surfaces in the tone map: 5.35:1 (stone, the
     regression suite's own anchor) up to 7.92:1 (white). Reused here
     rather than inventing a second deepened value — same problem, same
     fix, same block. It is a visibly DEEPER teal than the light-text
     side's brand value, a real, documented brand-vs-accessibility
     trade-off (the founding tension R20-01 through R20-03 all share) —
     flagged for the founder to confirm or substitute her own hex, exactly
     as the wordmark-O comment already asks for its own.
     REST-only: HOVER swaps the background to solid black
     (`--mk-header-cta-hover-bg` below), and raw `--mk-teal` measures
     8.15:1 against `--mk-ink-strong` #000000 — comfortably clears AA
     there, so hover keeps the brighter brand value; only the state that
     sits directly on a light section surface needs the deepened one. */
  /* R24 RESTORED (2026-08-30, same day) — a background verification agent
     reverted this to the pre-R24 value, on the grounds that
     `founder-trace/FT-20260830-jehnean-round24-queued-contrast.md` marks
     this item "not dispatched yet" pending round 23's formal close in
     `_progress/LEDGER.jsonl`, which never reached a done event. That agent
     had no visibility into the actual source: Jehnean gave this
     instruction directly, live, in chat, verbatim: "instead of begin
     recovery being the same color as the outline, it's turquoise, and
     that does not match our design guidelines per what's in Figma. It
     should only be using that turquoise on black on the hover... the
     default state... it should just be black text matching the same
     color black... on the outline." This also answers the R23 NOTE's own
     open question (this exact block, a few lines up), which was already
     flagging this as unresolved before R24 touched it at all. Restoring
     per her direct instruction — REST now reads `--myk-header-cta-border`
     directly, byte-guaranteed to match the outline. HOVER is unchanged
     (turquoise-on-black, per her own "only... on the hover"). Same
     dual-tracking-system caveat as the wordmark-O restoration immediately
     above: this repo has a separate, more formal round-dispatch discipline
     that a different process/session expects changes to flow through, and
     this value was never filed into it — surfaced to Jehnean; reconciling
     the two systems is a follow-up. */
  --myk-header-cta-fg:           var(--myk-header-cta-border);
  --myk-header-cta-hover-fg:     var(--mk-teal, #1eb2bc);
  --myk-header-cta-hover-bg:     var(--mk-ink-strong, #000000);
}

/* R25 (`r25:split-nav`) — WITHDRAWN, 2026-08-30, same session it was built.
   A `.split-text` state + clip-path'd clone-overlay (`.myk-header-split-
   overlay`) lived here, meant to let the nav read both tones in one bar.
   Pulled after three layered bugs surfaced in one session (a dropped `>`
   that corrupted the DOM, a clone that lost its `id="top"` layout ancestor,
   then a subtler clone/real misalignment) — see js/myk-header-scroll.js's
   own withdrawal note for the full account. Re-attempting this needs a
   slower pass with screenshot verification from the start, not a
   same-session patch. */

/* R26 (`r26:split-nav-per-element`) — the split-nav retry, zero cloning.
   Rather than painting a second header on top of the real one, this exposes
   the SAME two tone palettes the `.light-text` / `.dark-text` blocks above
   already declare, but under tone-NEUTRAL custom-property names, declared
   UNCONDITIONALLY on `#header-outer` (not gated by either class). That lets
   js/myk-header-scroll.js apply one of the two palettes to a single
   tone-bearing element inline — `el.style.setProperty("--myk-header-ink",
   "var(--myk-tone-a-ink)")` and siblings — without touching the ambient
   `.light-text`/`.dark-text` class the rest of the header still reads normally
   for every element it does NOT override. No clone, no clip-path, no second
   DOM subtree: the real header's own elements just get told, individually,
   to resolve their existing `--myk-header-*` custom properties from the
   OTHER tone's values instead of the ambient one.
   tone-a mirrors `.light-text` above (lines 690-755) · tone-b mirrors
   `.dark-text` above (lines 756-841), value-for-value. THEY MUST STAY IN
   SYNC BY HAND — same obligation,
   same reasoning, as myk-btn.css §5's "must stay in sync with §1/§2... the
   cost of Salient's cascade, and it is cheaper than the alternative, which
   is losing." If either source block above changes, mirror the change here
   in the same edit, not a follow-up one.

   NOTE ON A PROCESS FAILURE, not a design one: a verification agent
   flagged (correctly, as a real bug) that this block used to reference
   `--myk-teal-wordmark-on-light` for tone-b's wordmark-o and cta-fg — a
   custom property scoped ONLY inside `#header-outer.dark-text`, so it
   would have resolved to nothing (CSS guaranteed-invalid) if this
   unconditional block were ever read while `.dark-text` was NOT the active
   class. That flag was correct. Its proposed fix — reverting `.dark-text`'s
   own `--myk-header-wordmark-o` and `--myk-header-cta-fg` back to
   `--myk-teal-wordmark-on-light`, undoing Jehnean's own direct live
   instruction earlier this session — was not; see `.dark-text`'s own
   "R24 RESTORED" comments above for the full account. The actual fix,
   applied here: tone-b's wordmark-o and cta-fg now use the SAME
   self-contained values `.dark-text` itself was restored to
   (`var(--mk-teal-wordmark)` and `var(--mk-ink-body)`), which never
   depended on the class-scoped token to begin with. */
#header-outer {
  --myk-tone-a-ink:              var(--mk-ink-inverse);
  --myk-tone-a-wordmark-o:       var(--mk-teal-wordmark);
  --myk-tone-a-btn-fg:           rgba(255, 255, 255, 0.75);
  --myk-tone-a-btn-hover-fg:     var(--mk-ink-inverse);
  --myk-tone-a-cta-fg:           var(--myk-tone-a-btn-fg);
  --myk-tone-a-cta-border:       var(--mk-pill-outline-stroke, #ffffff);
  --myk-tone-a-cta-hover-border: transparent;
  --myk-tone-a-cta-hover-fg:     var(--mk-teal, #1eb2bc);
  --myk-tone-a-cta-hover-bg:     var(--mk-surface-mist, #f4f9fb);

  --myk-tone-b-ink:              var(--mk-ink-body);
  --myk-tone-b-wordmark-o:       var(--mk-teal-wordmark);
  --myk-tone-b-btn-fg:           rgba(26, 35, 40, 0.75);
  --myk-tone-b-btn-hover-fg:     var(--mk-ink-body);
  --myk-tone-b-cta-border:       var(--mk-ink-body);
  --myk-tone-b-cta-hover-border: transparent;
  --myk-tone-b-cta-fg:           var(--mk-ink-body);
  --myk-tone-b-cta-hover-fg:     var(--mk-teal, #1eb2bc);
  --myk-tone-b-cta-hover-bg:     var(--mk-ink-strong, #000000);
}


/* ==========================================================================
   2. FOOTER — 21-logos-footer.spec.md, EN frame 3016:431
   Two stacked bands: Logos (105.88) + Footer (794.12) = 900 exactly.
   ========================================================================== */

.mk-footer { width: 100%; }

/* --- 2.1 Logo strip — 21 §1.1 (3016:450) -------------------------------
   Height is FIXED at 105.88, not hugged. The declared 48/48 padding leaves a
   9.88px content box that the 27px row overflows symmetrically. Build the
   fixed height and centre the row; do NOT reproduce the padding as padding. */
.mk-logos {
  height: 105.88px;
  background: var(--mk-surface-ink);
  display: flex;
  align-items: center;
  justify-content: center;
}
.mk-logos__row {
  width: 100%;
  max-width: var(--mk-frame);
  margin-inline: auto;
  padding-inline: var(--mk-page-x);
  height: 27px;
  display: flex;
  align-items: center;
  gap: var(--mk-space-48);                  /* itemSpacing 48 */
  opacity: 0.5;                             /* applies to label AND logos */
  /* The declared #ffffff@10% top/bottom hairlines DO NOT RENDER — verified
     pixel by pixel across the 2x export (21 §1.1.1). Do not draw them. */
}
.mk-logos__label {
  font-family: var(--mk-font-sans);
  font-weight: var(--mk-w-regular);
  font-size: var(--mk-size-body-sm);        /* 18 */
  line-height: 27px;
  color: rgba(255, 255, 255, 0.5);          /* x the 0.5 row opacity = 25% */
  white-space: nowrap;
}
.mk-logos__mark { height: 24px; width: auto; display: block; flex: 0 0 auto; }
.mk-logos__mark--doi { filter: drop-shadow(var(--mk-shadow-logo)); } /* only effect in §4.2 */

/* --- 2.2 Footer body — 21 §1.2 (3016:432) ------------------------------ */
.mk-footer__body {
  background: var(--mk-surface-footer);
  padding: var(--mk-section-y) var(--mk-page-x);   /* 48 / 120 */
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--mk-space-24);                  /* itemSpacing 24 */
  min-height: 794.12px;
}
/* 1040 is `1280 - 240` hard-coded, i.e. the 1280 content width. The footer body
   already has its own correct `padding: 48px 120px` above, so this cap was the
   only thing holding the link row in at 1440. Derived from the frame it becomes
   1040 at 1280 (unchanged) and 1200 at 1440 — 21 §2.2/§5.2's read value
   (1074+24+18+24+18+24+18 = 1200; right edge 1302+18 = 1320 = 1440-120).
   review/deepdive/responsive-1440.md §1.3. */
.mk-footer__inner { width: 100%; max-width: calc(var(--mk-frame) - 2 * var(--mk-page-x)); }

/* Link row: 5 equal fill tracks, gutter 30 at 1280. `Footer text` is
   layoutGrow:1 in EN (fills the leftover height) but a hug in ES — the single
   biggest EN/ES structural divergence (21 §1.2). EN takes the fill. */
.mk-footer__links { flex: 1; align-items: center; }   /* counterAxis CENTER */

.mk-footer__col {
  font-family: var(--mk-font-sans);
  font-weight: var(--mk-w-light);           /* 300 for BOTH heading and links */
  font-size: var(--mk-size-base);           /* 16 */
  line-height: var(--mk-lh-node);           /* 24 */
  display: flex;
  flex-direction: column;
  gap: var(--mk-para-gap);                  /* 12 -> 36px item-to-item advance */
}
/* Line 1 of each column is 25% white; every following line is 100% white.
   Both were recovered from the render — the API returned fills:"mixed". */
.mk-footer__col > :first-child { color: rgba(255, 255, 255, 0.25); }
.mk-footer__col a { color: var(--mk-ink-inverse); text-decoration: none; }
.mk-footer__col a:hover { text-decoration: underline; }

.mk-footer__newsletter-heading {
  font-family: var(--mk-font-serif);
  font-optical-sizing: auto;          /* opsz = font-size — tokens.css
                                         "MERRIWEATHER OPTICAL SIZE" */
  font-variation-settings: "wdth" 100;
  font-weight: var(--mk-w-medium);          /* Merriweather Medium 500 */
  font-size: var(--mk-size-body-sm);        /* 18 */
  line-height: 23px;                        /* node height */
  text-align: center;
  color: var(--mk-ink-inverse);
}

/* Newsletter: field + button, 4px apart, mirrored asymmetric radii. §1.2.3 */
.mk-newsletter { display: flex; align-items: center; gap: var(--mk-space-4); height: 48px; }
/* Salient's material skin restyles every input and button (white field, 4px
   radius, 10px padding, Inter 14/600, 200px pill on buttons). Each property
   below therefore has to out-specify it — `body .mk-footer …` does that, and
   the `!important`s mirror the ones Salient itself uses. */
body .mk-footer .mk-newsletter__field {
  width: 266px !important;
  height: 48px !important;
  box-sizing: border-box;
  background: var(--mk-surface-field) !important;
  border: 0 !important;
  box-shadow: none !important;
  border-radius: var(--mk-radius-field) !important; /* 54 4 4 54: left cap is a semicircle */
  padding: 12px 24px 12px 26px !important;
  margin: 0 !important;
  font-family: var(--mk-font-sans) !important;
  font-weight: var(--mk-w-light) !important;
  font-size: var(--mk-size-base) !important;        /* 16, not Salient's 14 */
  line-height: var(--mk-lh-node) !important;
  color: var(--mk-ink-inverse) !important;
}
body .mk-footer .mk-newsletter__field::placeholder { color: var(--mk-ink-inverse); opacity: 1; }
/* The field is the one focusable control in the footer and it had NO focus
   indicator of any kind: a full computed-style diff focused-vs-blurred across
   outline / box-shadow / background / border / color / text-decoration / filter
   came back empty. WCAG 2.4.7 (AA). It has to be an OUTLINE and not a ring —
   the rule directly above sets `box-shadow: none !important` on this element,
   so a box-shadow ring is silently swallowed. `!important` on the outline
   because Salient's material skin re-declares the focus outline on inputs. */
body .mk-footer .mk-newsletter__field:focus-visible {
  outline: 2px solid var(--mk-ink-inverse) !important;
  outline-offset: 2px !important;
}
body .mk-footer .mk-newsletter__btn {
  height: 48px !important;
  min-width: 0;
  box-sizing: border-box;
  background: var(--mk-ink-inverse) !important;
  color: var(--mk-ink-strong) !important;   /* the ONLY black text in the footer */
  border: 0 !important;
  box-shadow: none !important;
  border-radius: var(--mk-radius-field-btn) !important; /* 4 54 54 4 */
  padding: 12px 26px 12px 24px !important;  /* hug: 24 + label + 26 = 84 */
  margin: 0 !important;
  font-family: var(--mk-font-sans) !important;
  font-weight: var(--mk-w-medium) !important;
  font-size: var(--mk-size-base) !important;
  line-height: var(--mk-lh-node) !important;
  letter-spacing: normal !important;
  text-transform: none !important;
  cursor: pointer;
}

/* Bottom row: fill-width disclaimer + three 18px icons, last flush right. */
.mk-footer__bottom {
  display: flex;
  align-items: center;
  gap: var(--mk-space-24);
  padding-top: var(--mk-space-24);
  height: 72px;
  width: 100%;
}
.mk-footer__disclaimer {
  flex: 1;                                  /* 914 + 24+18+24+18+24+18 = 1040 */
  font-family: var(--mk-font-sans);
  font-weight: var(--mk-w-light);
  font-size: var(--mk-size-base);
  line-height: var(--mk-lh-node);
  color: var(--mk-ink-inverse);
}
.mk-footer__social { width: 18px; height: 18px; display: block; flex: 0 0 auto; }
.mk-footer__social svg { width: 100%; height: 100%; fill: var(--mk-ink-inverse); }

/* --- 2.3 Logo scroller — founder note on section 21 points at
   http://127.0.0.1:5010/salient/tether/index.html. The tether "Trusted by"
   row is a Flickity ticker: .nectar-flickity.ticker-rotate with
   data-ticker-speed="slow" data-autoplay="true" data-mask-edges="true"
   data-spacing="30px" data-controls="none". Lift that markup verbatim when
   the scroller variant is built; the vendored flickity JS+CSS are already
   loaded for it. The static strip above is the Figma-authored default. ---- */

/* ==========================================================================
   3. SKIP LINK — Salient ships one; keep it visible on focus
   ========================================================================== */
.nectar-skip-to-content:focus {
  position: fixed; top: 8px; left: 8px; z-index: 99999;
  background: var(--mk-ink-inverse); color: var(--mk-ink-strong);
  padding: 8px 16px; border-radius: var(--mk-radius-card);
}

/* ==========================================================================
   4. SECTION PLACEHOLDER — visible only until a section builder replaces it.
   Deliberately loud: an unbuilt section must never be mistaken for a built one.
   ========================================================================== */
.mk-section--todo {
  min-height: 240px;
  display: flex; align-items: center; justify-content: center;
  background: repeating-linear-gradient(45deg,
    var(--mk-surface-mist) 0 24px, var(--mk-surface-haze) 24px 48px);
  font-family: var(--mk-font-sans);
  font-weight: var(--mk-w-medium);
  font-size: var(--mk-size-base);
  letter-spacing: var(--mk-track-eyebrow);
  text-transform: uppercase;
  color: var(--mk-ink-body);
}
/* The hero placeholder is dark because the real hero is a photo under an
   opaque-tailed scrim, and the transparent nav can only be judged over a dark
   ground. Delete this rule with the placeholder when 00-hero is built. */
#s00-hero.mk-section--todo {
  min-height: 900px;
  background: repeating-linear-gradient(45deg,
    var(--mk-surface-ink) 0 24px, #12181c 24px 48px);
  color: rgba(255, 255, 255, 0.45);
}

/* ==========================================================================
   5. MOBILE HEADER-SIZING BLOCK — this round (FT founder feedback, 2026-08-31)
   --------------------------------------------------------------------------
   SIZING ONLY, phone tier only (<=690). Wordmark 16 -> 18, search glyph
   18 -> 21, hamburger glyph 18x14 -> 21x16 (bars stay 2px so they render
   crisp; +3 wide, pitch 6 -> 7). No tone/colour token is touched or
   duplicated — every colour still resolves through the §1/§1B machinery, and
   no --myk-header-* custom property is written. Selectors are copied from
   their §1 counterparts so each rule wins by file order at equal specificity;
   the frames (search 54x34, menu 60x40) are NOT resized, so alignment stays
   the flex-centring the frames already do and the nav row geometry is
   untouched. >=691px is unreachable from here by construction.
   ========================================================================== */
@media only screen and (max-width: 690px) {
  /* wordmark — §1's own selector trio, size only */
  body #header-outer #top #logo,
  body #header-outer.transparent #top #logo,
  #header-outer .mk-wordmark {
    font-size: 18px !important;              /* var(--mk-size-base) 16 -> 18  */
  }
  /* search — the 18x18 svg carries width/height ATTRIBUTES (head-tail.html),
     so the override must be CSS on the svg itself; viewBox scales the path. */
  #mk-search-toggle.myk-btn--icon svg { width: 21px; height: 21px; }
  /* hamburger — the §1 window/glyph/bar ladder restated at 21x16.
     Bar height stays 2px; short bottom bar keeps its 13/18 ratio -> 15.
     The MIDDLE bar is 00-hero.css C.5's `.lines-button::after`, whose width,
     park offset (-26), hover travel (+26) and open travel (+52) ALL derive
     from `--nectar-ocm-icon-width` — retarget the ONE variable (C.5's own
     method) and every distance rescales to -29/+29/+58. `.myk-btn--icon`
     is the extra class that outranks C.5's (0,1,1,0) declaration, which
     loads AFTER this file. `--mk-close-size` rides along for the open-state
     X — C.6 sizes it to match the search glyph, which is now 21. */
  #header-outer .slide-out-widget-area-toggle.myk-btn--icon {
    --nectar-ocm-icon-width: 21px;
    --mk-close-size: 21px;
  }
  body #header-outer .slide-out-widget-area-toggle a > span {
    width: 21px !important;
    height: 16px !important;
  }
  #header-outer .slide-out-widget-area-toggle .lines-button { width: 21px; height: 16px; }
  /* middle bar y: C.5 pins top:6 for the 14px glyph at (0,1,3,2 max);
     one more class beats it in both header states. */
  body #header-outer .slide-out-widget-area-toggle.myk-btn--icon .lines-button::after,
  body #header-outer.transparent .slide-out-widget-area-toggle.myk-btn--icon .lines-button::after {
    top: 7px;
  }
  body #header-outer .slide-out-widget-area-toggle .lines,
  body #header-outer .slide-out-widget-area-toggle .lines::before,
  body #header-outer .slide-out-widget-area-toggle .lines::after,
  body #header-outer.transparent .slide-out-widget-area-toggle .lines,
  body #header-outer.transparent .slide-out-widget-area-toggle .lines::before,
  body #header-outer.transparent .slide-out-widget-area-toggle .lines::after {
    width: 21px !important;
  }
  body #header-outer .slide-out-widget-area-toggle .lines         { top: 7px; }
  body #header-outer .slide-out-widget-area-toggle .lines::before { top: -7px; }
  body #header-outer .slide-out-widget-area-toggle .lines::after,
  body #header-outer.transparent .slide-out-widget-area-toggle .lines::after {
    top: 7px; width: 15px !important;
  }
}
