/* ==========================================================================
   FLATROCK CUSTOMS — global chrome module (header, nav, drawer, footer).
   Owned by Agent 9. Loaded AFTER style.css so it may override chrome rules
   only. No page styles, no component styles, no new colour values that are
   not already design tokens.

   Contents:
     A. Scrolled-header transparency fallbacks (bug fix, see note)
     B. Header brand + nav polish
     C. Nav CTA pill (replaces the old .btn in .nav-cta)
     D. Mobile drawer: scrim, scroll lock, focus order, reduced motion
     E. Footer: top block, columns, contact list, bottom bar
     F. Focus-visible guarantees

   CONTRAST — every pair used below, measured, not estimated
   (WCAG 2.x relative-luminance formula, computed with python3):

     #d8d4cc  --on-dark        on #21201F charcoal ............ 11.01:1  AA
     #ff9d52  --on-dark-accent on #21201F charcoal .............  7.90:1  AA
     #FCF9F0  --cream          on #21201F charcoal ............. 15.45:1  AA
     #ffffff  white            on #21201F charcoal ............. 16.27:1  AA
     #a19c94  footer bottom    on #21201F charcoal .............  5.96:1  AA
     #21201F  charcoal         on #FCF9F0 cream ................ 15.45:1  AA
     #B44B07  --orange-deep    on #FCF9F0 cream ................  5.05:1  AA
     #21201F  charcoal         on #F1EEE6 (worst scrolled hdr) . 14.03:1  AA
     #B44B07  --orange-deep    on #F1EEE6 (worst scrolled hdr) .  4.59:1  AA
     #3d3405  --ph-ink         on #FFF2B8 --ph-bg ..............  8.76:1  AA

   The scrolled-header worst case is a charcoal section sliding under the
   rgba(252,249,240,.95) tint, which composites to #F1EEE6. That is the same
   worst case style.css §23 documents; nothing here changes the tint alpha.
   No new colour is introduced anywhere in this file.
   ========================================================================== */


/* ==========================================================================
   A. SCROLLED HEADER — transparency fallbacks, re-asserted
   ==========================================================================
   style.css DOES contain both fallbacks (§20d, around line 1890), but they
   are declared BEFORE the §23 rule that actually applies the blur:

     line ~1891  @supports not (backdrop-filter …) { .site-header.is-scrolled { background-color: var(--cream) } }
     line ~1903  @media (prefers-reduced-transparency: reduce) { .site-header.is-scrolled { backdrop-filter: none; … } }
     line ~2114  .site-header.is-scrolled { backdrop-filter: blur() saturate(); background-color: var(--glass-tint-light) }

   All three selectors are specificity (0,2,0); @supports and @media add
   nothing. So the LAST one wins and the blur/translucency comes back even
   when the user has asked for reduced transparency. That is the gap Agent 8
   flagged — it is an ordering bug, not a missing rule. chrome.css loads after
   style.css, so re-stating the fallbacks here is the fix and it is the
   minimal one: no change to style.css, no second scroll listener, no JS.

   Going opaque only ever IMPROVES contrast here: #FCF9F0 is lighter than the
   worst-case composite #F1EEE6, so charcoal nav text rises 14.03:1 -> 15.45:1
   and the aria-current link rises 4.59:1 -> 5.05:1. Elevation and the charcoal
   bottom rule are preserved, so the scrolled state is still legible AS a
   state without relying on transparency. */

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .site-header.is-scrolled {
    background-color: var(--cream);
  }
}

@media (prefers-reduced-transparency: reduce) {
  .site-header.is-scrolled {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    background-color: var(--cream);
    /* keep the state readable without transparency */
    box-shadow: var(--elev-2);
    border-bottom-color: var(--charcoal);
  }
}

/* Forced-colors (Windows High Contrast): backdrop-filter is meaningless and
   the lit hairline is invisible. Fall back to a system border. */
@media (forced-colors: active) {
  .site-header.is-scrolled {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    border-bottom: 2px solid CanvasText;
  }
  .site-header.is-scrolled::after { display: none; }
}

/* The header slides from flat cream to tinted glass. Under reduced motion the
   colour still changes (state is never signalled by motion alone) but nothing
   animates. */
@media (prefers-reduced-motion: reduce) {
  .site-header {
    transition: none;
  }
}


/* ==========================================================================
   B. HEADER / NAV POLISH
   ========================================================================== */

/* The brand is a single link containing decorative artwork plus a visually
   hidden accessible name. Stop the browser from letting the flex children be
   split across lines at narrow widths. */
