/* site-header — sits over the hero image, so it is out of flow.
 * The hero reserves space for it with its own top padding. */

.site-header {
  position: absolute;
  inset: 0 0 auto 0;
  z-index: 10;
  color: var(--color-text-inv);
}

/* -- Utility bar -------------------------------------------------------- */
/* -- Eyebrow bar --------------------------------------------------------
 * Restored 2026-08-21. It was folded away when the nav became an island,
 * which cost the phone number its place — and phoning is how this client's
 * buyers actually convert, so that was the wrong trade.
 *
 * Rather than a solid band above a floating pill (two competing headers), it
 * floats too: transparent, sitting in the margin above the pill, white on
 * the photograph. The hero's top scrim is restored to give it ground.
 * ---------------------------------------------------------------------- */
.site-header__utility {
  background: none;
  font-size: 13px;
  color: var(--color-text-inv);
}
.site-header__utility-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  min-height: 0;
  /* Matches the pill exactly — same width, same inner padding — so the
   * social icons sit over the logo's left edge and the phone ends where the
   * nav ends. Rob 2026-08-21. */
  width: var(--nav-w);
  max-width: calc(100% - 2rem);
  margin-inline: auto;
  padding-block: 0;
  padding-inline: var(--nav-pad-x);
}
.site-header__utility-nav {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}
.site-header__utility-nav ul {
  display: flex;
  gap: var(--space-sm);
}
/* WCAG 2.2 AA (2.5.8) wants 24x24 minimum. These sat at 14px tall. The
 * "inline" exception only covers targets inside a sentence, which these are
 * not. Height only — the labels already exceed 24px wide.
 *
 * Scoped to `ul a`, NOT `.site-header__utility-nav a`: the phone is a sibling
 * of the list, and the broader selector was specificity (0,1,1) against the
 * phone's own (0,1,0), so it beat the 44px touch rule below and left the
 * phone at 24px on mobile. */
.site-header__utility-nav ul a {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
}
.site-header__utility-nav a { transition: opacity var(--dur-fast) var(--ease-out); }
.site-header__utility-nav a:hover { opacity: 0.7; }
.site-header__phone {
  display: inline-flex;
  align-items: center;
  /* 24x24 floor at every width; the 44px touch rule below takes over on
   * narrow viewports. Its own declaration rather than relying on the list
   * rule above — the phone is a sibling of the list, not inside it. */
  min-height: 24px;
  font-weight: var(--fw-bold);
}
@media (max-width: 992px) {
  /* The utility nav collapses to the phone number alone here, which makes it
   * the single most likely thing to be tapped. */
  .site-header__phone { min-height: 44px; }
}

/* .social lives in base.css — it is shared with site-footer. */

/* -- Main bar ----------------------------------------------------------- */
/* Fluid island nav — a floating glass pill under the eyebrow bar.
 * Rob's change 2026-08-21: 88vw wide with symmetric padding, rather than
 * max-content. A pill sized to its contents floated in the middle of the
 * viewport and read as a widget; spanning the measure reads as a header. */
.site-header__main {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-lg);
  width: var(--nav-w);
  max-width: calc(100% - 2rem);
  margin-inline: auto;
  padding: 0.5rem var(--nav-pad-x);
  background: rgb(255 255 255 / 0.72);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border: 1px solid rgb(255 255 255 / 0.6);
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-md);
  color: var(--color-text);
}
.site-header__main .site-header__logo img { filter: invert(1); }
.site-header__primary ul { font-size: 14px; gap: var(--space-sm); }
/* Only ever one of these two lists exists at a given breakpoint — see the
 * comment in site-header.html. */
.site-header__drawer-utility { display: none; }

/* Floating call button is mobile-only; the eyebrow bar carries the number
 * on desktop. */
.site-header__call { display: none; }

.site-header__primary a::after { height: 1px; }
.site-header__logo {
  /* The mark shrinks to 42px at the small end, which is under the 44px tap
   * minimum. The anchor keeps a 44px hit area regardless; the negative
   * margin stops that box pushing the mark off the shared left edge it
   * lines up with the eyebrow bar on. */
  display: grid;
  place-items: center;
  min-width: 44px;
  min-height: 44px;
  /* min(), not a bare calc: above 44px the expression flips positive and
   * would push the mark 6px INWARD, off the edge the eyebrow bar aligns to.
   * This way it only ever pulls the 44px box back, never pushes. */
  margin-inline: min(0px, calc((44px - var(--logo-size)) / -2));
  transition: opacity var(--dur-fast) var(--ease-out);
}
.site-header__logo:hover { opacity: 0.85; }
/* --logo-size is fluid across every width, with NO mobile override. There
 * used to be one, left from when the logo was a fixed 98px and mobile needed
 * it shrunk; once the token went fluid that override became a growth to the
 * clamp's own maximum, so the logo rendered 18px LARGER on a phone than the
 * fluid value and inflated the pill with it. */
.site-header__logo img {
  width:  var(--logo-size);
  height: var(--logo-size);
}

.site-header__primary ul {
  display: flex;
  gap: var(--space-sm);
  font-family: var(--font-display);
  font-size: var(--step--1);
}
.site-header__primary a {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  padding-block: var(--space-3xs);
}
/* Underline grows from the left rather than fading — the nav sits on a photo
 * and an opacity change is hard to read there. */
/* Only ever one of these two lists exists at a given breakpoint — see the
 * comment in site-header.html. */
.site-header__drawer-utility { display: none; }

/* Floating call button is mobile-only; the eyebrow bar carries the number
 * on desktop. */
.site-header__call { display: none; }

