/* ============================================================
   Farmers Imports — Components
   Reference: design-system.md §5. Structure follows micfood.com:
   quiet catalog cards, spec-sheet product pages.
   ============================================================ */

/* ── HEADER — floating pill ─────────────────────────────── */

/* brand | links | actions. The 1fr side tracks are equal, so the centre
   track lands in the true centre of the bar. */
.hdr {
  position: fixed; inset: 16px 16px auto 16px; z-index: 100;
  display: grid; grid-template-columns: 1fr auto 1fr;
  align-items: center; gap: 24px;
  background: #fff;
  border: .5px solid var(--line-1);
  border-radius: var(--r-pill);
  /* Symmetric padding — asymmetric padding shifts the centre grid track
     off the pill's optical centre. Logo breathing room comes from the
     brand's own padding instead. */
  padding: 8px 12px;
  box-shadow: var(--sh-header);
  backdrop-filter: blur(14px) saturate(140%);
  transition: background-color var(--d-nav) var(--ease-nav),
              border-color     var(--d-nav) var(--ease-nav),
              box-shadow       var(--d-nav) var(--ease-nav),
              padding          var(--d-nav) var(--ease-nav),
              top              var(--d-nav) var(--ease-nav);
}
.hdr__brand   { justify-self: start; padding-left: 10px; }
.hdr__logo    { height: 50px; width: auto; transition: height var(--d-nav) var(--ease-nav); }
.hdr__logo--light { display: none; }
.hdr__menu    { display: contents; }
.hdr__nav     { justify-self: center; display: flex; align-items: center; gap: 30px; }
.hdr__actions { justify-self: end; display: flex; align-items: center; gap: 14px; }

.hdr__link {
  position: relative;
  font-family: var(--fb); font-weight: 500; font-size: 15.5px;
  color: rgba(28, 66, 53, .70);
  transition: color var(--d-base) var(--ease-out);
}
.hdr__link::after {
  content: ''; position: absolute; left: 0; bottom: -4px;
  width: 100%; height: 1.5px; background: var(--li);
  transform: scaleX(0); transform-origin: left;
  transition: transform var(--d-base) var(--ease-out);
}
.hdr__link:hover,
.hdr__link[aria-current='page'] { color: var(--fg-1); }
.hdr__link:hover::after,
.hdr__link[aria-current='page']::after { transform: scaleX(1); }

/* ── Over-hero state ────────────────────────────────────────
   On pages whose first section is a dark full-bleed hero (body.nav-over-hero),
   the header starts with no pill at all — it sits *inside* the artwork, larger
   and in warm white. Once the hero has cleared the bar, JS adds .is-scrolled
   and every declaration below stops applying, so the header falls back to the
   floating white pill defined above. The solid state is the default on
   purpose: with JS off, or on every other page, the header is always legible. */

.nav-over-hero .hdr:not(.is-scrolled) {
  top: 22px;
  background: transparent;
  border-color: transparent;
  box-shadow: none;
  backdrop-filter: none;
  padding: 14px 12px;
}
.nav-over-hero .hdr:not(.is-scrolled) .hdr__logo--dark  { display: none; }
.nav-over-hero .hdr:not(.is-scrolled) .hdr__logo--light { display: block; height: 60px; }

.nav-over-hero .hdr:not(.is-scrolled) .hdr__link { color: rgba(249, 246, 240, .80); }
.nav-over-hero .hdr:not(.is-scrolled) .hdr__link:hover,
.nav-over-hero .hdr:not(.is-scrolled) .hdr__link[aria-current='page'] { color: var(--bl); }

.nav-over-hero .hdr:not(.is-scrolled) .lang           { border-color: var(--line-dark-2); }
.nav-over-hero .hdr:not(.is-scrolled) .lang__opt      { color: rgba(249, 246, 240, .62); }
.nav-over-hero .hdr:not(.is-scrolled) .lang__opt--on  { background: var(--bl); color: var(--fg-1); }
.nav-over-hero .hdr:not(.is-scrolled) .lang__opt--soon{ color: rgba(249, 246, 240, .34); }
.nav-over-hero .hdr:not(.is-scrolled) a.lang__opt:hover { background: rgba(249, 246, 240, .14); color: var(--bl); }

/* Deep green on a dark video reads as a hole rather than a button. A hairline
   gives it an edge without changing the fill. */
.nav-over-hero .hdr:not(.is-scrolled) .btn--forest {
  box-shadow: inset 0 0 0 1px rgba(249, 246, 240, .30);
}

/* Scrolled: a touch more compact than the resting pill on other pages, so the
   change registers as more than a colour swap. */
.nav-over-hero .hdr.is-scrolled { padding: 6px 12px; }
.nav-over-hero .hdr.is-scrolled .hdr__logo { height: 46px; }

/* ── Catalog dropdown ───────────────────────────────────── */

.hdr__item { position: relative; display: flex; align-items: center; }

.dropdown {
  position: absolute; top: calc(100% + 22px); left: 50%;
  z-index: 120;
  display: grid; grid-template-columns: 1fr 1fr; gap: 4px 40px;
  min-width: 460px;
  background: #fff;
  border: .5px solid var(--line-1);
  border-radius: var(--r-card-l);
  box-shadow: 0 18px 52px rgba(28, 66, 53, .14);
  padding: 24px 28px 18px;
  opacity: 0; visibility: hidden; pointer-events: none;
  transform: translateX(-50%) translateY(-8px);
  transition: opacity var(--d-base) var(--ease-out),
              transform var(--d-base) var(--ease-out),
              visibility var(--d-base);
}

/* Bridges the gap between link and panel so the pointer can travel
   without the panel closing underneath it. */
.dropdown::before {
  content: ''; position: absolute; left: 0; right: 0;
  top: -26px; height: 26px;
}

