/*
 * Global site header / primary navigation.
 *
 * Independent clean-room implementation, written directly from a
 * dictated written specification (selectors, computed declarations,
 * cascade facts, and load-order notes only). No prior version of this
 * file -- on any branch, in any diff, or in any capture -- was read,
 * viewed, or referenced while authoring the rules below.
 *
 * Covers the sticky top bar (#main-nav.nav-bar), the desktop link row
 * with its Services / Service Areas hover-and-focus dropdowns, and the
 * off-canvas mobile menu with its accordion sections. Color, radius,
 * spacing and timing values all come from custom properties defined
 * upstream; nothing in this file declares a custom property of its
 * own.
 */

/* Header surface tokens (2026-09-15, logo readability).
   --ocf-nav-bg / --ocf-nav-fg are the ONE pair of knobs that decide whether
   the top bar is painted light or dark. They default to exactly what this
   file used before they existed (the page background and the heading ink),
   so nothing changes for any site that does not ask for the dark header.
   Every look reads the same two tokens, so the switch works in all of them.

   Why they exist: a roofer's logo is very often light-coloured artwork on a
   TRANSPARENT background. Dropped onto a white header it simply disappears
   -- Top View Roofing's white-and-red wordmark on the Bold look's white bar,
   2026-09-15. tools/wp_push.py measures the real logo pixels at build time
   and sets oneclick_site('nav_theme') to 'dark' when that would happen;
   header.php prints it as data-nav on <html> and the rule below repaints the
   bar. html[data-nav="dark"] outranks :root on specificity, so it wins
   whatever order the stylesheets happen to load in. */
:root {
  --ocf-nav-bg: var(--ocf-bg);
  --ocf-nav-fg: var(--ocf-heading);
}

html[data-nav="dark"] {
  --ocf-nav-bg: var(--ocf-dark-bg);
  --ocf-nav-fg: var(--ocf-dark-heading);
}

/* Dark bar: the border and divider are drawn from the bar's own ink instead
   of the page's light border tokens, which would be invisible on it, and
   hover goes lighter rather than to the brand colour (a deep brand colour on
   a near-black bar is unreadable). */
html[data-nav="dark"] .nav-bar {
  border-bottom-color: color-mix(in srgb, var(--ocf-nav-fg) 22%, transparent);
}
html[data-nav="dark"] .nav-divider {
  background-color: color-mix(in srgb, var(--ocf-nav-fg) 30%, transparent);
}
html[data-nav="dark"] .nav-link:hover,
html[data-nav="dark"] .nav-link:focus-visible,
html[data-nav="dark"] .nav-dropdown-trigger:hover,
html[data-nav="dark"] .nav-dropdown-trigger:focus-visible {
  color: color-mix(in srgb, var(--ocf-nav-fg) 70%, var(--ocf-primary));
}

/* 2026-09-10 (utility-bar-above-nav fix): sticky, not fixed. A fixed nav
   sits outside normal document flow and paints over whatever is in flow
   at the top of the page -- the preview banner and (Ultimate-only) utility
   bar both render BEFORE this element in header.php's markup on purpose
   (utility bar spec: "a thin utility strip -- phone + street address --
   above the main nav"), but a fixed nav painted over them regardless of
   that order, and body's old padding-top only ever reserved room for the
   nav itself, never for what precedes it. Sticky keeps the nav in normal
   flow -- it renders right after the banner/bar (so they show above it,
   as specced) and only pins to `top` once scrolled past them, which is
   also the standard "secondary bar scrolls away, nav stays pinned"
   pattern. See tests/test_utility_bar_order.py. */
.nav-bar {
  position: sticky;
  top: calc(var(--wp-admin-bar-offset, 0px) + var(--wp-admin-bar-gap, 0px));
  right: 0;
  bottom: auto;
  left: 0;
  z-index: 100;
  border-bottom-color: var(--ocf-border-light);
  border-bottom-style: solid;
  border-bottom-width: 1px;
  background-color: color-mix(in srgb, var(--ocf-nav-bg) 96%, transparent);
}

.nav-inner {
  justify-content: space-between;
  align-items: center;
  display: flex;
  min-height: 4.5rem;
  row-gap: 1.25rem;
  column-gap: 1.25rem;
}

/* Shared layout for every inline cluster in the header: a horizontal
   flex row, centered on the cross axis. */
.nav-logo,
.nav-right,
.nav-links,
.nav-phone,
.nav-dropdown-trigger,
.dropdown-item,
.mobile-link,
.mobile-accordion-trigger {
  align-items: center;
  display: flex;
}

.nav-logo {
  min-width: 0;
  color: var(--ocf-nav-fg);
  font-weight: var(--font-weight-bold);
}

