/* AEKE .sg — site header.
 *
 * A port of the aeke.com theme's own header rules, taken from the three files that
 * carry them upstream (`app.css`, `subheader.css`, `mobile-menu.css`) and reduced to
 * the parts our markup actually uses. Declarations are kept as the theme writes
 * them; only the *values* are re-pointed at tokens in `tokens.css`, so there is
 * still exactly one place a colour or size is defined in this project.
 *
 * Why a separate stylesheet rather than Tailwind utilities: this component is a
 * cascade, not a set of classes. The desktop sub-menu opens on `:hover` *and*
 * `:focus-within`, the overlay header acquires a background on `:hover` *or*
 * `.is-sticky`, and the mobile drawer's height is derived from a runtime custom
 * property. Expressing that as utilities would mean re-deriving the same rules with
 * higher specificity, which is the opposite of faithful. The theme ships these
 * rules as their own files too.
 *
 * Loaded after `app.css` so it wins over preflight, exactly as upstream does.
 *
 * MEASURED BREAKPOINTS (live site, verified at nine widths — see execution-plan.md):
 *   768px  — the top bar appears; the gutter widens 15px -> 50px
 *   1068px — 66.75em, the same breakpoint the type scale uses. Desktop nav replaces
 *            the hamburger and the row grows to 80px.
 *
 * MEASURED GEOMETRY (1440px): row 80px · logo 26px tall / 152.9px wide · top bar
 * 38px · nav link 16.5px weight 500 · nav item padding 0 15px · sub-menu 17px 26px
 * on the drawer colour, min-width 190px · badge 10px/600, radius 5px, teal on the
 * badge text colour.
 *
 * No colour value appears in this file except through `var(...)` — the palette is
 * defined once in tokens.css and a test enforces it. Even in comments: the check
 * greps the file for colour literals, and a hex in a comment is still a hex that
 * someone will later copy out of the wrong place.
 */

/* ===========================================================================
   Sticky shell
   ===========================================================================
   The sticky element is a zero-height wrapper, and the header inside it is
   absolutely positioned on top of the page. That combination is what lets the
   header overlay a hero *and* pin to the top on scroll without a fixed element
   reserving layout space. Copying only `position: sticky` onto the header itself
   would look identical until the first scroll and then break. */
.header-section {
  position: sticky;
  top: 0;
  left: 0;
  z-index: 50;
  width: 100%;
}

/* ===========================================================================
   Top bar (`subheader` upstream)
   ===========================================================================
   Hidden below 768px — on a phone the row is pure overhead. */
.subheader {
  position: relative;
  z-index: 51;
  display: none;
  align-items: center;
  min-height: 38px;
  margin: 0;
  padding: 5px 0;
  background: var(--color-secondary-menu-bg);
  color: var(--color-secondary-menu-text);
  font-size: 0.75rem;
}

@media (min-width: 48em) {
  .subheader {
    display: flex;
  }
}

.subheader--inner {
  display: grid;
  grid-template-columns: auto auto;
  width: 100%;
  max-width: 100%;
  gap: 15px;
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.subheader--left,
.subheader--right {
  display: flex;
  align-items: center;
}

.subheader--right {
  justify-content: flex-end;
  text-align: right;
}

/* The live site's top bar has an empty left cell and two dropdowns on the right.
   We have one market, so the right cell holds a single non-interactive label. */
.subheader--right > * {
  flex-shrink: 0;
  margin-left: 15px;
}

.subheader .thb-full-menu {
  text-align: left;
}

.subheader .thb-full-menu > li {
  padding: 0 10px;
}

.subheader .thb-full-menu > li > a {
  margin: 0;
  font-size: calc(var(--font-navigation-scale) * 12px);
  font-weight: 400;
}

.subheader .thb-full-menu > li:first-child {
  padding-left: 0;
}

/* Market label. Styled to sit exactly where the live country selector sits and at
   the same size, but as a <span>: our store is single-market, and a dropdown with
   one option is a control that lies about being a choice. */
.market-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
  color: var(--color-secondary-menu-text);
}