.hdr__item:hover .dropdown,
.hdr__item:focus-within .dropdown {
  opacity: 1; visibility: visible; pointer-events: auto;
  transform: translateX(-50%) translateY(0);
}

.dd__head {
  display: flex; align-items: baseline; gap: 8px;
  font-family: var(--fd); font-weight: 600;
  font-size: 10px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--fg-1);
  padding-bottom: 10px; margin-bottom: 6px;
  border-bottom: .5px solid var(--line-1);
}
.dd__no { font-family: var(--fb); font-weight: 500; color: var(--fg-faint); letter-spacing: .06em; font-variant-numeric: tabular-nums; }

.dd__link {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  font-family: var(--fb); font-weight: 300; font-size: .88rem;
  color: var(--fg-3);
  padding: 7px 10px; margin: 0 -10px;
  border-radius: 8px;
  transition: background var(--d-base) var(--ease-out),
              color      var(--d-base) var(--ease-out);
}
.dd__link:hover { background: var(--bg-tint); color: var(--fg-1); }

.dd__n { font-family: var(--fb); font-weight: 500; font-size: 11px; color: var(--fg-faint); flex: none; font-variant-numeric: tabular-nums; }

.dd__all {
  grid-column: 1 / -1;
  display: flex; align-items: center; justify-content: space-between;
  margin-top: 14px; padding-top: 14px;
  border-top: .5px solid var(--line-1);
  font-family: var(--fd); font-weight: 600; font-size: .84rem;
  color: var(--fg-1);
}
.dd__all:hover { color: var(--na); }

/* ── Contact popover ─────────────────────────────────────
   Click-toggled (not hover), since its trigger is a <button> that has to
   work identically on touch. Shares the catalog dropdown's card language:
   white panel, hairline border, soft lift shadow. */

.contact-pop { position: relative; display: inline-flex; }

.contact-pop__panel {
  position: absolute; top: calc(100% + 14px); left: 50%;
  z-index: 120; min-width: 240px;
  background: #fff;
  border: .5px solid var(--line-1);
  border-radius: var(--r-card-l);
  box-shadow: 0 18px 52px rgba(28, 66, 53, .14);
  padding: 10px;
  transform: translateX(-50%);
}
.contact-pop__panel[hidden] { display: none; }

.contact-pop__link {
  display: flex; align-items: center; gap: 12px;
  font-family: var(--fb); font-weight: 300; font-size: .88rem;
  color: var(--fg-3);
  padding: 10px; border-radius: 8px;
  transition: background var(--d-base) var(--ease-out), color var(--d-base) var(--ease-out);
}
.contact-pop__link svg { width: 17px; height: 17px; flex: none; color: var(--fg-faint); }
.contact-pop__link:hover { background: var(--bg-tint); color: var(--fg-1); }

/* In the header the trigger sits near the pill's right edge — centring the
   panel under it would push half its width past the viewport, so it hangs
   from the right instead. The hero CTA is screen-centred and keeps the
   default centred panel. */
.hdr__actions .contact-pop__panel { left: auto; right: 0; transform: none; }

/* Warm-white pill, so this holds up on the header's dark over-hero state too. */
.nav-over-hero .hdr:not(.is-scrolled) .contact-pop__panel { border-color: var(--line-dark-2); }

/* ── Language switcher ──────────────────────────────────── */

.lang {
  display: inline-flex; align-items: center;
  border: .5px solid var(--line-2);
  border-radius: var(--r-pill);
  padding: 3px;
}
.lang__opt {
  font-family: var(--fd); font-weight: 600; font-size: 11px;
  letter-spacing: .06em;
  padding: 5px 11px; border-radius: var(--r-pill);
  color: rgba(28, 66, 53, .55);
  transition: background var(--d-base) var(--ease-out),
              color      var(--d-base) var(--ease-out);
}
.lang__opt--on { background: var(--fg-1); color: var(--bl); }
.lang__opt--soon { color: rgba(28, 66, 53, .32); cursor: not-allowed; }
a.lang__opt:hover { background: var(--bg-tint); color: var(--fg-1); }

.hdr__burger { display: none; width: 44px; height: 44px; background: none; border: 0; }