/* NOTE: do NOT make .site-header .wrap position:relative. .site-nav is a
   child of .wrap and is absolutely positioned at top:100% with left/right:0 —
   its containing block must stay .site-header (position:sticky) so the drawer
   goes full-bleed. Positioning .wrap would inset the drawer to the content
   column. The drawer scrim in §D uses z-index:-1 for the same reason. */
.site-header .brand { flex: 0 0 auto; min-width: 0; }
.site-header .brand img { display: block; }

/* The hover opacity dip is the only hover signal on the brand; give it the
   token duration instead of an instant jump, and drop it under reduced
   motion (opacity is a colour change, so it is kept — only the easing goes). */
.brand { transition: opacity var(--dur) var(--ease); }

/* Toggle: make the tap target 44px tall at every size, and give it the same
   hover treatment the nav links get. */
.nav-toggle {
  min-height: 44px;
  transition:
    background-color var(--dur) var(--ease),
    color var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease);
}
.nav-toggle:hover {
  background-color: var(--surface-3);
}
.nav-toggle__label { line-height: 1; }

/* The bar-to-X morph. style.css does the transform; give it duration and an
   escape hatch. */
.nav-toggle__bars,
.nav-toggle__bars::before,
.nav-toggle__bars::after {
  transition:
    transform var(--dur) var(--ease-out-expo),
    top var(--dur) var(--ease-out-expo),
    background-color var(--dur-fast) var(--ease);
}
@media (prefers-reduced-motion: reduce) {
  .nav-toggle__bars,
  .nav-toggle__bars::before,
  .nav-toggle__bars::after { transition: none; }
  .brand { transition: none; }
}


/* ==========================================================================
   C. NAV CTA — pill, not .btn
   ==========================================================================
   The header CTA is now .pill.pill--solid.pill--accent. style.css sizes the
   old markup through `.site-nav .nav-cta .btn`, which no longer matches, so
   the equivalent rules are restated here for .pill.

   WHY SOLID AND NOT GLASS: COMPONENTS.md §1 lists "the scrolled sticky
   header" as one of the three glass-appropriate backdrops, but that refers to
   the header SURFACE — the thing that does the refracting. The surface behind
   the CTA is either flat cream (unscrolled) or a 95%-opaque cream tint
   (scrolled). Neither is busy. A glass pill needs something to refract; put
   one on a 95% cream tint and §1.5's own warning applies — it reads as a
   washed-out grey lozenge sitting on a second sheet of glass. Solid accent
   also keeps the nav CTA visually identical to the footer CTA and to every
   in-page primary CTA, which is what a nav CTA should be. */

.site-nav .nav-cta { border-bottom: 0; }
.site-nav .nav-cta .pill {
  width: 100%;
  justify-content: center;
}
@media (min-width: 900px) {
  .site-nav .nav-cta .pill {
    width: auto;
    /* 19px is the locked AA floor for a white label on --orange
       (#FFFFFF on #DC6212 = 3.62:1, large-text bar 3:1). COMPONENTS.md §1.5:
       never set font-size on a pill. This does not — it only sets padding. */
    padding-block: var(--s-3);
    padding-inline: var(--s-5);
  }
}

/* The desktop underline-grow that style.css adds to .site-nav a must not run
   across the pill — it would paint an orange bar over an orange fill. */
@media (min-width: 900px) {
  .site-nav .nav-cta a::after { content: none; }
}
/* Same for the aria-current inset bar, in case an integrator marks the CTA. */
.site-nav .nav-cta a[aria-current="page"] {
  box-shadow: var(--elev-2);
  padding-left: var(--s-5);
}


/* ==========================================================================
   D. MOBILE DRAWER
   ==========================================================================
   Behaviour contract with assets/js/main.js (Agent 6 owns that file — the
   exact diff is in Agent 9's report). The CSS side is:

     html.nav-open                 set by main.js while the drawer is open
     --scrollbar-gap               set by main.js to the measured gutter width
     .site-nav[hidden]             already handled by style.css

   The drawer is a panel hanging off the bottom of the sticky header, NOT a
   full-screen overlay. The toggle stays on screen above it, stays focusable,
   and doubles as the close control via the existing X transform — so a user
   who cannot see a separate close affordance is never trapped. Tab order is
   DOM order: skip-link -> brand -> toggle -> nav links -> CTA, and the rest
   of the page is made `inert` by main.js while open, so Tab from the CTA
   leaves the document rather than wandering into hidden content. */