/* ===========================================================================
   Header
   =========================================================================== */
.header {
  display: block;
  position: relative;
  z-index: 30;
  width: 100%;
  padding-inline: var(--gutter);
  background: transparent;
  color: var(--color-header-text);
  /* The theme re-points the generic tokens at the header's own, so any component
     nested in the header (buttons, prices) inherits the header palette rather
     than the page's. Replicated, because dropping it silently changes every
     nested colour. */
  --color-body: var(--color-header-links);
  --color-accent: var(--color-header-links);
  --color-accent-rgb: var(--color-header-links-rgb, var(--color-accent-rgb));
}

/* The header paints its own background on a pseudo-element so the change can be
   transitioned without animating `background-color` across two states. */
.header::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--color-header-bg);
  opacity: 1;
  transition: opacity var(--duration-theme) var(--ease-theme);
}

/* Drop shadow, only once the header is pinned. `header--shadow-medium` upstream. */
.header::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--duration-theme) var(--ease-theme);
}

.header--shadow-medium::after {
  box-shadow: var(--shadow-header-sticky);
}

.header.is-sticky::after {
  opacity: 1;
}

/* ---------------------------------------------------------------- overlay mode
   On the homepage the header floats over the hero with no background, and picks
   one up on hover or once it sticks. `transparent--true` upstream.

   NOTE: because the overlay also turns the links white, the menu is invisible
   wherever the hero happens to be light. That is upstream behaviour, reproduced
   here rather than quietly altered; it is flagged in the phase notes as a
   legibility risk that the hero artwork has to respect. */
.header--overlay {
  position: absolute;
  inset-inline: 0;
}

.header--overlay::before {
  opacity: 0;
}

.header--overlay:hover::before,
.header--overlay.is-sticky::before {
  opacity: 1;
}

.header--overlay:not(:hover):not(.is-sticky) .logolink,
.header--overlay:not(:hover):not(.is-sticky) .thb-full-menu > li > a,
.header--overlay:not(:hover):not(.is-sticky) .thb-secondary-area-item {
  color: var(--color-header-transparent-text);
}

.header--overlay:not(:hover):not(.is-sticky) .thb-full-menu > li > a::after {
  background: var(--color-header-transparent-text);
}

.header--overlay:not(:hover):not(.is-sticky) .thb-full-menu > li > a > svg path {
  stroke: var(--color-header-transparent-text);
}

.header--overlay:not(:hover):not(.is-sticky) .thb-secondary-area svg path {
  fill: var(--color-header-transparent-text);
}

.header--overlay:not(:hover):not(.is-sticky) .thb-secondary-area .thb-item-count {
  color: var(--color-header-bg);
}

.header--overlay:not(:hover):not(.is-sticky) .mobile-toggle span {
  background: var(--color-header-transparent-text);
}

/* ------------------------------------------------------------------- the row */
.header--inner {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  column-gap: 20px;
  width: 100%;
  max-width: var(--grid-width);
  min-height: var(--header-row-height);
  margin-inline: auto;
}

/* The header ships in the theme's `style1` arrangement: logo left, menu in the
   middle band, actions right. The middle band is capped at 70% of the row, which
   is what stops a long menu from squeezing the logo or the actions.
 *
 * The theme writes this as `auto minmax(auto,70%) auto`. Porting that declaration
 * verbatim did NOT reproduce the live geometry: `minmax(auto, 70%)` lets the
 * middle track settle at its own content width (790px) and hands the leftover
 * space to the two `auto` tracks instead — 254.9 | 790.3 | 254.9, where the live
 * site renders 187.7 | 927.4 | 169.8. An explicit `70%` produces the measured
 * result and, more importantly, reproduces the observable consequence: the menu
 * runs out of room and wraps onto a second line between 1068px and ~1218px, which
 * is why the live header is 93px tall in that band and 80px outside it.
 *
 * Matching the rendering rather than the declaration, again — the same lesson as
 * the type scale in P1. */
.header.style1 .header--inner {
  grid-template-columns: auto 70% auto;
}

