/* site-header — the kit's one chrome bar: three uniform ZONES (left /
 * center / right), each an ordered mixed list of KIT ELEMENTS (header-footer/ —
 * logo, nav, link, button, cart, language, separator, text). The `1fr auto
 * 1fr` grid keeps the center zone truly centered; there are no privileged
 * slots — a logo is a zone element like any other. Flush per
 * SITE-KIT.md: the bar runs edge to edge and owns its own inset.
 * Element paint lives on the parts (base.css); this sheet is bar + zone
 * geometry only. */

.sk-header {
  background-color: var(--sk-bg);
}

/* The STICK axis (data-stick="stick") — the header pins to the viewport
 * top and the page slides under a translucent blur. The tint derives from
 * the theme's own background token — never a hand-picked rgba — so every
 * look keeps its own glass. (A preceding announcement-bar strip scrolls
 * away normally: sticky pins the bar only once its own flow position
 * reaches the viewport top.)
 *
 * The GLASS HAIRLINE waits for the SCROLL STAMP (data-scrolled — the engine
 * stamps every stick bar, overlap or not): the edge exists to seat the glass
 * on the content sliding under it, so a bar resting at the top of the page
 * draws no line — the same "transparent at the top, the glass once scrolled"
 * posture the overlap float already keeps. The border keeps its width at all
 * times (color-only swap, no layout jump). Scripts off the stamp never
 * arrives, so the hairline stays on — the sticky glass still needs its edge. */
.sk-header[data-stick="stick"] {
  position: sticky;
  top: 0;
  z-index: 30;
  background-color: color-mix(in srgb, var(--sk-bg) 92%, transparent);
  backdrop-filter: saturate(180%) blur(12px);
  -webkit-backdrop-filter: saturate(180%) blur(12px);
  border-bottom: var(--sk-border-width) solid transparent;
  transition: border-color 0.3s ease;
}
html[data-sk-js] .sk-header[data-stick="stick"][data-scrolled],
html:not([data-sk-js]) .sk-header[data-stick="stick"] {
  border-bottom-color: var(--sk-header-rule, var(--sk-stroke));
}

/* ── The OVERLAP axis (data-overlap="hero") — the bar as a LAYER ──────────
 * The bar stops being a band: the page's first section starts at y=0 and
 * transparent chrome floats on it (the editorial gesture). Alone the bar is
 * ABSOLUTE — it scrolls away with the hero; with `stick` it is FIXED,
 * transparent at the top and solidifying to the glass on the engine's
 * data-scrolled stamp.
 *
 * ONE GATE, WRITTEN ONCE — AND IT FAILS CLOSED. Everything the float changes
 * nests inside the single :has() condition below: the positioning, the
 * transparent fill, §4's overlay INK, and the sibling band's chrome
 * clearance. The posture and its legibility are the SAME rule, so they
 * cannot drift apart — there is no second condition to keep in sync.
 *
 * The condition IS §4's floor, with TWO arms for its two shapes: the next
 * band is a lockup carrying real media in a BLEED-family layout, OR a bleed
 * band whose frames wear the ON-MEDIA CONTRACT marker (base.css — the
 * slideshow's opener; the contract guarantees the same dark base + tonality
 * veil whatever the frame's photo does, so the floor holds through every
 * rotation). Anything else matches NOTHING here and `overlap: hero` renders
 * as the plain strip above (in flow, glass, theme inks): a column layout,
 * the shallow strip band (no stage — a floated bar would cover most of it),
 * an imageless lockup, a front door that isn't a lockup, or no following
 * band at all.
 *
 * The CLOSED failure is the whole point. The rule this replaced floated the
 * bar ANYWAY and only withheld the near-white ink — "over a column front
 * door the bar keeps the PAGE inks, brand surface is up top". Half the band
 * is: a split's media column reaches y=0 under the OTHER half (and column
 * layouts drop the veil entirely), so a full-width bar straddled two
 * registers wearing one ink, and page-dark type landed on a raw photograph.
 * A bar that straddles two registers has no readable ink — so it does not
 * float. Same for an unmatched condition of any other shape: the strip is a
 * designed posture, an illegible float is not.
 *
 * (The floor is also why an imageless bleed no longer floats, though page
 * ink IS readable on that band: "the first band has NO media" can only be
 * written as a `:not(:has(…))` INSIDE this :has(), which is invalid CSS —
 * browsers drop the whole rule. The way back to that posture is a marker
 * attribute stamped by lockup.html, never a second uncoupled condition.)
 *
 * SELECTOR SHAPE IS LOAD-BEARING: :has() may not nest inside :has() (the
 * spec forbids it; browsers drop the WHOLE rule as invalid — and this rule
 * dropping now means a SOLID bar, not an illegible one). So the real-media
 * check rides the descendant chain POSITIVELY (`> .sk-lockup-media` — the
 * `.sk-media` BOX, which lockup.html emits only when a real photo exists),
 * mirroring the lockup's own overlay-ink condition in base.css. The kit lint
 * (site-kit.test.ts) rejects any nested :has() and pins this as the kit's
 * ONLY copy of the floor condition. */