@media (max-width: 880px) {
  /* backdrop-filter must be off here: it makes .hdr a containing block for
     position:fixed descendants, which traps the nav overlay inside the pill.
     The header background is opaque #fff anyway, so nothing is lost. */
  .hdr {
    inset: 8px 8px auto 8px; padding: 8px 10px;
    display: flex; justify-content: space-between; align-items: center;
    backdrop-filter: none;
  }
  .hdr__logo { height: 42px; }
  .hdr__menu { display: none; }

  /* Logo and burger must stay clickable above the open overlay — the overlay
     is position:fixed, so unpositioned siblings would paint underneath it. */
  .hdr > a:first-child,
  .hdr__burger { position: relative; z-index: 101; }

  /* Bars are absolutely placed at 15/21/27px so the open-state transform
     has exact offsets to collapse to. Grid + gap left them uncentred and
     the "close" icon rendered as a chevron instead of a cross.
     The box is 44px — the touch minimum — while the glyph stays 22px. */
  .hdr__burger { display: block; position: relative; }
  .hdr__burger span {
    position: absolute; left: 11px; width: 22px; height: 2px;
    background: var(--fg-1); border-radius: 2px;
    transition: transform 300ms var(--ease-out), opacity 200ms;
  }
  .hdr__burger span:nth-child(1) { top: 15px; }
  .hdr__burger span:nth-child(2) { top: 21px; }
  .hdr__burger span:nth-child(3) { top: 27px; }
  .hdr__burger[aria-expanded='true'] span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
  .hdr__burger[aria-expanded='true'] span:nth-child(2) { opacity: 0; }
  .hdr__burger[aria-expanded='true'] span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

  /* No backdrop-filter: the fill is .98 opaque, so the blur is invisible and
     only costs a full-screen composite on every scroll frame of a phone. */
  /* justify-content:center centres the block, but a centred flex column that
     outgrows its container overflows in BOTH directions and the top half
     becomes unreachable — there is no scrolling back above the start. At
     740x360 (a phone in landscape) this cleared by 6px. `auto` + `safe center`
     means it centres while it fits and scrolls from the top once it does not. */
  .hdr__menu--open {
    display: flex; flex-direction: column; align-items: center;
    justify-content: safe center;
    position: fixed; inset: 0; z-index: 99; gap: 26px;
    padding: 76px 20px 32px;
    background: var(--bg-base);
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
  }
  .hdr__menu--open .hdr__nav {
    flex-direction: column; align-items: center; gap: 6px; width: 100%;
  }
  /* The catalog filter panel covers families on mobile. */
  .dropdown { display: none; }
  /* Padding, not gap: the whole row has to be tappable, not just the glyphs. */
  .hdr__menu--open .hdr__link {
    font-size: 1.4rem; text-align: center;
    display: block; padding: 14px 24px; min-height: 52px;
  }
  .hdr__menu--open .hdr__link::after { display: none; }
  .hdr__menu--open .hdr__actions { flex-direction: column; gap: 18px; }
  .hdr__menu--open .lang { transform: scale(1.15); }

  /* ── Logo while the overlay is open ───────────────────────
     On the hero pages the header is in its transparent state, which means
     the WHITE logo is showing. The overlay that opens on top of it is warm
     white, so the wordmark vanished completely. .is-menu-open is set by the
     burger handler in layout.js; it flips the pair back to the dark mark.
     A class, not :has(), so the state is explicit and testable. */
  .nav-over-hero .hdr.is-menu-open .hdr__logo--light { display: none; }
  .nav-over-hero .hdr.is-menu-open .hdr__logo--dark  { display: block; }

  /* Over-hero, mobile. Only the logo and the burger are visible at this width,
     so those are the only things that need the light treatment. */
  .nav-over-hero .hdr:not(.is-scrolled) .hdr__logo--light { height: 46px; }
  .nav-over-hero .hdr.is-scrolled .hdr__logo { height: 42px; }
  .nav-over-hero .hdr:not(.is-scrolled) .hdr__burger span { background: var(--bl); }

  /* The open menu is a light overlay: the burger becomes the close cross on
     that surface, and the nav inside it goes back to dark type. */
  .nav-over-hero .hdr:not(.is-scrolled) .hdr__burger[aria-expanded='true'] span { background: var(--fg-1); }
  .nav-over-hero .hdr:not(.is-scrolled) .hdr__menu--open .hdr__link { color: rgba(28, 66, 53, .70); }
  .nav-over-hero .hdr:not(.is-scrolled) .hdr__menu--open .hdr__link:hover,
  .nav-over-hero .hdr:not(.is-scrolled) .hdr__menu--open .hdr__link[aria-current='page'] { color: var(--fg-1); }
  .nav-over-hero .hdr:not(.is-scrolled) .hdr__menu--open .lang { border-color: var(--line-2); }
  .nav-over-hero .hdr:not(.is-scrolled) .hdr__menu--open .lang__opt { color: rgba(28, 66, 53, .55); }
  .nav-over-hero .hdr:not(.is-scrolled) .hdr__menu--open .lang__opt--on { background: var(--fg-1); color: var(--bl); }
  .nav-over-hero .hdr:not(.is-scrolled) .hdr__menu--open .lang__opt--soon { color: rgba(28, 66, 53, .32); }

  /* In the overlay the switcher is a primary control, not a header afterthought. */
  .hdr__menu--open .lang__opt { font-size: 12.5px; padding: 9px 18px; }
}

/* ── NAV OVERLAY, PHONE IN LANDSCAPE ────────────────────────
   Three 52px rows stacked over a switcher and a button need ~350px,
   which is the entire height of a phone turned sideways. The panel
   scrolls rather than clipping either way, but scrolling a menu of
   four items is a failure of layout, not a feature: compress the
   rows and put the switcher beside the button instead.
   ─────────────────────────────────────────────────────────── */
@media (max-width: 880px) and (max-height: 500px) and (orientation: landscape) {
  .hdr__menu--open { padding: 60px 20px 20px; gap: 14px; }
  .hdr__menu--open .hdr__nav { gap: 0; }
  .hdr__menu--open .hdr__link {
    font-size: 1.15rem; padding: 10px 24px; min-height: 44px;
  }
  .hdr__menu--open .hdr__actions { flex-direction: row; gap: 14px; }
  .hdr__menu--open .lang { transform: none; }
}

/* ── BUTTONS ────────────────────────────────────────────── */

/* Buttons use the body sans (Outfit), not the display or mono face — small
   UI labels and numbers stay in the running-text family for a calmer,
   less "typeset" feel. Weight 500 gives the pill enough presence. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  font-family: var(--fb); font-weight: 500; font-size: .92rem; letter-spacing: .005em;
  padding: .85rem 1.4rem;
  border: 0; border-radius: var(--r-pill);
  transition: background var(--d-base) var(--ease-out),
              color      var(--d-base) var(--ease-out),
              transform  var(--d-fast) var(--ease-out);
}
.btn:active { transform: scale(.98); }
.btn svg { width: 17px; height: 17px; flex: none; }

.btn--primary { background: var(--na); color: var(--bl); }
.btn--primary:hover { background: var(--fi-naranja-hover); }

/* Two filled alternatives to the orange. They exist so a CTA can sit on
   artwork or inside the header without the orange pill dominating the frame;
   orange stays the page-level call to action. */