/* ...and the 70% is a *desktop* number. On a phone the menu lives in the drawer, so the middle
 * track holds nothing but the logo, and 70% of a 330px row is 231px — wider than the logo needs
 * and, with the two `auto` tracks and the 40px of gaps, 44px wider than the row itself. The grid
 * then overflows and takes the cart badge with it: measured at 375, the action area's right edge
 * sat at x=389 in a 360px viewport and every page on the site carried 41px of horizontal scroll.
 * `minmax(0, 1fr)` lets the logo's track give back what it does not need, which puts the actions
 * at x=275..345 — the same numbers the live site reports.
 *
 * The `0` minimum matters: a bare `1fr` will not shrink below its content's min-content width, so
 * the logo could hold the row open again. */
@media (max-width: 47.99em) {
  .header.style1 .header--inner {
    grid-template-columns: auto minmax(0, 1fr) auto;
  }
}

.header.style1 .logolink {
  text-align: left;
  margin-right: auto;
  justify-content: flex-start;
}

/* `header--full-width` upstream: the row spans the viewport, held in by the
   gutter, instead of being capped at --grid-width. Measured: the live row starts
   at x=50 and ends 50px short of the right edge. */
.header--full-width .header--inner {
  max-width: 100%;
}

@media (min-width: 1068px) {
  .header--inner {
    min-height: var(--header-row-height-lg);
  }
}

/* Hairline under the row. Suppressed on the homepage, where it would draw a line
   across the hero. */
.header--inner::before {
  content: "";
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 1px;
  background: var(--color-header-border);
}

.header--overlay .header--inner::before {
  content: none;
}

/* ------------------------------------------------------------------- the logo */
.logolink {
  display: inline-flex;
  position: relative;
  margin: 20px 0;
  margin-right: auto;
  justify-content: flex-start;
  text-align: left;
}

.logolink .logoimg {
  width: auto;
  height: var(--logo-height-mobile);
  object-fit: contain;
  object-position: left;
}

@media (min-width: 1068px) {
  .logolink .logoimg {
    height: var(--logo-height);
  }
}

/* The theme ships two logo images — a light variant that sits on the transparent
   header — stacked with the second absolutely positioned. Both files are the same
   artwork upstream; keeping the structure means a client who later supplies a
   dark-background logo has somewhere for it to go without a template change. */
.logolink .logoimg--light {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  opacity: 0;
}

.header--overlay:not(:hover):not(.is-sticky) .logolink .logoimg {
  opacity: 0;
}

.header--overlay:not(:hover):not(.is-sticky) .logolink .logoimg--light {
  opacity: 1;
}

/* ------------------------------------------------------------------ mobile nav
   The hamburger and the drawer it opens. Hidden from 1068px up. */
.thb-header-mobile-left {
  display: inline-flex;
  margin-right: auto;
}

@media (min-width: 1068px) {
  .thb-header-mobile-left {
    display: none;
  }
}

.mobile-toggle-wrapper {
  display: inline-flex;
}

.mobile-toggle-wrapper summary {
  list-style: none;
}

.mobile-toggle-wrapper summary::-webkit-details-marker {
  display: none;
}

.mobile-toggle {
  display: inline-flex;
  position: relative;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  margin-left: -15px;
  cursor: pointer;
}

/* Three bars drawn as absolutely positioned 18x1.5px spans, positioned at
   18/23/28px from the top of the 48px box. The doubled `display` in the theme
   (inline-flex then flex) is collapsed to `flex` here — a bug upstream, with no
   observable effect. */
.mobile-toggle span {
  position: absolute;
  top: 18px;
  left: 15px;
  width: 18px;
  height: 1.5px;
  background: var(--color-header-icons);
  border-radius: 1px;
  transition: transform var(--duration-theme) var(--ease-theme), opacity var(--duration-theme) var(--ease-theme);
}

.mobile-toggle span:nth-child(1) {
  transform-origin: top left;
}

.mobile-toggle span:nth-child(2) {
  top: 23px;
}