.sk-header[data-overlap="hero"]:has(
    + .sk-section
      .sk-lockup:not([data-layout^="split-"], [data-layout^="overlap-"], [data-layout="strip"])
      > .sk-lockup-media,
    + .sk-section[data-layout="bleed"] .sk-on-media
  ) {
  /* Both FLOATING postures: the transparent fill and §4's overlay ink set —
   * the fixed near-whites the hero's dark base + veil guarantee. The theme's
   * --sk-bg/--sk-surface stay un-remapped, so the solid sub-surfaces below
   * keep their own paint. Scripts-off the sticky variant never floats, so it
   * is excluded here too and keeps the glass strip's theme inks. */
  &:not([data-stick="stick"]),
  html[data-sk-js] &[data-stick="stick"]:not([data-scrolled]) {
    /* THE FLOATING FLAG — the scrim below reads it instead of repeating this
     * compound condition, so "is the bar floating" is written once here. */
    --sk-chrome-scrim-opacity: 1;
    /* §4's overlay ink set — the OVERLAY WHITES tokens (base.css), the
     * same constants the on-media contract remaps, so the float and the
     * hero it floats over can never drift apart. */
    --sk-ink: var(--sk-overlay-ink);
    --sk-ink-muted: var(--sk-overlay-ink-muted);
    --sk-accent: var(--sk-overlay-ink-muted);
    --sk-stroke: var(--sk-overlay-stroke);
    --sk-btn-bg: var(--sk-overlay-ink);
    --sk-btn-ink: rgb(14, 12, 10);
    color: var(--sk-ink);
    background-color: transparent;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    border-bottom-color: transparent;
  }
  /* No `top`: the STATIC position places the float — y=0 alone at the
   * body's top, and exactly BELOW a preceding announcement-bar strip (the
   * strip is in flow, so the bar's hypothetical box starts at its bottom
   * edge). One rule for both, no measurement. Full viewport width on
   * purpose — the page cap is a CONTENT-RAIL width, and the chrome strip
   * is paint: the BAR's own padding carries the rail (below), so the
   * brand and actions sit on the capped column while the strip bleeds. */
  &:not([data-stick="stick"]) {
    position: absolute;
    left: 0;
    right: 0;
    z-index: 30;
  }
  /* Overlap + stick, scripts on: FIXED, then the glass on the stamp — and
   * the theme inks with it, since the remap above excludes data-scrolled.
   * No `top` here either: the static position starts the bar below a
   * preceding announcement-bar strip, and the engine walks it up as the
   * strip scrolls away (the inline top in site-header.js — a fixed box
   * ignores scroll, so CSS alone would leave a strip-height gap). */
  html[data-sk-js] &[data-stick="stick"] {
    position: fixed;
    left: 0;
    right: 0;
    transition:
      background-color 0.3s ease,
      border-color 0.3s ease;
  }
  html[data-sk-js] &[data-stick="stick"][data-scrolled] {
    background-color: color-mix(in srgb, var(--sk-bg) 92%, transparent);
    backdrop-filter: saturate(180%) blur(12px);
    -webkit-backdrop-filter: saturate(180%) blur(12px);
    /* The rule token, not a hardcoded stroke: an authored accent line
     * (data-accent-line, end of sheet) comes back with the glass. */
    border-bottom-color: var(--sk-header-rule, var(--sk-stroke));
  }
  /* THE BAR'S OWN FLOOR — §4 applied to the CHROME. The near-white ink above
   * used to lean entirely on the hero's tonality veil, which is theme-tunable
   * (--sk-tone-wash-intensity) and WEAKEST at the top of the band — exactly
   * where the bar sits, and exactly where photographs are brightest (a sky, a
   * window). So the floating bar paints its own scrim: legibility is carried
   * by the kit, never by the photo — whatever the image turns out to be, and
   * whatever a look does to the wash. It rides the OPACITY flag the floating
   * block sets (not a second copy of that selector), so it fades out in step
   * with the glass on the scroll stamp instead of popping. */
  & .sk-header-bar {
    position: relative;
  }
  & .sk-header-bar::before {
    content: "";
    position: absolute;
    inset: 0 0 auto;
    height: calc(100% + var(--sk-chrome-scrim-fade));
    z-index: -1;
    background: var(--sk-chrome-scrim);
    opacity: var(--sk-chrome-scrim-opacity, 0);
    pointer-events: none;
    transition: opacity 0.3s ease;
  }
  /* Solid sub-surfaces INSIDE the float re-derive the THEME inks: the
   * dropdown panel paints its own theme fill (--sk-bg / --sk-surface,
   * un-remapped above), so near-white ink would vanish on it. An authored
   * data-tone stamp on a panel keeps winning (the :not gate). */
  & .sk-el-nav-panel:not([data-tone]) {
    --sk-ink: var(--kit-foreground);
    --sk-ink-muted: var(--kit-muted);
    --sk-accent: var(--kit-accent);
    --sk-stroke: var(--kit-divider);
    --sk-btn-bg: var(--kit-foreground);
    --sk-btn-ink: var(--kit-background);
    color: var(--sk-ink);
  }
  /* The band under the float CLEARS the chrome for its overlay copy: the CSS
   * floor is the bar-height dial (the lockup folds --sk-chrome-clear into its
   * top frame inset); site-header.js refines it to the measured chrome
   * height — and only while the bar really floats, which it reads back off
   * this rule's own verdict. */
  & + .sk-section {
    --sk-chrome-clear: var(--sk-bar-height);
  }
}

