/* ============================================================================
   ⚠ SHARED FILE — THE HEADER LIVES IN FOUR FILES. EDIT THEM TOGETHER.

     site/final/_partials/header.html      CANONICAL MARKUP for the four static
                                           pages. Edit there, then re-inject:
                                             cd site && node _tools/inject-header.mjs
                                           NEVER patch the pages inline.
     source/src/components/SiteHeader.jsx  the same markup for React → / and
                                           /services/
     source/src/bto-header.css             the React copy.
     site/final/bto-css/bto-header.css   ← THIS FILE. The static pages' copy.

   Comment prose may differ between the two sheets — each describes its own
   side. THE RULE SET MAY NOT. Prove both halves before you commit:

       cd site && node _tools/check-shared-css.mjs
       cd site && node _tools/inject-header.mjs --check

   ⚠ THE TWO SHEETS HOLD 3 BLOCKS IN A DIFFERENT ORDER, AND THAT IS LEFT ALONE.
   The resting-transparency block sits on the other side of the `.bh` token
   block, and `.bh { transition: none }` sits at the other end of the
   prefers-reduced-motion block. Both are inert: in each case no two of the
   blocks involved set the same property at equal specificity, so source order
   decides nothing. Measured 2026-08-13 — 46 rules, identical. Do not "tidy"
   them into agreement, and do not let a real divergence hide next to them.
   ============================================================================ */

/* ============================================================================
   bto-header.css — THE header. One implementation, every page.

   Built from scratch on 2026-07-30 to replace three divergent headers:
     · index.html / work.html ran Mokko's, which needs jQuery, bootstrap and
       fontawesome to function, cross-fades two logo marks by opacity, and hides
       its own pill until a scroll class lands
     · services/ ran a React rebuild that only LOOKED aligned — its font files
       404'd, so it rendered Helvetica while reporting "Neue Montreal"
   Neither is reused. This file owns the appearance; nothing inherits from Mokko.

   Self-contained: no framework, no jQuery, no icon font, no CSS variables from
   other sheets. Load it anywhere and the header looks the same.
   Geometry matches what index.html measured at 1440x900 — 1320px inner, x=60,
   top 20px, logo at x=80 — because those proportions were right; only the
   implementation was the problem.
   ============================================================================ */

/* ==========================================================================
   RESTING TRANSPARENCY — FOUNDER, 2026-08-05
   ==========================================================================
   "we are also making the header transparent when not in use and a typical
   fade in when hover with the header for everypage."

   ⚠ THIS FILE IS THE STATIC PAGES' COPY. The React builds compile their own
   header from bto-spylt/src/bto-header.css. The two are NOT one file, so
   "every page" means BOTH — this block is the byte-equivalent of the one added
   there on 2026-08-05. Change one, change the other, or the header behaves
   differently on about/work/contact than it does on home and services.

   🔴 THE WHOLE ELEMENT FADES, NOT JUST THE PLATE. `.bh__logo` is ink (#13181B)
   and the Menu pill is #2B2B2B; on a transparent plate over a dark ground the
   wordmark goes near-invisible while the amber CTA stays bright, so the header
   half-disappears instead of receding. Fading the whole element keeps every
   part in the same relationship to every other at all times.

   ⚠ Opacity never affects hit-testing — the header is fully clickable at rest.
   Restored by hover, by :focus-within (a keyboard user never hovers), and by
   .bh--open (the menu is open, so the header is in use). */
.bh {
  opacity: .62;
  transition: opacity 260ms ease;
}
.bh:hover,
.bh:focus-within,
.bh.bh--open { opacity: 1; }

.bh {
  --bh-ink: #13181B;
  --bh-canvas: #F0EEEB;
  --bh-plate: rgba(248, 247, 245, 0.92);
  --bh-amber: #FFBF65;
  --bh-disc: #F7F7F7;
  --bh-glyph: #4F5663;
  --bh-tag: #555859;
  --bh-menu: #2B2B2B;
  --bh-face: "Neue Montreal", -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif;

  position: fixed;
  top: 20px;
  left: 50%;
  transform: translateX(-50%);
  width: 100%;
  max-width: 1320px;
  z-index: 600;
  font-family: var(--bh-face);
}