.mobile-toggle span:nth-child(3) {
  top: 28px;
  transform-origin: top left;
}

/* Open state. Driven from `[open]` so it works with no JavaScript at all — the
   drawer is a <details>, which is the theme's own choice and worth keeping. */
.mobile-toggle-wrapper[open] .mobile-toggle span:nth-child(1) {
  transform: rotate(45deg) translateY(-3px);
}

.mobile-toggle-wrapper[open] .mobile-toggle span:nth-child(2) {
  opacity: 0;
}

.mobile-toggle-wrapper[open] .mobile-toggle span:nth-child(3) {
  transform: rotate(-45deg) translateY(1px);
}

.mobile-menu-drawer {
  position: absolute;
  top: 100%;
  left: 0;
  /* `100%`, not `100vw`. `vw` counts the scrollbar and the containing block does not, so a closed
     drawer measured 322px in a 320px viewport and gave every product page a 2px horizontal scroll —
     Gate 4 caught it at 320px and nowhere else, which is exactly where it hurts. The drawer is
     absolutely positioned against the header, which already spans the page, so `100%` is the same
     width the `vw` was reaching for. */
  width: 100%;
  height: calc(100vh - var(--header-offset));
  overflow-x: hidden;
  overflow-y: auto;
  text-align: left;
  background: var(--color-header-bg);
  border-top: 1px solid var(--color-header-border);
  opacity: 0;
  visibility: hidden;
  transform: translateY(50px);
  transition: opacity var(--duration-theme) var(--ease-theme), transform var(--duration-theme) var(--ease-theme);
  --color-body: var(--color-header-links);
  --color-accent: var(--color-header-links);
}

@supports (height: 100dvh) {
  .mobile-menu-drawer {
    height: calc(100dvh - var(--header-offset));
  }
}

.mobile-toggle-wrapper[open] .mobile-menu-drawer {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.mobile-menu-drawer--inner {
  display: flex;
  flex-direction: column;
  min-height: 100%;
  position: relative;
}

/* ------------------------------------------------------------------ drawer list
   Ported from the theme's own `mobile-menu.css`. The drawer is a stack of
   <details> panels: opening one slides its sub-menu in over the list, and the first
   row of that sub-menu is a Back button. That is upstream's model and it is a good
   one — a phone user gets a real "back" affordance instead of a menu that grows
   ever taller. */
.mobile-menu {
  margin: 0;
  padding: 0;
  list-style: none;
}

.mobile-menu > li > a,
.mobile-menu .parent-link {
  display: flex;
  align-items: center;
  width: 100%;
  padding: 15px var(--gutter);
  border-bottom: 1px solid var(--color-header-border);
  color: var(--color-header-links);
  font-size: calc(var(--font-navigation-scale) * 15px);
  font-weight: var(--font-body-medium-weight);
  text-align: left;
}

.mobile-menu .parent-link {
  cursor: pointer;
  list-style: none;
}

.mobile-menu .parent-link::-webkit-details-marker {
  display: none;
}

/* The chevron sits hard right and points at the panel it opens. */
.mobile-menu .link-forward {
  display: inline-flex;
  margin-left: auto;
}

.mobile-menu .sub-menu {
  position: absolute;
  inset: 0;
  margin: 0;
  padding: 0;
  list-style: none;
  background: var(--color-header-bg);
  overflow-y: auto;
  opacity: 0;
  visibility: hidden;
  transform: translateX(100%);
  transition: transform var(--duration-theme) var(--ease-theme),
              opacity var(--duration-theme) var(--ease-theme),
              visibility var(--duration-theme) var(--ease-theme);
}

.mobile-menu details[open] > .sub-menu {
  opacity: 1;
  visibility: visible;
  transform: translateX(0);
}

.mobile-menu .parent-link-back {
  border-bottom: 1px solid var(--color-header-border);
}

.mobile-menu .parent-link-back--button {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 15px var(--gutter);
  border: 0;
  background: none;
  color: var(--color-header-links);
  font-size: calc(var(--font-navigation-scale) * 15px);
  font-weight: var(--font-body-medium-weight);
  text-align: left;
  cursor: pointer;
}

.mobile-menu .parent-link-back--button span {
  display: inline-flex;
}

.mobile-menu .sub-menu li a {
  display: block;
  padding: 13px var(--gutter);
  border-bottom: 1px solid var(--color-header-border);
  color: var(--color-header-links);
  font-size: calc(var(--font-navigation-scale) * 15px);
}

/* ------------------------------------------------------------------ social row */
.mobile-menu-drawer .social-links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 5px;
  margin: 0;
  padding: 15px var(--gutter);
  list-style: none;
}

