/*
 * Global shell: Announcement bar, Desktop/Mobile header, Desktop navigation.
 * Mobile nav overlay + drawers live in overlay.css (shared overlay mechanics).
 */

/**
 * Component: AnnouncementBar (.announcement-bar)
 * Purpose: top strip promo message (free shipping threshold). Static/CMS content.
 * Header redesign 2026-09-11: rebuilt as a repeating ticker per the new reference (was a single
 * centered line, hidden on desktop — that 2026-07-22 desktop-hidden decision is superseded now
 * that the new reference explicitly shows this band on desktop too). The PHP side already repeats
 * the message N times and marks the whole visual row aria-hidden with one real sr-only announcement
 * alongside it, so this is purely a static flex-wrap layout — no JS, no @keyframes/marquee, matching
 * "static repeating pattern... preferable if cleaner/more performant" from the brief. Same warm-
 * ivory background as the rest of the header (--color-background-primary), not the accent green
 * band it used to be, per the new reference's "same coherent warm background system" requirement.
 */
.announcement-bar {
  background: var(--color-background-primary);
  color: var(--color-text-primary);
  border-bottom: var(--border-width) solid var(--color-border-default);
  overflow: hidden;
}
.announcement-bar__inner {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  padding-block: 7px;
  gap: var(--space-6);
}
.announcement-bar__item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  flex-shrink: 0;
  font-size: 11px;
  letter-spacing: var(--letter-spacing-label);
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--color-text-muted);
}
.announcement-bar__item svg { flex-shrink: 0; width: 10px; height: 10px; stroke: var(--color-background-accent); }

/**
 * Component: SiteHeader (.site-header)
 * Purpose: logo, nav, search, cart entry point.
 * Variants: desktop (inline nav), mobile (hamburger). Collapses under 1024px (DESIGN_RULES §12).
 * A11y: <header> + <nav aria-label="Main">; hamburger is a real <button aria-expanded>.
 * Woo dependency: cart count from WC()->cart->get_cart_contents_count().
 */
.site-header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
}
/**
 * Real bug, found live 2026-08-13: the sticky header never accounted for the WP admin bar (only
 * ever visible to logged-in staff, not real customers, which is why full-session QA as a guest
 * never caught it). The admin bar is `position: fixed; top: 0` at its own height (32px desktop,
 * 46px on WP's own <783px breakpoint) — with .site-header's `top: 0` unadjusted, scrolling past
 * the header's natural position made it stick directly under the viewport top instead of under
 * the admin bar, which either overlapped it or (depending on stacking/paint timing) could read as
 * a gap where the admin bar used to visually anchor it. Matches WP core's own admin-bar CSS
 * breakpoint exactly, not a made-up value.
 */
body.admin-bar .site-header { top: 32px; }
@media screen and (max-width: 782px) {
  body.admin-bar .site-header { top: 46px; }
}
.site-header {
  background: var(--color-background-primary);
  /* Header redesign 2026-09-11, follow-up: real bug, found live — removing our own border-bottom
     declaration here didn't actually remove the visible line; getComputedStyle still reported
     rgb(240,240,240), 1px. Same class of unidentified Storefront/parent-theme leak documented
     repeatedly elsewhere in this file (line ~63 above) — a live CSSOM scan for every stylesheet
     rule matching .site-header only turned up Storefront's own transparent
     `border-bottom:1px solid rgba(0,0,0,0)`, not a rule with this visible gray, so the exact
     competing selector wasn't pinned down (likely a comma-grouped selector list a naive
     first-selector-only matcher misses). !important closes it off the same way the margin/padding
     leaks below already do. The reference shows exactly one dividing line in the whole header
     (announcement-bar's own border-bottom, between the ticker and the logo) — this one used to sit
     at the very end of .site-header, i.e. below the nav row, reading as a second, unwanted line. */
  border-bottom: none !important;
  /* Layout correction (2026-07-23): something in Storefront (parent theme) computes a
     margin-bottom of ~63.5px on .site-header that a plain override doesn't beat (confirmed via
     live devtools-equivalent inspection: our own margin-bottom:0 rule is present in the parsed
     stylesheet but still loses at render time) — the exact competing selector wasn't
     identified, but !important is justified here the same way as the .homepage-desktop-only
     utility fix (Milestone 2A): this component owns its own spacing via .section-gap on the
     following section, never an inherited parent-theme margin. Caused the unintended gap
     between the header and the Hero. */
  margin-bottom: 0 !important;
  /* Bug fix (2026-07-23): found the actual source of the reported "blank strip above the
     header" this time — .site-header was carrying a computed padding-top of ~39.27px, the same
     class of Storefront (parent theme) leak as the margin-bottom one above, just on a different
     property, and one the previous pass's margin-top hardening didn't touch since the real leak
     was never on margin. Confirmed via direct getComputedStyle() inspection: padding-top alone
     was non-zero (bottom/left/right were already 0). Fixed the same way, with the same
     justification. */
  padding-top: 0 !important;
  /* Defensive parity, unchanged from the previous pass — no active margin-top leak found, but
     hardening it closes off the same class of bug if it surfaces elsewhere. */
  margin-top: 0 !important;
}
/**
 * Header redesign 2026-09-11, single-row pass: previously TWO stacked desktop rows —
 * .site-header__brand-row (logo alone) and .site-header__nav-row (search / nav / actions) —
 * merged back into this ONE row. Mobile is unaffected (it was always this one row: hamburger,
 * logo, a compact icon search+cart pair) — only the ≥1024px rule below changes, from a plain
 * centered flex row into a `1fr auto 1fr` grid with nav on the left and actions on the right.
 * A flex row with `justify-content: space-between` would only center the logo BETWEEN the nav and
 * actions groups — it would drift off true center the moment either group's width changes (a
 * longer/shorter menu, the cart capsule gaining a second digit). The grid's two 1fr side columns
 * are always equal width regardless of their content, so the auto-sized center column (the logo)
 * is always at the row's true mathematical center; `justify-self: start`/`end` on the nav/actions
 * (below) keeps their own content pinned to the outer edges within those equal tracks.
 */
