/* site-header component — GENERATED by tools/make-fixtures.py --emit-components
   from the same source ranges as widgets/site-header/fixture.html
   (../../site/css/shared-responsive.css + ../../site/css/blocks-responsive.css + build/css/responsive.css via fixtures.config.json). Byte-identical rules are
   the contract: edit the stage-2 source and regenerate, never this file. */
/* STICKY at every width. At rest it is transparent over the hero photo (the hero section carries the whole
   photo and pulls up under the header by --header-h); once the page has scrolled past the bar it takes the
   design's SECOND header state — the cream ground with black nav that the file keeps hidden under the hero
   photo (Frame 183) — through a scroll-driven animation (Chrome 115+, Safari 26; no JS in this stage, the
   widget adds a class-toggle fallback). Below --bp-desktop the bar is 80 tall: logo, ENQUIRE (from 600),
   and a menu button that opens the nav list as a cream panel (CSS-only disclosure). */
.site-header { position: sticky; top: 0; z-index: 10; min-height: var(--header-h); color: var(--c-white); }   /* min: the bar grows if a client-edited menu needs a second row */
/* GUARD, do not remove. `animation: header-stuck linear both` sets NO duration, so where scroll timelines are
   unsupported the declaration degrades to a 0s animation on the document timeline and `both` PARKS the header
   in its end state: cream from scroll 0, the transparent resting state never seen. Measured on Safari 17
   (QA, iPhone 15) and reproduced in Chrome by dropping the property — cream at scrollY 0 either way.
   Inside the feature query, unsupported browsers keep the resting state and the widget's JS class drives it. */
@supports (animation-timeline: scroll()) {
  .site-header { animation: header-stuck linear both; animation-timeline: scroll(root block); animation-range: 633px 743px; }
  /* 633→743, not 40→110: the bar must stay transparent over the hero and take its second state as the hero
     goes behind it — 743 is the hero's bottom (860) less the header (117) at the design width. QA saw the old
     range flip the bar the moment the page moved. These are DESIGN-WIDTH numbers and stage 2 is a review
     artifact; the WordPress build measures the hero at runtime instead (assets/js/dc009-header.js). */
}
@keyframes header-stuck { to { background: var(--c-cream); color: var(--c-black); box-shadow: 0 2px 4px rgb(0 0 0 / 0.25); } }
/* the desktop stuck state (from 1024, below): the design's own sticky frame, Frame 183 (12640:654) — a 125 bar with the
   97 row centred, 14 above and 14 below (developer ticket 1: "equal padding"). The resting header is the row 20 below
   the top of a 117 band. The flow box keeps --header-h so NOTHING below the header moves: the row rises 6px and a
   solid cream shadow paints the bar's extra 8px beneath it, with the design's hairline under that. */
/* The shadow is the design's, READ from the file, not invented: Frame 183 carries DROP_SHADOW rgba(0,0,0,0.25)
   offset y 2, blur 4. The first cut shipped a hard 1px hairline at 6% — about a quarter of the intended
   strength and no blur at all — because Frame 183 sits hidden under the hero photo in Figma and never appears
   in the flat PNG the pixel gate compares against. It is offset 10, not 2: the bar paints 8px of solid cream
   beneath itself (below), so the design's 2px clears that block. */
@keyframes header-stuck-desktop { to { background: var(--c-cream); color: var(--c-black); box-shadow: 0 8px 0 var(--c-cream), 0 10px 4px rgb(0 0 0 / 0.25); } }
@keyframes masthead-stuck { to { margin-top: 14px; } }
.masthead { display: flex; align-items: center; justify-content: space-between; min-height: 80px; }   /* the compact bar never wraps: its nav lives in the dropdown. A `flex-wrap: wrap` here made Elementor's flex-column container size the header widget as if the row HAD wrapped — logo 60 + menu 44 = a 104px wrapper at 390, 110 at 600 (measured on the live page; a block parent read 80) */
/* the logo swap for the scrolled state is ONE element: the light logo <img> fades out while the link's own
   background switches to the dark mark (a discrete keyframe — background-image flips at the range's midpoint).
   A second stacked <img> read as an occlusion in verify.mjs (hit-testing is forced through pointer-events). */