.social-links li a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  color: var(--color-header-icons);
}

.social-links li a:hover,
.social-links li a:focus {
  color: var(--color-accent);
}

/* --------------------------------------------------------------- drawer footer */
/* Pinned to the bottom of the drawer, so the market is reachable by thumb rather
   than by scrolling back to the top. */
.mobile-menu-drawer .thb-mobile-menu-footer {
  margin-top: auto;
  position: sticky;
  bottom: 0;
  padding: 15px var(--gutter);
  border-top: 1px solid var(--color-header-border);
  background: var(--color-header-bg);
  text-align: center;
}

/* ===========================================================================
   Desktop navigation
   =========================================================================== */
.full-menu {
  display: none;
}

@media (min-width: 1068px) {
  .full-menu {
    display: flex;
  }
}

.thb-full-menu {
  margin: 0;
  padding: 0;
  list-style: none;
  text-align: center;
  font-size: 0.9375rem;
}

.thb-full-menu > li {
  display: inline-flex;
  align-items: center;
  padding: 0 15px;
}

.thb-full-menu > li > a {
  margin: 10px 0;
  font-weight: var(--font-body-medium-weight);
}

.thb-full-menu--link {
  position: relative;
  color: var(--color-header-links);
  font-size: calc(var(--font-navigation-scale) * 15px);
}

/* The hover underline: a 1px rule that scales from the left, not a border that
   appears and shifts the text. Applies to focus as well as hover, so it doubles
   as the keyboard affordance. */
.thb-full-menu--link::after {
  content: "";
  display: block;
  position: absolute;
  top: 100%;
  left: 0;
  width: 100%;
  height: 1px;
  background: var(--color-header-links-hover);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--duration-theme) var(--ease-theme);
  will-change: transform;
}

.thb-full-menu--link:hover,
.thb-full-menu--link:focus {
  color: var(--color-header-links-hover);
}

.thb-full-menu--link:hover::after,
.thb-full-menu--link:focus::after {
  transform: scaleX(1);
}

.thb-full-menu--link:hover svg path,
.thb-full-menu--link:focus svg path {
  stroke: var(--color-header-links-hover);
}

.thb-full-menu li.menu-item-has-children {
  position: relative;
  z-index: 1;
}

.thb-full-menu li.menu-item-has-children:hover,
.thb-full-menu li.menu-item-has-children:focus-within {
  z-index: 2;
}

/* Room for the chevron. */
.thb-full-menu li.menu-item-has-children > .thb-full-menu--link {
  padding-right: 15px;
  position: relative;
}

.thb-full-menu li.menu-item-has-children > .thb-full-menu--link svg {
  position: absolute;
  top: 50%;
  right: 0;
  margin-top: -3px;
}

/* ----------------------------------------------------------------- the sub-menu
   Two ways to open, and which one applies depends on whether scripting is on.

   WITHOUT JavaScript, `:hover` and `:focus-within` are the only mechanisms there
   are, so both open the panel. That keeps the menu usable on a page where the
   script failed to load, which is the whole point of the `no-js` class.

   WITH JavaScript, the trigger owns the state instead. The reason is Escape: if
   `:focus-within` still opens the panel, dismissing it is impossible, because the
   only place to put focus back is the trigger — and the trigger is inside the
   panel's own list item, so the panel immediately re-opens. The first version of
   this did exactly that, and the result was worse than not handling Escape at all:
   it announced "collapsed" to a screen reader while leaving the links on screen
   and clickable. One source of truth, and it is the script.

   CSS-only open is scoped to `.no-js` so the two never fight. */