@media (max-width: 899px) {

  /* Sit above the scrim, inside the header's own stacking context. */
  .site-nav {
    z-index: 2;
    /* Keep the drawer scrollable on short phones without hiding the toggle. */
    max-height: calc(100dvh - 76px);
    overscroll-behavior: contain;
  }

  /* Scrim. Purely decorative: pointer-events:none, so it never swallows a tap
     and never becomes an invisible close button that a screen-reader user
     cannot find. Closing is the toggle, Escape, or choosing a link.

     ABSOLUTE, not fixed, deliberately: once .is-scrolled is on, the header
     carries a backdrop-filter, and a backdrop-filter establishes a containing
     block for position:fixed descendants. A fixed scrim would collapse to the
     header's own 76px box the moment the user scrolled. Absolute + top:100%
     anchors it to the header (position:sticky is a positioned ancestor) and
     hangs a viewport-tall tint below the drawer. Body scroll is locked while
     it is open, so 100dvh is always enough. */
  .site-header::before {
    content: "";
    position: absolute;
    left: 0; right: 0;
    top: 100%;
    height: 100dvh;
    /* -1 keeps it above the header's own background but below every in-flow
       child (.wrap, brand, toggle) and below the positioned drawer, without
       needing a z-index on any of them. The header is already a stacking
       context (position:sticky + z-index:100), so -1 cannot escape it. */
    z-index: -1;
    background: rgba(33, 32, 31, .42);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition:
      opacity var(--dur) var(--ease),
      visibility 0s linear var(--dur);
  }
  .nav-open .site-header::before {
    opacity: 1;
    visibility: visible;
    transition:
      opacity var(--dur) var(--ease),
      visibility 0s linear 0s;
  }

  /* Give each drawer row a 44px target. */
  .site-nav a { min-height: 44px; }

  /* The CTA gets air above it so it reads as an action, not a sixth link. */
  .site-nav .nav-cta { padding-top: var(--s-4); }
}

/* Body scroll lock. The gutter is measured in JS and written to
   --scrollbar-gap so the page does not jump sideways when overflow is
   hidden. On overlay-scrollbar platforms (all phones, macOS by default) the
   measurement is 0 and nothing moves. The padding goes on <body>, not <html>,
   so the position:sticky header shifts with the content it sits over. */
html.nav-open {
  overflow: hidden;
}
html.nav-open body {
  padding-right: var(--scrollbar-gap, 0px);
}

/* Above the breakpoint the drawer is a desktop row again. style.css already
   forces display and overrides [hidden]; do not fight it — just make sure the
   drawer-only affordances are gone. */
@media (min-width: 900px) {
  .site-header::before { content: none; }
  html.nav-open { overflow: visible; }
  html.nav-open body { padding-right: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .site-header::before { transition: none; }
}
/* The scrim is a flat tint, not a blur, so there is no backdrop-filter to
   fall back from here. Under reduced transparency drop it to fully opaque
   charcoal — the drawer itself is opaque cream and sits above it. */
@media (prefers-reduced-transparency: reduce) {
  .site-header::before { background: var(--charcoal); }
}
@media (forced-colors: active) {
  .site-header::before { display: none; }
}


/* ==========================================================================
   E. FOOTER
   ==========================================================================
   Hierarchy: brand + tagline + one positioning line and a single CTA, then a
   light chevron rule, then three columns, then the legal bar. Flat charcoal
   fill, so the CTA is .pill--solid.pill--accent — COMPONENTS.md §1.5
   explicitly forbids glass in the footer. */

.site-footer__top {
  display: grid;
  gap: var(--s-6);
  align-items: start;
}
@media (min-width: 900px) {
  .site-footer__top {
    grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
    gap: var(--s-7);
    align-items: end;
  }
}

.site-footer__tagline {
  font-family: var(--font-display);
  font-size: var(--step-2);
  line-height: 1.15;
  color: var(--cream);          /* #FCF9F0 on #21201F = 15.45:1 */
  margin: 0 0 var(--s-3);
  max-width: 18ch;
}
.site-footer__positioning {
  color: var(--on-dark);        /* #d8d4cc on #21201F = 11.01:1 */
  margin: 0;
  max-width: 48ch;
}

.site-footer__cta-text {
  color: var(--on-dark);        /* 11.01:1 */
  margin: 0 0 var(--s-4);
  max-width: 34ch;
}
@media (min-width: 900px) {
  .site-footer__cta { justify-self: end; text-align: right; }
  .site-footer__cta-text { margin-left: auto; }
}

/* The footer CTA is a pill, but style.css's generic `.site-footer a` rules
   want to recolour it and grow an underline under it. Neutralise both.
   The label stays #FFFFFF on --orange (3.62:1, large-text PASS — identical to
   every other .pill--solid.pill--accent on the site, COMPONENTS.md §6). */
.site-footer .pill {
  text-decoration: none;
}
.site-footer a.pill:hover,
.site-footer a.pill:focus-visible {
  text-decoration: none;
}
.site-footer a.pill--solid.pill--accent,
.site-footer a.pill--solid.pill--accent:hover,
.site-footer a.pill--solid.pill--accent:focus-visible { color: #fff; }
.site-footer a.pill::after { content: none; }

/* The divider. .chevron-rule--light is cream at .32 opacity over charcoal —
   decorative only, carries no information, and is aria-hidden in the markup,
   so it is not held to a text contrast bar. */
.site-footer .chevron-rule {
  margin-block: var(--s-7);
}

/* Columns. The brand has moved out of the grid, so the old 1.3fr/1fr/1fr
   weighting no longer applies — the contact column carries the widest content
   (placeholder tokens wrap) and gets the extra room. */
@media (min-width: 760px) {
  .site-footer__grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.25fr);
  }
}