/* The logo box (2026-09-15, full display).
   Hannah's rule: the roofer's logo always shows IN FULL -- never cropped,
   never clipped by a fixed slot, on a phone as much as on a desktop.

   So this is a BOX, not a frame: a height cap AND a width cap with both
   dimensions auto, which makes the browser scale the file down inside the
   box at its OWN aspect ratio until both caps are met. Nothing is ever cut
   off, whatever shape the roofer's file is. object-fit: contain is the
   belt-and-braces half -- if any future rule ever pins both dimensions, the
   image still letterboxes instead of cropping.

   The width cap is deliberately the PHONE budget (min(40vw, 13rem)): fit a
   phone and the desktop is fitted too. It is set below 50vw on purpose --
   assets/components/showcase-logo.css scales the nav logo up by 1.26-1.35,
   and a transform grows past the layout box, so the pre-scale budget has to
   leave that room.

   --ocf-logo-max-h is the one per-site knob: tools/wp_push.py raises it for
   a square/stacked mark, which the wordmark-shaped default would otherwise
   shrink to a stamp. Unset on every other site, so the default applies. */
.nav-logo-img {
  max-height: var(--ocf-logo-max-h, 2.75rem);
  max-width: var(--ocf-logo-max-w, min(40vw, 13rem));
  width: auto;
  height: auto;
  object-fit: contain;
}

.nav-logo-text {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.nav-links {
  font-size: var(--font-label-size);
  color: var(--ocf-nav-fg);
  row-gap: clamp(1.25rem, 2.2vw, 2rem);
  column-gap: clamp(1.25rem, 2.2vw, 2rem);
}

.nav-link {
  padding-bottom: 0.75rem;
  padding-top: 0.75rem;
}

.nav-link,
.nav-dropdown-trigger {
  /* 2026-09-12 (skin/form-nav-cool, Hannah, verbatim: "the nav bar words
     should not be colored by default"): these are <a> elements, so the
     sitewide `a { color: var(--color-accent) }` rule (base.css) was
     winning over the inherited (not directly-declared) color from the
     .nav-links ancestor above -- an inherited value always loses to any
     rule that targets the element itself, however low its specificity.
     .nav-phone/.dropdown-item/.mobile-link already declared their own
     color for the same reason and were never affected. Default is now the
     neutral heading ink; :hover/:focus-visible below goes accent, same as
     every other link on the page (base.css a:hover) -- there is no
     current-page indicator in this nav's markup to wire up (header.php
     builds the menu from fixed routes, not a WP menu walker with
     current-menu-item classes), so none was invented. The CTA button
     (.nav-cta) is untouched and stays accent-colored. */
  color: var(--ocf-nav-fg);
  font-weight: var(--font-weight-semibold);
}

.nav-link:hover,
.nav-link:focus-visible,
.nav-dropdown-trigger:hover,
.nav-dropdown-trigger:focus-visible {
  color: var(--ocf-primary);
}

.nav-right {
  column-gap: 0.75rem;
  row-gap: 0.75rem;
}

.nav-phone {
  font-size: var(--font-label-size);
  color: var(--ocf-nav-fg);
  column-gap: 0.4rem;
  row-gap: 0.4rem;
}

.nav-phone:hover,
.nav-phone:focus-visible {
  color: var(--ocf-primary);
}

/* Small glyphs across the header share a fixed box and never flex, so
   they hold their size under a tight flex row. */
.nav-phone svg,
.nav-dropdown-chevron,
.dropdown-item svg,
.dropdown-item-icon svg,
.mobile-accordion-chevron,
.mobile-phone svg {
  flex-basis: auto;
  flex-grow: 0;
  flex-shrink: 0;
  height: 1rem;
  width: 1rem;
}

/* The Services/Areas trigger chevron is smaller than the shared icon
   box above. Kept AFTER that shared rule on purpose: same
   specificity, so source order decides and this wins for
   .nav-dropdown-chevron only. */
.nav-dropdown-chevron {
  height: 0.75rem;
  width: 0.75rem;
}

.nav-divider {
  height: 1.5rem;
  width: 1px;
  background-color: var(--ocf-border-light);
}

.nav-mobile-btn {
  color: var(--ocf-nav-fg);
  display: none;
  border-width: 0;
  background-color: transparent;
}

.nav-dropdown {
  position: relative;
}

.nav-dropdown-trigger {
  column-gap: 0.25rem;
  row-gap: 0.25rem;
}

/* Hidden by default: no pointer events, transparent, nudged down a
   touch; fades and slides into place on reveal. */
.nav-dropdown-panel {
  position: absolute;
  left: 0;
  top: 100%;
  min-width: 14rem;
  transform: translateY(0.5rem);
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--duration) var(--ease), transform var(--duration) var(--ease);
}