.masthead__logo-link { display: block; flex: none; width: 181px; background: none center / 100% 100% no-repeat;   /* the compact bar's logo width; its height is the image's own 292:97 */
  }
.masthead__logo { width: 100%; height: auto; }
/* same guard and same range as the header band — an unguarded logo swap parks the DARK mark over the hero photo */
@supports (animation-timeline: scroll()) {
  .masthead__logo-link { animation: logo-dark linear both; animation-timeline: scroll(root block); animation-range: 633px 743px; }
  .masthead__logo { animation: logo-light linear both; animation-timeline: scroll(root block); animation-range: 633px 743px; }
}
@keyframes logo-dark  { to { background-image: url("../img/logo-header-dark.png"); } }
@keyframes logo-light { to { opacity: 0; } }
.nav-toggle { position: absolute; opacity: 0; width: 1px; height: 1px; }
.masthead__menu { display: flex; align-items: center; justify-content: center; width: 44px; height: 44px; margin-right: -8px; cursor: pointer; }
.masthead__menu-bars { position: relative; display: block; width: 26px; height: 18px; }
.masthead__menu-bars::before, .masthead__menu-bars::after, .masthead__menu-bars span { content: ""; position: absolute; left: 0; width: 26px; height: 2px; background: currentColor; }
.masthead__menu-bars::before { top: 0; } .masthead__menu-bars span { top: 8px; } .masthead__menu-bars::after { top: 16px; }
/* Open, the three bars become a close (X) — QA 12.6. The design has no mobile menu at all, so there is no
   design position to contradict; this is the standard affordance. Transform only, markup untouched: the two
   outer bars meet at the middle bar's line and cross, the middle one fades. */
.masthead__menu-bars::before, .masthead__menu-bars::after, .masthead__menu-bars span { transition: transform 0.2s ease, opacity 0.2s ease, top 0.2s ease; }
.nav-toggle:checked ~ .masthead__menu .masthead__menu-bars::before { top: 8px; transform: rotate(45deg); }
.nav-toggle:checked ~ .masthead__menu .masthead__menu-bars::after { top: 8px; transform: rotate(-45deg); }
.nav-toggle:checked ~ .masthead__menu .masthead__menu-bars span { opacity: 0; }
@media (prefers-reduced-motion: reduce) { .masthead__menu-bars::before, .masthead__menu-bars::after, .masthead__menu-bars span { transition: none; } }
.masthead__cta { display: none; flex: none; white-space: nowrap; }   /* the header CTA never wraps or shrinks: when the bar is short of room the NAV gives way (it wraps its own items) */
/* the menu panel: the nav list under the bar, hidden until the toggle is checked — the cream/black header state */
/* The open menu fills the screen below the bar rather than dropping as a short panel over the hero (QA 12.7).
   FIXED, not absolute: the panel is measured from the viewport, so it cannot be cut short by the header's own
   box, and the list scrolls inside it if a client-edited menu outgrows the screen. dvh, not vh — mobile
   Safari's vh is the address-bar-less height and would run the panel under the browser chrome. */
.masthead__nav { display: none; position: fixed; left: 0; right: 0; top: var(--header-h); bottom: 0; max-height: calc(100dvh - var(--header-h)); overflow-y: auto; overscroll-behavior: contain; padding: 10px var(--gutter) 20px; background: var(--c-cream); color: var(--c-black); box-shadow: 0 8px 24px rgb(0 0 0 / 0.08); }
.nav-toggle:checked ~ .masthead__nav { display: block; }
/* the page behind a full-screen menu must not scroll under it. :has() so the CSS-only disclosure stays
   CSS-only (stage 2 carries no JS); a browser without :has() simply keeps the old scroll-through behaviour. */