.site-header__primary a::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 2px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-base) var(--ease-out);
}
.site-header__primary a:hover::after,
.site-header__primary a:focus-visible::after { transform: scaleX(1); }

/* -- Mobile toggle — no design exists for this; see inventory -----------
 * Sized to a 44px hit area. The bars are pseudo-elements, so without an
 * explicit box the button measured 40x4 and was effectively untappable. */
.site-header__toggle {
  display: none;
  width: 44px;
  height: 44px;
  place-items: center;
  margin-right: calc(var(--space-3xs) * -1);
}
.site-header__toggle:active { transform: scale(0.92); }
.site-header__bars,
.site-header__bars::before,
.site-header__bars::after {
  display: block;
  width: 28px; height: 2px;
  background: currentColor;
}
.site-header__bars::before,
.site-header__bars::after { content: ""; position: relative; }
.site-header__bars::before { top: -9px; }
.site-header__bars::after  { top: 7px; }

@media (max-width: 1200px) {
  .site-header__primary ul { gap: var(--space-xs); }
}

/* -- Breakpoint-exclusive pieces ----------------------------------------
 * Each of these exists at exactly one breakpoint, so the duplicated nav
 * links are never both in the accessibility tree at once.
 *
 * The drawer list needs the child combinator: `.site-header__primary ul` is
 * specificity (0,1,1) and set display:flex, which beat a bare
 * `.site-header__drawer-utility` at (0,1,0) and left the list visible on
 * desktop — four duplicated links in the tree, the exact thing this is
 * meant to prevent.
 * ---------------------------------------------------------------------- */
.site-header__primary > .site-header__drawer-utility { display: none; }
.site-header__call { display: none; }

@media (max-width: 768px) {
  .site-header__utility-nav ul { display: none; }
  /* Replaced by the floating call button below, so the number is never two
   * links at the same breakpoint. */
  .site-header__phone { display: none; }
  .site-header__toggle { display: grid; }

  /* -- Drawer ----------------------------------------------------------
   * It sets its own charcoal ground but sits inside the pill, which sets a
   * near-black text colour for its glass. That was black on black — the
   * colour has to be restated here, not inherited.
   * -------------------------------------------------------------------- */
  .site-header__primary {
    position: absolute;
    inset: 100% 0 auto 0;
    margin-top: var(--space-2xs);
    padding: var(--space-2xs) 0;
    background: var(--color-charcoal);
    color: var(--color-text-inv);
    border-radius: var(--radius-core);
    box-shadow: var(--shadow-md);
    display: none;
  }

  /* A panel opening is the one state change here that genuinely earns
   * motion. A keyframe on open, not a transition off `display` — the closed
   * state stays the plain display:none that already worked.
   *
   * TRANSFORM ONLY, no opacity. A running animation applies its from-frame
   * whatever the fill-mode, so `from { opacity: 0 }` would leave the drawer
   * display:block but invisible wherever the animation clock stalls, and
   * mobile would have no nav at all. Animating position means the worst case
   * is a drawer sitting 8px high — visible and tappable. */
  .site-header__primary[data-open="true"] {
    display: block;
    animation: drawer-in var(--dur-base) var(--ease-out);
  }
  @keyframes drawer-in {
    from { transform: translateY(-8px); }
    to   { transform: none; }
  }

  .site-header__primary ul {
    flex-direction: column;
    gap: 0;
    padding: 0 var(--nav-pad-x);
    font-size: var(--step--1);
  }
  .site-header__primary li + li { border-top: 1px solid rgb(255 255 255 / 0.15); }
  .site-header__primary a {
    display: flex;
    align-items: center;
    min-height: 48px;
  }
  /* The sliding underline is a desktop pointer affordance; on a tap target
   * the row itself should respond. */
  .site-header__primary a::after { content: none; }
  .site-header__primary a:hover,
  .site-header__primary a:focus-visible { color: var(--color-text-inv); opacity: 0.75; }

  /* -- The eyebrow links, folded into the drawer ----------------------- */
  .site-header__primary > .site-header__drawer-utility {
    display: block;
    margin-top: var(--space-2xs);
    padding-top: var(--space-2xs);
    border-top: 1px solid rgb(255 255 255 / 0.15);
  }
  .site-header__drawer-utility a { opacity: 0.75; }

  /* -- Floating call button ---------------------------------------------
   * The single most likely action on a phone for a client whose buyers ring
   * them, and it survives the drawer being shut.
   * -------------------------------------------------------------------- */
  .site-header__call {
    position: fixed;
    z-index: 60;
    right: var(--space-sm);
    bottom: calc(var(--space-sm) + env(safe-area-inset-bottom, 0px));

    display: inline-flex;
    align-items: center;
    gap: 0.55em;
    min-height: 52px;
    padding-inline: var(--space-sm);

    background: var(--color-primary);
    color: var(--color-text-inv);
    border-radius: var(--radius-pill);
    box-shadow: var(--shadow-md);

    font-size: var(--step--1);
    font-weight: var(--fw-bold);
    letter-spacing: 0.01em;
    white-space: nowrap;

    transition: transform var(--dur-base) var(--ease-out);
  }
  .site-header__call:active { transform: scale(0.97); }

  /* The number always shows. An icon-only variant was tried at <=380 and
   * removed: 375 is one of the commonest phone widths and the full pill is
   * only 141px there, so hiding the number cost information for no space. */
  .site-header__call-icon { width: 20px; height: 20px; flex: none; }

  /* The button floats over the page, so the last thing on the page must not
   * sit underneath it. */
  .site-footer { padding-bottom: calc(72px + env(safe-area-inset-bottom, 0px)); }
}

