/* ════════════════════════════════════════════════════════════════════════
   css/chrome.css — the shared chrome for Tier 1 and Tier 2.
   service.tnaado.ca · pairs with partials/chrome.html + js/chrome.js

   ONE STRUCTURAL IDEA, and it is css/scene.css's idea applied to the chrome:
   everything OUTSIDE html.chrome-live is the page as it exists with no
   JavaScript — a bar, a plain list of five in-page links, a full navigation
   tree with every submenu open, and a footer, all in normal flow, in reading
   order. Everything inside html.chrome-live is the summoned version. Only
   js/chrome.js can add that class, and it adds it as its first act.

   Consequence, not negotiable: NO RULE OUTSIDE .chrome-live MAY FIX, PARK,
   CLIP OR HIDE A SHEET. If you write `.navsheet { transform: translateY(-101%) }`
   at the top level, the no-JS navigation is gone.

   WHY DOM ORDER AND VISUAL ORDER DISAGREE. The bypass row is the first thing
   after the skip link in the markup, because a keyboard or screen-reader user
   should meet the shortcut past the animation before meeting the logo. It is
   drawn second, under the bar, because that is where a sighted reader looks for
   it. `order` on a flex container is the only mechanism that separates the two
   without moving the markup — it does not touch tab order, which is the point.

   COLOUR. Locals, resolved from the page's tokens with the locked brand values
   as fallbacks, so this sheet renders correctly on a page that has not defined
   them and inherits the page's if it has. --red (#c8102e) is 3.37:1 on ink and
   is used here ONLY as rules and fills, never as text. Every text colour in
   this file is measured: --c-dim #b9b3a6 = 9.4:1, --c-quiet rgba(bone,.62) =
   7.2:1, --c-red-ink #ef5c6e = 6.06:1. The index's chrome used rgba(bone,.42)
   for its door numerals, which is 3.77:1 and fails AA; that value is not
   reproduced here.

   NO BACKDROP-FILTER, ANYWHERE. A blurred backdrop over a full-screen animated
   canvas is a per-frame full-screen blur on the compositor. Flat alpha only.
   ════════════════════════════════════════════════════════════════════════ */