@media (max-width: 1023.98px) {
  body:has(.nav-toggle:checked) { overflow: hidden; }   /* scoped: above 1024 there is no disclosure, and a checkbox left checked by a resize must not freeze the page */
  /* An open full-screen menu takes the bar with it. Opened at the top of the page the bar is still the
     transparent hero state, so a white logo over the photo sat above a cream sheet and read as two different
     headers. Same paint as the stuck state — :has on the header itself, since the toggle is its descendant. */
  .site-header:has(.nav-toggle:checked) { background: var(--c-cream); color: var(--c-black); }
  .site-header:has(.nav-toggle:checked) .masthead__logo { opacity: 0; }
  .site-header:has(.nav-toggle:checked) .masthead__logo-link { background-image: var(--logo-dark, url("../img/logo-header-dark.png")); }
}
.nav { display: flex; flex-wrap: wrap; flex-direction: column; }
.nav__item { border-bottom: 1px solid rgb(156 118 69 / 0.3); }
.nav__link { display: block; padding: 12px 0; font-family: var(--f-title); font-weight: 700; font-size: var(--t-nav); line-height: var(--t-nav-lh); letter-spacing: var(--ls-title); text-transform: uppercase; color: inherit; white-space: nowrap; }
.masthead__nav .btn { margin-top: 20px; }
@media (min-width: 600px) {
  .masthead__cta { display: inline-flex; margin-left: auto; margin-right: 20px; }
  .masthead__nav .btn { display: none; }
}
@media (min-width: 1024px) {
  /* the desktop header, fluid 1024 → 1600: Frame 184 is [80,20 1439×97], a row with gap 75 — logo 292×97 ·
     nav 788×30 · CTA 209×50 at 1600; at 1024 the same row at logo 170, gaps 12, nav 12px, CTA padding 12 (fits the
     922px container with room). The responsive markup carries the CTA before the nav; order restores the row. */
  .site-header { display: flow-root; animation-name: header-stuck-desktop; }   /* flow-root: the row's top margin must not collapse through the sticky header */
  @supports (animation-timeline: scroll()) {
    .masthead { animation: masthead-stuck linear both; animation-timeline: scroll(root block); animation-range: 633px 743px; }   /* 20 → 14 above the row once stuck (keyframes above); guarded like the band — unguarded it parks at 14 and the resting bar is 6px short */
  }
  /* from here the NAV gives up width and wraps its own items; a wrapping masthead would put logo, nav and CTA on three lines (measured: a 300px bar with two extra menu items) */
  /* logo · nav · CTA with the ends on the container edges and the space BETWEEN them, as at 1600 — the first cut packed
     them at the left with gaps growing to the design's 75, and between 1546 and 1599 that row was a few pixels wider
     than the container: CONTACT dropped to a second line and the CTA label wrapped (developer, ticket 1). The gap is
     now the MINIMUM (12 → 40 at 1600); space-between spends the rest, which lands the design's 75 at 1600. */
  .masthead { min-height: calc(var(--header-h) - 20px); margin-top: 20px; justify-content: space-between; gap: clamp(12px, 4.86111vw - 37.7278px, 40px); }
  .masthead__logo-link { order: 1; } .masthead__nav { order: 2; } .masthead__cta { order: 3; }
  .masthead__logo-link, .masthead__logo { width: clamp(170px, 21.1806vw - 46.8389px, 292px); height: auto; }   /* the mark's own 292:97 — the file's 584×194 cut carries it */
  .masthead__menu { display: none; }
  .masthead__nav, .nav-toggle:checked ~ .masthead__nav { display: block; position: static; padding: 0; background: none; color: inherit; box-shadow: none; flex: 0 1 auto; min-width: 0; max-height: none; overflow: visible; }   /* max-height/overflow reset too: the mobile panel's full-screen box must not survive into the desktop row */   /* shrinkable so the nav's items wrap instead of pushing the CTA off the frame */
  .nav { flex-direction: row; flex-wrap: wrap; gap: clamp(12px, 4.86111vw - 37.7278px, 40px); }
  .nav__item { flex: none; border: 0; text-align: center; }
  .nav__link { padding: 0; font-size: clamp(12px, 0.694444vw + 4.93889px, 16px); letter-spacing: var(--ls-title); }
  .masthead__cta { margin: 0; font-size: clamp(12px, 0.694444vw + 4.93889px, 16px); letter-spacing: var(--ls-title); padding-left: clamp(12px, 2.25694vw - 11.0611px, 25px); padding-right: calc(clamp(12px, 2.25694vw - 11.0611px, 25px) - var(--ls-title)); }
}
@media (min-width: 1600px) {
  /* the stage-1 composition. Frame 181 is a hug row of hug items with a 40 gap — 788 wide in Figma's own
     text metrics; Chrome sets the four labels 2.4–2.9px wider each, so min-width holds the design's 788 and
     space-between spends the difference on the gaps (measured: every label within 1.75px of its Figma x,
     against 3.4 for a flat 40px gap). No item is pinned — a fifth menu item just grows the row. */
  .masthead { min-height: 97px; margin-top: 20px; justify-content: space-between; gap: 40px; }
  .masthead__logo-link, .masthead__logo { width: 292px; height: auto; }
  .nav { flex-wrap: wrap; justify-content: space-between; gap: 24px; min-width: 788px; }
  .nav__link { font-size: var(--t-nav); }
  .masthead__cta { font-size: var(--t-nav); padding-left: 25px; padding-right: calc(25px - var(--ls-title)); }
}