.btn--teal { background: var(--tl); color: var(--bl); }
.btn--teal:hover { background: var(--to); }

.btn--forest { background: var(--vo); color: var(--bl); }
.btn--forest:hover { background: #143026; }

.btn--ghost { background: transparent; color: var(--fg-1); border: 1px solid var(--line-3); }
.btn--ghost:hover { background: var(--fg-1); color: var(--bl); }

.btn--ghost-light {
  background: rgba(249, 246, 240, .06); color: var(--bl);
  border: 1px solid var(--line-dark-2);
}
.btn--ghost-light:hover { background: var(--bl); color: var(--fg-1); }

.btn--sm { font-size: 13px; padding: 10px 18px; }

/* ── BADGES & PILLS ─────────────────────────────────────── */

.badge {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--fd); font-weight: 600;
  font-size: .66rem; letter-spacing: .08em; text-transform: uppercase;
  padding: .3rem .7rem; border-radius: var(--r-pill);
}
.badge--frozen  { background: var(--accent-frozen); color: var(--bl); }
.badge--fresh   { background: var(--accent-fresh);  color: var(--bl); }
.badge--outline { border: .5px solid var(--line-2); color: inherit; }

/* Claim badges on the product page — icon + label, tinted teal */
.claims { display: flex; flex-wrap: wrap; gap: 10px; }
.claim {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: var(--fd); font-weight: 600; font-size: .78rem;
  color: var(--to);
  background: rgba(43, 126, 134, .09);
  padding: 8px 15px; border-radius: var(--r-pill);
}
.claim svg { width: 15px; height: 15px; flex: none; stroke: var(--tl); }

/* ── EYEBROW ────────────────────────────────────────────── */

/* The site carries no monospace face — removed by client decision on
   2026-10-12. Uppercase labels are the body sans at 600 with open
   tracking, the exact treatment the home's .eyebrow-t already used, so
   every eyebrow on the site now reads as one voice. */
.eyebrow {
  font-family: var(--fb); font-weight: 600; font-size: 11.5px;
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--tl);
}
.on-dark .eyebrow { color: var(--li); }

.eyebrow--pill {
  display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--fd); font-weight: 600; font-size: 11px;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--tl);
  background: rgba(43, 126, 134, .08);
  padding: 8px 14px 8px 10px; border-radius: var(--r-pill);
}
.eyebrow--pill::before {
  content: ''; width: 8px; height: 8px; border-radius: 50%;
  background: var(--li); box-shadow: 0 0 0 4px rgba(114, 184, 74, .15);
}

/* ── BREADCRUMB ─────────────────────────────────────────── */

.crumb {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  font-family: var(--fb); font-weight: 400; font-size: 12px; letter-spacing: .02em;
  color: var(--fg-mute);
}
.crumb a:hover { color: var(--fg-1); }
.crumb span    { color: rgba(28, 66, 53, .25); }
.on-dark .crumb   { color: var(--fg-on-dark-3); }
.on-dark .crumb a:hover { color: var(--bl); }
.on-dark .crumb span    { color: rgba(249, 246, 240, .25); }

/* ============================================================
   CATALOG
   ============================================================ */

/* Page header — compact and centred, in the spirit of micfood.com:
   say what the page is, then get out of the way.

   Inverted: dark green field, warm-white type. The oversized bottom-left
   corner is the brand signature from design-system.md §3.2/§3.3 — this is
   the one asymmetric radius on the page, as the checklist requires. */
.pagehead {
  background: var(--bg-dark);
  border-radius: 0 0 0 var(--r-pagehead, 110px);
  text-align: center;
  padding: 156px 0 68px;
}
.pagehead .crumb { justify-content: center; }
.pagehead__title { margin: 16px 0 14px; color: var(--bg-base); }
.pagehead__lede  { max-width: 56ch; margin: 0 auto; }
.pagehead__rule {
  width: 44px; height: 2px; margin: 32px auto 0;
  background: var(--li); border-radius: 2px;
}

.cat-layout {
  display: grid; grid-template-columns: 250px 1fr; gap: 56px;
  align-items: start;
}

/* ── Sidebar filters ────────────────────────────────────── */

/* The panel is taller than most laptop viewports. Without its own scroll
   area, sticky pins the top and the Brand group at the bottom becomes
   unreachable — you can never scroll to it. */
.filters {
  position: sticky; top: 104px;
  max-height: calc(100vh - 128px);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-right: 8px;
  scrollbar-width: thin;
  scrollbar-color: var(--line-2) transparent;
}
.filters::-webkit-scrollbar { width: 6px; }
.filters::-webkit-scrollbar-thumb { background: var(--line-2); border-radius: 3px; }
.filters::-webkit-scrollbar-track { background: transparent; }

.filters__group { margin-bottom: 34px; }
.filters__group:last-of-type { margin-bottom: 8px; }

/* Desktop: the sidebar is always open, so the toggle is not rendered. */
.filters__toggle { display: none; }

.filters__title {
  font-family: var(--fd); font-weight: 600; font-size: 11px;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--fg-1);
  padding-bottom: 12px; margin-bottom: 12px;
  border-bottom: .5px solid var(--line-2);
}

.filters__list { list-style: none; display: flex; flex-direction: column; gap: 2px; }

.fbtn {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; text-align: left;
  background: none; border: 0;
  font-family: var(--fb); font-weight: 300; font-size: .89rem;
  color: var(--fg-3);
  padding: 7px 10px; border-radius: 8px;
  transition: background var(--d-base) var(--ease-out),
              color      var(--d-base) var(--ease-out);
}
.fbtn:hover { background: var(--bg-tint); color: var(--fg-1); }