.site-header__brand-row {
  /* Explicit request: nav (left) / actions (right) should land flush with the hero image's own
     edges above ~1400px viewports, where .hero (capped at 1600px, homepage.css) reads wider than
     the rest of the page's own .container (capped at 1280px, --breakpoint-xl). Unlike .hero,
     this row's content sits inset from its own box by --space-9 (60px, the padding-inline
     below) rather than filling it edge-to-edge — so matching .hero's 1600px max-width here isn't
     enough on its own; it would still leave the nav/actions 60px further in than the hero's own
     edges. 1720px = 1600 + 2×60, so that after this row's own padding is applied, the resulting
     content edges land exactly on the hero's outer edges. Only affects ultra-wide viewports; at
     everything narrower both this row and .container are already viewport-width-constrained the
     same way, so nothing else on the page shifts. */
  max-width: 1720px;
  margin-inline: auto;
  padding-inline: var(--space-5);
  min-height: 54px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}
.site-header__mobile-actions { display: flex; align-items: center; gap: var(--space-2); }
@media (min-width: 1024px) {
  .site-header__brand-row {
    padding-inline: var(--space-9);
    /* Single-row height target: ~90-110px total (explicit request) — this padding plus the
       row's tallest child (the 40px account/cart touch targets, taller than the ~34px logo)
       lands at ~100px: 40 + 2×30. */
    padding-block: var(--space-header-padding-y);
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: var(--space-6);
  }
  .site-header__mobile-actions { display: none; }
}

/* Visual alignment pass 2026-08-13: swapped the text wordmark for the real logo lockup. Sized by
   width with height:auto so the aspect ratio always holds; mobile stays smaller than desktop. */
.site-header__logo { display: inline-flex; line-height: 0; grid-column: 2; justify-self: center; }
.site-header__logo-img { width: 200px; height: auto; display: block; }
@media (min-width: 1024px) {
  /* Single-row pass (2026-09-11): reduced from 443px — that size was sized for a standalone
     centered logo band with nothing beside it; sharing one row with nav + actions needs a smaller
     wordmark to keep the whole row inside the ~90-110px height target. 320px at this logo's own
     6091:632 SVG ratio ≈ 33px tall — still the visually dominant element (larger than the 14px nav
     links or the account/cart controls beside it), just no longer alone driving the row's height. */
  .site-header__logo-img { width: 320px; }
}

.site-header__nav-desktop { display: none; }
.site-header__hamburger { display: inline-flex; }
@media (min-width: 1024px) {
  /* LEFT column. Single-row pass (2026-09-11): was its own centered row (.site-header__nav-row,
     now removed) — now grid-column 1 of the merged .site-header__brand-row, justify-self:start
     keeps it pinned to the row's left edge regardless of how wide this 1fr column actually is. */
  .site-header__nav-desktop {
    display: flex;
    grid-column: 1;
    justify-self: start;
  }
  /* Must come after the unguarded `.site-header__hamburger { display: inline-flex }` base rule
     above (line ~161) — real bug, found live: an earlier attempt hid this from inside the
     .site-header__brand-row media block further up the file instead, which lost the cascade tie
     (equal specificity, but that rule came BEFORE this later unconditional one in source order) —
     the hamburger stayed visible and its reserved flex space pushed the logo 30px off true center. */
  .site-header__hamburger { display: none; }
}