/* hover: the nav item set's second variant (12202:429) turns the label gold; same state on keyboard focus */
.nav__link { transition: color 0.2s ease; }
.nav__link:hover, .nav__link:focus-visible { color: var(--c-gold); }
@media (prefers-reduced-motion: reduce) { .nav__link { transition: none; } }


/* ==== hand-maintained widget-phase additions (widgets/site-header/wp-extra.css) ==== */
/* site-header — WIDGET-PHASE rules with no stage-2 counterpart (appended to dc009-site-header.css by
   make-fixtures --emit-components). */
/* Elementor wraps every widget in position: relative and the header's own sticky would only travel
   inside that wrapper (exactly its height — no travel at all): the WRAPPER sticks instead. */
.elementor-widget-dc009-site-header { position: sticky; top: 0; z-index: 10; }
.elementor-widget-dc009-site-header .site-header { position: relative; }
/* On the DELIVERABLE the JS class is the only driver: dc009-header.js measures the hero at runtime, so the
   bar changes exactly as the hero goes behind it at EVERY width, in EVERY browser — including Safari below 26,
   where scroll timelines do not exist. Stage 2 is CSS-only and carries design-width numbers instead; here we
   switch its animation off so the two cannot disagree.
   This also removes a cascade trap: a running CSS animation outranks normal author declarations, so while the
   keyframes were live no edit to the rules below had any effect — including in DevTools, which is why the
   shadow looked unfixable. */
.site-header, .site-header .masthead, .site-header .masthead__logo, .site-header .masthead__logo-link { animation: none; }
.site-header { transition: background-color 0.25s linear, color 0.25s linear, box-shadow 0.25s linear; }
.site-header .masthead__logo { transition: opacity 0.25s linear; }
@media (prefers-reduced-motion: reduce) { .site-header, .site-header .masthead__logo { transition: none; } }
/* the stuck paint. Shadow READ from the design: Frame 183 DROP_SHADOW rgba(0,0,0,0.25), offset y 2, blur 4 —
   not the 6% hairline the first cut invented (Frame 183 hides under the hero photo in Figma, so it never
   reached the flat PNG the pixel gate compares against). */
.site-header.is-stuck { background: var(--c-cream); color: var(--c-black); box-shadow: 0 2px 4px rgb(0 0 0 / 0.25); }
.site-header.is-stuck .masthead__logo { opacity: 0; }
.site-header.is-stuck .masthead__logo-link { background-image: var(--logo-dark); }
@media (min-width: 1024px) {   /* the design's 125px sticky bar: row 14 from the top, 8px of cream painted below, the design's shadow clearing that block at 10 */
  .site-header.is-stuck { box-shadow: 0 8px 0 var(--c-cream), 0 10px 4px rgb(0 0 0 / 0.25); }
  .site-header.is-stuck .masthead { margin-top: 14px; }
}
/* the dark logo is a media control: the link carries it as --logo-dark (template), so the stage-2
   keyframe's literal url is redeclared to read the variable (a later @keyframes of the same name wins) */
@keyframes logo-dark { to { background-image: var(--logo-dark); } }