/* Revealed on pointer hover over the wrapper, or when keyboard focus
   lands anywhere inside it (so the menu stays reachable without a
   mouse). */
.nav-dropdown:hover .nav-dropdown-panel,
.nav-dropdown:focus-within .nav-dropdown-panel {
  transform: none;
  opacity: 1;
  pointer-events: auto;
}

.dropdown-menu {
  display: grid;
  row-gap: 0.25rem;
  column-gap: 0.25rem;
  border-top-left-radius: var(--card-radius);
  border-top-right-radius: var(--card-radius);
  border-bottom-right-radius: var(--card-radius);
  border-bottom-left-radius: var(--card-radius);
  border-color: var(--ocf-border-light);
  border-style: solid;
  border-width: 1px;
  background-color: var(--ocf-bg);
  padding-top: 0.5rem;
  padding-right: 0.5rem;
  padding-bottom: 0.5rem;
  padding-left: 0.5rem;
}

.dropdown-menu--wide {
  min-width: 18rem;
}

.dropdown-item {
  color: var(--ocf-heading);
  row-gap: 0.5rem;
  column-gap: 0.5rem;
  padding-top: 0.65rem;
  padding-right: 0.75rem;
  padding-bottom: 0.65rem;
  padding-left: 0.75rem;
}

.dropdown-item:hover {
  color: var(--ocf-heading);
  background-color: var(--ocf-bg-alt);
}

.mobile-menu {
  border-top-color: var(--ocf-border-light);
  border-top-style: solid;
  border-top-width: 1px;
  display: none;
  background-color: var(--ocf-bg);
}

.mobile-menu-inner {
  display: grid;
  row-gap: 0.25rem;
  column-gap: 0.25rem;
  padding-top: 1rem;
  padding-right: var(--container-pad);
  padding-bottom: 1rem;
  padding-left: var(--container-pad);
}

.mobile-link,
.mobile-accordion-trigger {
  text-align: left;
  justify-content: space-between;
  width: 100%;
  color: var(--ocf-heading);
  border-width: 0;
  background-color: transparent;
  padding-top: 0.75rem;
  padding-right: 0;
  padding-bottom: 0.75rem;
  padding-left: 0;
}

.mobile-accordion-panel {
  padding-left: 1rem;
  display: none;
}

/* Opened by chrome.js: toggles .is-open on the accordion wrapper when
   its trigger button is clicked. */
.mobile-accordion.is-open .mobile-accordion-panel {
  display: grid;
}

.mobile-actions {
  display: grid;
  row-gap: 0.75rem;
  column-gap: 0.75rem;
  margin-top: 0.75rem;
  border-top-color: var(--ocf-border-light);
  border-top-style: solid;
  border-top-width: 1px;
  padding-top: 1rem;
}

.mobile-cta,
.mobile-phone {
  align-items: center;
  justify-content: center;
  display: flex;
  min-height: 3rem;
  font-weight: var(--font-weight-bold);
  border-top-left-radius: var(--button-radius);
  border-top-right-radius: var(--button-radius);
  border-bottom-right-radius: var(--button-radius);
  border-bottom-left-radius: var(--button-radius);
}

.mobile-cta {
  color: var(--ocf-primary-contrast);
  background-color: var(--ocf-primary);
}

.mobile-phone {
  row-gap: 0.5rem;
  column-gap: 0.5rem;
  color: var(--ocf-heading);
  border-color: var(--ocf-border-light);
  border-style: solid;
  border-width: 1px;
  background-color: var(--ocf-bg);
}

.mobile-phone-icon {
  align-items: center;
  display: inline-flex;
}

/* Below this width the desktop link row / phone / divider / CTA give
   way to the hamburger button and the off-canvas menu above. */
@media (max-width: 980px) {
  .nav-links,
  .nav-phone,
  .nav-divider,
  .nav-cta {
    display: none;
  }

  .nav-mobile-btn {
    display: inline-flex;
  }

  .mobile-menu {
    overscroll-behavior-y: contain;
    overflow-y: auto;
    max-height: calc(100vh - var(--wp-admin-bar-offset, 0px) - var(--wp-admin-bar-gap, 0px) - 4rem);
    -webkit-overflow-scrolling: touch;
  }

  /* Dynamic viewport height tracks mobile browser chrome better than
     100vh; falls back to the rule above where dvh isn't supported.
     Kept after it on purpose so it wins when the feature query
     matches. */
  @supports (height: 100dvh) {
    .mobile-menu {
      max-height: calc(100dvh - var(--wp-admin-bar-offset, 0px) - var(--wp-admin-bar-gap, 0px) - 4rem);
    }
  }

  .mobile-menu.is-open {
    display: block;
  }

  .nav-inner {
    min-height: 4rem;
  }
}
