/* =============================================================================
   Impertinente Shop — PrestaShop 9 theme stylesheet (AGE-35, Step 3)
   custom.css — auto-loaded by the FrontController for the active theme, AFTER
   classic's theme.css, so these rules layer on top of the inherited classic base.

   Two layers:
     §1–17  the ORIGINAL Impertinente design system (ported verbatim from the
            AGE-34 static replica) — applies to the templates this theme overrides
            (chrome, home, product miniature, CMS, 404).
     §18    the "classic bridge" — maps PrestaShop classic's native markup
            (PDP, category/PLP, cart, checkout, account, module output) onto the
            same tokens so the inherited pages render in the Impertinente look.

   ORIGINAL work per the AGE-32 rights memo. ohlalaboutique.fr (Shopify "Stiletto"
   theme) was used ONLY as a layout/UX reference for generic e-commerce IA. No
   Stiletto CSS/JS/asset/font was copied. Tokens below are an ORIGINAL Impertinente
   system (warm Mediterranean palette fitting the client's summer prêt-à-porter
   range), not the reference theme's stylesheet.

   Brand fonts (Syne/Switzer/etc. used by the reference) are commercial and are
   NOT used here. We ship system/safe stacks; licensed brand fonts get swapped
   into --font-display / --font-body later by the client.
   ============================================================================= */

/* ----------------------------------------------------------------------------
   1. Design tokens
   ---------------------------------------------------------------------------- */
:root {
  /* Palette — original Impertinente cream + terracotta + deep-green, gold accent */
  --c-cream:        #f9f6f3;   /* soft warm tint (sections / footer-light) */
  --c-cream-2:      #f2ebe2;   /* cream surface / secondary button */
  --c-sand:         #e4d5c4;   /* warm border / hover */
  --c-ink:          #102b26;   /* deep teal-green ink */
  --c-ink-soft:     #44544f;
  --c-muted:        #8c948f;
  --c-line:         #e8e6e2;   /* neutral hairline */
  --c-white:        #ffffff;
  --c-terracotta:   #b5572f;   /* legacy accent — kept for compat, used sparingly */
  --c-terracotta-d: #8f4222;
  --c-green:        #102b26;   /* unified with ink */
  --c-rose:         #c4857c;   /* brand dusty-rose (logo rules) — AGE-68 */
  --c-cream-warm:   #f3e9e0;   /* brand warm cream (logo bg / tiles) — AGE-68 */
  --c-gold:         #a68d54;   /* single metallic accent */
  --c-sale:         #c31818;   /* sale red */
  --c-ok:           #478947;

  /* Semantic — white base, dark-ink actions (matches the reference boutique) */
  --bg:             var(--c-white);
  --surface:        var(--c-white);
  --text:           var(--c-ink);
  --text-soft:      var(--c-ink-soft);
  --accent:         var(--c-ink);
  --accent-ink:     var(--c-white);

  /* Typography — independently-licensed (Google Fonts, OFL) */
  --font-logo:      "Syne", system-ui, sans-serif;
  --font-display:   "Fraunces", Georgia, "Times New Roman", serif;
  --font-body:      "Manrope", system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  --fs-50:  0.75rem;   /* 12 */
  --fs-75:  0.8125rem; /* 13 */
  --fs-100: 0.9375rem; /* 15 */
  --fs-200: 1.0625rem; /* 17 */
  --fs-h6:  1.125rem;  /* 18 */
  --fs-h5:  1.375rem;  /* 22 */
  --fs-h4:  1.75rem;   /* 28 */
  --fs-h3:  2.25rem;   /* 36 */
  --fs-h2:  3rem;      /* 48 */
  --fs-h1:  clamp(2.5rem, 5vw, 4.25rem);

  /* Spacing scale */
  --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px; --sp-4: 16px;
  --sp-5: 24px; --sp-6: 32px; --sp-7: 48px; --sp-8: 64px; --sp-9: 96px;

  /* Layout */
  --container: 1400px;          /* per audit 03-design-tokens §A.4 (--max-width) */
  --container-narrow: 747px;    /* narrow content column (CMS / forms) */
  --gutter:    clamp(16px, 3.3vw, 40px);
  --radius:    2px;
  --radius-lg: 2px;
  --shadow:    0 1px 2px rgba(16,43,38,.06), 0 10px 30px rgba(16,43,38,.07);
  --header-h:  64px;
  --ease:      cubic-bezier(.2,.7,.2,1);

  /* Breakpoints (reference only — used in media queries below)
     mobile <640 · tablet 640–1023 · desktop >=1024 */
}

/* ----------------------------------------------------------------------------
   2. Reset / base
   ---------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0;
  overflow-x: hidden; /* off-canvas mobile-nav / cart drawer must not create a horizontal scrollbar */
  font-family: var(--font-body);
  font-size: var(--fs-100);
  line-height: 1.6;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}