/* 12px / 20px gap — repeated t2 header (also reused verbatim on the Fragrance Guide page),
   not the one-off 13px/24px t3 Collection/Checkout variant. See TODO.md source-priority note. */
.site-header__nav-desktop { align-items: center; gap: var(--space-header-nav-gap); }
.site-header__nav-desktop a {
  /* Single-row pass (2026-09-11): 15px, within the requested 15-17px range for a restrained,
     editorial left-aligned nav (was 14px) — not the shared --font-size-nav (12px), overridden
     locally since that token is also used outside the header (homepage.css, shop.css,
     components.css). */
  font-size: 15px;
  color: var(--color-text-primary);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  padding-bottom: 2px;
  transition: border-color 150ms var(--animation-easing);
}
.site-header__nav-desktop a:hover,
.site-header__nav-desktop a:focus-visible { border-bottom-color: var(--color-text-primary); }
.site-header__nav-desktop a[aria-current="page"] { font-weight: var(--font-weight-emphasis); border-bottom-color: var(--color-background-accent); }

/**
 * Dropdown submenus (.menu-item-has-children) — header redesign 2026-09-11. WordPress core adds
 * this class to any top-level item with children automatically (wp_nav_menu default Walker, no
 * custom Walker needed) and nests the children in a real <ul class="sub-menu">, so this is purely
 * CSS on markup that already exists whenever a real "primary" menu with submenus is assigned.
 * :focus-within (not just :hover) is what makes this keyboard-accessible: tabbing onto any link
 * inside the submenu keeps it visible, exactly as a mouse hover would, with no extra JS/ARIA state
 * needed since these are plain, always-in-the-DOM links, not a disclosure widget.
 */
.site-header__nav-desktop li { position: relative; }
.site-header__nav-desktop .menu-item-has-children > a { display: inline-flex; align-items: center; gap: 4px; }
.site-header__nav-desktop .menu-item-has-children > a::after {
  content: '';
  width: 5px;
  height: 5px;
  border-right: 1.4px solid currentColor;
  border-bottom: 1.4px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  opacity: 0.6;
}
.site-header__nav-desktop .sub-menu {
  display: none;
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  z-index: 1;
  min-width: 180px;
  margin: var(--space-3) 0 0;
  padding: var(--space-3) 0;
  list-style: none;
  background: var(--color-background-surface);
  border: var(--border-width) solid var(--color-border-default);
  border-radius: var(--radius-small);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.06);
}
.site-header__nav-desktop .menu-item-has-children:hover > .sub-menu,
.site-header__nav-desktop .menu-item-has-children:focus-within > .sub-menu { display: block; }
.site-header__nav-desktop .sub-menu a {
  display: block;
  padding: var(--space-2) var(--space-5);
  border-bottom: none;
  white-space: nowrap;
}
.site-header__nav-desktop .sub-menu a:hover,
.site-header__nav-desktop .sub-menu a:focus-visible { background: var(--color-background-primary); }

/* Hidden at mobile (base rule) — single-row pass (2026-09-11): .site-header__actions used to live
   inside .site-header__nav-row, which had its own `display: none` hiding it and everything in it
   below 1024px. Now that it's a direct child of .site-header__brand-row (the row mobile also
   uses, via .site-header__mobile-actions instead), it needs its own explicit mobile hide so it
   doesn't render a second search/account/cart group alongside the mobile icon pair. */
.site-header__actions { display: none; align-items: center; gap: var(--space-2); }
@media (min-width: 1024px) {
  .site-header__actions {
    display: flex;
    gap: var(--space-header-actions-gap);
    grid-column: 3;
    justify-self: end;
  }
}

/**
 * Component: HeaderAction (.header-action) — Search/Account/Cart header triggers.
 * Icon-only at every breakpoint (accessible name comes from aria-label, same as before — only the
 * previously-visible desktop text label is gone). Header redesign 2026-09-11: the earlier t2/
 * Fragrance-Guide reference showed icon+visible-label ("Пошук", "Кошик (N)") on desktop; the new
 * reference is icon-only with a small numeric badge instead, which is why .header-action__label is
 * no longer rendered in the markup at all (see site-header.php) rather than just hidden here.
 * 44px min touch target preserved at every size.
 */