.fbtn[aria-pressed='true'] {
  background: var(--fg-1); color: var(--bl);
  font-family: var(--fd); font-weight: 600;
}
.fbtn[aria-pressed='true'] .fbtn__n { color: rgba(249, 246, 240, .6); }

/* A combination that would return nothing is unreachable, not a dead end. */
.fbtn[disabled] { opacity: .3; cursor: not-allowed; }
.fbtn[disabled]:hover { background: none; color: var(--fg-3); }

.fbtn--sub { padding-left: 20px; font-size: .86rem; }

.fbtn__n {
  font-family: var(--fb); font-weight: 500; font-size: 11px;
  color: var(--fg-faint); flex: none;
  font-variant-numeric: tabular-nums;
}

.filters__clear {
  font-family: var(--fd); font-weight: 600; font-size: .76rem;
  color: var(--na); background: none; border: 0; padding: 4px 0;
}
.filters__clear:hover { text-decoration: underline; }
.filters__clear[hidden] { display: none; }

/* ── Result bar ─────────────────────────────────────────── */

.cat-bar {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 20px; flex-wrap: wrap;
  padding-bottom: 18px; margin-bottom: 26px;
  border-bottom: .5px solid var(--line-1);
}
/* El contador se leía en mono a 11px con tracking abierto: al lado de las
   fichas y del panel de filtros parecía una etiqueta de depuración, no
   parte de la página. Va en la display del sitio, al tamaño en que se lee
   de verdad. tabular-nums evita que la línea salte al filtrar. */
.cat-bar__count {
  font-family: var(--fd); font-weight: 500;
  font-size: .92rem; letter-spacing: -.01em;
  font-variant-numeric: tabular-nums;
  color: var(--fg-3);
}

/* ── Product grid ───────────────────────────────────────── */

.pgrid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px;
}

.pcard {
  display: flex; flex-direction: column;
  background: var(--bg-card);
  border: .5px solid var(--line-1);
  border-radius: var(--r-card-xl);
  overflow: hidden;
  transition: transform var(--d-slow) var(--ease-out),
              box-shadow var(--d-slow) var(--ease-out);
}
.pcard:hover { transform: translateY(-3px); box-shadow: var(--sh-card); }
.pcard[hidden] { display: none; }

/* White, not tinted: most packshots have a white background baked in,
   so a tinted box would show them as white rectangles floating on green.

   The image is absolutely inset instead of being a padded grid item. On a box
   whose height comes from `aspect-ratio`, a PERCENTAGE height on the child has
   nothing definite to resolve against, so `height: 100%` silently fell back to
   the image's intrinsic size — and `object-fit: contain` then had nothing left
   to contain. Every portrait packshot (which is most of the bags) was rendered
   at full width and chopped off at the bottom by `overflow: hidden`, at every
   width including desktop. Insetting by --media-pad and capping both axes
   against the box makes the fit exact and never depends on that resolution. */
.pcard__media {
  position: relative;
  aspect-ratio: 4 / 3;
  --media-pad: 22px;
  background: #fff;
  border-bottom: .5px solid var(--line-1);
  overflow: hidden;
}
.pcard__media img {
  position: absolute; inset: var(--media-pad); margin: auto;
  width: auto; height: auto;
  max-width:  calc(100% - var(--media-pad) * 2);
  max-height: calc(100% - var(--media-pad) * 2);
  transition: transform 600ms var(--ease-out);
}
.pcard:hover .pcard__media img { transform: scale(1.04); }

/* z-index is required: on hover the image gets a transform, which makes it
   paint alongside positioned elements. Being later in the DOM, it would
   otherwise cover this pill. */
.pcard__temp {
  position: absolute; top: 12px; left: 12px; z-index: 2;
  font-family: var(--fd); font-weight: 600;
  font-size: .6rem; letter-spacing: .1em; text-transform: uppercase;
  padding: .28rem .6rem; border-radius: var(--r-pill);
  color: var(--bl);
}
.pcard__temp--frozen { background: var(--accent-frozen); }
.pcard__temp--fresh  { background: var(--accent-fresh); }

.pcard__body { padding: 20px 22px 24px; display: flex; flex-direction: column; gap: 7px; flex: 1; }

.pcard__fam {
  font-family: var(--fd); font-weight: 600;
  font-size: 10px; letter-spacing: .12em; text-transform: uppercase;
  color: rgba(28, 66, 53, .55);
}
.pcard__name {
  font-family: var(--fd); font-weight: 700;
  font-size: 1.2rem; line-height: 1.15; letter-spacing: -.015em;
  color: var(--fg-1);
}
.pcard__name em { font-style: normal; color: var(--vm); }

.pcard__meta {
  margin-top: auto; padding-top: 14px;
  font-family: var(--fb); font-weight: 400; font-size: 11.5px; letter-spacing: .02em;
  color: var(--fg-mute);
}

/* Empty state when filters match nothing */
.pgrid__empty {
  grid-column: 1 / -1;
  text-align: center; padding: 70px 20px;
  color: var(--fg-mute);
}
.pgrid__empty[hidden] { display: none; }

/* ============================================================
   PRODUCT PAGE
   ============================================================ */

.phero { padding: 128px 0 0; }

.phero__grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 64px;
  align-items: start;
  margin-top: 26px;
}

/* Gallery */
/* 4:3, not square — a 1:1 stage left the info column with a large
   dead gap beneath it on desktop. */
.pgal__main {
  position: relative;
  --media-pad: 38px;
  background: #fff;
  border: .5px solid var(--line-1);
  border-radius: var(--r-card-xl);
  aspect-ratio: 4 / 3;
  overflow: hidden;
}
/* Same construction as .pcard__media, and for the same reason: neither
   `height: 100%` nor `max-height: 100%` resolves against an aspect-ratio box,
   so the packshot was being cropped rather than contained. See the note there. */