/* THE COMPLEMENT: a bar that does NOT float is IN FLOW, so it spends real
 * viewport before the band below it ever starts. A "full height" hero then
 * measures 100svh from its own top and lands one bar-height BELOW the fold
 * — every such site opened with a sliver of forced scroll. The band under
 * an in-flow bar subtracts it (--sk-chrome-push, read by the height axis in
 * base.css): full height means the viewport, not the viewport plus chrome.
 *
 * The bar-height dial is the CSS floor; site-header.js refines it to the
 * MEASURED height (a preceding announcement-bar strip included — it spends
 * viewport too) off the same `floats()` verdict it already uses for the
 * clearance, so the fail-closed case — a bar stamped for the hero that the
 * §4 gate refuses to float — pushes correctly too. */
.sk-header:not([data-overlap="hero"]) + .sk-section {
  --sk-chrome-push: var(--sk-bar-height);
}
/* Reduced motion: base.css's floor covers [data-sk] DESCENDANTS only, so
 * the bar ROOT's own transitions — the float↔solid swap and the glass
 * hairline's fade — need this one arm (the old ::before arm was redundant
 * with the floor and is gone). */
@media (prefers-reduced-motion: reduce) {
  .sk-header[data-stick="stick"] {
    transition: none;
  }
}

/* The bar. `1fr auto 1fr` keeps the center zone geometrically centered
 * whatever the side zones hold. Geometry reads the
 * CHROME GEOMETRY dials (base.css — bar-height a min-height, bar-pad-x the
 * gutters, bar-gap between zones), so one theme is a 44px dense strip and
 * another a tall airy bar with zero section CSS. */
.sk-header-bar {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--sk-bar-gap);
  min-height: var(--sk-bar-height);
  padding-block: var(--sk-bar-pad-y);
  /* The bar's gutter grows to the PAGE CAP's centering margin on a capped
   * page (base.css, the band-gutter home's rail formula — own floor, same
   * math): the strip bleeds, the brand/nav/actions sit on the content
   * rail with every band's copy. */
  padding-inline: max(var(--sk-bar-pad-x), calc((100% - var(--sk-page-max, 200vw)) / 2));
  border-bottom: calc(var(--kit-bar-divider) * 1px) solid var(--sk-stroke);
}