.site-footer__license {
  margin-top: var(--s-5);
  margin-bottom: 0;
  color: var(--on-dark);        /* 11.01:1 */
  line-height: 1.7;
}

/* Contact rows: a small uppercase label above each token so the tokens are
   self-describing. The label is --on-dark-accent (#ff9d52 on #21201F =
   7.90:1) — NOT --orange, which is 2.5:1 on charcoal and would fail. */
.site-footer__contact li {
  margin-bottom: var(--s-4);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 5px;
}
.site-footer__contact li:last-child { margin-bottom: 0; }
.f-label {
  font-size: var(--step--2);
  font-weight: 800;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--on-dark-accent); /* #ff9d52 on #21201F = 7.90:1 */
}
/* Placeholder tokens keep their own high-contrast treatment from style.css
   (--ph-ink #3d3405 on --ph-bg #FFF2B8 = 8.76:1) and must stay obviously
   unfinished on the dark fill. Just stop them stretching the flex row. */
.site-footer__contact .ph { align-self: flex-start; }

/* Legal bar. Existing #a19c94 on charcoal = 5.96:1 — passes AA for small
   text, so it is left alone. The disclosure line is pushed to its own row so
   it is readable rather than crammed between the copyright and the links. */
.site-footer__bottom {
  align-items: baseline;
}
.site-footer__disclosure {
  flex-basis: 100%;
  order: 3;
  max-width: 70ch;
  line-height: 1.6;
}
.site-footer__bottom-nav { margin-left: auto; }
@media (max-width: 759px) {
  .site-footer__bottom-nav { margin-left: 0; }
}


/* ==========================================================================
   F. FOCUS-VISIBLE GUARANTEES
   ==========================================================================
   style.css sets a global 3px --orange-deep ring and swaps it to
   --on-dark-accent inside .site-footer. These restate it explicitly for every
   chrome control so a later rule cannot quietly remove it, and add the
   offset-gap separator so the ring never dissolves into the surface it sits
   on. Ratios:
     ring #B44B07 on cream header        = 5.05:1   (bar 3:1 for UI) PASS
     ring #B44B07 on worst scrolled #F1EEE6 = 4.59:1                 PASS
     ring #ff9d52 on charcoal footer     = 7.90:1                    PASS */

.site-header a:focus-visible,
.site-header button:focus-visible,
.site-nav a:focus-visible,
.nav-toggle:focus-visible {
  outline: 3px solid var(--orange-deep);
  outline-offset: 3px;
  box-shadow: 0 0 0 3px var(--cream);
}
/* On the scrolled glass header the separator has to be the tint, not pure
   cream, or it reads as a halo. --glass-tint-light composites to the same
   family, so the ring keeps its 4.59:1 minimum. */
.site-header.is-scrolled a:focus-visible,
.site-header.is-scrolled button:focus-visible {
  box-shadow: 0 0 0 3px var(--glass-tint-light);
}

.site-footer a:focus-visible {
  outline: 3px solid var(--on-dark-accent);
  outline-offset: 3px;
  box-shadow: 0 0 0 3px var(--charcoal);
}

@media (forced-colors: active) {
  .site-header a:focus-visible,
  .site-header button:focus-visible,
  .site-footer a:focus-visible {
    outline: 3px solid Highlight;
    box-shadow: none;
  }
}