img, svg, video { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
a:hover { text-decoration: underline; }
button { font: inherit; cursor: pointer; }
ul, ol { margin: 0; padding: 0; list-style: none; }
h1, h2, h3, h4, h5, h6 { font-family: var(--font-display); font-weight: 600; line-height: 1.12; margin: 0 0 .5em; letter-spacing: .01em; }
h1 { font-size: var(--fs-h1); }
h2 { font-size: var(--fs-h3); }
h3 { font-size: var(--fs-h4); }
p { margin: 0 0 1em; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ----------------------------------------------------------------------------
   3. Layout primitives
   ---------------------------------------------------------------------------- */
.container { width: 100%; max-width: var(--container); margin-inline: auto; padding-inline: var(--gutter); }
.section { padding-block: var(--sp-8); }
.section--tight { padding-block: var(--sp-6); }
.stack > * + * { margin-top: var(--sp-4); }
.eyebrow {
  font-family: var(--font-body); font-size: var(--fs-50); letter-spacing: .22em;
  text-transform: uppercase; color: var(--c-muted); margin: 0 0 var(--sp-3);
}
.section-head { text-align: center; margin-bottom: var(--sp-6); }
.section-head h2 { margin: 0; }
.section-head .link-more { font-size: var(--fs-75); letter-spacing: .12em; text-transform: uppercase; color: var(--accent); }

.grid { display: grid; gap: var(--sp-5); }
.grid--2 { grid-template-columns: repeat(2, 1fr); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
.grid--4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 1023px) { .grid--4 { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 767px)  { .grid--3, .grid--4 { grid-template-columns: repeat(2, 1fr); } .grid--2 { grid-template-columns: 1fr; } }

/* ----------------------------------------------------------------------------
   4. Image placeholders (NO real imagery in this build — AGE-34 constraint)
   ---------------------------------------------------------------------------- */
.ph {
  position: relative;
  background-color: var(--c-cream-2);
  background-image:
    linear-gradient(135deg, rgba(181,87,47,.05) 25%, transparent 25%),
    linear-gradient(225deg, rgba(20,58,48,.05) 25%, transparent 25%);
  background-size: 28px 28px;
  border: 1px solid var(--c-line);
  border-radius: var(--radius);
  overflow: hidden;
  color: var(--c-muted);
}
.ph::after {
  content: attr(data-label);
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: var(--fs-50); letter-spacing: .16em; text-transform: uppercase;
  text-align: center; padding: var(--sp-3);
}
.ph--portrait { aspect-ratio: 2 / 3; }
.ph--square   { aspect-ratio: 1 / 1; }
.ph--wide     { aspect-ratio: 16 / 9; }
.ph--hero     { aspect-ratio: 21 / 9; min-height: 320px; }
.ph--avatar   { aspect-ratio: 1 / 1; border-radius: 50%; }

/* ----------------------------------------------------------------------------
   5. Buttons & badges
   ---------------------------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  padding: 14px 30px; border: 1px solid var(--text); border-radius: var(--radius);
  background: transparent; color: var(--text);
  font-family: var(--font-logo); font-weight: 600; font-size: var(--fs-75); letter-spacing: .04em; text-transform: uppercase;
  transition: background .2s var(--ease), color .2s var(--ease), border-color .2s var(--ease);
}
.btn:hover { text-decoration: none; }
.btn--primary { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.btn--primary:hover { background: #0a1f1a; border-color: #0a1f1a; }
.btn--dark { background: var(--c-green); border-color: var(--c-green); color: var(--c-white); }
.btn--dark:hover { background: #0a1f1a; }
.btn--ghost:hover { background: var(--text); color: var(--c-white); }
.btn--block { width: 100%; }
.btn--sm { padding: 8px 16px; }

.badge {
  display: inline-block; padding: 3px 10px; font-size: var(--fs-50);
  letter-spacing: .12em; text-transform: uppercase; border-radius: 999px;
  background: var(--c-sand); color: var(--c-ink);
}
.badge--sale { background: var(--c-sale); color: #fff; }
.badge--new  { background: var(--c-green); color: #fff; }
.badge--soon { background: var(--c-gold); color: #fff; }

/* ----------------------------------------------------------------------------
   6. Header / announcement / nav / mega-menu
   ---------------------------------------------------------------------------- */
.announce {
  background: var(--c-green); color: var(--c-cream);
  font-size: var(--fs-50); letter-spacing: .14em; text-transform: uppercase;
  text-align: center; padding: 8px var(--gutter);
}
.site-header { position: sticky; top: 0; z-index: 50; background: var(--surface); border-bottom: 1px solid var(--c-line); }
/* Single row: brand LEFT · menu CENTRE · icons RIGHT */
.header-bar { display: flex; align-items: center; gap: var(--sp-5); min-height: var(--header-h); padding-block: var(--sp-3); }
.brand { font-family: var(--font-logo); font-weight: 800; font-size: clamp(1.15rem, 1.7vw, 1.6rem); letter-spacing: -.01em; white-space: nowrap; color: var(--c-ink); flex: 0 0 auto; }
.brand .brand-mark { font-family: var(--font-logo); font-weight: 800; }
.brand img.logo { max-height: 46px; width: auto; }
/* Real brand wordmark (AGE-68): SVG script logo — a touch taller than the old
   text wordmark so the hand-lettering reads; footer variant is the cream logo. */
.brand img.brand-logo { max-height: 58px; }
.brand--footer img.brand-logo { max-height: 46px; }

.header-actions { display: flex; align-items: center; justify-content: flex-end; gap: var(--sp-5); flex: 0 0 auto; }
.header-action { position: relative; display: inline-flex; align-items: center; color: var(--text); }
.header-action:hover { color: var(--c-gold); text-decoration: none; }
/* the search icon is a <button> toggle — strip native chrome so it matches links */
button.header-action { background: none; border: 0; padding: 0; cursor: pointer; font: inherit; }
.icon { width: 22px; height: 22px; stroke: currentColor; fill: none; stroke-width: 1.5; }

/* Search reveal panel (AGE-73) — full-width strip below the header bar, toggled by
   the search icon (initHeaderSearch). Reuses the sticky .site-header as its band. */
.header-search { background: var(--surface); border-top: 1px solid var(--c-line); }
.header-search[hidden] { display: none; }
.header-search__form { display: flex; align-items: center; gap: var(--sp-2); padding-block: var(--sp-4); }
.header-search__input {
  flex: 1 1 auto; height: 48px; padding: 0 16px;
  border: 1px solid var(--c-line); border-radius: var(--radius);
  font-family: var(--font-body); font-size: 15px; letter-spacing: .01em;
  background: var(--surface); color: var(--text);
}
.header-search__input:focus { outline: none; border-color: var(--accent); }
.header-search__submit {
  flex: 0 0 auto; width: 48px; height: 48px; display: inline-flex;
  align-items: center; justify-content: center; cursor: pointer;
  border: 1px solid var(--c-ink); background: var(--c-ink); border-radius: var(--radius);
}
.header-search__submit .icon { stroke: #fff; }
.cart-action .cart-count {
  position: absolute; top: -8px; right: -10px; min-width: 18px; height: 18px;
  display: grid; place-items: center; background: var(--c-ink); color: #fff;
  border-radius: 999px; font-family: var(--font-body); font-size: 10px; font-weight: 600; padding: 0 5px;
}

.nav-toggle { display: none; background: none; border: 0; color: var(--text); padding: 0; }

/* Primary nav (desktop) — inline in the single header row; no divider line */
.primary-nav { border-top: 0; }
.primary-nav > .container > ul { display: flex; justify-content: center; gap: clamp(12px, 2vw, 34px); }
.primary-nav .nav-item { position: relative; }
.primary-nav .nav-link {
  display: inline-block; padding: 14px 2px; font-size: var(--fs-75);
  letter-spacing: .14em; text-transform: uppercase;
}
.primary-nav .nav-link:hover { text-decoration: none; color: var(--accent); }
.primary-nav .nav-item--accent .nav-link { color: var(--accent); }

/* Mega-menu panel */
.mega {
  position: absolute; left: 50%; top: 100%; transform: translateX(-50%) translateY(8px);
  min-width: 540px; background: var(--surface); border: 1px solid var(--c-line);
  box-shadow: var(--shadow); border-radius: var(--radius-lg); padding: var(--sp-6);
  display: grid; grid-template-columns: repeat(3, 1fr) 1.2fr; gap: var(--sp-6);
  opacity: 0; visibility: hidden; transition: opacity .18s var(--ease), transform .18s var(--ease); z-index: 60;
}
.nav-item:hover > .mega, .nav-item:focus-within > .mega { opacity: 1; visibility: visible; transform: translateX(-50%) translateY(0); }
.mega h4 { font-family: var(--font-body); font-size: var(--fs-50); letter-spacing: .18em; text-transform: uppercase; color: var(--c-muted); margin-bottom: var(--sp-3); }
.mega li { margin-bottom: var(--sp-2); }
.mega a { font-size: var(--fs-100); }
.mega a:hover { color: var(--accent); }
.mega .mega-feature .ph { margin-bottom: var(--sp-2); }

/* ----------------------------------------------------------------------------
   7. Hero
   ---------------------------------------------------------------------------- */
.hero { position: relative; }
.hero .ph--hero { display: flex; align-items: center; justify-content: center; }
.hero-overlay {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; text-align: center;
  padding: var(--gutter); gap: var(--sp-4); color: var(--c-ink);
}
.hero-overlay h1 { margin: 0; max-width: 14ch; }
.hero-overlay p { font-size: var(--fs-200); color: var(--text-soft); max-width: 42ch; margin: 0; }

/* ----------------------------------------------------------------------------
   8. Product card + carousel
   ---------------------------------------------------------------------------- */
.product-card { position: relative; }
.product-card .media { position: relative; margin-bottom: var(--sp-3); }
.product-card .media .badge { position: absolute; top: var(--sp-3); left: var(--sp-3); z-index: 2; }
/* Quick-view: a refined frosted bar that rises from the base of the image on
   hover, with an eye glyph + uppercase spaced label (overrides the .btn--ghost
   outline the markup ships with). */
.product-card .quick-add {
  position: absolute; left: var(--sp-3); right: var(--sp-3); bottom: var(--sp-3);
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 12px 16px; border: 0 !important; border-radius: var(--radius);
  background: rgba(16,43,38,.90) !important; -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  color: #fff !important; font-family: var(--font-logo); font-weight: 600; font-size: var(--fs-75);
  letter-spacing: .14em; text-transform: uppercase; line-height: 1;
  box-shadow: 0 10px 26px rgba(16,43,38,.30);
  opacity: 0; transform: translateY(10px); transition: opacity .25s var(--ease), transform .25s var(--ease), background .2s var(--ease);
}
.product-card .quick-add::before {
  content: ""; width: 15px; height: 15px; flex: 0 0 auto;
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M1 12s4-7 11-7 11 7 11 7-4 7-11 7-11-7-11-7z'/><circle cx='12' cy='12' r='3'/></svg>") center/contain no-repeat;
}
.product-card .quick-add:hover { background: var(--c-gold) !important; color: #fff !important; box-shadow: 0 12px 30px rgba(166,141,84,.4); }
.product-card:hover .quick-add { opacity: 1; transform: translateY(0); }
/* Touch devices have no hover: the reveal-on-hover "Aperçu rapide" bar triggers
   iOS's two-tap behaviour — the first tap shows the bar (looking like a broken
   quick-view) instead of opening the product. Hide it on touch so a single tap
   goes straight to the product page. */
@media (hover: none) {
  .product-card .quick-add { display: none; }
}
.product-card .title { font-size: var(--fs-100); margin: 0 0 var(--sp-1); }
.product-card .title a:hover { color: var(--accent); }
.product-card .price { font-size: var(--fs-100); color: var(--text-soft); }
.product-card .price .was { color: var(--c-muted); text-decoration: line-through; margin-right: var(--sp-2); }
.product-card .price .now { color: var(--c-sale); }

/* Home "La boutique" category tiles (impcathighlights). The category name sits BELOW
   the photo — it used to be a white band laid over the bottom of the picture, and the
   founder's client didn't want the image covered. So the <h3> is now a plain sibling
   of .media, in normal flow, and needs no positioning at all. */
.category-card .title { margin: var(--sp-3) 0 0; }
.category-card .title a {
  display: block; color: var(--c-ink);
  font-family: var(--font-logo); font-weight: 600; font-size: var(--fs-75);
  letter-spacing: .08em; text-transform: uppercase; text-align: center; line-height: 1.35;
  /* Always ONE line, truncated with an ellipsis. A long name ("Combis & Ensembles")
     would otherwise wrap in the narrow 2-up phone carousel and make that tile taller
     than its neighbours — the captions must sit on the same line across the row. */
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  transition: color .2s var(--ease);
}
/* The whole tile is one link, so hovering the photo underlines its caption. */
.category-card:hover .title a, .category-card .title a:hover {
  color: var(--c-ink); text-decoration: underline; text-underline-offset: 4px;
}
/* In the narrow 2-up carousel the wide tracking is what forces the ellipsis so early
   ("COMBIS & EN…"). Tighten it so more of a long name survives — still one line. */
@media (max-width: 991px) {
  .category-card .title a { letter-spacing: .03em; }
}

/* Horizontal scroll carousel (no JS dependency for basic scroll) */
.carousel { position: relative; }
.carousel-track {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(220px, 1fr);
  gap: var(--sp-5); overflow-x: auto; scroll-snap-type: x mandatory;
  padding-bottom: var(--sp-3); scrollbar-width: thin;
}
@media (min-width: 1024px) { .carousel-track { grid-auto-columns: minmax(0, calc((100% - 3 * var(--sp-5)) / 4)); } }
.carousel-track > * { scroll-snap-align: start; }
.carousel-btn {
  position: absolute; top: 38%; z-index: 3; width: 40px; height: 40px;
  border-radius: 50%; background: var(--surface); border: 1px solid var(--c-line);
  box-shadow: var(--shadow); display: grid; place-items: center;
}
.carousel-btn[disabled] { opacity: .35; cursor: default; }
.carousel-btn--prev { left: -8px; } .carousel-btn--next { right: -8px; }
@media (max-width: 767px) { .carousel-btn { display: none; } }

/* ----------------------------------------------------------------------------
   9. Collections grid / shop-the-look / story / trust / instagram
   ---------------------------------------------------------------------------- */
.collection-card { position: relative; display: block; }
.collection-card .ph { transition: transform .4s var(--ease); }
.collection-card:hover .ph { transform: scale(1.02); }
.collection-card .label {
  position: absolute; inset: auto 0 0 0; padding: var(--sp-5); text-align: center;
  color: #fff; background: linear-gradient(to top, rgba(20,58,48,.55), transparent);
}
.collection-card .label h3 { color: #fff; margin: 0 0 var(--sp-2); }

.story { display: grid; grid-template-columns: 1.1fr 1fr; align-items: center; gap: var(--sp-8); }
.story .ph { aspect-ratio: 4/3; }
@media (max-width: 767px) { .story { grid-template-columns: 1fr; } }

.trust { display: grid; grid-template-columns: repeat(4,1fr); gap: var(--sp-5); text-align: center; }
.trust .item h4 { font-family: var(--font-body); font-size: var(--fs-100); letter-spacing: .04em; margin: var(--sp-3) 0 var(--sp-1); }
.trust .item p { font-size: var(--fs-75); color: var(--c-muted); margin: 0; }
.trust .glyph { width: 34px; height: 34px; margin-inline: auto; stroke: var(--accent); fill: none; stroke-width: 1.4; }
@media (max-width: 767px) { .trust { grid-template-columns: repeat(2,1fr); gap: var(--sp-6); } }

.insta-grid { display: grid; grid-template-columns: repeat(4,1fr); gap: var(--sp-3); }
@media (max-width: 767px) { .insta-grid { grid-template-columns: repeat(2,1fr); } }

/* ----------------------------------------------------------------------------
   10. PLP — toolbar, filters, sidebar
   ---------------------------------------------------------------------------- */
.breadcrumbs { font-size: var(--fs-75); color: var(--c-muted); padding-block: var(--sp-4); }
.breadcrumbs a:hover { color: var(--accent); }
.page-head { text-align: center; padding-block: var(--sp-5) var(--sp-6); }
.page-head p { color: var(--text-soft); max-width: 60ch; margin-inline: auto; }

.plp { display: grid; grid-template-columns: 248px 1fr; gap: var(--sp-7); align-items: start; }
@media (max-width: 1023px) { .plp { grid-template-columns: 1fr; } .plp .filters { display: none; } }
.filters .filter-group { border-bottom: 1px solid var(--c-line); padding-block: var(--sp-4); }
.filters h4 { font-family: var(--font-body); font-size: var(--fs-75); letter-spacing: .12em; text-transform: uppercase; }
.filters label { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-100); padding-block: 3px; color: var(--text-soft); }
.swatch { width: 16px; height: 16px; border-radius: 50%; border: 1px solid rgba(0,0,0,.15); }

.plp-toolbar { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4); margin-bottom: var(--sp-5); flex-wrap: wrap; }
.plp-toolbar .count { font-size: var(--fs-75); color: var(--c-muted); }
.plp-toolbar select { padding: 8px 12px; border: 1px solid var(--c-line); border-radius: var(--radius); background: var(--surface); font-size: var(--fs-75); }
.filter-pills { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-bottom: var(--sp-5); }
.pill { display: inline-flex; gap: var(--sp-2); align-items: center; font-size: var(--fs-75); border: 1px solid var(--c-line); border-radius: 999px; padding: 4px 12px; }

.pagination { display: flex; justify-content: center; gap: var(--sp-2); margin-top: var(--sp-7); }
.pagination a, .pagination span { min-width: 40px; height: 40px; display: grid; place-items: center; border: 1px solid var(--c-line); border-radius: var(--radius); font-size: var(--fs-75); }
.pagination .is-current { background: var(--text); color: #fff; border-color: var(--text); }

/* ----------------------------------------------------------------------------
   11. PDP
   ---------------------------------------------------------------------------- */
.pdp { display: grid; grid-template-columns: 1.15fr 1fr; gap: var(--sp-8); align-items: start; }
@media (max-width: 899px) { .pdp { grid-template-columns: 1fr; gap: var(--sp-6); } }
.pdp-gallery { display: grid; grid-template-columns: 72px 1fr; gap: var(--sp-3); }
.pdp-gallery .thumbs { display: flex; flex-direction: column; gap: var(--sp-3); }
.pdp-gallery .thumbs .ph { aspect-ratio: 3/4; cursor: pointer; }
@media (max-width: 599px) { .pdp-gallery { grid-template-columns: 1fr; } .pdp-gallery .thumbs { flex-direction: row; } .pdp-gallery .thumbs .ph { width: 64px; } }
.pdp-info .price-row { display: flex; align-items: baseline; gap: var(--sp-3); margin-bottom: var(--sp-4); }
.pdp-info .price-row .now { font-size: var(--fs-h5); }
.pdp-info .price-row .was { color: var(--c-muted); text-decoration: line-through; }
.option-group { margin-bottom: var(--sp-5); }
.option-group .label-row { display: flex; justify-content: space-between; font-size: var(--fs-75); letter-spacing: .06em; text-transform: uppercase; margin-bottom: var(--sp-3); }
.size-options, .color-options { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.size-options button { min-width: 46px; padding: 10px 12px; border: 1px solid var(--c-line); background: var(--surface); border-radius: var(--radius); font-size: var(--fs-75); }
.size-options button[aria-pressed="true"] { border-color: var(--text); background: var(--text); color: #fff; }
.color-options button { width: 30px; height: 30px; border-radius: 50%; border: 1px solid var(--c-line); }
.color-options button[aria-pressed="true"] { box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--text); }
.qty { display: inline-flex; align-items: center; border: 1px solid var(--c-line); border-radius: var(--radius); }
.qty button { width: 42px; height: 44px; background: none; border: 0; font-size: 18px; }
.qty input { width: 44px; height: 44px; text-align: center; border: 0; border-inline: 1px solid var(--c-line); background: var(--surface); }
.add-row { display: flex; gap: var(--sp-3); margin-block: var(--sp-5); }
.add-row .btn { flex: 1; }
.accordion { border-top: 1px solid var(--c-line); }
.accordion details { border-bottom: 1px solid var(--c-line); }
.accordion summary { display: flex; justify-content: space-between; align-items: center; padding: var(--sp-4) 0; font-size: var(--fs-75); letter-spacing: .1em; text-transform: uppercase; cursor: pointer; list-style: none; }
.accordion summary::-webkit-details-marker { display: none; }
.accordion summary::after { content: "+"; font-size: 18px; }
.accordion details[open] summary::after { content: "–"; }
.accordion .body { padding-bottom: var(--sp-4); color: var(--text-soft); }

/* ----------------------------------------------------------------------------
   12. Cart
   ---------------------------------------------------------------------------- */
.cart { display: grid; grid-template-columns: 1fr 360px; gap: var(--sp-7); align-items: start; }
@media (max-width: 899px) { .cart { grid-template-columns: 1fr; } }
.cart-line { display: grid; grid-template-columns: 96px 1fr auto; gap: var(--sp-4); padding-block: var(--sp-5); border-bottom: 1px solid var(--c-line); align-items: start; }
.cart-line .ph { aspect-ratio: 3/4; }
.cart-line .meta .name { font-family: var(--font-display); font-size: var(--fs-200); }
.cart-line .meta .attrs { font-size: var(--fs-75); color: var(--c-muted); }
.cart-line .remove { font-size: var(--fs-75); color: var(--c-muted); text-decoration: underline; background: none; border: 0; padding: 0; }
.summary { background: var(--surface); border: 1px solid var(--c-line); border-radius: var(--radius-lg); padding: var(--sp-6); position: sticky; top: calc(var(--header-h) + 16px); }
.summary .row { display: flex; justify-content: space-between; padding-block: var(--sp-2); font-size: var(--fs-100); }
.summary .row.total { border-top: 1px solid var(--c-line); margin-top: var(--sp-3); padding-top: var(--sp-4); font-family: var(--font-display); font-size: var(--fs-h6); }

/* Cart drawer (mini) */
.drawer-backdrop { position: fixed; inset: 0; background: rgba(20,58,48,.4); opacity: 0; visibility: hidden; transition: .25s var(--ease); z-index: 90; }
.drawer-backdrop.is-open { opacity: 1; visibility: visible; }
.cart-drawer { position: fixed; top: 0; right: 0; height: 100dvh; width: min(420px, 92vw); background: var(--surface); box-shadow: var(--shadow); transform: translateX(100%); transition: transform .28s var(--ease); z-index: 1201; display: flex; flex-direction: column; }
.cart-drawer.is-open { transform: none; }
.cart-drawer header { display: flex; justify-content: space-between; align-items: center; padding: var(--sp-5); border-bottom: 1px solid var(--c-line); }
.cart-drawer .items { flex: 1; overflow-y: auto; padding: var(--sp-5); }
.cart-drawer footer { padding: var(--sp-5); border-top: 1px solid var(--c-line); }
/* mini-cart chrome + line items (populated by initCartDrawer from updateCart) */
.cart-backdrop { position: fixed; inset: 0; background: rgba(20,20,20,.4); opacity: 0; visibility: hidden; transition: opacity .28s var(--ease), visibility .28s; z-index: 1200; }
.cart-backdrop.is-open { opacity: 1; visibility: visible; }
.cart-drawer__title { font-family: var(--font-display); font-size: var(--fs-h4); }
.cart-drawer__close { background: none; border: 0; font-size: 28px; line-height: 1; cursor: pointer; color: var(--text); }
.cart-line { display: flex; gap: var(--sp-3); padding: var(--sp-3) 0; border-bottom: 1px solid var(--c-line); }
.cart-line:last-child { border-bottom: 0; }
.cart-line__img { width: 64px; height: 80px; object-fit: cover; border-radius: var(--radius); flex: 0 0 auto; background: var(--c-cream); }
.cart-line__info { flex: 1 1 auto; min-width: 0; }
.cart-line__name { font-weight: 500; color: var(--text); }
.cart-line__attrs { font-size: var(--fs-75); color: var(--c-muted); margin-top: 2px; }
.cart-line__meta { display: flex; gap: 8px; margin-top: 6px; font-size: var(--fs-100); color: var(--text); }
.cart-empty { color: var(--c-muted); }
.cart-drawer__line { display: flex; justify-content: space-between; font-size: var(--fs-100); color: var(--c-muted); margin-bottom: var(--sp-1); }
.cart-drawer__total { display: flex; justify-content: space-between; font-family: var(--font-display); font-size: var(--fs-h4); margin-bottom: var(--sp-4); }
.cart-drawer footer .btn { width: 100%; }
.cart-drawer footer .btn + .btn { margin-top: var(--sp-2); }
/* guarantee readable contrast on the primary CTA regardless of token resolution */
.cart-drawer footer .btn--primary { background: var(--c-ink); border-color: var(--c-ink); color: #fff; }

/* ----------------------------------------------------------------------------
   13. Forms / account / CMS
   ---------------------------------------------------------------------------- */
.field { margin-bottom: var(--sp-4); }
.field label { display: block; font-size: var(--fs-75); letter-spacing: .08em; text-transform: uppercase; margin-bottom: var(--sp-2); color: var(--text-soft); }
.field input, .field textarea, .field select {
  width: 100%; padding: 12px 14px; border: 1px solid var(--c-line); border-radius: var(--radius);
  background: var(--surface); font: inherit; font-size: var(--fs-100);
}
.field input:focus, .field textarea:focus { border-color: var(--accent); outline: none; }
.auth-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-8); max-width: 920px; margin-inline: auto; }
@media (max-width: 767px) { .auth-grid { grid-template-columns: 1fr; gap: var(--sp-6); } }
.auth-card { background: var(--surface); border: 1px solid var(--c-line); border-radius: var(--radius-lg); padding: var(--sp-7); }
.cms { max-width: 760px; margin-inline: auto; }
/* Imported legal pages are a Word paste with inline text-align:justify on every
   paragraph; the rivers/gaps read as broken (worse where the source dropped
   inter-word spaces). Force left alignment over the inline style. */
.cms, .cms p, .cms div, .cms li, .cms td { text-align: left !important; }
.cms h2 { margin-top: var(--sp-6); }
.cms ul { list-style: disc; padding-left: 1.4em; margin-bottom: 1em; }
.cms ul li { margin-bottom: .35em; }

/* 404 */
.notfound { text-align: center; padding-block: var(--sp-9); }
.notfound .code { font-family: var(--font-display); font-size: clamp(5rem, 18vw, 11rem); line-height: .9; color: var(--c-sand); }

/* ----------------------------------------------------------------------------
   14. Newsletter / footer
   ---------------------------------------------------------------------------- */
/* Footer region = two warm bands: the newsletter in SAND (--c-sand, the tan already
   used for pill hovers / warm borders) stepping down into the FOOTER in gold
   (--c-gold, the old "La boutique" selected-pill colour). Both are light enough to
   need DARK ink text — the cream that worked on the old dark-green band would be
   invisible. Sand is light (ink reads ~10.5:1), gold is a mid-tone (~4.7:1), so
   only the field/button treatments differ between them. */
.newsletter, .section.newsletter {
  --foot-fg: var(--c-ink);
  --foot-fg-muted: var(--c-ink);          /* muting by opacity dies on these bgs — see footer note */
  --foot-border: rgba(16,43,38,.22);
  --foot-field: rgba(255,255,255,.55);    /* near-white field: reads as an input against the sand */
  background: var(--c-sand); color: var(--foot-fg); text-align: center;
}
.newsletter h2 { color: var(--foot-fg); }
.newsletter form { display: flex; gap: var(--sp-2); max-width: 440px; margin: var(--sp-5) auto 0; }
.newsletter input { flex: 1; padding: 12px 14px; border: 1px solid rgba(16,43,38,.35); background: var(--foot-field); color: var(--foot-fg); border-radius: var(--radius); }
.newsletter input::placeholder { color: rgba(16,43,38,.65); }

/* Footer in SAND (--c-sand), the same tone as the newsletter band above it — the two
   read as ONE continuous block. It was gold (--c-gold) with the newsletter in sand;
   the client asked to keep only the lighter of the two and drop the gold.

   Sand is light, so the text stays DARK ink — and gets a lot more headroom than it had
   on gold: ink-on-sand is ~10.5:1 against ~4.7:1. The three tokens below are what the
   footer's original on-dark cream values were re-pointed at, so the whole light/dark
   decision still lives in one place. */
.site-footer {
  --foot-fg: var(--c-ink);                 /* body + links (was cream .85) */
  /* Headings/tagline/bottom-bar. On the old dark footer these were softly muted
     (cream .6/.7). That trick is what fails on a light ground — muting by opacity
     pulls the text toward the background — so they stay full ink and lean on the
     uppercase + letter-spacing + size for hierarchy instead. */
  --foot-fg-muted: var(--c-ink);
  --foot-border: rgba(16,43,38,.22);       /* hairlines — no text-contrast need */
  background: var(--c-sand); color: var(--foot-fg); padding-block: var(--sp-8) var(--sp-5);
}
.footer-grid { display: grid; grid-template-columns: 1.4fr repeat(3, 1fr); gap: var(--sp-7); }
@media (max-width: 899px) { .footer-grid { grid-template-columns: 1fr 1fr; gap: var(--sp-6); } }
@media (max-width: 519px) { .footer-grid { grid-template-columns: 1fr; } }
.site-footer h4 { font-family: var(--font-body); font-size: var(--fs-50); letter-spacing: .2em; text-transform: uppercase; color: var(--foot-fg-muted); margin-bottom: var(--sp-4); }
.site-footer a { color: var(--foot-fg); font-size: var(--fs-100); }
.site-footer a:hover { color: #000; }
.site-footer li { margin-bottom: var(--sp-2); }
.footer-bottom { border-top: 1px solid var(--foot-border); margin-top: var(--sp-7); padding-top: var(--sp-5); display: flex; justify-content: space-between; flex-wrap: wrap; gap: var(--sp-3); font-size: var(--fs-75); color: var(--foot-fg-muted); }
.social { display: flex; gap: var(--sp-4); }
.social .icon { width: 20px; height: 20px; }

/* ----------------------------------------------------------------------------
   15. Mobile drawer nav
   ---------------------------------------------------------------------------- */
.mnav { position: fixed; inset: 0 30% 0 0; max-width: 360px; background: var(--surface); transform: translateX(-100%); transition: transform .28s var(--ease); z-index: 100; overflow-y: auto; padding: var(--sp-5); }
.mnav.is-open { transform: none; }
.mnav .m-item > a { display: flex; justify-content: space-between; padding: var(--sp-4) 0; border-bottom: 1px solid var(--c-line); font-size: var(--fs-200); letter-spacing: .06em; }
.mnav .m-sub { padding-left: var(--sp-4); }
.mnav .m-sub a { display: block; padding: var(--sp-2) 0; color: var(--text-soft); font-size: var(--fs-100); }

/* ---------------------------------------------------------------------------
   THE BURGER RANGE
   The viewports that get the mobile drawer instead of the desktop mega-menu:
   anything narrower than 1024px, plus a 1024px-wide viewport held PORTRAIT
   (iPad Pro 12.9"). Every rule that swaps the desktop nav for the burger, or
   drops the in-page left column, repeats this exact condition — search the file
   for "burger range" and keep them in sync.

   Two bugs this closes. The burger used to appear below 1024px while the drawer
   was hidden above 991px, so between 992 and 1023 the header showed BOTH navs
   and the burger opened nothing. And a portrait iPad Pro (1024px) fell through
   to the desktop nav entirely.
   --------------------------------------------------------------------------- */
@media (max-width: 1023px), (max-width: 1024px) and (orientation: portrait) {
  .primary-nav { display: none; }
  .nav-toggle { display: inline-flex; }
  .header-bar { grid-template-columns: auto 1fr auto; }
}
@media (min-width: 1024px) { .mnav, .drawer-backdrop.for-nav { display: none; } }

/* ----------------------------------------------------------------------------
   16. Account area (dashboard / orders / order detail / addresses)
   ---------------------------------------------------------------------------- */
.account-layout { display: grid; grid-template-columns: 220px 1fr; gap: var(--sp-7); align-items: start; }
@media (max-width: 767px) { .account-layout { grid-template-columns: 1fr; gap: var(--sp-5); } }
.account-nav ul { border: 1px solid var(--c-line); border-radius: var(--radius-lg); overflow: hidden; background: var(--surface); }
.account-nav a { display: block; padding: var(--sp-3) var(--sp-4); font-size: var(--fs-100); border-bottom: 1px solid var(--c-line); }
.account-nav li:last-child a { border-bottom: 0; }
.account-nav a:hover { background: var(--c-cream-2); text-decoration: none; }
.account-nav a.is-active { background: var(--text); color: #fff; }

.info-card { background: var(--surface); border: 1px solid var(--c-line); border-radius: var(--radius-lg); padding: var(--sp-5); }
.info-card h3 { margin-top: 0; }

.account-table { width: 100%; border-collapse: collapse; font-size: var(--fs-100); }
.account-table th, .account-table td { text-align: left; padding: var(--sp-3); border-bottom: 1px solid var(--c-line); vertical-align: middle; }
.account-table th { font-family: var(--font-body); font-size: var(--fs-50); letter-spacing: .12em; text-transform: uppercase; color: var(--c-muted); }
@media (max-width: 599px) {
  .account-table, .account-table tbody, .account-table tr, .account-table td { display: block; }
  .account-table thead { display: none; }
  .account-table tr { padding-block: var(--sp-3); border-bottom: 1px solid var(--c-line); }
  .account-table td { border: 0; padding: 2px 0; }
}

.status { display: inline-block; padding: 2px 10px; border-radius: 999px; font-size: var(--fs-50); letter-spacing: .04em; }
.status--shipped   { background: #fbeadf; color: var(--c-terracotta-d); }
.status--delivered { background: #e3efe8; color: var(--c-ok); }
.status--processing{ background: var(--c-cream-2); color: var(--text-soft); }

/* Free-shipping progress bar (cart page + drawer) */
.ship-progress { background: var(--c-cream-2); border: 1px solid var(--c-line); border-radius: var(--radius); padding: var(--sp-3) var(--sp-4); margin-bottom: var(--sp-5); font-size: var(--fs-75); }
.ship-progress p { margin: 0 0 var(--sp-2); }
.ship-progress .bar { height: 6px; border-radius: 999px; background: var(--c-sand); overflow: hidden; }
.ship-progress .bar span { display: block; height: 100%; background: var(--c-green); }

/* Sub-collection chips (PLP lateral drill-down) */
.chip-grid { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-bottom: var(--sp-5); }
.chip { border: 1px solid var(--c-line); border-radius: 999px; padding: 6px 16px; font-size: var(--fs-75); background: var(--surface); }
.chip:hover { border-color: var(--text); text-decoration: none; }

/* Utilities */
.text-center { text-align: center; }
.mt-6 { margin-top: var(--sp-6); }
.mb-0 { margin-bottom: 0; }
.flex { display: flex; gap: var(--sp-3); align-items: center; }
.between { justify-content: space-between; }

/* ----------------------------------------------------------------------------
   17. Reconciliation with AGE-33 audit — additions not already covered above
   (account area, .ship-progress and .chip styles live in §16 above)
   ---------------------------------------------------------------------------- */

/* Active sub-collection chip (PLP lateral drill-down — audit §3.2) */
.chip.is-active { background: var(--text); color: #fff; border-color: var(--text); }

/* Empty state (audit §2.16) */
.empty-state { text-align: center; padding-block: var(--sp-8); }
.empty-state .glyph { width: 48px; height: 48px; margin-inline: auto; stroke: var(--c-muted); fill: none; stroke-width: 1.2; margin-bottom: var(--sp-4); }
.empty-state p { color: var(--text-soft); }

/* CMS / narrow content uses the audit narrow token */
.cms { max-width: var(--container-narrow); }

/* Accessibility: honour reduced-motion (audit 04 §3) */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; scroll-behavior: auto !important; }
}

/* ============================================================================
   18. PrestaShop classic bridge
   Maps classic's native markup + module output onto the Impertinente tokens for
   the controllers this theme inherits rather than overrides (PDP, category/PLP,
   cart, checkout, account) and for the modules rendered through our chrome
   (ps_searchbar, ps_shoppingcart, ps_mainmenu, ps_linklist, ps_emailsubscription,
   ps_facetedsearch). Scoped to classic selectors so it never fights §1–17.
   ============================================================================ */

/* ---- 18.1 Page scaffold ---- */
#wrapper { background: var(--bg); }
#wrapper > .container { padding-block: var(--sp-5); }
#main .page-header h1, .page-heading { font-family: var(--font-display); }
.breadcrumb { background: none; padding: var(--sp-4) 0; font-size: var(--fs-75); color: var(--c-muted); }
.breadcrumb ol { padding: 0; margin: 0; list-style: none; display: flex; flex-wrap: wrap; gap: 6px; }
.breadcrumb li:not(:last-child)::after { content: "/"; margin-left: 6px; color: var(--c-muted); }
.breadcrumb a { color: var(--c-muted); }
.breadcrumb a:hover { color: var(--accent); }

/* ---- 18.2 Bootstrap buttons → Impertinente buttons ---- */
.btn-primary, .btn.btn-primary {
  background: var(--accent); border-color: var(--accent); color: var(--accent-ink);
  border-radius: var(--radius); letter-spacing: .12em; text-transform: uppercase; font-size: var(--fs-75);
}
.btn-primary:hover, .btn.btn-primary:hover { background: var(--c-terracotta-d); border-color: var(--c-terracotta-d); }
.btn-secondary, .btn.btn-secondary { background: var(--c-green); border-color: var(--c-green); color: #fff; border-radius: var(--radius); }
.btn-secondary:hover { background: #0d2b23; }
.add-to-cart, button.add-to-cart { background: var(--accent); border-color: var(--accent); color: #fff; }
.add-to-cart:hover { background: #0d2b23; }

/* ---- 18.3 Header module output (menu) ----
   ps_searchbar rides displayTop with the menu; we have our own search icon, so
   hide the inline widget. The mega-menu (ps_mainmenu) is the visible nav. */
.primary-nav #search_widget, .primary-nav .ps-search { display: none; }
/* inline, centred menu sharing the single header row */
.primary-nav { flex: 1 1 auto; display: flex; justify-content: center; min-width: 0; }
.primary-nav .menu, .primary-nav > div { width: 100%; }

/* --- Top level (data-depth=0): a single centred, horizontal row.
   Scoped to depth 0 so it NEVER cascades into the dropdown sub-menus. --- */
#_desktop_top_menu > ul.top-menu,
#_desktop_top_menu ul.top-menu[data-depth="0"] {
  display: flex; flex-wrap: nowrap; justify-content: center; align-items: center;
  gap: clamp(14px, 2vw, 36px); margin: 0; padding: 0; list-style: none;
}
#_desktop_top_menu ul.top-menu[data-depth="0"] > li { position: relative; }
#_desktop_top_menu ul.top-menu[data-depth="0"] > li > a {
  font-family: var(--font-logo); font-weight: 600; font-size: var(--fs-75);
  letter-spacing: .04em; text-transform: uppercase; padding: 8px 2px; color: var(--c-ink); white-space: nowrap;
  display: inline-flex; align-items: center;
}
#_desktop_top_menu ul.top-menu[data-depth="0"] > li > a:hover { color: var(--c-gold); text-decoration: none; }
#_desktop_top_menu .navbar-toggler, #_desktop_top_menu .collapse-icons { display: none; } /* mobile-only toggles */

/* --- Dropdown popover (data-depth=1 lives inside .sub-menu): hidden until hover --- */
#_desktop_top_menu .sub-menu {
  position: absolute; top: 100%; left: 50%; transform: translateX(-50%) translateY(6px);
  /* size to the widest column so long labels (e.g. "Combinaisons & ensembles")
     never overflow the card; cap so it can't run off-screen. */
  width: max-content; min-width: 240px; max-width: min(560px, 92vw); margin: 0; padding: var(--sp-5) var(--sp-6);
  background: #fff; border: 1px solid var(--c-line); border-radius: var(--radius-lg);
  box-shadow: var(--shadow); z-index: 1100;
  opacity: 0; visibility: hidden; pointer-events: none; transition: opacity .18s var(--ease), transform .18s var(--ease);
}
/* Shown via JS-set `.is-open` (custom.js initMegaMenu, with a close delay) NOT
   :hover — so the pointer travelling from the label across the gap to the panel
   can never close it mid-move. :focus-within keeps it keyboard-accessible. */
#_desktop_top_menu ul.top-menu[data-depth="0"] > li.is-open > .sub-menu,
#_desktop_top_menu ul.top-menu[data-depth="0"] > li:focus-within > .sub-menu {
  opacity: 1; visibility: visible; pointer-events: auto; transform: translateX(-50%) translateY(0);
}
/* depth-1 laid out as columns inside the card */
#_desktop_top_menu .sub-menu ul.top-menu {
  display: flex; flex-wrap: wrap; gap: var(--sp-3) var(--sp-7); margin: 0; padding: 0; list-style: none;
  justify-content: flex-start; align-items: flex-start;
}
#_desktop_top_menu .sub-menu ul.top-menu[data-depth="1"] > li { min-width: 150px; }
#_desktop_top_menu .sub-menu a {
  font-family: var(--font-body); text-transform: none; letter-spacing: 0; white-space: nowrap;
  display: block; padding: 5px 0; color: var(--c-ink);
}
/* depth-1 headers (have children) read as a small caps label */
#_desktop_top_menu .sub-menu a.dropdown-submenu {
  font-family: var(--font-logo); font-weight: 600; font-size: var(--fs-75);
  letter-spacing: .04em; text-transform: uppercase; color: var(--c-ink); padding-bottom: var(--sp-2);
}
#_desktop_top_menu .sub-menu a:hover { color: var(--c-gold); text-decoration: none; }
/* nested depth-2 wrapper: always shown inside the open card, stacked under its header */
#_desktop_top_menu .sub-menu .collapse { display: block !important; height: auto !important; visibility: visible !important; }
#_desktop_top_menu .sub-menu ul.top-menu[data-depth="2"] { flex-direction: column; gap: 0; margin-top: 2px; }
#_desktop_top_menu .sub-menu ul.top-menu[data-depth="2"] a { font-size: var(--fs-75); color: var(--c-mute); padding: 3px 0; }

/* unused wrapper (mobile nav = category drawer); was rendering a white band under the hero */
/* Safety net. The theme no longer renders this wrapper (see header.tpl), but if a
   module ever emits one, classic's theme.js will jQuery-.toggle() it — writing an
   INLINE display:block that beats a plain `display: none` — and then hide
   #wrapper/#footer whenever it reads as visible, blanking the page. `!important`
   keeps its computed display at none, so jQuery's :visible test stays false and the
   page content is never hidden. */
#mobile_top_menu_wrapper { display: none !important; }

/* ---- 18.4 Category / PLP + home product blocks ----
   Force every PrestaShop product list (category grid, search, and the home
   featured/new/promo blocks — which render a BARE .products, not .products.row)
   onto the same responsive card grid. align-items:start stops the uneven-height
   overlap that the module's default flow caused. */
#js-product-list .products,
.products.row,
.featured-products .products,
ul.product_list,
#products .products,
#blockEmailSubscription_displayFooterBefore ~ .products {
  display: grid !important;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--sp-5);
  align-items: start;
  float: none;
  /* Several of these lists are a Bootstrap `.row`, which carries -15px side
     margins meant to be cancelled by the .col-* padding on its children. Our
     cards are bare grid items with no such padding, so the negative margin just
     drags the grid 15px outside its container: on phones the tiles run to the
     screen edge, and on desktop the first column sits 15px left of the sort bar
     above it. Grid does its own gutters — zero them. */
  margin-left: 0; margin-right: 0;
}
.featured-products .products .product-card,
.products .product-card, .products .product, .products > li { width: auto; margin: 0; float: none; }
@media (max-width: 1199px) { .featured-products .products, .products.row, #js-product-list .products { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 991px)  { .featured-products .products, .products.row, #js-product-list .products { grid-template-columns: repeat(2, 1fr); } }
/* keep TWO columns on phones (matches the reference) — never collapse to 1-up */
@media (max-width: 480px)  { .featured-products .products, .products.row, #js-product-list .products { grid-template-columns: repeat(2, 1fr); gap: var(--sp-3); } }
/* category/PLP grid stays 3-up (sidebar present) */
#js-product-list .products { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 1023px) { #js-product-list .products { grid-template-columns: repeat(2, 1fr); } }
#search_filters { border: 0; }
#search_filters .facet { border-bottom: 1px solid var(--c-line); padding-block: var(--sp-4); }
#search_filters .facet .facet-title,
#search_filters .h6 { font-family: var(--font-body); font-size: var(--fs-75); letter-spacing: .12em; text-transform: uppercase; color: var(--text); }
#search_filters .facet-label, #search_filters label { font-size: var(--fs-100); color: var(--text-soft); }
.products-sort-order .select-title { display: flex; align-items: center; gap: var(--sp-2); min-height: 42px; padding: 0 12px; line-height: 1; border: 1px solid var(--c-line); border-radius: var(--radius); background: var(--surface); font-size: var(--fs-75); }
.products-sort-order .select-title > i, .products-sort-order .select-title .material-icons { margin-left: auto; }
#js-product-list-top .total-products, .total-products p { font-size: var(--fs-75); color: var(--c-muted); }
.active_filters { background: none; padding: 0; margin-bottom: var(--sp-5); display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.active_filters .filter-block { border: 1px solid var(--c-line); border-radius: 999px; padding: 4px 12px; font-size: var(--fs-75); background: var(--surface); }
/* Pagination (classic markup: nav.pagination > .col > ul.page-list) — compact,
   centred square buttons; count on the left, pages on the right. */
.pagination { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: var(--sp-4); margin-top: var(--sp-7); border-top: 1px solid var(--c-line); padding-top: var(--sp-5); }
.pagination > div { width: auto; padding: 0; }
.pagination .col-md-4, .pagination .col-md-8 { flex: 0 0 auto; max-width: none; }
.pagination .page-list { display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: var(--sp-2); list-style: none; margin: 0; padding: 0; }
.pagination .page-list li { margin: 0; }
.pagination .page-list li a, .pagination .page-list li span {
  display: inline-flex; align-items: center; justify-content: center; min-width: 42px; height: 42px; padding: 0 12px;
  border: 1px solid var(--c-line); border-radius: var(--radius); background: var(--surface);
  font-size: var(--fs-75); color: var(--c-ink); line-height: 1; white-space: nowrap; gap: 4px;
}
.pagination .page-list li a:hover { border-color: var(--c-ink); text-decoration: none; }
.pagination .page-list li.current a, .pagination .page-list li.current span { background: var(--c-ink); color: #fff; border-color: var(--c-ink); }
.pagination .page-list li.disabled span, .pagination .page-list li.disabled a { opacity: .35; pointer-events: none; }
.pagination .showing, .pagination .total-products, .pagination .col-md-4 p { font-size: var(--fs-75); color: var(--c-muted); margin: 0; }
@media (max-width: 575px) { .pagination { justify-content: center; } }

/* ---- 18.5 Product page (PDP) ---- */
/* Two-column PDP (gallery | buy-box). PS 9.1 classic renders .product-container as
   a plain BLOCK with floated .col-md-6 children (not the CSS grid an earlier
   revision assumed). Left to auto width, a product with a long description widens
   the info column until the two floats no longer fit 100% and the info wraps BELOW
   the gallery (single-column on some products, two-column on others). Pin it to a
   real flex 50/50 at md+ so every product lays out identically; stack < 992px. */
.product-container { display: flex; flex-wrap: wrap; align-items: flex-start; }
.product-container > .col-md-6 { flex: 0 0 50%; max-width: 50%; width: 50%; float: none; }
/* the images column wraps the gallery in .page-content, which classic shrink-wraps
   + centres inside the col; force it full-width so the gallery aligns left. */
.product-container > .col-md-6 > .page-content { width: 100% !important; max-width: none !important; }
.product-container > .col-md-6:last-child { padding-left: var(--sp-6); }
@media (max-width: 991px) {
  .product-container > .col-md-6 { flex-basis: 100%; max-width: 100%; width: 100%; padding-left: 15px; }
}
/* Hide the unconfigured Customer-Reassurance block: out of the box it renders
   placeholder "(edit with the Customer Reassurance module)" text and points at
   broken pack2 SVG icons (http://modules/... → 404). The home trust-band already
   carries the reassurance message. A merchant who configures the module can drop
   this rule. */
.blockreassurance_product { display: none; }
.product-information h1, .product-detail-name { font-family: var(--font-display); }
.product-prices .current-price, .current-price span { font-size: var(--fs-h5); }
.product-prices .regular-price { color: var(--c-muted); text-decoration: line-through; }
.product-prices .discount { background: var(--c-sale); color: #fff; border-radius: 999px; }
.product-variants .control-label { font-size: var(--fs-75); letter-spacing: .06em; text-transform: uppercase; color: var(--text); }
/* Variant pickers (AGE-73): Couleur = `color` group → circular swatches;
   Taille = `radio` group → square size buttons. The native radios are hidden and
   the <span.color>/<span.radio-label> are the controls. Out-of-stock values are
   shown greyed-out (PS_DISP_UNAVAILABLE_ATTR=1) — the theme sets `disabled` on the
   unavailable input, which we fade. */
.product-variants .product-variants-item ul { display: flex; flex-wrap: wrap; gap: 10px; margin: 6px 0 0; padding: 0; list-style: none; }
.product-variants .product-variants-item li { float: none; margin: 0; }
.product-variants label { margin: 0; cursor: pointer; }
.product-variants input[type="radio"] { position: absolute; width: 0; height: 0; opacity: 0; }

/* colour dots */
.product-variants .color {
  position: relative;
  display: block; width: 30px; height: 30px; border-radius: 50%;
  border: 1px solid rgba(0,0,0,.18); background-size: cover; background-position: center;
  cursor: pointer; transition: box-shadow .15s ease, transform .15s ease;
}
.product-variants .color:hover { transform: scale(1.06); }
.product-variants .input-color:checked + .color,
.product-variants .input-color:focus-visible + .color {
  box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--accent);
}

/* size squares */
.product-variants .radio-label {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 42px; height: 42px; padding: 0 10px;
  border: 1px solid var(--c-line); border-radius: var(--radius);
  font-size: var(--fs-75); letter-spacing: .04em; color: var(--text);
  background: var(--surface); cursor: pointer;
  transition: border-color .15s ease, background .15s ease, color .15s ease;
}
.product-variants .radio-label:hover { border-color: var(--text); }
.product-variants input[type="radio"]:checked + .radio-label {
  border-color: var(--accent); background: var(--accent); color: #fff;
}
.product-variants input[type="radio"]:focus-visible + .radio-label { border-color: var(--accent); }

/* out-of-stock / unavailable COLOUR → keep the swatch's real colour visible (so
   shoppers can still tell what it is) and mark it unavailable with a single thin
   diagonal slash. The slash is a dark core with a faint white halo so it reads on
   any swatch (black, kaki, beige…); selecting stays blocked (input is disabled). */
.product-variants input:disabled + .color {
  cursor: not-allowed; box-shadow: none;
}
.product-variants input:disabled + .color:hover { transform: none; }
.product-variants input:disabled + .color::after {
  content: "";
  position: absolute; inset: 0; border-radius: 50%;
  background: linear-gradient(135deg,
    transparent            calc(50% - 2px),
    rgba(255,255,255,.8)   calc(50% - 2px),
    rgba(255,255,255,.8)   calc(50% - .75px),
    rgba(20,20,20,.65)     calc(50% - .75px),
    rgba(20,20,20,.65)     calc(50% + .75px),
    rgba(255,255,255,.8)   calc(50% + .75px),
    rgba(255,255,255,.8)   calc(50% + 2px),
    transparent            calc(50% + 2px));
}
.product-variants input:disabled + .radio-label {
  opacity: .45; cursor: not-allowed; text-decoration: line-through;
  border-color: var(--c-line); background: var(--surface); color: var(--text-soft);
}
.product-actions .add-to-cart { width: 100%; padding: 16px; font-size: var(--fs-75); letter-spacing: .14em; }
.product-quantity .qty .input-group, .product-quantity #quantity_wanted { border: 1px solid var(--c-line); border-radius: var(--radius); }
.tabs, .product-tabs { border-top: 1px solid var(--c-line); }
.tabs .nav-tabs .nav-link { font-size: var(--fs-75); letter-spacing: .1em; text-transform: uppercase; color: var(--text-soft); }
.tabs .nav-tabs .nav-link.active { color: var(--text); border-color: var(--accent); }

/* ---- 18.6 Cart & checkout ----
   NB: classic's .cart-grid is a Bootstrap .row with col-md-8 / col-md-4 children;
   do NOT override it to CSS grid or the summary column collapses and clips the
   checkout button. Just restyle the cards and let Bootstrap own the layout. */
.cart-grid { align-items: start; }
.cart-grid-right, .cart-summary { width: 100%; }
.cart-item { border-bottom: 1px solid var(--c-line); padding-block: var(--sp-5); }
.cart-summary, .card { border: 1px solid var(--c-line); border-radius: var(--radius-lg); box-shadow: none; }
.cart-summary .cart-total, .cart-total { font-family: var(--font-display); font-size: var(--fs-h6); }
.cart-detailed-totals .label, .checkout .step-title { font-family: var(--font-display); }
.product-line-grid-body .label, .product-price { color: var(--text); }
#checkout .checkout-step.-current .step-title { color: var(--accent); }

/* ---- 18.7 Customer account & authentication ----
   Classic ships auth as raw Bootstrap: label-left/field-right .form-group rows, a
   grey "show password" slab and a boxed card. Restyle to the brand — one centred
   card, full-width stacked fields, on-brand inputs/buttons/links. */
.page-customer-account #content {
  background: var(--surface); border: 1px solid var(--c-line); border-radius: var(--radius-lg); padding: var(--sp-7);
}
/* auth pages (login + register): narrow, centred column, single frame (no inner box) */
.page-authentication #main { max-width: 460px; margin-inline: auto; }
.page-authentication h1 { text-align: center; font-size: clamp(1.8rem, 4vw, 2.6rem); margin-bottom: var(--sp-6); }
#authentication .login-form, #authentication .register-form { border: 0; padding: 0; background: none; }

/* stack every field — label above a full-width control */
.page-authentication .form-group.row { display: block; margin-bottom: var(--sp-4); }
.page-authentication .form-group.row > label,
.page-authentication .form-control-label {
  float: none; display: block; width: 100%; max-width: none; text-align: left; padding: 0; margin: 0 0 6px;
  font-size: var(--fs-75); letter-spacing: .06em; text-transform: uppercase; color: var(--text); font-weight: 500;
}
/* the grid floats the columns left (shrinks a block to content) — un-float and
   let each column fill the stacked row */
.page-authentication .form-group.row > div[class*="col-"] { float: none; width: 100%; max-width: 100%; padding: 0; }
.page-authentication .form-control-comment { font-size: var(--fs-50); color: var(--c-muted); margin-top: 4px; }
.page-authentication .form-control,
.page-authentication input[type="text"],
.page-authentication input[type="email"],
.page-authentication input[type="password"] {
  width: 100%; height: 48px; padding: 0 14px; font-size: 15px;
  border: 1px solid var(--c-line); border-radius: var(--radius); background: var(--surface); color: var(--text);
}
.page-authentication .form-control:focus { outline: none; border-color: var(--accent); }

/* password + show-password on one row; the toggle is a subtle attached button, not a grey slab */
.page-authentication .input-group { display: flex; align-items: stretch; }
.page-authentication .input-group .form-control { flex: 1 1 auto; border-top-right-radius: 0; border-bottom-right-radius: 0; }
/* Override classic's high-specificity grey slab (.input-group .input-group-btn>.btn
   [data-action=show-password]{background:#7a7a7a;color:#fff}) — match its path so
   the toggle becomes a subtle attached button. */
.page-authentication .input-group .input-group-btn > .btn[data-action="show-password"] {
  flex: 0 0 auto; height: 48px; padding: 0 14px; cursor: pointer;
  border: 1px solid var(--c-line); border-left: 0; border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--surface); color: var(--c-muted);
  font-size: var(--fs-50); font-weight: 500; letter-spacing: .1em; text-transform: uppercase;
}
.page-authentication .input-group .input-group-btn > .btn[data-action="show-password"]:hover { color: var(--text); }

/* actions + links */
.page-authentication .forgot-password { text-align: center; margin: var(--sp-2) 0 var(--sp-5); font-size: var(--fs-75); }
.page-authentication .form-footer { text-align: center; margin-top: var(--sp-5); }
.page-authentication .form-footer .btn, .page-authentication #submit-login { width: 100%; }
.page-authentication .no-account { text-align: center; margin-top: var(--sp-6); font-size: var(--fs-100); }

.page-my-account #content .links a { color: var(--text); }
#history .order-actions a, .addresses .address { border: 1px solid var(--c-line); border-radius: var(--radius-lg); }
.table thead th { font-family: var(--font-body); font-size: var(--fs-50); letter-spacing: .12em; text-transform: uppercase; color: var(--c-muted); }
.order-status .label, .label { border-radius: 999px; }

/* ---- 18.8 Footer module output ----
   ps_linklist emits col-md-6 / col-md-3 blocks (one nesting its own .row). We
   can't rely on Bootstrap's grid resolving correctly inside our overridden
   footer, so lay the columns out with explicit flexbox and only style colour. */
.site-footer .footer-grid { display: flex; flex-wrap: wrap; gap: var(--sp-7); margin-top: var(--sp-2); }
.site-footer .footer-brand { flex: 0 0 clamp(200px, 22%, 280px); }
.site-footer .footer-links { flex: 1 1 540px; min-width: 0; display: flex; }
/* ps_linklist nests the four link blocks in Bootstrap rows/cols:
     .footer-links > .row > [ .col-md-6.links > .row > (.wrapper ×2), account.wrapper, contact.wrapper ]
   Lay every level out with explicit flexbox (more robust than display:contents,
   which lets the deeply-nested contact block escape its flex container). */
.site-footer .footer-links > .row { display: flex; flex-wrap: wrap; gap: var(--sp-6) var(--sp-7); width: 100%; margin: 0; align-items: flex-start; }
.site-footer .footer-links > .row > .col-md-6.links { flex: 2 1 300px; display: flex; padding: 0; }      /* holds Products + Our company */
.site-footer .footer-links > .row > .wrapper { flex: 1 1 150px; min-width: 130px; padding: 0; }          /* account, contact */
.site-footer .footer-links .col-md-6.links > .row { display: flex; flex-wrap: wrap; gap: var(--sp-6) var(--sp-7); width: 100%; margin: 0; }
.site-footer .footer-links .col-md-6.links > .row > .wrapper { flex: 1 1 130px; min-width: 120px; padding: 0; }
@media (max-width: 767px) {
  .site-footer .footer-grid { flex-direction: column; gap: var(--sp-6); }
  /* column flex makes flex-basis the HEIGHT — reset to auto so the stacked links
     size to content instead of being clipped to 540px and overlapping the copyright. */
  .site-footer .footer-links { flex: 1 1 auto; }
  .site-footer .footer-links > .row, .site-footer .footer-links .col-md-6.links > .row { gap: var(--sp-6); }
  .site-footer .footer-links > .row > .col-md-6.links { flex: 1 1 100%; flex-direction: column; gap: var(--sp-6); }
  .site-footer .footer-links > .row > .wrapper,
  .site-footer .footer-links .col-md-6.links > .row > .wrapper { flex: 1 1 100%; min-width: 0; }
}
.site-footer .footer-brand .footer-tagline { color: var(--foot-fg-muted); font-size: var(--fs-100); margin-top: var(--sp-4); max-width: 34ch; }
.site-footer .links .h3, .site-footer .h3, .site-footer .h4, .site-footer .title, .site-footer .myaccount-title, .site-footer .block-contact .h4 { font-family: var(--font-body); font-size: var(--fs-50); letter-spacing: .2em; text-transform: uppercase; color: var(--foot-fg-muted) !important; margin-bottom: var(--sp-4); white-space: normal; }
.site-footer .links ul a, .site-footer a { color: var(--foot-fg); font-size: var(--fs-100); }
/* title links (e.g. the account block's "Votre compte" is an <a>) match the muted title tone */
.site-footer .h3 a, .site-footer .h4 a, .site-footer .myaccount-title a, .site-footer .title a { color: var(--foot-fg-muted) !important; font-size: inherit; }
/* was white-space:nowrap — long legal labels ("Politique de confidentialité")
   then overflowed their narrow column onto the next; let them wrap instead. */
.site-footer .links ul li, .site-footer .account-list li { margin-bottom: var(--sp-2); white-space: normal; }
.site-footer .links ul a:hover, .site-footer a:hover { color: #000; }
.site-footer .block-contact .navigation-pipe { display: none; }
/* The ps_contactinfo "Informations" block renders its store name/address in a
   bare .collapse div (not an <li>) which inherits a light grey from classic —
   ~1.4:1 on gold. Force the whole block (and any inner span/link) to footer ink;
   !important + the descendant reach beat classic's #footer id-scoped grey. */
.site-footer .block-contact li { color: var(--foot-fg-muted); font-size: var(--fs-100); margin-bottom: var(--sp-2); }
.site-footer .block-contact, .site-footer .block-contact * { color: var(--foot-fg) !important; }
/* Keep the footer link lists always open (don't depend on the collapse JS) and
   never show the +/- accordion toggles. Force the real (hidden-sm-down) titles
   visible on every width so mobile shows headings, not just links. */
.site-footer .title.clearfix.hidden-md-up, .site-footer .navbar-toggler { display: none !important; }
.site-footer .collapse, .site-footer .account-list.collapse { display: block !important; height: auto !important; visibility: visible !important; }
.site-footer .footer-links .h3, .site-footer .footer-links .h4, .site-footer .footer-links .myaccount-title { display: block !important; }
/* Newsletter band (ps_emailsubscription on the gold footer-before): force DARK
   text so nothing is invisible on the gold, and centre the layout. */
.section.newsletter { text-align: center; }
.section.newsletter .container { max-width: 980px; }
.section.newsletter, .section.newsletter .block_newsletter,
.section.newsletter h1, .section.newsletter h2, .section.newsletter h3,
.section.newsletter .h1, .section.newsletter .h2, .section.newsletter .h3,
.section.newsletter p, .section.newsletter label, .section.newsletter .block-title,
.section.newsletter .block_newsletter_alert { color: var(--foot-fg) !important; }
.section.newsletter .block_newsletter { background: none; box-shadow: none; padding: 0; }
.section.newsletter .h3, .section.newsletter h2 { font-family: var(--font-display); font-size: var(--fs-h4); margin: 0 0 var(--sp-5); }
/* Wider field on desktop + a clean flex row. Classic wraps the input and a
   FLOATED submit inside a .row > .col, so the field only got ~170px — un-float the
   button, make the col a flex row, and let the field grow. */
/* Force block so the success/error <p> (a form child) stacks on its own line
   instead of sitting flex-squished beside the input row. */
.section.newsletter form { display: block !important; max-width: 600px; margin: 0 auto; }
.section.newsletter form .row { margin: 0; }
.section.newsletter form .row > [class*="col-"] { display: flex; gap: var(--sp-2); align-items: stretch; padding: 0; }
/* order: -1 puts the field first so the submit button sits on the RIGHT — the
   classic markup lists the (floated) submit BEFORE the input in the DOM. */
.section.newsletter .input-wrapper { flex: 1 1 auto; min-width: 0; order: -1; }
.section.newsletter form [type="submit"] { float: none !important; flex: 0 0 auto; }
.section.newsletter input[type="text"], .section.newsletter input[type="email"] {
  width: 100%; height: 48px; padding: 0 16px; background: var(--foot-field);
  border: 1px solid rgba(16,43,38,.35); color: var(--foot-fg); border-radius: var(--radius);
}
.section.newsletter input::placeholder { color: rgba(16,43,38,.65); }
/* Chrome/Safari autofill paints the field yellow/blue — mask it with an inset
   shadow (you can't set background-color on :-webkit-autofill) so it stays on-theme.
   Opaque near-white to match --foot-field composited over the sand band. */
.section.newsletter input:-webkit-autofill,
.section.newsletter input:-webkit-autofill:hover,
.section.newsletter input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--c-ink);
  -webkit-box-shadow: 0 0 0 1000px #f1ebe3 inset;
  caret-color: var(--c-ink); transition: background-color 9999s ease-out 0s;
}
/* CTA is dark ink on the light sand. It used to be a WHITE button, which worked on
   the old dark-green band but nearly disappears against sand. */
.section.newsletter [type="submit"], .section.newsletter .btn {
  background: var(--c-ink); border-color: var(--c-ink); color: var(--c-cream); white-space: nowrap;
  height: 48px; padding: 0 24px; display: inline-flex; align-items: center; justify-content: center;
}
.section.newsletter [type="submit"]:hover { background: #0a1f1a; border-color: #0a1f1a; }
.section.newsletter p:last-child, .section.newsletter .text-muted { font-size: var(--fs-75); color: var(--foot-fg) !important; margin-top: var(--sp-4); }
/* Confirmation / error: the global light .alert-success bg + forced text colour =
   unreadable on the band. Render as a subtle translucent chip with ink text. */
.section.newsletter .alert, .section.newsletter .block_newsletter_alert,
.section.newsletter .alert-success, .section.newsletter .alert-danger {
  background: rgba(255,255,255,.6) !important; border: 1px solid rgba(16,43,38,.3) !important;
  color: var(--foot-fg) !important; border-radius: var(--radius); box-shadow: none;
  padding: 10px 16px; margin: var(--sp-4) auto 0; max-width: 460px;
}
.site-footer .social-sharing li, .site-footer .social a { background: none; }

/* Map PrestaShop flag types (product.flags[].type) onto the replica badges */
.badge--on-sale, .badge--discount { background: var(--c-sale); color: #fff; }
.badge--new { background: var(--c-green); color: #fff; }
.badge--pack, .badge--online-only { background: var(--c-gold); color: #fff; }
.badge--out_of_stock { background: var(--c-muted); color: #fff; }

/* On the 404 the layout prints the meta-title as a redundant <h1> above our
   branded card — suppress it so only the .notfound block shows. */
.page-pagenotfound #main .page-header { display: none; }

/* ---- 18.9 Notifications / alerts ---- */
.notifications-container .alert { border-radius: var(--radius); border: 1px solid var(--c-line); }
.alert-success { background: #e3efe8; color: var(--c-ok); }
.alert-danger { background: #fbeadf; color: var(--c-terracotta-d); }

/* ============================================================================
   18.10 Polish pass — bring inherited/module markup to a clean, pro finish
   ============================================================================ */

/* Product flags (PDP + classic miniatures) → replica badges */
.product-flags { position: absolute; top: var(--sp-3); left: var(--sp-3); z-index: 2; margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 6px; }
.product-flag { display: inline-block; background: var(--c-sand); color: var(--c-ink); border-radius: 999px; padding: 3px 10px; font-size: var(--fs-50); letter-spacing: .12em; text-transform: uppercase; line-height: 1.6; }
.product-flag.new { background: var(--c-green); color: #fff; }
.product-flag.discount, .product-flag.on-sale, .product-flag.reduced-price { background: var(--c-sale); color: #fff; }
.product-flag.out_of_stock { background: var(--c-muted); color: #fff; }
.product-miniature, .product-card { position: relative; }

/* Search widget: keep the icon inside, clear of the placeholder */
#search_widget { width: clamp(200px, 26vw, 320px); }
#search_widget form { position: relative; display: block; }
#search_widget input[type="text"] { width: 100%; padding-right: 42px; }
#search_widget button[type="submit"] { position: absolute; right: 0; top: 0; height: 100%; width: 40px; display: grid; place-items: center; color: var(--c-muted); }
#search_widget .search:before, #search_widget button .search { color: var(--c-muted); }

/* Header nav (top utility bar): tidy spacing + separators */
.header-nav .container { padding-block: 8px; }
.header-nav .row { align-items: center; }
.header-nav a, .header-nav .expand-more, .header-nav .links a { font-size: var(--fs-75); color: var(--text-soft); }
.header-top .header-bar { gap: var(--sp-5); }

/* Category / listing header: clean text banner, drop stray demo cover thumbs */
/* Category header: classic reserves min-height:220px for a cover-image banner we
   don't use (migrated cats have no curated imagery), leaving a huge empty gap
   above the subcategories — collapse it so the title sits tight. */
#category #left-column #search_filters_wrapper, #category .block-category { border: 0; }
#category .block-category, .block-category { min-height: 0 !important; }
.block-category, #category-description { background: transparent; border: 0; border-radius: 0; padding: 0; }
.block-category h1, #js-product-list-header h1 { font-family: var(--font-display); margin: 0; }
.category-cover, .block-category .category-cover, .block-category-inner:empty { display: none; }
#category #content-wrapper .block-category .category-cover img { display: none; }

/* Burger range: hide the left-column category-tree menu (.block-categories —
   "Accueil / Vêtements / Accessoires / Chaussures"). It duplicates the burger
   menu and ate a lot of space; keep only the breadcrumb + the burger. Desktop is
   unchanged. (founder 2026-07-09; extended to portrait tablets 2026-07-10) */
@media (max-width: 1023px), (max-width: 1024px) and (orientation: portrait) {
  #left-column .block-categories { display: none; }
  /* Hiding the tree empties the column but Bootstrap's `col-md-4` still reserves
     a third of the row beside the grid — from 768px up that was a dead gutter
     squeezing the products into two-thirds of the width. Drop the column and let
     the content span the row.
     The :has() guard keeps this from silently hiding faceted-search filters, which
     live in this same column, if that module is ever installed. Test for
     `#search_filters` (the module's output), NOT `#search_filters_wrapper` —
     classic renders that wrapper unconditionally around an empty controls div, so
     it is always present and would defeat the guard. Browsers without :has() drop
     the rule and keep the (empty) column — a safe fallback. */
  #left-column:not(:has(#search_filters)) { display: none; }
  /* classic's grid is FLOAT-based (`.col-md-8 { float: left; width: 66.67% }`),
     not flexbox — overriding flex-basis/max-width here does nothing. */
  #left-column:not(:has(#search_filters)) ~ #content-wrapper {
    float: none; width: 100%; max-width: 100%;
  }
}
/* On phones (<768px) the faceted-search filters are hidden too (`hidden-sm-down`),
   so a left column that survived the rule above has nothing left in it. */
@media (max-width: 767px) {
  #category #left-column { padding: 0; margin: 0; border: 0; }
}

/* Subcategories as PILLS (match the homepage) instead of big cards. flex-wrap
   keeps them inside the card at every width — fixes the mobile overflow. */
/* The in-content "Sous-catégories" block duplicates the left-column category tree,
   so hide it (founder call). Pill styling below is kept dormant in case it's ever
   re-enabled. */
#subcategories, .subcategories { display: none !important; }
#subcategories .subcategory-heading, .subcategories .subcategory-heading { font-family: var(--font-display); font-size: var(--fs-h6); margin: 0 0 var(--sp-4); }
.subcategories-list, #subcategories ul, .subcategories ul { display: flex; flex-wrap: wrap; gap: var(--sp-3); list-style: none; padding: 0; margin: 0; }
.subcategories-list li, #subcategories li, .subcategories li { margin: 0; flex: 0 0 auto !important; width: auto !important; min-width: 0 !important; max-width: none !important; }
.subcategory-image { display: none; }   /* PS serves a grey placeholder — drop it */
.subcategories-list h5, #subcategories h5, .subcategories h5 { margin: 0; display: inline-flex; }
.subcategory-name {
  display: inline-flex; align-items: center; padding: 10px 22px; border-radius: 999px;
  background: var(--c-cream-2); color: var(--c-ink);
  font-family: var(--font-logo); font-weight: 600; font-size: var(--fs-75); letter-spacing: .02em;
  white-space: nowrap; transition: background .2s var(--ease), color .2s var(--ease);
}
.subcategory-name:hover { background: var(--c-sand); text-decoration: none; }

/* Product card cover: lock aspect ratio so rows never collapse/overlap */
.product-card .thumbnail, .product-miniature .thumbnail { display: block; }
/* Product-tile image (desktop grids). height:auto is REQUIRED — the <img> carries
   an HTML height="750" attribute, so without it the aspect-ratio is ignored and the
   tile renders at the full photo height. A 3/4 crop (top-anchored) keeps tiles
   compact instead of ~750px tall (founder request; supersedes the earlier
   board "whole photo" ask, which still applies to the mobile carousel below). */
.product-card .product-thumbnail, .product-card .media img,
.product-miniature .thumbnail img, #js-product-list .thumbnail img {
  width: 100%; height: auto; aspect-ratio: 3/4; object-fit: cover; object-position: top center;
  border-radius: var(--radius); background: var(--c-cream-2);
}
.product-card .ph { aspect-ratio: 3/4; }

/* Brand mark: the real Impertinente logo (AGE-68) ships as an SVG image in the
   header/footer, so the old Syne two-line wordmark replica fallback is gone.
   `.brand-mark` (text) survives only as the alt/last-resort fallback. */
.brand { display: inline-flex; align-items: center; line-height: 1; }
.brand .brand-mark { font-family: var(--font-logo); font-weight: 800; letter-spacing: -.01em; }

/* Branded theme hero (home) — full-bleed lifestyle photo + dark scrim for the
   left-aligned copy. Ship assets/img/hero.jpg with the theme; the client swaps
   in their own seasonal hero image. */
.hero-band {
  position: relative;
  background-color: var(--c-green);
  background-image:
    linear-gradient(90deg, rgba(16,43,38,.86) 0%, rgba(16,43,38,.55) 42%, rgba(16,43,38,.12) 100%),
    url("../img/hero.jpg");
  background-size: cover, cover;
  background-position: center, center right;
  background-repeat: no-repeat;
  color: var(--c-cream);
  border-bottom: 1px solid rgba(247,241,232,.12);
}
.hero-band .hero-inner { position: relative; padding-block: clamp(var(--sp-8), 13vw, 160px); max-width: 640px; }
.hero-band .eyebrow { color: rgba(247,241,232,.85); }
.hero-band h1 { color: #fff; margin: 0 0 var(--sp-4); max-width: 16ch; text-shadow: 0 1px 3px rgba(0,0,0,.35), 0 2px 26px rgba(0,0,0,.5); }
.hero-band .hero-sub { font-size: var(--fs-200); color: rgba(255,255,255,.95); margin: 0 0 var(--sp-6); max-width: 46ch; text-shadow: 0 1px 3px rgba(0,0,0,.4), 0 2px 18px rgba(0,0,0,.45); }
.hero-band .btn--primary { background: #fff; border-color: #fff; color: var(--c-ink); box-shadow: 0 10px 30px rgba(0,0,0,.22); }
.hero-band .btn--primary:hover { background: var(--c-cream-2); border-color: var(--c-cream-2); }
@media (max-width: 768px) {
  .hero-band {
    background-image:
      linear-gradient(180deg, rgba(16,43,38,.32) 0%, rgba(16,43,38,.78) 100%),
      url("../img/hero.jpg");
    background-position: center, center top;
    text-align: center;
  }
  .hero-band .hero-inner { max-width: none; padding-block: clamp(var(--sp-8), 26vw, 200px); }
  .hero-band h1 { margin-inline: auto; }
  .hero-band .hero-sub { margin-inline: auto; }
}

/* Hero slideshow arrows: visible on the cream backdrop */
.carousel .direction .arrow-left, .carousel .direction .arrow-right, #carousel .carousel-control { color: var(--c-ink); opacity: .8; }

/* blockreassurance row (PDP): even spacing, muted icons */
.block-reassurance { border: 1px solid var(--c-line); border-radius: var(--radius-lg); margin-top: var(--sp-5); }
.block-reassurance li { border-color: var(--c-line); }
.block-reassurance li span { color: var(--text-soft); font-size: var(--fs-75); }

/* ============================================================================
   18.11 Category pills (home "La boutique") + mobile category nav
   Matches the reference's selectable category tabs and keeps categories
   visible/tappable on phones.
   ============================================================================ */
.shop-intro { padding-top: var(--sp-7); }
.shop-intro .section-head { margin-bottom: var(--sp-5); }
.category-pills { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--sp-3); }
.category-pills:empty { display: none; }
.category-pills a {
  display: inline-flex; align-items: center; padding: 11px 24px; border-radius: 999px;
  background: var(--c-cream-2); color: var(--c-ink);
  font-family: var(--font-logo); font-weight: 600; font-size: var(--fs-75);
  letter-spacing: .02em; white-space: nowrap; transition: background .2s var(--ease), color .2s var(--ease);
}
.category-pills a:hover { background: var(--c-sand); text-decoration: none; }
.category-pills a.is-active { background: var(--c-gold); color: #fff; }

/* Mobile header: burger LEFT · small wordmark · icons RIGHT, single row.
   The desktop mega-menu is hidden; the burger opens a category drawer (custom.js
   initMobileNav, built from the same menu). Burger range — keep in sync. */
@media (max-width: 1023px), (max-width: 1024px) and (orientation: portrait) {
  .header-bar, .header-top .header-bar { flex-wrap: nowrap; gap: 8px; }
  .header-bar .nav-toggle { display: inline-flex; order: 0; flex: 0 0 auto; }
  /* scope to the header bar — the footer reuses .brand and must not inherit the
     compact/clipped header treatment. */
  .header-bar .brand { order: 1; flex: 0 1 auto; flex-direction: row; align-items: center; min-width: 0; max-width: 60%; overflow: hidden; text-align: left; }
  .header-bar .brand .brand-mark { display: block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .header-bar .brand, .header-bar .brand .brand-mark { font-size: .6rem; letter-spacing: .02em; }
  .header-bar .header-actions { order: 2; flex: 0 0 auto; margin-left: auto; gap: var(--sp-3); }
  .primary-nav { display: none; }
}

/* ============================================================================
   18.12 Product rows = horizontal swipe carousel on mobile/tablet
   Scoped to the CURATED rows only — home featured/new/popular/special blocks and
   PDP related / recently-viewed. The LISTING pages (category, new-products,
   best-sales, search) are deliberately excluded: they keep the desktop mosaic
   grid at every breakpoint (founder request) — see 18.4, which already steps
   4→3→2 columns and holds 2-up on phones. Home's "Produits populaires" renders a
   `.products.row` inside `.featured-products`, so the scoped selector still
   catches it while `#js-product-list .products.row` stays a grid.
   Full 2:3 image, ~2.3 cards per line, draggable.
   ============================================================================ */
@media (max-width: 991px) {
  .featured-products .products,
  ul.product_list {
    display: flex !important;
    grid-template-columns: none !important;
    flex-wrap: nowrap;
    /* MUST be flex-start: with overflow-x scroll, justify-content:center (from
       classic) centres the track and pushes the first card off-screen where it
       can't be scrolled back into view. */
    justify-content: flex-start !important;
    overflow-x: auto;
    scroll-snap-type: x proximity;
    scroll-padding-left: 0;
    overscroll-behavior-x: contain;   /* keep swipes from triggering browser back/forward */
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    gap: var(--sp-4);
    margin-left: 0 !important; margin-right: 0 !important;   /* neutralise Bootstrap .row */
  }
  .featured-products .products::-webkit-scrollbar { display: none; }
  /* ~2.3 cards per line (2 full + a peek) */
  .featured-products .products > *,
  ul.product_list > * {
    flex: 0 0 42% !important;
    max-width: 42% !important;
    scroll-snap-align: start;
  }
  /* Show the WHOLE photo at its natural aspect ratio — no crop; card height
     follows the image (board request). Carousel rows only: in the listing mosaic
     an uncropped image gives ragged, uneven-height tiles, so those keep 18.4's
     3/4 top-anchored crop that desktop uses. */
  .featured-products .product-card .product-thumbnail,
  .featured-products .product-card .media img,
  .featured-products .product-miniature .thumbnail img,
  ul.product_list .thumbnail img {
    aspect-ratio: auto !important;
    height: auto !important;
    object-fit: contain !important;
    object-position: center !important;
  }
  .featured-products .product-card .media,
  .featured-products .product-card .thumbnail { height: auto; }
}

/* ============================================================================
   18.13 "À propos" band (impabout module) — home
   Big picture LEFT, copy RIGHT on desktop; on mobile one column, so the copy
   stacks UNDER the picture. The template puts the <figure> first in the DOM, which
   IS the mobile order — so the mobile case needs no rules at all beyond the single
   column, and there is no duplicated markup or source-order trickery.
   ============================================================================ */
.about-band { padding-block: var(--sp-7); }
.about-grid { display: grid; grid-template-columns: 1fr; gap: var(--sp-5); align-items: center; }
@media (min-width: 992px) {
  /* Picture gets the larger share — it's the point of the band. */
  .about-grid { grid-template-columns: 1.15fr 1fr; gap: clamp(var(--sp-6), 5vw, var(--sp-8)); }
}
/* The merchant uploads whatever she has, so DON'T crop to a fixed ratio — show the
   photo at its natural proportions and just cap how tall it can get, so a very
   portrait shot can't run away with the page. */
.about-media { margin: 0; }
.about-media img {
  display: block; width: 100%; height: auto;
  max-height: 78vh; object-fit: cover; object-position: center;
  border-radius: var(--radius-lg); background: var(--c-cream-2);
}
.about-title { font-family: var(--font-display); font-size: var(--fs-h4); margin: 0 0 var(--sp-4); }
.about-text { color: var(--text-soft); font-size: var(--fs-200); line-height: 1.65; }
/* Rich text from the BO editor — keep its paragraphs/lists on-theme. */
.about-text > :first-child { margin-top: 0; }
.about-text > :last-child { margin-bottom: 0; }
.about-text p { margin: 0 0 var(--sp-4); }
.about-text a { color: var(--c-ink); text-decoration: underline; text-underline-offset: 3px; }
.about-text ul, .about-text ol { margin: 0 0 var(--sp-4); padding-left: 1.2em; }

/* ============================================================================
   19. PDP swipe gallery (product-cover-thumbnails override)
   Swipeable main image + dots + thumbnail strip, mobile & desktop.
   ============================================================================ */
.pdp-gallery { display: block; }
/* desktop: fill the left column but cap the height; left-aligned so there is no
   dead gap between the page edge and the image. */
@media (min-width: 992px) {
  .pdp-gallery { max-width: 500px; margin-left: 0; margin-right: auto; }
  /* Compact main image on desktop: 4/5 (top-anchored crop) instead of the full
     2/3 portrait, so the gallery doesn't tower over the buy-box. Mobile keeps 2/3
     (the whole photo). Specific selector so it wins over the base .pdp-slide. */
  .pdp-gallery .pdp-slide { aspect-ratio: 4 / 5; }
}
.pdp-gallery-main {
  display: flex; flex-wrap: nowrap; overflow-x: auto;
  scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; scrollbar-width: none;
  /* stop the browser back/forward gesture from eating one swipe direction */
  overscroll-behavior-x: contain;
  /* Keep the finger-swipe on the platform's own scroll physics. The global
     html{scroll-behavior:smooth} otherwise applies to THIS scroller too — iOS
     Safari ignores it for touch (native momentum), but Android Chrome honours
     it and animates every swipe, which fought the snap and made it clunky.
     Explicit dot/thumb taps still animate: JS calls scrollTo({behavior:'smooth'}). */
  scroll-behavior: auto;
  border-radius: var(--radius); background: var(--c-cream-2);
}
.pdp-slide-img { -webkit-user-drag: none; user-select: none; }
.pdp-gallery-main::-webkit-scrollbar { display: none; }
.pdp-slide {
  flex: 0 0 100%; max-width: 100%; margin: 0; scroll-snap-align: center;
  /* Advance exactly one image per swipe — without this a fast Android flick
     blows past 2–3 images and the mandatory snap yanks it back (the "clunky"
     overshoot). iOS<15 ignores it and just falls back to normal snap. */
  scroll-snap-stop: always;
  aspect-ratio: 2/3; overflow: hidden;
}
.pdp-slide picture { display: block; height: 100%; }
.pdp-slide-img {
  width: 100%; height: 100%; object-fit: cover; object-position: top center;
  display: block; background: var(--c-cream-2);
}
.pdp-dots { display: flex; justify-content: center; gap: 8px; margin-top: var(--sp-3); }
.pdp-dot { width: 8px; height: 8px; border-radius: 999px; border: 0; background: var(--c-sand); padding: 0; cursor: pointer; transition: transform .2s var(--ease), background .2s var(--ease); }
.pdp-dot.is-active { background: var(--c-ink); transform: scale(1.2); }
.pdp-thumbs { display: flex; gap: var(--sp-2); margin-top: var(--sp-3); overflow-x: auto; scrollbar-width: none; padding-bottom: 2px; }
.pdp-thumbs::-webkit-scrollbar { display: none; }
.pdp-thumb { flex: 0 0 auto; width: 64px; padding: 0; border: 1px solid var(--c-line); background: none; border-radius: var(--radius); overflow: hidden; cursor: pointer; transition: border-color .2s var(--ease); }
.pdp-thumb.is-active { border-color: var(--c-ink); }

/* Product video (impvideo) — the last slide of the gallery. Sized exactly like a photo
   slide so the scroll-snap track keeps one slide = one viewport-width. */
.pdp-slide--video { background: var(--c-cream-2); }
.pdp-slide-video {
  width: 100%; height: 100%; object-fit: cover; object-position: top center;
  display: block; background: var(--c-cream-2);
}
/* Gallery dots/thumbs are <button>s: keep the focus ring for keyboard users only, so a
   tap or click doesn't leave a system-blue box on the thumbnail (same rule as the
   mobile drawer's back arrow). */
.pdp-thumb:focus, .pdp-dot:focus { outline: none; }
.pdp-thumb:focus-visible, .pdp-dot:focus-visible {
  outline: 2px solid var(--c-ink); outline-offset: 2px;
}
/* Play badge on the video's thumbnail, so it's obvious which one moves.
   A bare white triangle was the first attempt and it read as nothing at all: at ~11px
   on a pale garment shot, white-on-white is invisible. It needs its own GROUND — a dark
   disc — so the icon holds up whatever photo sits behind it. Both pseudo-elements are
   centred with inset:0 + margin:auto. */
.pdp-thumb--video { position: relative; }
.pdp-thumb--video::before {
  content: ''; position: absolute; inset: 0; margin: auto;
  width: 26px; height: 26px; border-radius: 50%;
  background: rgba(16,43,38,.62);
  box-shadow: 0 0 0 1px rgba(255,255,255,.55), 0 1px 6px rgba(0,0,0,.3);
  transition: background .2s var(--ease);
}
.pdp-thumb--video::after {
  content: ''; position: absolute; inset: 0; margin: auto;
  width: 0; height: 0; border-style: solid;
  border-width: 6px 0 6px 10px;
  border-color: transparent transparent transparent #fff;
  /* a triangle's visual centre sits left of its bounding box — nudge it back */
  transform: translateX(2px);
}
.pdp-thumb--video:hover::before,
.pdp-thumb--video.is-active::before { background: var(--c-ink); }
.pdp-thumb img { width: 100%; aspect-ratio: 2/3; object-fit: cover; object-position: top center; display: block; }
@media (min-width: 992px) { .pdp-thumb { width: 72px; } }

/* ============================================================================
   20. Home full-screen hero + transparent→solid header (home only)
   The hero fills the viewport (full width + height) with the header floating
   transparently over it; the header turns solid white on scroll. Scoped to the
   home (body.page-index) so interior pages keep the normal solid header.
   ============================================================================ */
body.page-index #wrapper { padding-top: 0 !important; }
body.page-index #wrapper > .container,
body.page-index #content-wrapper { padding-top: 0; }

/* header overlays the hero */
body.page-index #header {
  position: absolute; top: 0; left: 0; right: 0; z-index: 500;
  background: transparent; border: 0; box-shadow: none;
}
body.page-index #header .site-header { position: static; background: transparent; border-bottom: 0; box-shadow: none; }
body.page-index #header .site-header .header-top, body.page-index #header .header-bar { border: 0; }
body.page-index #header .announce { background: transparent; color: #fff; }
/* transparent state: white chrome, legible via a soft shadow (no scrim gradient) */
body.page-index #header:not(.header-solid) .brand,
body.page-index #header:not(.header-solid) .brand-mark,
body.page-index #header:not(.header-solid) .header-action,
body.page-index #header:not(.header-solid) .nav-toggle,
body.page-index #header:not(.header-solid) #_desktop_top_menu a,
body.page-index #header:not(.header-solid) .announce { color: #fff !important; text-shadow: 0 1px 12px rgba(0,0,0,.35); }
body.page-index #header:not(.header-solid) .header-action .icon,
body.page-index #header:not(.header-solid) .nav-toggle .icon { filter: drop-shadow(0 1px 6px rgba(0,0,0,.4)); }
body.page-index #header:not(.header-solid) #_desktop_top_menu a:hover { color: var(--c-cream) !important; }
body.page-index #header:not(.header-solid) .cart-action .cart-count { background: #fff; color: var(--c-ink); }
/* Dual brand logo (AGE-73): a raster wordmark can't be recoloured by the
   `color:#fff` trick above, so we ship a dark + a cream variant and swap the
   asset by header state. Dark is the default (solid header, interior pages);
   the cream twin shows only while the header floats transparent over the hero.
   nav-open (dropdown solidifies the header) counts as solid → dark logo. */
/* Gate on BODY-level state (hdr-solid / hdr-navopen, set by custom.js), not on
   #header:not(...): the theme renders a duplicate id="header" (announce wrapper +
   inner .site-header), so an #header:not(.header-solid) selector still matches
   through the inner header that never receives the class, leaking the cream logo
   onto the solid white header. A body class is a single, unambiguous element. */
.brand__logo--light { display: none; }
body.page-index:not(.hdr-solid):not(.hdr-navopen) #header .brand__logo--dark { display: none; }
body.page-index:not(.hdr-solid):not(.hdr-navopen) #header .brand__logo--light { display: inline-block; }
/* Cream wordmark sits over bright golden-hour footage — give it a soft dark halo
   so it stays legible without a heavy header scrim.
   Keep the halo TIGHT. drop-shadow renders a shadow of the image's alpha, so a wide
   14px/.5 halo turned the old raster logo's faint keying residue into a visible grey
   BOX (that logo is now the clean SVG — see header.tpl — but a big halo also just
   reads as a smudge). One close, low-opacity shadow is enough for legibility. */
body.page-index:not(.hdr-solid):not(.hdr-navopen) #header .brand__logo--light {
  filter: drop-shadow(0 1px 3px rgba(0,0,0,.38));
}
/* dropdown links live on a white card — keep them dark even over the transparent hero */
body.page-index #header #_desktop_top_menu .sub-menu a { color: var(--c-ink) !important; text-shadow: none; }
body.page-index #header #_desktop_top_menu .sub-menu ul.top-menu[data-depth="2"] a { color: var(--c-mute) !important; }
body.page-index #header #_desktop_top_menu .sub-menu a:hover { color: var(--c-gold) !important; }

/* scrolled: SOLID WHITE header, BLACK text + icons, no line/gradient */
body.page-index #header.header-solid {
  position: fixed; top: 0; background: #fff; box-shadow: 0 1px 0 var(--c-line), 0 6px 20px rgba(16,43,38,.06); border: 0;
}
body.page-index #header.header-solid .site-header { background: #fff; }
body.page-index #header.header-solid .brand,
body.page-index #header.header-solid .brand-mark,
body.page-index #header.header-solid .header-action,
body.page-index #header.header-solid .nav-toggle,
body.page-index #header.header-solid #_desktop_top_menu a { color: var(--c-ink) !important; text-shadow: none; }
body.page-index #header.header-solid .header-action .icon,
body.page-index #header.header-solid .nav-toggle .icon { filter: none; }
body.page-index #header.header-solid .announce { display: none; }

/* mega-menu open over the transparent hero: solidify the header so the hovered
   label (and all chrome) stays legible instead of light-on-light against the
   white dropdown card. custom.js toggles .nav-open on hover. */
body.page-index #header.nav-open { background: #fff; box-shadow: 0 1px 0 var(--c-line), 0 6px 20px rgba(16,43,38,.06); }
body.page-index #header.nav-open .site-header { background: #fff; }
body.page-index #header.nav-open .brand,
body.page-index #header.nav-open .brand-mark,
body.page-index #header.nav-open .header-action,
body.page-index #header.nav-open .nav-toggle,
body.page-index #header.nav-open #_desktop_top_menu a { color: var(--c-ink) !important; text-shadow: none; }
body.page-index #header.nav-open #_desktop_top_menu ul.top-menu[data-depth="0"] > li:hover > a { color: var(--c-gold) !important; }
body.page-index #header.nav-open .header-action .icon,
body.page-index #header.nav-open .nav-toggle .icon { filter: none; }
body.page-index #header.nav-open .announce { display: none; }

/* full-bleed, full-height hero */
body.page-index .hero-band {
  width: 100vw; margin-left: calc(50% - 50vw); margin-top: 0;
  min-height: 100svh; display: flex; align-items: center; justify-content: center;
  text-align: center; border-bottom: 0;
}
body.page-index .hero-band .hero-inner { max-width: 720px; padding-block: 0; margin-inline: auto; }
body.page-index .hero-band h1 { margin-inline: auto; }
body.page-index .hero-band .hero-sub { margin-inline: auto; }
body.page-index .hero-band .eyebrow { color: rgba(255,255,255,.9); }
/* AGE-73 — brand-tagline hero (matches the reference): uppercase, letter-spaced
   tagline. */
body.page-index .hero-band h1 { text-transform: uppercase; letter-spacing: .14em;
  font-weight: 500; font-size: clamp(1.7rem, 4vw, 3.05rem); max-width: 18ch; }
body.page-index .hero-band .hero-sub { letter-spacing: .01em; }
/* nudge the centred copy below the floating header */
@media (min-width: 992px) { body.page-index .hero-band .hero-inner { padding-top: 40px; } }

/* ============================================================================
   AGE-73 — Scroll-scrubbing hero video
   A tall wrapper pins the hero (sticky) while the page scrolls through it;
   custom.js maps scroll progress → video.currentTime. The video + a gradient
   scrim replace the CSS background image so the copy stays legible over motion.
   Enhancement is gated on .has-hero-scrub (added by JS only when the video is
   seekable on a large, motion-OK viewport); otherwise the hero is a static
   full-height poster — identical to before.
   ============================================================================ */
body.page-index .hero-band { position: relative; overflow: hidden; }

body.page-index .hero-band .hero-img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  object-position: center; z-index: 0; pointer-events: none; background: var(--c-green);
}
/* Picture 2 cross-dissolves in over picture 1 as you scroll (JS drives opacity).
   It MUST start at 0 so the hero opens on picture 1. */
body.page-index .hero-band .hero-img--2 { opacity: 0; will-change: opacity; }
body.page-index .hero-band .hero-scrim {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  /* Light-touch legibility ONLY — it's a fashion hero, keep the clothes/photo
     visible. Soft dark at the very top (nav) + a whisper at the bottom (cue) and
     a faint halo behind the centred tagline; the middle stays clear. */
  background:
    linear-gradient(180deg, rgba(16,43,38,.40) 0%, rgba(16,43,38,0) 15%),
    linear-gradient(0deg,   rgba(16,43,38,.24) 0%, rgba(16,43,38,0) 18%),
    radial-gradient(80% 60% at 50% 50%, rgba(16,43,38,.18) 0%, rgba(16,43,38,0) 66%);
}
@media (max-width: 768px) {
  body.page-index .hero-band .hero-scrim {
    background:
      linear-gradient(180deg, rgba(16,43,38,.38) 0%, rgba(16,43,38,0) 24%, rgba(16,43,38,0) 58%, rgba(16,43,38,.5) 100%);
  }
}
body.page-index .hero-band .hero-inner { position: relative; z-index: 2; }

/* Pinned scrub: only on large viewports with motion allowed, and only once the
   video is confirmed seekable (JS adds .has-hero-scrub). */
@media (min-width: 992px) and (prefers-reduced-motion: no-preference) {
  body.page-index.has-hero-scrub .hero-scroll { height: 280vh; }
  body.page-index.has-hero-scrub .hero-band {
    position: sticky; top: 0; height: 100svh; min-height: 100svh; width: 100vw;
    margin-left: calc(50% - 50vw);
  }
}

/* Scroll cue — a soft bouncing indicator, hidden once the hero is scrubbed away. */
body.page-index .hero-scrollcue {
  position: absolute; left: 50%; bottom: 26px; z-index: 2; transform: translateX(-50%);
  width: 22px; height: 34px; border: 1.5px solid rgba(255,255,255,.7); border-radius: 12px;
  pointer-events: none;
}
body.page-index .hero-scrollcue::after {
  content: ""; position: absolute; left: 50%; top: 7px; width: 3px; height: 7px;
  margin-left: -1.5px; border-radius: 2px; background: rgba(255,255,255,.9);
  animation: heroCue 1.8s var(--ease, ease) infinite;
}
@keyframes heroCue { 0%{ transform: translateY(0); opacity: 1 } 70%{ transform: translateY(10px); opacity: 0 } 100%{ opacity: 0 } }
@media (prefers-reduced-motion: reduce) { body.page-index .hero-scrollcue::after { animation: none; } }
/* Keep the transparent header pinned over the hero (it is otherwise absolute and
   would scroll away with the hero). initTransparentHeader flips it to solid-white
   once the hero has scrolled past. (Previously gated on .has-hero-scrub, which is
   no longer added now the scroll-scrub is disabled — 2026-07-08.) */
body.page-index #header:not(.header-solid) { position: fixed; }

/* ============================================================================
   22. Mobile category drawer (burger menu)
   Full-screen drawer of sliding panels, built by custom.js initMobileNav from
   the live ps_mainmenu tree. One panel per category-with-children: the root
   slides in from the left, each sub-panel slides in from the right over it.
   ============================================================================ */
/* `visibility` keeps the closed drawer and the inactive panels out of the tab
   order. It is transitioned with a DELAY, not a duration: hiding waits for the
   slide to finish (so the element stays painted on its way out), showing flips
   instantly. A duration would instead leave `visibility` computing to `hidden`
   at progress 0 — which silently makes .focus() a no-op on the frame we open a
   panel, so keyboard focus would fall back to <body>. */
/* Hidden by default and switched ON inside the burger range (below), rather than
   switched off above it — one condition to keep in sync instead of its inverse. */
.mobile-drawer {
  position: fixed; inset: 0; z-index: 1300;
  background: var(--surface);
  display: none; flex-direction: column;
  transform: translateX(-100%); visibility: hidden;
  transition: transform .3s var(--ease), visibility 0s linear .3s;
}
@media (max-width: 1023px), (max-width: 1024px) and (orientation: portrait) {
  .mobile-drawer { display: flex; }   /* burger range */
}
.mobile-drawer.is-open {
  transform: none; visibility: visible;
  transition: transform .3s var(--ease), visibility 0s;
}

.mobile-drawer__head {
  flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-4); padding: var(--sp-4) var(--sp-5);
}
.mobile-drawer__brand img { display: block; height: 30px; width: auto; }
.mobile-drawer__close { background: none; border: 0; padding: 6px; line-height: 0; color: var(--c-ink); }
.mobile-drawer__close .icon { width: 26px; height: 26px; }

/* `overflow: hidden` clips the off-screen panels but STILL makes this a scroll
   container, and their translateX(±100%) leaves it with a scrollWidth twice its
   width — so anything that scrolls it (notably the browser auto-scrolling to reveal
   a freshly-focused control) drags the whole panel track sideways. `overflow: clip`
   clips WITHOUT creating a scroll container, killing the bug at the root; `hidden`
   stays as the fallback for engines without clip (older iOS), where the JS
   preventScroll + scrollLeft pin in initMobileNav covers it. */
.mobile-drawer__viewport { position: relative; flex: 1 1 auto; overflow: hidden; overflow: clip; }
.mobile-drawer__panel {
  position: absolute; inset: 0; overflow-y: auto; -webkit-overflow-scrolling: touch;
  background: var(--surface); padding: var(--sp-4) var(--sp-5) var(--sp-7);
  transform: translateX(100%); visibility: hidden;
  transition: transform .3s var(--ease), visibility 0s linear .3s;
}
.mobile-drawer__panel.is-active { transform: none; }
/* The `visibility: visible` MUST be gated on the drawer being open. Unscoped, the
   active panel re-shows itself out of the closed drawer's inherited `hidden` — its
   rows stay focusable, so tabbing off the end of the page lands in an off-screen
   menu. */
.mobile-drawer.is-open .mobile-drawer__panel.is-active {
  visibility: visible;
  transition: transform .3s var(--ease), visibility 0s;
}
.mobile-drawer__panel.is-past { transform: translateX(-100%); }
@media (prefers-reduced-motion: reduce) {
  .mobile-drawer, .mobile-drawer.is-open,
  .mobile-drawer__panel, .mobile-drawer__panel.is-active { transition: none; }
}

.mobile-drawer__back { background: none; border: 0; padding: var(--sp-3) 0; line-height: 0; color: var(--c-ink); }
.mobile-drawer__back .icon { width: 28px; height: 28px; }
/* Opening a panel moves focus to its back arrow (for screen readers / keyboard).
   Safari then paints its default focus ring even though the user TAPPED — so show a
   ring only for real keyboard focus, and make it on-brand rather than system blue. */
.mobile-drawer__back:focus, .mobile-drawer__row:focus { outline: none; }
.mobile-drawer__back:focus-visible, .mobile-drawer__row:focus-visible {
  outline: 2px solid var(--c-ink); outline-offset: 2px; border-radius: 4px;
}
.mobile-drawer__title {
  font-family: var(--font-display); font-size: var(--fs-h4); line-height: 1.1;
  margin: var(--sp-3) 0 var(--sp-5); color: var(--c-ink);
}

.mobile-drawer__list { list-style: none; margin: 0; padding: 0; }
.mobile-drawer__list li { margin: 0; border-top: 1px solid var(--c-line); }
.mobile-drawer__list li:last-child { border-bottom: 1px solid var(--c-line); }
.mobile-drawer__row {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3);
  width: 100%; padding: var(--sp-4) 0; background: none; border: 0; text-align: left;
  font-family: var(--font-logo); font-weight: 600; font-size: var(--fs-75);
  letter-spacing: .1em; text-transform: uppercase; color: var(--c-ink);
}
a.mobile-drawer__row:hover { text-decoration: none; }
.mobile-drawer__row .icon { flex: 0 0 auto; width: 20px; height: 20px; }
.mobile-drawer__all {
  display: inline-block; margin-top: var(--sp-5); padding-bottom: 3px;
  font-family: var(--font-logo); font-weight: 700; font-size: var(--fs-75);
  letter-spacing: .1em; text-transform: uppercase; color: var(--c-ink);
  border-bottom: 1px solid var(--c-ink);
}
.mobile-drawer__all:hover { text-decoration: none; }
.mobile-drawer__foot { margin-top: var(--sp-7); }
.mobile-drawer__account { display: inline-flex; align-items: center; gap: var(--sp-3); color: var(--text); font-size: var(--fs-100); }
.mobile-drawer__account .icon { width: 22px; height: 22px; }


/* ============================================================================
   23. Store locator (/magasins — cms/stores.tpl)
   Clean card list; the classic markup is Bootstrap cols, so lay each store out
   with flexbox and style the hours table to match the theme.
   ============================================================================ */
.page-stores { display: flex; flex-direction: column; gap: var(--sp-5); }
.page-stores .store-item {
  border: 1px solid var(--c-line); border-radius: var(--radius-lg); background: var(--surface);
  padding: var(--sp-6); overflow: hidden;
}
.page-stores .store-item-container { display: flex; flex-wrap: wrap; gap: var(--sp-6); align-items: flex-start; }
.page-stores .store-picture { flex: 0 0 200px; max-width: 200px; }
.page-stores .store-picture img { width: 100%; height: auto; border-radius: var(--radius); display: block; }
.page-stores .store-description { flex: 1 1 260px; min-width: 0; }
.page-stores .store-description .card-title { font-family: var(--font-display); font-size: var(--fs-h5); margin: 0 0 var(--sp-2); }
.page-stores .store-description address { color: var(--c-muted); font-style: normal; line-height: 1.6; margin: 0 0 var(--sp-3); }
.page-stores .store-description a[data-toggle] { display: inline-flex; align-items: center; gap: 4px; color: var(--c-ink); font-size: var(--fs-75); }
.page-stores .store-description a[data-toggle]:hover { color: var(--c-gold); text-decoration: none; }
.page-stores .store-hours { flex: 1 1 240px; min-width: 0; }
.page-stores .store-hours table { width: 100%; border-collapse: collapse; }
.page-stores .store-hours th { text-align: left; font-family: var(--font-body); font-weight: 600; color: var(--c-ink); padding: 3px 0; font-size: var(--fs-75); }
.page-stores .store-hours td { text-align: right; color: var(--c-muted); padding: 3px 0; font-size: var(--fs-75); }
.page-stores .store-hours ul { list-style: none; margin: 0; padding: 0; }
.page-stores .store-item-footer { border-top: 1px solid var(--c-line); margin-top: var(--sp-5); padding-top: var(--sp-4); }
.page-stores .store-item-footer ul { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-6); }
.page-stores .store-item-footer li { display: inline-flex; align-items: center; gap: 6px; color: var(--c-mute); font-size: var(--fs-75); }
@media (max-width: 767px) { .page-stores .store-hours { flex-basis: 100%; } }

/* ============================================================================
   Cookie-consent banner (AGE-47)
   Bottom notice mirroring the source site's cookie banner; text links to the
   Politique de confidentialité CMS page. Shown/dismissed by custom.js
   (initCookieBanner), hidden entirely without JS. Sits below modals (1300).
   ============================================================================ */
.cookie-banner {
  position: fixed; inset: auto 0 0 0; z-index: 1250;
  background: var(--surface); border-top: 1px solid var(--c-line); box-shadow: var(--shadow);
}
.cookie-banner__inner { display: flex; flex-wrap: wrap; gap: var(--sp-3) var(--sp-6); align-items: center; padding-top: var(--sp-4); padding-bottom: var(--sp-4); }
.cookie-banner__text { flex: 1 1 420px; margin: 0; font-size: var(--fs-75); color: var(--c-muted); }
.cookie-banner__text b { color: var(--c-ink); }
.cookie-banner__text a { color: var(--c-ink); text-decoration: underline; }
.cookie-banner__text a:hover { color: var(--c-gold); }
.cookie-banner__actions { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin: 0; }
/* On phones the two long labels ("Continuer sans accepter" / "J'accepte") don't
   fit side by side and the accept button ran off the right edge — stack them
   full-width so both stay on-screen and tappable. */
@media (max-width: 767px) {
  .cookie-banner__actions { flex-direction: column; width: 100%; }
  .cookie-banner__actions .btn { width: 100%; }
}

/* ============================================================================
   §21 Checkout form validation visibility (QA C4)
   Classic renders required checkboxes (CGV, confidentialité RGPD) as an
   opacity-0 native input under a styled <span>. Native browser validation
   blocks the submit, but the transient bubble is easy to miss and the custom
   box shows no invalid state — the form just "does nothing". After a failed
   submit attempt (:user-invalid), flag the box and its label; also mark
   required checkboxes with an asterisk so the constraint is visible upfront.
   ============================================================================ */
label:has(> input[type="checkbox"][required])::after {
  content: " *"; color: #b02a2f; font-weight: 600;
}
label > input[type="checkbox"]:user-invalid + span {
  box-shadow: 0 0 0 2px #b02a2f; border-radius: 3px;
}
label:has(> input[type="checkbox"]:user-invalid) {
  color: #b02a2f;
}

/* ============================================================================
   §22 Listing infinite scroll (custom.js initInfiniteScroll)
   Progressive enhancement over classic's numbered pagination. The <nav> stays in
   the DOM — crawlers keep following the rel=next/page links, and with JS off the
   numbered buttons are the visible control. When the script takes over it adds
   `.has-infinite`, which swaps the page-list for a sentinel button that an
   IntersectionObserver auto-triggers as it nears the viewport.
   ============================================================================ */
#js-product-list.has-infinite nav.pagination .page-list { display: none; }
/* the page-list's bootstrap column collapses to nothing — drop its offset so the
   "Affichage 1-24 de 38" counter isn't stranded against the left gutter. */
#js-product-list.has-infinite nav.pagination > div[class*="offset-"] { margin-left: 0; }
#js-product-list.has-infinite nav.pagination { justify-content: center; }

.inf-more-wrap { display: flex; flex-direction: column; align-items: center; gap: var(--sp-3); padding-block: var(--sp-5); }
/* .btn sets display:inline-flex, which outranks the UA's [hidden] rule */
.inf-more[hidden] { display: none; }
.inf-status { font-size: var(--fs-75); color: var(--text-soft); min-height: 1.2em; text-align: center; margin: 0; }
.inf-spinner {
  width: 22px; height: 22px; border-radius: 50%;
  border: 2px solid var(--c-line); border-top-color: var(--c-ink);
  animation: inf-spin .7s linear infinite;
}
.inf-spinner[hidden] { display: none; }
@keyframes inf-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .inf-spinner { animation-duration: 2s; }
}