.pgal__main img {
  position: absolute; inset: var(--media-pad); margin: auto;
  width: auto; height: auto;
  max-width:  calc(100% - var(--media-pad) * 2);
  max-height: calc(100% - var(--media-pad) * 2);
}

.pgal__thumbs { display: flex; gap: 10px; margin-top: 12px; }
.pgal__thumb {
  width: 76px; height: 76px; flex: none;
  background: #fff;
  border: .5px solid var(--line-1);
  border-radius: var(--r-card-s);
  padding: 8px; overflow: hidden;
  transition: border-color var(--d-base) var(--ease-out);
}
.pgal__thumb img { width: 100%; height: 100%; object-fit: contain; }
.pgal__thumb[aria-pressed='true'] { border: 1.5px solid var(--vm); }

/* Info column */
.pinfo__name {
  font-family: var(--fd); font-weight: 700;
  font-size: clamp(2.1rem, 3.8vw, 3.1rem);
  line-height: 1.02; letter-spacing: -.025em;
  margin: 10px 0 0;
}
.pinfo__name span { color: var(--vm); }

.pinfo__desc { margin: 18px 0 26px; max-width: 46ch; }

.pinfo__actions { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 30px; }

/* Stat cards — circle icon + label + value */
.stats { display: flex; flex-wrap: wrap; gap: 14px; margin-bottom: 30px; }

.stat {
  display: flex; align-items: center; gap: 14px;
  flex: 1 1 200px;
  background: var(--bg-tint);
  border-radius: var(--r-card-l);
  padding: 16px 20px;
}
.stat__icon {
  width: 38px; height: 38px; flex: none;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--vm);
}
.stat__icon svg { width: 18px; height: 18px; stroke: var(--bl); }
.stat__label {
  display: block;
  font-family: var(--fd); font-weight: 600;
  font-size: 10px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--fg-mute);
  margin-bottom: 3px;
}
.stat__value {
  display: block;
  font-family: var(--fd); font-weight: 700;
  font-size: 1rem; line-height: 1.25; color: var(--fg-1);
}

/* ── Specification sheet ────────────────────────────────────
   design-system.md §5.7: a dark card with hairline-divided rows —
   uppercase Outfit key on the left, Bricolage value right-aligned.
   Replaces the zebra table, which was generic and off-system.
   ─────────────────────────────────────────────────────────── */

.specs { margin-top: 8px; text-align: center; }

.specs__title { margin: 14px 0 8px; }

.specs__note {
  max-width: 52ch; margin: 0 auto 34px;
  color: var(--fg-mute); font-size: .89rem; line-height: 1.65;
}

.specsheet {
  max-width: 760px; margin: 0 auto;
  background: var(--bg-dark);
  border-radius: var(--r-card-l);
  padding: 14px 34px;
  text-align: left;
}

.specsheet__row {
  display: flex; align-items: baseline; justify-content: space-between; gap: 32px;
  padding: 13px 0;
  border-bottom: .5px solid rgba(249, 246, 240, .16);
}
.specsheet__row:last-child { border-bottom: 0; }

.specsheet__k {
  flex: none;
  font-family: var(--fb); font-weight: 600; font-size: 10.5px;
  letter-spacing: .12em; text-transform: uppercase;
  color: rgba(249, 246, 240, .58);
}
.specsheet__v {
  font-family: var(--fd); font-weight: 600; font-size: .88rem;
  line-height: 1.45; color: var(--bl); text-align: right;
}

/* Related products */
.related { border-top: .5px solid var(--line-1); }
.related__grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; margin-top: 30px; }

/* ============================================================
   CTA + FOOTER
   ============================================================ */

.cta {
  background: var(--bg-dark); color: var(--bl);
  border-radius: var(--r-cap);
  margin-top: 90px;
  padding: 100px 0 110px;
  text-align: center;
}
.cta__title { margin: 16px 0 14px; }
.cta__sub   { max-width: 48ch; margin: 0 auto 34px; color: var(--fg-on-dark-2); }
.cta__btns  { display: flex; flex-wrap: wrap; gap: 14px; justify-content: center; }

.footer {
  background: var(--bg-dark); color: var(--fg-on-dark-2);
  border-top: .5px solid rgba(249, 246, 240, .08);
  padding: 70px 0 34px;
}
.footer__grid { display: grid; grid-template-columns: 1.6fr 1fr 1fr 1fr; gap: 44px; }
/* Text logotype in the footer — the mark itself was removed by request. */
.footer__brand {
  font-family: var(--fd); font-weight: 700;
  font-size: 1.5rem; letter-spacing: -.02em;
  color: var(--bl);
  margin-bottom: 16px;
}

/* Explicit light colour: the generic .t-small token is tuned for light
   backgrounds and was rendering near-invisible against the dark footer. */
.footer__blurb {
  max-width: 34ch;
  color: var(--fg-on-dark-2);
  font-size: .86rem; line-height: 1.7;
}
.footer__h {
  font-family: var(--fd); font-weight: 600;
  font-size: 11px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--li); margin-bottom: 14px;
}
.footer__list { list-style: none; display: flex; flex-direction: column; gap: 9px; font-size: .86rem; }
.footer__list a:hover { color: var(--bl); }
.footer__bot a { text-decoration: underline; text-decoration-thickness: .5px; text-underline-offset: 3px; }
.footer__bot a:hover { color: var(--bl); }
.footer__bot {
  display: flex; justify-content: space-between; flex-wrap: wrap; gap: 14px;
  margin-top: 50px; padding-top: 22px;
  border-top: .5px solid rgba(249, 246, 240, .08);
  font-family: var(--fb); font-weight: 400; font-size: 12px; letter-spacing: .02em;
  color: rgba(249, 246, 240, .6);
}