/* An EMPTY center zone needs no symmetry: content-sized side tracks, the
 * empty middle taking the slack — an asymmetric bar (light left, heavy
 * right) fits at its true width instead of 2 × its heavier side. The gate
 * counts ELEMENT children (the zone div always ships, whitespace inside),
 * and site-header.js mirrors it in the measured collapse. */
.sk-header-bar:not(:has(> [data-zone="center"] > *)) {
  grid-template-columns: auto 1fr auto;
}

/* A zone: an ordered horizontal row of elements (zone-gap dial). Alignment
 * is fixed by position — left starts, center centers, right ends. */
.sk-header-zone {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sk-zone-gap);
  min-width: 0;
}
.sk-header-zone[data-zone="left"] {
  justify-content: flex-start;
}
.sk-header-zone[data-zone="center"] {
  justify-content: center;
}
.sk-header-zone[data-zone="right"] {
  justify-content: flex-end;
}

/* Small screens, SCRIPTS OFF: the grid relaxes to a wrapping row, zones
 * flowing in order — the structural floor (never a hidden nav; print,
 * readers, and no-JS visitors always see everything). Scripts ON never
 * wears this: the engine's measured collapse below covers every width, so
 * a bar that FITS keeps its real grid at any width. */
@media (max-width: 640px) {
  html:not([data-sk-js]) .sk-header-bar {
    display: flex;
    flex-wrap: wrap;
  }
  html:not([data-sk-js]) .sk-header-zone {
    flex: 1 1 auto;
    justify-content: center;
  }
}

/* COMPACT, scripts on (SITE-HEADER-PLAN step 7 — the toggle + sheet).
 * NOT a breakpoint: site-header.js MEASURES the bar's natural content
 * width and stamps data-compact whenever the bar is narrower than it — a
 * crowded bar collapses right where it stops fitting, a sparse one keeps
 * its full grid far narrower, and nothing ever wraps into a two-row bar.
 * base.css's compact-chrome block hides the sheet-bound elements (nav,
 * buttons, language, …; logo and cart/icon affordances stay) and paints
 * the toggle + the engine-built menu sheet.
 *
 * The ZONES DISSOLVE (display: contents): which zone an element was
 * authored into is a DESKTOP layout decision — an all-center bar (apple)
 * would otherwise strand its surviving cluster mid-track. The bar becomes
 * one flex row of the surviving elements, normalized to the convention:
 * logo left (its auto margin claims the slack), icons + toggle right. */
html[data-sk-js] .sk-header[data-compact] .sk-header-bar {
  display: flex;
  align-items: center;
  gap: var(--sk-zone-gap);
}
html[data-sk-js] .sk-header[data-compact] .sk-header-zone {
  display: contents;
}
html[data-sk-js] .sk-header[data-compact] .sk-header-bar .sk-el-logo {
  margin-right: auto;
}
/* No logo on the bar: the toggle's own auto margin keeps itself (and via
 * the gap, the icons beside it) pinned right instead of packing left. */
html[data-sk-js] .sk-header[data-compact] .sk-header-bar:not(:has(.sk-el-logo)) .sk-header-toggle {
  margin-left: auto;
}

/* ── The BOTTOM ACCENT LINE (data-accent-line) ────────────────────────
 * Opt-in: a hairline in the ACCENT ink along the bar's bottom edge. It
 * lives on the ROOT border — the same border stick's glass hairline draws —
 * so the two can never stack into a double line (this block sits after the
 * stick rule; equal specificity, later wins). The theme's own bar-divider
 * dial yields for the same reason: one bottom line, whoever asked for it.
 * The overlap float needs nothing new — its border-bottom-color: transparent
 * already lands on this border, and the scrolled glass restores it through
 * --sk-header-rule above. Tone remaps --sk-accent, so the line keeps reading
 * on inverted/accent bands for free. */
.sk-header:not([data-accent-line=""]) {
  --sk-header-rule: var(--sk-accent);
  border-bottom: var(--sk-border-width) solid var(--sk-header-rule);
}
.sk-header:not([data-accent-line=""]) .sk-header-bar {
  border-bottom: none;
}