.header-action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: var(--space-2);
  background: none;
  border: none;
  border-radius: var(--radius-small);
  color: var(--color-text-primary);
  font-family: var(--font-body);
  cursor: pointer;
  text-decoration: none;
  transition: background var(--animation-duration) var(--animation-easing);
}
.header-action:hover { background: color-mix(in srgb, var(--color-text-primary) 7%, transparent); }
/* Active/open state — overlay.js sets aria-expanded="true" on the trigger for as long as its
   drawer is open (no extra JS/class needed here). Deliberately not just "undimmed default
   color": a solid accent pill + white icon reads as a clear "this one is open" indicator, using
   the same accent/on-accent pairing already used for active states elsewhere on the site
   (Scent Guide selector, mobile nav overlay). */
.header-action[aria-expanded="true"] { background: var(--color-background-accent); color: var(--color-text-on-accent); }
.header-action[aria-expanded="true"]:hover { background: var(--color-background-accent-hover); }
.header-action svg { flex-shrink: 0; width: 16px; height: 16px; stroke: currentColor; fill: none; }
@media (min-width: 1024px) {
  /* Sized against a real reference (gentlehabits.com.au, measured live: 40x40px touch target,
     28x28px icon inside — 6px of padding on each side). The old 32px/15px pairing read as "very
     small" against that reference. */
  .header-action { min-width: 40px; min-height: 40px; padding: 6px; }
  .header-action svg { width: 28px; height: 28px; }
}

/**
 * Desktop search-as-text (.site-header__search-text) — single-row pass (2026-09-11), explicit
 * request: "Пошук" as a visible word instead of only the magnifying-glass icon. Same
 * data-search-trigger hook/overlay.js behavior as the icon version (site-header__mobile-actions,
 * untouched) — only the visible content differs at this one breakpoint. Overrides .header-action's
 * fixed 40x40 icon touch-target box since text doesn't need a square target.
 */
.site-header__search-text {
  min-width: auto;
  min-height: auto;
  padding: var(--space-2) 0;
  font-size: 15px;
}
.site-header__search-text:hover { background: none; text-decoration: underline; }

/**
 * Desktop cart capsule (.cart-pill) — single-row pass (2026-09-11), explicit request: "КОШИК · N"
 * as a quiet outlined text control instead of an icon + numeric badge (.cart-btn, still used at
 * mobile, untouched). Reuses --color-border-default (the site's one neutral border token) and
 * --radius-pill (already used for badges/hero CTA) rather than inventing new values — deliberately
 * NOT a filled primary .btn, per "do not make it a filled primary CTA".
 * The inner <span data-cart-count-label> is exactly the fragment target WooCommerce's own
 * woocommerce_add_to_cart_fragments filter already refreshes after every AJAX add/remove
 * (inc/woocommerce-cart.php) — no new JS needed for the live count.
 */
.cart-pill {
  min-width: auto;
  min-height: 40px;
  padding: 0 var(--space-6);
  border: var(--border-width) solid var(--color-border-default);
  border-radius: var(--radius-pill);
  background: transparent;
}
.cart-pill:hover { background: color-mix(in srgb, var(--color-text-primary) 6%, transparent); }
.cart-pill .header-action__label {
  font-size: var(--font-size-button);
  letter-spacing: var(--letter-spacing-button);
  white-space: nowrap;
}

.site-header__hamburger-icon { position: relative; width: 18px; height: 12px; }
.site-header__hamburger-icon span,
.site-header__hamburger-icon span::before,
.site-header__hamburger-icon span::after {
  content: '';
  position: absolute;
  left: 0;
  width: 100%;
  height: 1.5px;
  background: currentColor;
}
.site-header__hamburger-icon span { top: 50%; transform: translateY(-50%); }
.site-header__hamburger-icon span::before { top: -6px; }
.site-header__hamburger-icon span::after { top: 6px; }

/**
 * Cart badge — CartButton (.cart-btn)
 * States: default, has-items (badge visible), empty (no badge).
 */
.cart-btn { position: relative; }
.cart-btn__count {
  position: absolute;
  top: 2px; right: 2px;
  min-width: 15px;
  height: 15px;
  padding: 0 3px;
  border-radius: 50%;
  background: var(--color-background-accent);
  color: var(--color-text-on-accent);
  /* A cutout ring in the header's own background color — without it, this badge (already
     accent-colored) would nearly disappear against the trigger's new [aria-expanded="true"]
     active background, which is that same accent color. */
  box-shadow: 0 0 0 2px var(--color-background-primary);
  font-size: 9px;
  font-weight: var(--font-weight-emphasis);
  display: flex;
  align-items: center;
  justify-content: center;
}
.cart-btn__count[data-count="0"] { display: none; }
/* Header redesign 2026-09-11: desktop used to show the count inline in a visible "Кошик (N)" text
   label instead of this overlay badge (2026-07-22 source-priority correction) — that label no
   longer exists in the markup (icon-only actions now, see .header-action above), so the badge is
   shown at every breakpoint instead, matching the new reference. */