/* ============================================================
   RESPONSIVE
   ============================================================ */

@media (max-width: 1080px) {
  .cat-layout { grid-template-columns: 210px 1fr; gap: 36px; }
  .pgrid      { grid-template-columns: repeat(2, 1fr); }
  .related__grid { grid-template-columns: repeat(3, 1fr); }
}

@media (max-width: 880px) {
  .cat-layout { grid-template-columns: 1fr; gap: 22px; }
  .filters {
    position: static;
    max-height: none; overflow-y: visible; padding-right: 0;
  }
  .filters__group { margin-bottom: 22px; }

  /* Collapsed by default — 15 filter rows above the grid would push
     every product below the fold. */
  .filters__toggle {
    display: flex; align-items: center; justify-content: space-between;
    width: 100%; gap: 10px;
    font-family: var(--fd); font-weight: 600; font-size: .88rem;
    color: var(--fg-1);
    background: var(--bg-card);
    border: .5px solid var(--line-2);
    border-radius: var(--r-pill);
    padding: 13px 20px;
  }
  .filters__toggle svg { width: 17px; height: 17px; transition: transform var(--d-base) var(--ease-out); }
  .filters__toggle[aria-expanded='true'] svg { transform: rotate(180deg); }

  .filters__body { display: none; padding-top: 22px; }
  .filters__body--open { display: block; }
  .phero__grid { grid-template-columns: 1fr; gap: 34px; }
  .footer__grid { grid-template-columns: 1fr 1fr; gap: 34px; }
  .related__grid { grid-template-columns: repeat(2, 1fr); }
}

/* ── PHONE ──────────────────────────────────────────────────
   Everything below 560px. The rule that shapes this block: a
   phone is a NARROW screen, not a SHORT one. Collapsing every
   grid to one column made the catalog 11,400px tall — eleven
   screens of scrolling for 22 SKUs — while leaving half the
   width of most rows empty. Two columns wherever the content
   survives it.
   ─────────────────────────────────────────────────────────── */
@media (max-width: 560px) {
  .pagehead { padding: 108px 0 44px; --r-pagehead: 44px; }
  .pagehead__rule { margin-top: 24px; }

  /* Two up, not one. A card is then ~160px wide — enough for the packshot
     to read, and the whole catalog fits in four screens instead of eleven. */
  .pgrid { grid-template-columns: repeat(2, 1fr); gap: 12px; }
  .pcard        { border-radius: var(--r-card-l); }
  /* Square, not 4:3. Almost every packshot is a portrait bag, and `contain`
     inside a small landscape box left it tiny with air either side. */
  .pcard__media { aspect-ratio: 1 / 1; --media-pad: 10px; }
  .pcard__temp  { top: 8px; left: 8px; font-size: .63rem; padding: .24rem .5rem; }
  .pcard__body  { padding: 12px 13px 15px; gap: 5px; }
  .pcard__fam   { font-size: 10px; letter-spacing: .09em; }
  .pcard__name  { font-size: .95rem; line-height: 1.2; }
  .pcard__meta  { padding-top: 9px; font-size: 10px; letter-spacing: .04em; }

  .cat-bar { padding-bottom: 14px; margin-bottom: 18px; }

  /* Filter rows are the primary navigation of this page on a phone —
     they need to be thumb-sized, not sidebar-sized. */
  .fbtn { padding: 11px 12px; font-size: .95rem; }
  .fbtn--sub { padding-left: 20px; font-size: .92rem; }
  .fbtn__n { font-size: 11px; }
  .filters__toggle { padding: 15px 20px; font-size: .95rem; }

  .stat  { flex: 1 1 100%; padding: 14px 16px; gap: 12px; }
  .stat__label { font-size: 10.5px; }

  .related__grid { grid-template-columns: repeat(2, 1fr); gap: 12px; }

  .cta { padding: 60px 0 66px; margin-top: 52px; }
  .cta__btns .btn { width: 100%; }

  /* The brand block keeps the full width; the three link columns pair up.
     One column made the footer 1,200px of near-empty green. */
  .footer { padding: 56px 0 28px; }
  .footer__grid { grid-template-columns: 1fr 1fr; gap: 30px 20px; }
  .footer__grid > :first-child { grid-column: 1 / -1; }
  .footer__blurb { max-width: none; }
  .footer__bot { margin-top: 34px; gap: 8px; }
}

/* ── SPEC SHEET ON A PHONE ──────────────────────────────────
   The desktop row is `key ......... value` on one line. At 320px
   the content box is ~250px: a 100px key plus a 32px gutter left
   ~120px for "Box of 20 lb — bags of 2 lb", so every long value
   broke into a ragged right-aligned stack jammed against the
   padding. Below 640 the row stacks instead — label over value,
   both flush left, which is how a spec sheet reads on paper too.
   ─────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
  .specsheet { padding: 8px 20px; border-radius: var(--r-card-m); }
  .specsheet__row {
    flex-direction: column; align-items: flex-start; gap: 3px;
    padding: 12px 0;
  }
  .specsheet__k { font-size: 10.5px; }
  .specsheet__v { text-align: left; font-size: .96rem; line-height: 1.35; }
  .specs__note  { margin-bottom: 24px; }

  .pgal__main   { --media-pad: 22px; border-radius: var(--r-card-l); }
  .pgal__thumb  { width: 64px; height: 64px; }
  .pinfo__desc  { max-width: none; margin: 14px 0 22px; }
  .pinfo__actions .btn { flex: 1 1 100%; }
  .phero { padding: 104px 0 0; }
  .phero__grid { margin-top: 20px; }
}

/* ── TOUCH TARGETS ──────────────────────────────────────────
   Keyed to 880px — the width where the header already switches to
   its touch layout — not to a phone breakpoint. A tablet in
   portrait is driven by the same thumb. The 44px floor is the
   iOS/Material minimum; these three were the only controls on the
   site under it. Padding, not height, so nothing moves visually
   beyond the extra breathing room.
   ─────────────────────────────────────────────────────────── */