.chrome,
.chrome-foot {
  --c-ink:      var(--ink, #0a0a0a);
  --c-bone:     var(--bone, #f5f1e8);
  --c-red:      var(--red, #c8102e);
  --c-red-ink:  var(--red-ink, #ef5c6e);
  --c-dim:      var(--dim-ink, #b9b3a6);
  --c-quiet:    rgba(245, 241, 232, .62);
  --c-hair:     var(--hair-ink, rgba(245, 241, 232, .14));
  --c-sans:     var(--sans, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif);
  --c-pad:      clamp(1.25rem, 4vw, 3rem);
  --c-ease:     cubic-bezier(.22, 1, .36, 1);
  --c-dur:      .35s;
}

/* Both wrappers are transparent to layout in the live state; in the static
   state .chrome is the flex column that re-orders the bar above the row, and
   .chrome-foot is nothing at all — its two children are body-level blocks. */
.chrome { display: flex; flex-direction: column; }
.chrome-foot { display: contents; }
.menubar  { order: 1; }
.bypass   { order: 2; }
/* The nav sheet is LAST in the static stack and must say so: without an explicit
   order it takes the default 0 and lands above the bar, which measured as
   visual order [navsheet, menubar, bypass] on the JS-off page. */
.navsheet { order: 3; }

/* NO SCRIPT: every control that only a script can honour is removed, because a
   button that does nothing is worse than no button. What is left is a bar, a
   plain list of five in-page links, the whole navigation tree with every
   submenu open, and a footer -- all of it in flow, in reading order. */
html:not(.chrome-live) .menubar__btn,
html:not(.chrome-live) .bypass__toggle,
html:not(.chrome-live) .navsheet__close,
html:not(.chrome-live) .footsheet__close,
html:not(.chrome-live) .footpull,
html:not(.chrome-live) .door__more { display: none; }

/* ── UTILITIES ─────────────────────────────────────────────────────────── */
/* Scoped as .chrome .u-skip so a page's own `.u-skip { z-index: 90 }` — which
   __storm-page.html has, and which would otherwise win on load order and bury
   the skip link under the bar — cannot outrank it. */
.chrome .u-skip {
  position: fixed; left: 1.5rem; top: 1.5rem; z-index: 1240;
  background: var(--c-bone); color: var(--c-ink);
  padding: .75rem 1.125rem;
  font-family: var(--c-sans); font-size: .8125rem; font-weight: 600;
  text-decoration: none;
  transform: translateY(-300%);
}
.chrome .u-skip:focus { transform: none; }
.chrome .u-vh, .chrome-foot .u-vh {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}
.chrome :focus-visible, .chrome-foot :focus-visible {
  outline: 2px solid var(--c-red-ink); outline-offset: 3px;
}

/* ── THE MENU BAR ──────────────────────────────────────────────────────── */
.menubar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1.5rem;
  padding: .8rem var(--c-pad);
  font-family: var(--c-sans);
}
.menubar__brand { display: flex; align-items: center; text-decoration: none; }
/* Height-driven at the lockup's native 240x55, so the ratio cannot be squashed
   by a width guess. */
.menubar__logo { height: 26px; width: auto; display: block; }

/* THE DESCRIPTOR. Present on Tier 1 and Tier 2 and absent on Tier 0: a storm
   page can be landed on cold from a paid ad, so the chrome is the only surface
   guaranteed to be on the page the stranger arrived at. Never two lines; below
   860px it is the first thing to go, since a phone bar cannot carry it. */
.menubar__desc {
  margin: 0; flex: 0 1 auto;
  font-size: .6875rem; letter-spacing: .09em; text-transform: uppercase;
  color: var(--c-dim); white-space: nowrap; overflow: hidden;
}
.menubar__btn {
  display: inline-flex; align-items: center; gap: .6rem;
  background: none; border: 0; cursor: pointer; padding: .35rem .1rem;
  font-family: inherit; font-size: .6875rem; font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--c-dim);
  transition: color .22s var(--c-ease);
}
.menubar__bars { display: grid; gap: 3px; width: 18px; }
.menubar__bars i {
  display: block; height: 1px; background: currentColor;
  transition: transform .22s var(--c-ease);
}
/* The three bars lean into the funnel's taper — each shorter than the last — so
   the control is a small picture of the thing it opens. */
.menubar__bars i:nth-child(2) { width: 76%; margin-left: 12%; }
.menubar__bars i:nth-child(3) { width: 48%; margin-left: 26%; }
@media (hover: hover) and (pointer: fine) {
  .menubar__btn:hover { color: var(--c-bone); }
  .menubar__btn:hover .menubar__bars i:nth-child(2) { transform: translateX(2px); }
  .menubar__btn:hover .menubar__bars i:nth-child(3) { transform: translateX(4px); }
}

/* ── THE BYPASS ROW ────────────────────────────────────────────────────── */
.bypass { font-family: var(--c-sans); }
.bypass__list {
  display: flex; align-items: stretch; flex-wrap: wrap;
  gap: 0 clamp(.75rem, 2.2vw, 2rem);
  margin: 0; padding: .1rem var(--c-pad) .35rem;
  list-style: none;
}
.bypass__list a {
  display: inline-flex; align-items: baseline; gap: .5rem;
  padding: .45rem 0;
  border-bottom: 2px solid transparent;
  font-size: .6875rem; font-weight: 600; letter-spacing: .14em;
  text-transform: uppercase; text-decoration: none;
  color: var(--c-dim);
  transition: color .2s var(--c-ease), border-color .2s var(--c-ease);
}
.bypass__n {
  font-style: normal; font-size: .625rem; letter-spacing: .1em;
  font-variant-numeric: tabular-nums; color: var(--c-quiet);
}
@media (hover: hover) and (pointer: fine) {
  .bypass__list a:hover { color: var(--c-bone); border-bottom-color: var(--c-hair); }
}
/* THE ONLY MARK OF POSITION, and it is driven by the attribute rather than by a
   class, so the aria state and the paint cannot drift apart: one write in
   js/chrome.js does both. --red as a 2px rule is a fill, which is what that
   value is for. */
.bypass__list a[aria-current] {
  color: var(--c-bone); border-bottom-color: var(--c-red);
}
.bypass__list a[aria-current] .bypass__n { color: var(--c-red-ink); }

/* The collapsed control. Hidden above 860px in every state; below it, the row's
   five labels do not fit a phone bar and would stop being chrome. */
.bypass__toggle { display: none; }

/* ── THE NAV SHEET ─────────────────────────────────────────────────────── */
.navsheet { font-family: var(--c-sans); background: var(--c-ink); }
.navsheet__inner {
  max-width: 68rem; margin: 0 auto;
  padding: clamp(2.5rem, 6vh, 4.5rem) var(--c-pad) 0;
}
.navsheet__kicker {
  margin: 0 0 1.4rem;
  font-size: .6875rem; font-weight: 600; letter-spacing: .18em;
  text-transform: uppercase; color: var(--c-red-ink);
}
.navsheet__kicker--firm { margin-top: 2.2rem; color: var(--c-quiet); }
.navsheet__doors { list-style: none; margin: 0; padding: 0; }

.door__row {
  display: flex; align-items: center; gap: 1rem;
  border-bottom: 1px solid var(--c-hair);
}
.door__link {
  flex: 1 1 auto;
  display: flex; align-items: baseline; gap: 1rem; flex-wrap: wrap;
  padding: .7rem 0;
  text-decoration: none; color: var(--c-bone);
  font-size: clamp(1.25rem, 3vw, 1.9rem); line-height: 1.1;
  transition: color .2s var(--c-ease);
}
.door__n {
  font-style: normal; font-size: .6875rem; font-weight: 600; letter-spacing: .12em;
  font-variant-numeric: tabular-nums; color: var(--c-quiet);
}
.door__link em {
  font-style: normal; font-size: .6875rem; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase; color: var(--c-dim);
}
/* The door a reader is already inside. It is still a link — a Tier 2 page has
   to be able to get back up to its own Tier 1 page from the chrome. */
.door__link[aria-current] { color: var(--c-bone); }
.door__link[aria-current] .door__n { color: var(--c-red-ink); }

/* The chevron is a SEPARATE control from the door. A summary that swallows its
   own link means a reader who wants /technology has to open a submenu to reach
   it, which is the "clean tree" turned back into a maze. */
.door__more {
  flex: 0 0 auto;
  width: 40px; height: 40px; display: grid; place-items: center;
  background: none; border: 0; cursor: pointer; color: var(--c-dim);
  transition: color .2s var(--c-ease);
}
.door__chev {
  display: block; width: 9px; height: 9px;
  border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  transition: transform .22s var(--c-ease);
}
.door__more[aria-expanded="true"] { color: var(--c-red-ink); }
.door__more[aria-expanded="true"] .door__chev { transform: translateY(2px) rotate(225deg); }
@media (hover: hover) and (pointer: fine) {
  .door__more:hover { color: var(--c-bone); }
  .door__link:hover { color: var(--c-bone); }
}
.door__sub {
  list-style: none; margin: 0; padding: .55rem 0 .9rem 2.1rem;
  display: flex; flex-direction: column; gap: .1rem;
  border-bottom: 1px solid var(--c-hair);
}
.door__sub a {
  display: inline-block; padding: .32rem 0;
  font-size: .8125rem; letter-spacing: .02em; text-decoration: none;
  color: var(--c-dim);
  transition: color .2s var(--c-ease);
}
@media (hover: hover) and (pointer: fine) { .door__sub a:hover { color: var(--c-bone); } }

.navsheet__firm { display: flex; flex-wrap: wrap; gap: .3rem 1.6rem; }
.navsheet__firm a {
  font-size: .6875rem; font-weight: 600; letter-spacing: .12em;
  text-transform: uppercase; text-decoration: none; color: var(--c-dim);
  padding: .3rem 0;
}
@media (hover: hover) and (pointer: fine) { .navsheet__firm a:hover { color: var(--c-bone); } }

.navsheet__cta {
  display: inline-block; margin: 1.8rem 0 0;
  padding: .6rem 1.1rem; border: 1px solid var(--c-red);
  font-size: .6875rem; font-weight: 600; letter-spacing: .12em;
  text-transform: uppercase; text-decoration: none; color: var(--c-bone);
  transition: background-color .2s var(--c-ease);
}
@media (hover: hover) and (pointer: fine) { .navsheet__cta:hover { background: var(--c-red); } }

.navsheet__close, .footsheet__close {
  position: absolute; top: 12px; right: 14px; z-index: 5;
  width: 34px; height: 34px; line-height: 1;
  background: rgba(245, 241, 232, .06);
  border: 1px solid rgba(245, 241, 232, .22);
  color: var(--c-bone); font-size: 1.1rem; cursor: pointer;
}

/* ── THE FOOT SHEET ────────────────────────────────────────────────────── */
.footpull {
  display: flex; align-items: center; gap: .8rem; width: 100%;
  padding: .85rem var(--c-pad);
  background: linear-gradient(to top, rgba(10, 10, 10, .92), rgba(10, 10, 10, 0));
  border: 0; cursor: pointer; text-align: left;
  font-family: var(--c-sans); font-size: .6875rem; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase; color: var(--c-dim);
  transition: color .22s var(--c-ease);
}
.footpull__rule { flex: 1 1 auto; height: 1px; background: var(--c-hair); }
.footpull__caret { transition: transform .22s var(--c-ease); }
/* The two elements a person aims at. Clicks bubble to the button, so the
   control still works with the bar itself inert. */
.chrome-live .footpull__label,
.chrome-live .footpull__caret { pointer-events: auto; }
@media (hover: hover) and (pointer: fine) {
  .footpull:hover { color: var(--c-bone); }
  .footpull:hover .footpull__caret { transform: translateY(-2px); }
}

.footsheet { background: var(--c-ink); }
.footdir { font-family: var(--c-sans); border-top: 3px solid var(--c-red); }
.footdir__inner { max-width: 74rem; margin: 0 auto; padding: 2.5rem var(--c-pad) 2rem; }
.footdir__grid {
  display: grid; gap: 2rem clamp(1.5rem, 3vw, 3rem);
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
}
.footdir__brand { grid-column: span 2; min-width: 0; }
.footdir__logo { height: 34px; width: auto; display: block; }
.footdir__tag { margin: .9rem 0 0; font-size: .8125rem; color: var(--c-dim); max-width: 22rem; }
.footdir__addr { margin: .6rem 0 0; font-size: .8125rem; font-style: normal; color: var(--c-dim); }
.footdir__col h2 {
  margin: 0 0 .8rem; font-size: .6875rem; font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase; color: var(--c-bone);
}
.footdir__col ul { list-style: none; margin: 0; padding: 0; }
.footdir__col li + li { margin-top: .35rem; }
.footdir__col a {
  font-size: .8125rem; text-decoration: none; color: var(--c-dim);
  transition: color .2s var(--c-ease);
}
@media (hover: hover) and (pointer: fine) { .footdir__col a:hover { color: var(--c-bone); } }
.footdir__legal {
  margin: 2rem 0 0; padding-top: 1.1rem; border-top: 1px solid var(--c-hair);
  font-size: .75rem; color: var(--c-dim);
}
.footdir__legal a { color: var(--c-red-ink); }

/* ════════════════════════════════════════════════════════════════════════
   LIVE. Everything below this line needs js/chrome.js to be running, and every
   rule above it is the page a crawler and a JS-off reader are served.
   ════════════════════════════════════════════════════════════════════════ */

/* The bar and the row travel together as ONE fixed slab, so the row never has
   to be told how tall the bar is — a measurement that would be wrong the moment
   the descriptor wraps or html.sc-live rescales the rem base at short heights. */
.chrome-live .chrome {
  position: fixed; top: 0; left: 0; right: 0; z-index: 1210;
  pointer-events: none;
}
.chrome-live .chrome > * { pointer-events: auto; }
.chrome-live .menubar {
  position: relative; z-index: 2;
  background: linear-gradient(to bottom, rgba(10, 10, 10, .96), rgba(10, 10, 10, .92));
}
.chrome-live .bypass {
  position: relative; z-index: 1;
  background: rgba(10, 10, 10, .92);
  border-top: 1px solid var(--c-hair);
}
/* The slab dissolves into the storm rather than ending on an edge. */
.chrome-live .bypass::after {
  content: ''; position: absolute; left: 0; right: 0; top: 100%; height: 26px;
  background: linear-gradient(to bottom, rgba(10, 10, 10, .92), rgba(10, 10, 10, 0));
  pointer-events: none;
}
.chrome-live .menubar__btn[aria-expanded="true"] { opacity: 0; pointer-events: none; }

.chrome-live .navsheet {
  position: fixed; top: 0; left: 0; right: 0; z-index: 3;
  display: flex; flex-direction: column;
  max-height: 92svh;
  box-shadow: 0 18px 50px rgba(0, 0, 0, .55);
  /* THE FUNNEL MOUTH. The lower edge is drawn in toward the centre so the open
     menu hangs over the page as the top of the storm rather than as a rectangle.
     Percentages, so the proportion holds at every width. */
  clip-path: polygon(0 0, 100% 0, 100% 90%, 66% 100%, 34% 100%, 0 90%);
  /* 101% so subpixel rounding at an odd DPR cannot leave a hairline showing. */
  transform: translateY(-101%);
  transition: transform var(--c-dur) var(--c-ease);
}
.chrome-live .navsheet.open { transform: translateY(0); }
/* The INNER scrolls, not the sheet: the close button is positioned on the sheet
   and has to stay put when a submenu makes the tree taller than the viewport.
   The padding-bottom keeps the last row clear of the taper. */
.chrome-live .navsheet__inner {
  flex: 1 1 auto; overflow-y: auto; overscroll-behavior: contain;
  padding-bottom: 5.5rem;
}
.door__sub[hidden] { display: none; }

/* ══ THE BAR IS FULL-WIDTH TO PAINT, NOT TO BE CLICKED ═══════════════════
   MEASURED DEFECT 2026-08-31, and it cost the homepage its primary CTA. This
   button is fixed across the whole viewport width, 41px tall, pinned to the
   bottom at z-index 1190. Its visible affordance is only the label and caret on
   the right; the rest is a gradient taper. But the BOX took the hit test across
   all 1440px, so anything the page put at the foot of the viewport became
   unclickable.

   On index.html at maximum scroll -- and it IS the maximum, the controls sit at
   the very end of the document, so no further scrolling can free them:
     button.bkx__go  "Book this time"          y 878-900  covered 100%
     a.bkx__alt      "Use the contact form"    y 878-898  covered 100%
   document.elementFromPoint() returned BUTTON.footpull at 5 of 5 sampled points
   on each, at 1440x900 and again at 390x844. A tap on the booking CTA opened the
   site-directory sheet instead. faq.html lost its "Link to this answer" control
   the same way.

   pointer-events: none on the bar and auto on the two things a person actually
   aims at. The gradient still paints, the click still works because it bubbles
   from the label to the button, and the rest of the foot of the page is free.
   The decorative rule stays inert -- it is aria-hidden and 1px tall. */
.chrome-live .footpull {
  pointer-events: none;
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 1190;
}
.chrome-live .footpull[aria-expanded="true"] { opacity: 0; pointer-events: none; }
.chrome-live .footsheet {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 1200;
  max-height: 86svh; overflow-y: auto; overscroll-behavior: contain;
  box-shadow: 0 -18px 50px rgba(0, 0, 0, .55);
  transform: translateY(101%);
  transition: transform var(--c-dur) var(--c-ease);
}
.chrome-live .footsheet.open { transform: translateY(0); }

/* ── THE COLLAPSED ROW, below 860px ────────────────────────────────────── */
@media (max-width: 860px) {
  .menubar__desc { display: none; }

  .chrome-live .bypass { position: relative; }
  .chrome-live .bypass__toggle {
    display: inline-flex; align-items: center; gap: .5rem;
    padding: .6rem var(--c-pad);
    background: none; border: 0; cursor: pointer;
    font-family: inherit; font-size: .6875rem; font-weight: 600;
    letter-spacing: .14em; text-transform: uppercase; color: var(--c-dim);
  }
  .chrome-live .bypass__caret {
    width: 7px; height: 7px;
    border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
    transform: translateY(-2px) rotate(45deg);
    transition: transform .22s var(--c-ease);
  }
  .chrome-live .bypass__toggle[aria-expanded="true"] { color: var(--c-red-ink); }
  .chrome-live .bypass__toggle[aria-expanded="true"] .bypass__caret {
    transform: translateY(2px) rotate(225deg);
  }
  /* The panel, not a flyout: it drops straight down from the row, full width,
     one flat column. Nothing in this chrome opens inside anything else. */
  .chrome-live .bypass__list {
    position: absolute; top: 100%; left: 0; right: 0;
    display: none; flex-direction: column; gap: 0;
    padding: .3rem var(--c-pad) .9rem;
    background: var(--c-ink); border-bottom: 1px solid var(--c-hair);
    box-shadow: 0 18px 40px rgba(0, 0, 0, .5);
  }
  .chrome-live .bypass__list.open { display: flex; }
  .chrome-live .bypass__list a { padding: .6rem 0; }
  .chrome-live .bypass::after { display: none; }

  .footdir__brand { grid-column: 1 / -1; }
}

/* THE INSTANT JUMP. scrollTo() honours the page's `html { scroll-behavior:
   smooth }`, which would fly the reader through the whole descent — the one
   thing the bypass row exists to avoid. js/chrome.js adds this class for the
   single frame in which it scrolls. */
html.chrome-jump { scroll-behavior: auto !important; }

/* ── REDUCED MOTION ────────────────────────────────────────────────────── */
/* Only the transitions go. The sheets still open and close: a reader who asked
   for less motion did not ask for less navigation. */
@media (prefers-reduced-motion: reduce) {
  .chrome *, .chrome-foot * { transition: none !important; }
}

/* ══ ROOM FOR THE BAR WHEN THE STORM IS OFF ═══════════════════════════════
   ADDED 2026-08-19. Found and measured during the /media build, fixed here at
   the system level rather than page-locally so all four storm pages inherit it.

   THE FAULT. .chrome-live .chrome is position:fixed, which is correct. On a
   live storm page nothing collides with it because the stage is its own fixed
   layer. But the storm switches itself OFF in four real situations -- a narrow
   viewport, no WebGL2, a lost context, and prefers-reduced-motion -- and in all
   four the page reverts to NORMAL FLOW while the bar stays fixed. Nothing
   reserved space for it, so the first content sat underneath it. Measured at
   390px wide: css/scene.css contributes clamp(3rem, 7vw, 6rem) = 48px against a
   bar that is 78-86px there, and the opening plate's kicker was under the
   "Jump to" row.

   Note which visitors that hit. Reduced motion and a phone are not edge cases,
   and paid traffic to the landing pages is majority mobile -- so the storm-off
   branch is the one MOST cold visitors see, not the fallback nobody looks at.

   The rule lives inside .chrome-live, as this file's own contract at the top
   requires: nothing outside .chrome-live may fix or park anything. It applies
   only when the chrome is live AND the storm is not.

   scroll-padding-top matters as much as the padding: the bypass row and the
   nav both jump to anchors, and without it an anchored beat lands under the
   bar -- which is the same class of bug as the padding, just deferred to the
   moment someone uses the feature. */
/* MEASURED AND CORRECTED 2026-08-19 by the /work/camera build, which reported
   the real slab heights rather than my estimates: the bar measures 94px on
   desktop and 86px on a phone. My first values were 5.5rem (88px) and 7.5rem
   (120px) -- so desktop UNDER-reserved by 6px and the phone OVER-reserved by
   34px of dead space above the first kicker on every Tier 2 page.
   Note the inversion, which is why guessing failed: the phone bar is SHORTER
   than the desktop one, because the bypass row collapses to a single control
   there. 6.25rem = 100px and 5.75rem = 92px, each clearing its real slab with a
   small margin and nothing spare. */
html.chrome-live { --chrome-bar-h: 6.25rem; }
@media (max-width: 860px) { html.chrome-live { --chrome-bar-h: 5.75rem; } }

html.chrome-live:not(.sc-live) body { padding-top: var(--chrome-bar-h); }
html.chrome-live:not(.sc-live) { scroll-padding-top: calc(var(--chrome-bar-h) + 1rem); }

/* ══ NO-JS SOURCE ORDER ═══════════════════════════════════════════════════
   ADDED 2026-08-19. Reported independently by the /media and /newsroom builds.

   THE FAULT. With JS off the nav sheet is in normal flow, and because it sits in
   the header position it renders BEFORE the page's first beat -- roughly one and
   a half screens of navigation links ahead of the headline. Measured on both
   pages. The /newsroom build's verdict was the useful one: it would show the
   reduced-motion and 390px states to a client without hesitation, but not the
   desktop JS-off state with that tree on top of the page.

   That is a real reader, not a hypothetical: JS-off, a crawler, and any visitor
   whose script request fails all get this order.

   THE FIX IS SOURCE-ORDER-FREE, deliberately. Two of the four storm pages were
   already finished and had copied partials/chrome.html verbatim when this was
   found, so a markup change would have fixed two pages and skipped two. Ordering
   with flex instead lands on every page that links this stylesheet, including the
   ones already built, and needs no page edited.

   Only the NAV moves. The menu bar keeps its place, the bypass row stays with it,
   and the footer is already last. The nav sheet goes after main, where a
   navigation tree belongs when it cannot be summoned. */
/* FIRST ATTEMPT WAS WRONG AND THE MEASUREMENT CAUGHT IT. `body > .navsheet`
   matched nothing: the nav sheet is not a child of body, it is a child of the
   .chrome wrapper, which also holds the bypass row and the menu bar. So the whole
   wrapper -- nav tree included -- rendered before main and the numbers did not
   move (navTop 93, mainTop 1163, h1 at 1342 on both finished pages).

   `display: contents` on the wrapper is what makes this work without touching
   markup: it promotes .chrome's children into body's flex context, so they can be
   ordered individually. The wrapper's own box disappears, which is correct here --
   in the no-JS state it is not a fixed bar and has nothing to draw. */
html:not(.chrome-live) body { display: flex; flex-direction: column; }
html:not(.chrome-live) .chrome { display: contents; }

html:not(.chrome-live) .u-skip { order: 0; }
html:not(.chrome-live) .menubar { order: 1; }
html:not(.chrome-live) main { order: 10; }
html:not(.chrome-live) .bypass { order: 80; }
html:not(.chrome-live) .navsheet { order: 90; }
html:not(.chrome-live) footer,
html:not(.chrome-live) .footsheet { order: 100; }


/* ══ THE FOOT PULL ON A LIGHT GROUND ══════════════════════════════════════
   ADDED 2026-08-19. Reported independently by the /apps and /work/camera builds.

   THE FAULT. .footpull carries linear-gradient(to top, rgba(10,10,10,.92), …) to
   lift its label off whatever is behind it. On an ink storm page that is
   invisible and correct. On a bone page -- the portfolios, the contact sheet --
   it darkens the bottom ~46px of the last section, so a card's caption sits under
   a grey wash for no reason. /work/camera measured it against real card captions.

   The fix keys the scrim off the ground rather than assuming ink. A page with a
   light foot declares it once with data-foot="light"; the label and its rule
   invert with it, so the control stays legible on either ground instead of
   trading one contrast problem for another. */
html.chrome-live [data-foot="light"] .footpull {
  background: linear-gradient(to top, rgba(245, 241, 232, .94), rgba(245, 241, 232, 0));
  color: rgba(10, 10, 10, .74);
}
html.chrome-live [data-foot="light"] .footpull__rule { background: rgba(10, 10, 10, .18); }
@media (hover: hover) and (pointer: fine) {
  html.chrome-live [data-foot="light"] .footpull:hover { color: #0a0a0a; }
}