.thb-full-menu .sub-menu {
  position: absolute;
  top: 100%;
  left: -11px;
  z-index: 2;
  min-width: 190px;
  margin: 0;
  padding: 17px 26px;
  list-style: none;
  background: var(--color-drawer-bg);
  color: var(--color-header-links);
  font-size: calc(var(--font-navigation-scale) * 15px);
  line-height: 1.1;
  text-align: left;
  white-space: nowrap;
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--duration-theme) var(--ease-theme),
              visibility var(--duration-theme) var(--ease-theme);
}

.no-js .thb-full-menu li.menu-item-has-children:hover > .sub-menu,
.no-js .thb-full-menu li.menu-item-has-children:focus-within > .sub-menu,
.js .thb-full-menu li.menu-item-has-children.is-open > .sub-menu {
  opacity: 1;
  visibility: visible;
}

.thb-full-menu .sub-menu .thb-full-menu--link {
  display: inline-block;
  padding-block: 7px;
}

.thb-full-menu .sub-menu .thb-full-menu--link::after {
  top: calc(100% - 3px);
}

/* ------------------------------------------------------------------- the badge
   "NEW" next to S1 Pro. Uppercase 10px on the brand teal at a 5px radius, nudged
   5px up so it sits on the cap line rather than the baseline. */
.menu-item-badge {
  display: inline-flex;
  align-items: center;
  margin-left: 10px;
  padding: 2px 8px;
  border-radius: 5px;
  background: var(--menu-badge-bg);
  color: var(--menu-badge-text);
  font-size: 0.625rem;
  font-weight: var(--font-body-bold-weight);
  letter-spacing: 0.03em;
  text-transform: uppercase;
  transform: translateY(-5px);
}

/* ===========================================================================
   Header actions: search, account, cart
   =========================================================================== */
.thb-secondary-area {
  display: inline-flex;
  align-items: center;
  justify-content: end;
  min-width: 70px;
  height: 100%;
  margin-left: auto;
  line-height: 1;
  white-space: nowrap;
}

@media (min-width: 48em) {
  .thb-secondary-area {
    min-width: 135px;
  }
}

.thb-secondary-area-item {
  display: inline-flex;
  align-items: center;
  height: 100%;
  padding: 0 7px;
  color: var(--color-header-links);
}

@media (min-width: 48em) {
  .thb-secondary-area-item {
    padding: 0 10px;
  }
}

.thb-secondary-area-item:last-child {
  padding-right: 0;
}

/* The account icon is hidden on a phone, which is what the live site does: measured at 375, its
 * action area is 70px wide holding search (34) and cart (31) only, and its own account item
 * computes to `display: none`. Ours kept all three. */
@media (max-width: 47.99em) {
  .thb-secondary-account {
    display: none;
  }
}

.thb-secondary-area-item svg {
  pointer-events: none;
}

.thb-secondary-cart .thb-secondary-item-icon {
  position: relative;
  transform: translateY(2px);
}

/* Cart count. Sits on the cart icon's top-right, circular, teal with dark text —
   the same 19px circle the live site uses. */
.thb-item-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  position: absolute;
  top: -8px;
  right: -12px;
  width: 19px;
  height: 19px;
  border-radius: 50%;
  background: var(--color-accent);
  color: var(--color-header-bg);
  font-size: 0.625rem;
  font-weight: var(--font-body-bold-weight);
  text-align: center;
}

/* An empty cart shows a 0 rather than hiding the badge — measured on the live
   site, and it also tells the shopper the control is there before they use it. */

/* The page behind the drawer must not scroll under it, or the drawer looks like a
   panel that has come loose. Set by the header script alongside `[open]`. */
body.menu-open {
  overflow: hidden;
}

@media (prefers-reduced-motion: reduce) {
  .header::before,
  .header::after,
  .thb-full-menu--link::after,
  .mobile-menu-drawer,
  .mobile-toggle span {
    transition-duration: 0.01ms;
  }
}