@media (max-width: 880px) {
  /* 18px-tall links sitting 9px apart are a coin toss under a thumb. */
  .footer__list   { gap: 2px; }
  .footer__list a { display: inline-block; padding: 10px 0; }
  .crumb a        { display: inline-block; padding: 9px 2px; }
  .hdr__brand     { display: flex; align-items: center; min-height: 44px; }
}

/* ── MINIMUM LEGIBLE TYPE ───────────────────────────────────
   design-system.md sets 9.6–11px uppercase labels, which hold
   up on a desktop monitor at arm's length and disappear on a
   phone. These are the floor, applied only where the label has
   to be read rather than merely sensed.
   ─────────────────────────────────────────────────────────── */
@media (max-width: 560px) {
  .lang__opt   { font-size: 12px; }
  .crumb       { font-size: 11.5px; gap: 4px 6px; }
  .eyebrow     { font-size: 11.5px; }
  .badge       { font-size: .7rem; }
  .claim       { font-size: .82rem; padding: 9px 15px; }
  .footer__h   { font-size: 11.5px; }
  .footer__list { font-size: .9rem; }
  .footer__bot { font-size: 11.5px; }
  .cat-bar__count { font-size: .86rem; }
  .filters__title { font-size: 11.5px; }
}

/* ============================================================
   INTERACTIVE BUTTON ANIMATION
   Vanilla adaptation of the 21st.dev "interactive hover button":
   an expanding dot fills the pill while the resting label slides
   out and a duplicate label + arrow slides in. The inner structure
   (.btn__text / .btn__slide / .btn__dot) is injected at runtime by
   the shared script in scripts/layout.js. Each variant keeps its
   own colours and type — only the motion is added.
   ============================================================ */

.btn { position: relative; overflow: hidden; isolation: isolate; }

.btn__text {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  position: relative; z-index: 2;
  transition: transform var(--d-base) var(--ease-out), opacity var(--d-base) var(--ease-out);
}
.btn:hover .btn__text,
.btn:focus-visible .btn__text { transform: translateX(1.5rem); opacity: 0; }

.btn__slide {
  position: absolute; inset: 0; z-index: 3;
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  opacity: 0; transform: translateX(-1.5rem);
  transition: transform var(--d-base) var(--ease-out), opacity var(--d-base) var(--ease-out);
}
.btn:hover .btn__slide,
.btn:focus-visible .btn__slide { opacity: 1; transform: translateX(0); }
.btn__slide svg { width: 17px; height: 17px; flex: none; }

.btn__dot {
  position: absolute; left: 20%; top: 40%; z-index: 1;
  width: 9px; height: 9px; border-radius: 50%;
  transform: scale(1); opacity: 0;                 /* hidden at rest — appears as it expands */
  transition: transform var(--d-base) var(--ease-out), width var(--d-base) var(--ease-out),
              height var(--d-base) var(--ease-out), left var(--d-base) var(--ease-out),
              top var(--d-base) var(--ease-out), opacity 120ms var(--ease-out),
              border-radius var(--d-base) var(--ease-out);
}
.btn:hover .btn__dot,
.btn:focus-visible .btn__dot {
  left: 0; top: 0; width: 100%; height: 100%; border-radius: 0; transform: scale(1.8); opacity: 1;
}

/* Dot fill + sliding-label colour per variant — these match each
   variant's existing hover end-state, so the palette is unchanged. */
.btn--primary     .btn__dot   { background: var(--fi-naranja-hover); }
.btn--primary     .btn__slide { color: var(--bl); }
.btn--ghost       .btn__dot   { background: var(--fg-1); }
.btn--ghost       .btn__slide { color: var(--bl); }
.btn--ghost-light .btn__dot   { background: var(--bl); }
.btn--ghost-light .btn__slide { color: var(--fg-1); }

/* For enhanced buttons the expanding dot provides the fill, so keep the
   resting background on hover (the circle reads instead of a flat swap).
   Gated on [data-enhanced] so non-JS buttons keep their original hover. */
.btn--primary[data-enhanced]:hover,
.btn--primary[data-enhanced]:focus-visible     { background: var(--na); }
.btn--ghost[data-enhanced]:hover,
.btn--ghost[data-enhanced]:focus-visible       { background: transparent; color: var(--fg-1); }
.btn--ghost-light[data-enhanced]:hover,
.btn--ghost-light[data-enhanced]:focus-visible { background: rgba(249, 246, 240, .06); color: var(--bl); }

/* ============================================================
   SCROLL REVEAL
   Elements tagged .reveal fade and rise as they enter the viewport
   (IntersectionObserver in scripts/layout.js adds .is-visible).
   Gated on .has-reveal (set on <html> by JS) so content is fully
   visible when JS is unavailable.
   ============================================================ */

.has-reveal .reveal {
  opacity: 0; transform: translateY(26px);
  transition: opacity .7s var(--ease-out), transform .7s var(--ease-out);
}
.has-reveal .reveal.is-visible { opacity: 1; transform: none; }
.has-reveal .reveal.r-d1 { transition-delay: .09s; }
.has-reveal .reveal.r-d2 { transition-delay: .18s; }
.has-reveal .reveal.r-d3 { transition-delay: .27s; }

@media (prefers-reduced-motion: reduce) {
  .has-reveal .reveal { opacity: 1; transform: none; transition: none; }
}