/* the plate. Always visible — not revealed on scroll. Over a dark hero a 70%
   alpha plate reads as murky grey, so this is opaque enough to be independent
   of whatever sits behind it. */
.bh__bar {
  position: relative;
  height: 60px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--bh-plate);
  border-radius: 40px;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

/* ---------- lockup ---------- */
.bh__logo {
  display: block;
  padding-left: 20px;
  text-decoration: none;
  color: var(--bh-ink);
}
.bh__logo h1,
.bh__logo p.bh__name {
  margin: 0;
  font-size: 24px;
  font-weight: 800;
  letter-spacing: -0.24px;
  line-height: 1.05;
  color: var(--bh-ink);
  text-transform: none;
  font-family: var(--bh-face);
}
.bh__tag {
  display: block;
  margin: 3px 0 0;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--bh-tag);
  font-family: var(--bh-face);
}

/* ---------- controls ---------- */
.bh__tools {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-right: 20px;
}
.bh__disc {
  width: 36px;
  height: 36px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  border-radius: 40px;
  background: var(--bh-disc);
  cursor: pointer;
  transition: filter 160ms ease;
}
.bh__disc:hover { filter: brightness(0.95); }
.bh__disc svg { width: 18px; height: 18px; display: block; }
/* The markup sets stroke-width but no stroke attribute, so an attribute
   selector never matched and both glyphs rendered as empty discs. Target the
   shapes directly. */
.bh__disc svg circle,
.bh__disc svg path { stroke: var(--bh-glyph); fill: none; }
/* #F7F7F7 on the near-white plate is invisible; a hairline gives the disc an
   edge on light grounds without darkening it on the dark-hero page. */
.bh__disc { box-shadow: inset 0 0 0 1px rgba(19, 24, 27, 0.09); }

.bh__cta {
  display: inline-flex;
  align-items: center;
  height: 32px;
  padding: 6px 16px;
  border-radius: 40px;
  background: var(--bh-amber);
  color: var(--bh-ink);
  font-size: 12.8px;
  font-weight: 600;
  white-space: nowrap;
  text-decoration: none;
  transition: filter 160ms ease;
}
.bh__cta:hover { filter: brightness(0.95); color: var(--bh-ink); }

/* ==========================================================================
   INLINE NAV — FOUNDER, 2026-08-05
   ==========================================================================
   "i want us to have a normal footer [header] where everything is written on
   and we dont have to click twice to go to the page."

   WHAT THIS REPLACES. Every page shipped six links behind the ☰ Menu pill, so
   every navigation on the site cost two clicks: open the panel, then pick. The
   six links now sit in the bar as text at ≥992px and the pill disappears.

   ⚠ THE PANEL IS NOT DELETED — it is the ≤991px implementation. Six links plus
   the CTA cannot sit in a 375px bar, so the hamburger is still the right answer
   there. One markup, two layouts, switched at one breakpoint.

   ⚠ display:none ON THE PANEL AT ≥992px IS LOAD-BEARING, not tidiness. The
   panel rests at `opacity:0; pointer-events:none`, which hides it from the eye
   and the mouse but NOT from the accessibility tree. Left as-is, a screen
   reader at desktop width would read the same six links twice. `display:none`
   is the only one of the three that removes it.

   🔴 THE UNDERLINE IS INK, NOT AMBER, AND THAT IS DELIBERATE. The panel hovers
   amber (#FFBF65) because it sits on the #2B2B2B panel where amber is legible.
   The bar plate is #F8F7F5, where #FFBF65 measures 1.41:1 — see the palette
   note. Ink also keeps amber meaning exactly one thing in this bar: the CTA.

   ⚠ THIS FILE IS THE STATIC PAGES' COPY. bto-spylt/src/bto-header.css is the
   React builds' copy. Change one, change the other — same rule as the resting
   transparency block above. */
.bh__nav { display: none; }
.bh__nav ul {
  display: flex;
  align-items: center;
  gap: clamp(14px, 1.6vw, 26px);
  list-style: none;
  margin: 0;
  padding: 0;
}
.bh__nav a {
  position: relative;
  display: block;
  padding: 7px 1px;
  font-family: var(--bh-face);
  font-size: 13.5px;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--bh-ink);
  text-decoration: none;
  white-space: nowrap;
  transition: opacity 160ms ease;
}
.bh__nav a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 2px;
  height: 1.5px;
  background: var(--bh-ink);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 220ms cubic-bezier(0.23, 1, 0.32, 1);
}
.bh__nav a:hover::after { transform: scaleX(1); }
.bh__nav a:hover { color: var(--bh-ink); }
/* the page you are on. Weight AND rule, because a rule alone is the same
   signal as hover and the two would be indistinguishable at rest. */
.bh__nav a[aria-current="page"] { font-weight: 700; }
.bh__nav a[aria-current="page"]::after { transform: scaleX(1); }
/* a nav item is a separator away from the two discs, not part of the group */
.bh__nav { margin-right: 6px; }

/* the menu control carries the word, not just an icon */
.bh__menu {
  width: 117px;
  height: 45px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 18px;
  border: 0;
  border-radius: 40px;
  background: var(--bh-menu);
  cursor: pointer;
  transition: filter 160ms ease;
}
.bh__menu:hover { filter: brightness(1.35); }
.bh__menu span.bh__mlabel {
  font-size: 13px;
  font-weight: 500;
  color: #fff;
  font-family: var(--bh-face);
}
.bh__bars { display: flex; flex-direction: column; gap: 4px; }
.bh__bars i { display: block; width: 16px; height: 1.5px; background: #fff; }

/* ---------- slide-out panel ---------- */
.bh__scrim {
  position: fixed;
  inset: 0;
  z-index: 700;
  background: rgba(19, 24, 27, 0.55);
  opacity: 0;
  pointer-events: none;
  transition: opacity 280ms ease;
}
.bh__panel {
  position: fixed;
  top: 20px;
  right: max(20px, calc((100vw - 1320px) / 2 + 20px));
  width: min(88vw, 300px);
  z-index: 710;
  padding: 26px 28px 30px;
  border-radius: 28px;
  background: var(--bh-menu);
  font-family: var(--bh-face);
  opacity: 0;
  pointer-events: none;
  transform: translateY(-12px);
  transition: opacity 280ms ease, transform 280ms ease;
}
.bh--open .bh__scrim,
.bh--open .bh__panel { opacity: 1; pointer-events: auto; }
.bh--open .bh__panel { transform: translateY(0); }

.bh__phead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 18px;
}
.bh__phead span {
  font-size: 13px;
  color: rgba(255, 255, 255, 0.45);
}
.bh__close {
  width: 28px; height: 28px;
  display: flex; align-items: center; justify-content: center;
  background: none; border: 0; cursor: pointer;
}
.bh__close i { display: block; width: 16px; height: 1.5px; background: #fff; }

.bh__panel ul { list-style: none; margin: 0; padding: 0; }
.bh__panel li { border-left: 1px dotted rgba(255, 255, 255, 0.28); padding-left: 18px; }
.bh__panel a {
  display: block;
  padding: 9px 0;
  font-size: 20px;
  font-weight: 500;
  color: #fff;
  text-decoration: none;
  transition: color 160ms ease;
}
.bh__panel a:hover { color: var(--bh-amber); }

/* ==========================================================================
   SKIP LINK — FIXES #9, 2026-08-13
   ==========================================================================
   Keyboard users were tabbing through all 14 header links on every one of the
   six pages before reaching any content. This is the escape hatch: the first
   focusable element on the page, jumping to `<main id="main">`.

   🔴 IT COSTS ZERO LAYOUT AT REST, AND THAT IS THE WHOLE CONSTRAINT. The
   header's appearance may not move by a pixel. `position: absolute` takes it
   out of flow entirely, so `.bh`'s only in-flow child is still `.bh__bar` and
   the bar is laid out exactly as before. `display: none` would have been
   simpler and is WRONG — it removes the element from the tab order, which is
   the one thing this element exists to be in. 1px + clip-path is the standard
   visually-hidden pattern for something that must stay focusable.

   ⚠ `:focus`, NOT `:focus-visible`. A 1px clipped element cannot realistically
   be clicked, so there is no stray-mouse-focus case to guard against, and
   :focus-visible has enough browser variance after a click-then-tab sequence to
   risk the link staying invisible exactly when it is needed.

   ⚠ POSITIONED AGAINST `.bh`, NOT THE VIEWPORT — `.bh` carries
   `transform: translateX(-50%)`, which makes it a containing block for even
   `position: fixed` descendants. So `top: calc(100% + 10px)` means 10px below
   the bar, and `left: 0` is the bar's own left edge at both widths. Writing
   `fixed` here would change nothing; `absolute` says what is actually true.

   Dropping BELOW the bar rather than sitting over it keeps the wordmark
   readable while the link is showing. The amber focus ring comes free from the
   `.bh a:focus-visible` rule below — same treatment as every other control in
   the header. `.bh:focus-within` already lifts the resting .62 opacity to 1, so
   the link is at full contrast the moment it is focused.

   ⚠ `.bh__skip` OUTRANKS palette.css's global `a, .link { color: … }` — class
   (0,1,0) beats element (0,0,1) — so the label colour is this file's to own on
   the static pages, not the palette's. */
.bh__skip {
  position: absolute;
  top: 0;
  left: 0;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  font-family: var(--bh-face);
  font-size: 14px;
  font-weight: 700;
  text-decoration: none;
  color: var(--bh-canvas);
}
.bh__skip:focus {
  top: calc(100% + 10px);
  width: auto;
  height: auto;
  padding: 13px 24px;
  overflow: visible;
  clip-path: none;
  background: var(--bh-menu);
  border-radius: 999px;
}

/* keyboard focus — one visible ring everywhere */
.bh a:focus-visible,
.bh button:focus-visible {
  outline: 2px solid var(--bh-amber);
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  /* the resting fade stays — it is a STATE, not motion. Only the animation goes. */
  .bh { transition: none; }
  .bh__scrim, .bh__panel, .bh__disc, .bh__cta, .bh__menu, .bh__panel a { transition: none; }
  /* the underline still APPEARS on hover and on the current page — only the
     wipe is removed. Dropping the rule entirely would cost these users the
     "you are here" signal, which is information, not decoration. */
  .bh__nav a, .bh__nav a::after { transition: none; }
}

/* ---------- wide: the bar carries the nav, the pill goes away ---------- */
/* 992px is not a new number — it is the breakpoint the CTA already used, so the
   bar has exactly two states instead of three overlapping ones. */
@media (min-width: 992px) {
  .bh__nav { display: block; }
  .bh__menu { display: none; }
  /* see the display:none note in the INLINE NAV block — this is the a11y half,
     not a cosmetic duplicate of the opacity rest state. */
  .bh__scrim,
  .bh__panel { display: none; }
}

/* ---------- narrow ---------- */
@media (max-width: 991px) {
  .bh__cta { display: none; }
}
@media (max-width: 600px) {
  .bh { top: 12px; max-width: none; width: calc(100% - 24px); }
  .bh__bar { height: 54px; }
  .bh__logo h1, .bh__logo p.bh__name { font-size: 19px; }
  .bh__tag { font-size: 8px; letter-spacing: 1.3px; }
  .bh__menu { width: auto; height: 40px; padding: 0 14px; gap: 10px; }
  .bh__disc { width: 32px; height: 32px; }
  .bh__panel { right: 12px; top: 12px; }
}
