/* ==========================================================================
   BERCI · shared design system  —  SF Pro, black / white, generous whitespace
   ========================================================================== */
:root{
  --ink:#0A0A0A; --paper:#FFFFFF;
  --g1:#16171A; --g2:#3A3D42; --g3:#6E7278; --g4:#A6AAAF; --g5:#D9DBDE;
  --g6:#EFF0F1; --g7:#F6F7F8; --edge:#E7E8EA;
  --ok:#0B7A46; --ok-bg:#E9F6EE; --warn:#8A6D0B; --warn-bg:#FBF3D9; --err:#B4231F; --err-bg:#FCECEB;
  --r:14px; --r-lg:20px;
  --font:-apple-system,"SF Pro Display","SF Pro Text",BlinkMacSystemFont,"Segoe UI","Helvetica Neue",Arial,sans-serif;
  --shadow-1:0 1px 2px rgba(16,24,40,.05),0 1px 3px rgba(16,24,40,.06);
  --shadow-2:0 12px 30px -16px rgba(16,24,40,.18);
  --shadow-3:0 30px 60px -30px rgba(16,24,40,.28);
}
*{box-sizing:border-box;margin:0;padding:0}
/* A deliberate, on-brand focus ring everywhere — never the browser default blue */
:focus-visible{outline:2px solid var(--ink);outline-offset:2px}
html{-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}
body{font-family:var(--font);color:var(--ink);background:var(--paper);line-height:1.5;letter-spacing:-.011em}

/* Cross-page continuity — a static multi-page site with no framework/router,
   so this is deliberately platform-native rather than a hand-rolled SPA
   transition: browsers that support cross-document view transitions
   (Chrome/Edge) get a real, free cross-fade between pages; everyone else
   just gets a normal navigation plus the quiet fade-in below. Zero JS,
   zero risk — an unsupported browser simply ignores the rule. */
@view-transition{navigation:auto}
main{animation:berci-arrive .4s ease both}
@keyframes berci-arrive{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){main{animation:none}}

/* Chrome/Edge's default cross-document view-transition is a plain cross-
   fade — replacing its two halves with the same fade+rise language as
   berci-arrive above makes a shortcut tap and the page it opens read as
   one continuous motion instead of two unrelated effects stitched together. */
@media not (prefers-reduced-motion:reduce){
  ::view-transition-old(root){animation:berci-vt-out .18s ease both}
  ::view-transition-new(root){animation:berci-vt-in .32s ease both}
}
@keyframes berci-vt-out{to{opacity:0}}
@keyframes berci-vt-in{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}

/* A brief, deliberate "pressed" hold — applied by JS just before a shortcut
   or card navigates away, so the tap reads as acknowledged rather than the
   page abruptly changing underneath the finger. See pressThenGo() in
   berci.js. */
.cat-card.pressed{transform:translateY(-1px) scale(.98);background:var(--g7);transition:transform .1s ease,background .1s ease}
.pcard.pressed{transform:scale(.98);box-shadow:none;transition:transform .1s ease,box-shadow .1s ease}
@media(prefers-reduced-motion:reduce){
  .cat-card.pressed,.pcard.pressed{transform:none}
}

/* Search-active — the moment typing begins, the page transforms in place:
   no navigation, no reload. Purely editorial/browsing sections disappear,
   leaving only the search field and results — nothing else, on every
   viewport. This is a plain, instant display:none, deliberately NOT
   animated: an earlier version animated this collapse (opacity + max-
   height) and it was the real cause of "the page pops/shifts when I tap
   search" — an animated height change competing with the keyboard's own
   animation reads as instability, not calm. Apple's App Store search
   doesn't animate its Suggested/Browse content away either; it just swaps.
   Nothing here ever scrolls the page, either — whatever the visitor was
   looking at stays exactly where it was. Scoped to body.search-active so
   it never touches product/account pages, which don't use these ids. */
body.search-active .hero,
body.search-active #dejaprepare,
body.search-active #home-extra,
body.search-active #pourquoi,
body.search-active #needsearch,
body.search-active #categories,
body.search-active #home-popular{
  display:none;
}
a{color:inherit;text-decoration:none}
img{max-width:100%;display:block}
.wrap{max-width:1120px;margin:0 auto;padding:0 24px}
.muted{color:var(--g3)}
.mono-num{font-variant-numeric:tabular-nums}
.hide{display:none!important}

/* Mark */
.mark{display:inline-flex;border-radius:22.5%;background:var(--ink);overflow:hidden;flex:none}
.mark.lite{background:#fff;border:1px solid var(--edge)}
.wordmark{font-weight:600;letter-spacing:.12em}

/* Header */
.hdr{position:sticky;top:0;z-index:40;background:rgba(255,255,255,.8);backdrop-filter:saturate(160%) blur(14px);border-bottom:1px solid var(--edge)}
.hdr .bar{display:flex;align-items:center;gap:32px;height:76px}
.brand{display:flex;align-items:center;gap:11px;flex:none}
.brand .mark{width:34px;height:34px;transition:transform .2s cubic-bezier(.2,.7,.2,1)}
.brand:hover .mark{transform:scale(1.04)}
.brand .wordmark{font-size:19px}
.spacer{flex:1}

.nav-links{display:flex;align-items:center;gap:28px;font-size:14px;font-weight:400;color:var(--g3);flex:none}
.nav-links a{position:relative;transition:color .2s}
.nav-links a:hover{color:var(--ink)}
@media(max-width:900px){.nav-links{display:none}}
/* Below 900px these text anchors (Catégories/Nouveautés/Incontournables)
   are the one thing genuinely safe to drop — they're page anchors,
   redundant with scrolling and search, not "essential actions." Favoris,
   Panier, langue and Se connecter are never hidden; see the mobile header
   rules further down, which reflow the bar into two rows instead. */

/* Search — a deliberate, handcrafted control, fully independent from the
   brand mark and nav links (its own block, its own breathing room). Same
   36px height and 14px radius as every other nav control for perfect
   baseline alignment. Every property below is scoped through `.search-wrap`
   so it can never lose a specificity fight with the generic `.input` rule
   later in this file — that exact collision was why the icon and the
   placeholder text used to overlap. A quiet keyboard-shortcut hint fades
   the moment you start typing — the kind of detail a real product team
   sweats over. */
.search-wrap{position:relative;flex:1;min-width:0;max-width:320px;margin-left:auto}
.search-wrap .search-icon{position:absolute;left:14px;top:50%;transform:translateY(-50%);width:16px;height:16px;color:var(--g4);pointer-events:none;transition:color .2s}
.search-wrap .search-input{height:36px;width:100%;padding:0 40px 0 40px;border-radius:var(--r);border:1px solid var(--edge);background:var(--g7);font-size:13.5px;color:var(--ink);line-height:36px}
.search-wrap .search-input::placeholder{color:var(--g4)}
.search-wrap .search-input:hover{border-color:var(--g4)}
.search-wrap .search-input:focus{background:#fff;border-color:var(--ink);box-shadow:0 0 0 3px rgba(10,10,10,.06)}
.search-wrap .search-input:focus ~ .search-icon{color:var(--g2)}
.search-kbd{position:absolute;right:10px;top:50%;transform:translateY(-50%);height:20px;min-width:20px;padding:0 6px;
  display:flex;align-items:center;justify-content:center;border-radius:6px;background:#fff;border:1px solid var(--edge);
  font-family:inherit;font-size:11px;font-weight:600;color:var(--g4);pointer-events:none;transition:opacity .2s}
.search-wrap .search-input:focus ~ .search-kbd{opacity:0}
@media(max-width:640px){
  .search-kbd{display:none}
  /* iOS Safari auto-zooms the page the instant a focused input's font-size
     is under 16px — a hard platform rule, not a heuristic. #search is the
     one real, always-focusable input on mobile (see the comment above), so
     it was silently triggering that zoom on every focus. Whether it read
     as a visible "jump" varied with the device's own remembered zoom level
     and accessibility text-size settings — which is exactly the kind of
     same-device, different-day inconsistency this was mistaken for a
     scroll bug for two rounds running. 16px removes the trigger outright. */
  .search-wrap .search-input{padding-right:16px;font-size:16px}
}

/* Large search block — the homepage/Discovery-page "De quoi avez-vous besoin
   ?" entry point. Same component, same rounded-pill scale already used for
   .btn-lg, just a bigger instance — not a new visual language. */
.search-wrap-lg{max-width:640px;margin:0 auto;flex:none}
.search-wrap-lg .search-input{height:58px;padding:0 24px 0 52px;font-size:16px;border-radius:999px;
  background:#fff;box-shadow:var(--shadow-1)}
.search-wrap-lg .search-input:focus{box-shadow:0 0 0 4px rgba(10,10,10,.06)}
.search-wrap-lg .search-icon{left:22px;width:19px;height:19px}

/* The hero "search box" is not a second real input — it's a tappable proxy
   for the one true input living in the sticky nav bar (#search). Search
   must never be interrupted: two focusable text fields meant syncing value
   between them, which meant something had to lose focus (or get hidden
   mid-keystroke, closing the keyboard) the moment either one changed state.
   One real input, always mounted, never hidden while it might be focused —
   this button just points at it. */
.needinput-proxy{appearance:none;-webkit-appearance:none;text-align:left;font-family:inherit;cursor:text;
  display:flex;align-items:center}
.needinput-proxy .needinput-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ink)}
.needinput-proxy .needinput-text.placeholder{color:var(--g4)}
.needinput-proxy:hover{border-color:var(--g4)}
.needinput-proxy:focus-visible{outline:2px solid var(--ink);outline-offset:2px}

/* A single brief pulse on arrival when the Discovery page has actually
   carried something over from the homepage (?q= or ?goal=) — the visual
   confirmation that "yes, what you asked for followed you here." Fires
   once, never loops — a loop would read as nagging, not continuity. */
@keyframes berci-arrive-pulse{0%{box-shadow:0 0 0 0 rgba(10,10,10,.14)}100%{box-shadow:0 0 0 12px rgba(10,10,10,0)}}
.berci-arrive-pulse{animation:berci-arrive-pulse .9s ease-out}
@media (prefers-reduced-motion:reduce){.berci-arrive-pulse{animation:none}}

.nav-utility{display:flex;align-items:center;gap:8px;flex:none}
/* Never hidden — Favoris, Panier, langue and Se connecter stay reachable
   at every width. This one used to disappear below 900px entirely (a real
   bug: essential navigation vanishing along with the merely-decorative
   nav-links); the mobile header rules below give it room instead. */

/* Utility icon buttons — favorites, downloads. Same radius as search/inputs
   (14px) since they share a row and a height — one visual system, not two. */
.nav-icon-btn{position:relative;width:36px;height:36px;display:flex;align-items:center;justify-content:center;
  border-radius:var(--r);border:none;background:none;color:var(--g3);cursor:pointer;transition:.2s cubic-bezier(.2,.7,.2,1)}
.nav-icon-btn:hover{color:var(--ink);background:var(--g7);transform:translateY(-1px)}
.nav-icon-btn svg{width:19px;height:19px;fill:none;stroke:currentColor;stroke-width:1.5}
.nav-icon-count{position:absolute;top:1px;right:1px;min-width:15px;height:15px;padding:0 3px;border-radius:999px;
  background:var(--ink);color:#fff;font-size:9.5px;font-weight:700;display:flex;align-items:center;justify-content:center;line-height:1}

.lang-select{position:relative}
.lang-btn{display:flex;align-items:center;gap:5px;height:36px;padding:0 11px;border-radius:999px;border:1px solid transparent;
  background:none;font-family:inherit;font-size:13px;font-weight:600;color:var(--g3);cursor:pointer;transition:.2s}
.lang-btn:hover{color:var(--ink);background:var(--g7)}
.lang-btn svg{transition:transform .2s cubic-bezier(.2,.7,.2,1)}
.lang-select.open .lang-btn{color:var(--ink);background:var(--g7)}
.lang-select.open .lang-btn svg{transform:rotate(180deg)}
.lang-menu{position:absolute;top:calc(100% + 8px);right:0;background:#fff;border:1px solid var(--edge);border-radius:12px;
  box-shadow:var(--shadow-2);padding:6px;min-width:140px;opacity:0;pointer-events:none;transform:translateY(-4px);transition:.16s cubic-bezier(.2,.7,.2,1)}
.lang-select.open .lang-menu{opacity:1;pointer-events:auto;transform:none}
.lang-option{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:8px 10px;border-radius:8px;font-size:13px;font-weight:500;color:var(--ink)}
.lang-option.on::after{content:"✓";color:var(--g3);font-size:12px}

.nav-signin{font-size:14px;font-weight:500;color:var(--g3);transition:color .2s}
.nav-signin:hover{color:var(--ink)}

.nav-divider{width:1px;height:22px;background:var(--edge);flex:none}
@media(max-width:900px){.nav-divider{display:none}}

/* Mobile header — logo and essential actions (Favoris, Panier, langue,
   Se connecter) stay on one compact row; the search bar, no longer
   squeezed into whatever space is left, wraps onto its own full-width
   row right below. Priority order stays exactly logo -> search ->
   essential actions, just across two rows instead of a single cramped
   one. Pure flex-wrap, no JS, nothing to keep in sync. */
@media(max-width:760px){
  .hdr .bar{flex-wrap:wrap;height:auto;padding:10px 0;row-gap:8px;column-gap:12px}
  .nav-utility{margin-left:auto;gap:4px}
  .nav-icon-btn{width:32px;height:32px}
  .lang-btn{padding:0 8px;height:32px}
  .nav-signin{font-size:13px}
  .search-wrap{order:10;flex:1 1 100%;max-width:none;margin-left:0}
}
@media(max-width:480px){.wrap{padding:0 16px}}

/* While typing on mobile, the header switches from sticky to fixed so it
   can never be dragged around by the reflow-based repositioning sticky
   elements are prone to when Safari's keyboard changes the viewport — it
   just stays pinned to the top of the screen. berci.js compensates by
   padding body by the header's own (measured) height, so nothing jumps the
   instant it leaves normal document flow. See pinHeaderForSearch(). */
@media(max-width:760px){
  body.search-active .hdr{position:fixed;top:0;left:0;right:0}
}

/* Buttons */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;height:40px;padding:0 18px;border-radius:999px;
  font-family:inherit;font-size:14px;font-weight:500;border:1px solid transparent;cursor:pointer;
  transition:background .2s,border-color .2s,color .2s,transform .2s cubic-bezier(.2,.7,.2,1),box-shadow .2s;white-space:nowrap;background:none}
.btn:active{transform:scale(.98)}
.btn-primary{background:var(--ink);color:#fff}
.btn-primary:hover{background:#26282c;transform:translateY(-1px);box-shadow:var(--shadow-1)}
.btn-ghost{color:var(--ink);border-color:var(--edge);background:#fff}
.btn-ghost:hover{border-color:var(--g4);transform:translateY(-1px);box-shadow:var(--shadow-1)}
.btn-quiet{color:var(--g2)}
.btn-quiet:hover{background:var(--g6)}
.btn-danger{color:var(--err);border-color:var(--edge);background:#fff}
.btn-danger:hover{background:var(--err-bg);border-color:#f3c9c7}
.btn-sm{height:32px;padding:0 12px;font-size:13px}
.btn:disabled{opacity:.45;cursor:not-allowed}
.btn-block{width:100%}

/* Inputs */
.field{display:block;margin-bottom:16px}
.field > label{display:block;font-size:13px;font-weight:600;margin-bottom:6px}
.field .hint{font-size:12px;color:var(--g4);margin-top:6px}
.input,.select,.textarea{width:100%;font-family:inherit;font-size:14px;color:var(--ink);background:#fff;
  border:1px solid var(--g5);border-radius:12px;padding:11px 13px;outline:none;transition:.2s}
.input:focus,.select:focus,.textarea:focus{border-color:var(--ink);box-shadow:0 0 0 3px rgba(10,10,10,.06)}
.textarea{resize:vertical;min-height:96px;line-height:1.55}
.select{appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M3 4.5 6 7.5 9 4.5' fill='none' stroke='%236E7278' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 13px center;padding-right:34px}

/* Chips */
.chips{display:flex;gap:8px;flex-wrap:wrap}
.chip{height:34px;padding:0 14px;border-radius:999px;border:1px solid var(--edge);background:#fff;color:var(--g2);
  font-size:13px;font-weight:500;cursor:pointer;display:inline-flex;align-items:center;transition:.2s;white-space:nowrap}
.chip:hover{border-color:var(--g4)}
.chip.on{background:var(--ink);color:#fff;border-color:var(--ink)}


/* Badges */
.badge{display:inline-flex;align-items:center;gap:6px;height:22px;padding:0 9px;border-radius:999px;font-size:12px;font-weight:600}
.badge-live{background:var(--ok-bg);color:var(--ok)}
.badge-draft{background:var(--g6);color:var(--g3)}

/* Product grid + cards */
.grid{display:grid;grid-template-columns:repeat(4,1fr);gap:22px}
@media(max-width:1000px){.grid{grid-template-columns:repeat(3,1fr)}}
@media(max-width:760px){.grid{grid-template-columns:repeat(2,1fr);gap:28px 14px}}
/* A magazine cover, not a mini product page: the hover exists only to
   confirm the card is interactive — a barely-there lift, a touch more
   shadow, nothing that explains or reveals. No expanding panel, no
   information before the click; curiosity belongs here, understanding
   belongs on product.html. Apple-level restraint: if this animation is
   memorable, it's too much. */
.pcard{position:relative;border:1px solid var(--edge);border-radius:var(--r-lg);background:#fff;overflow:hidden;cursor:pointer;
  transition:transform .25s cubic-bezier(.16,1,.3,1),box-shadow .25s cubic-bezier(.16,1,.3,1),border-color .25s;
  display:flex;flex-direction:column}
.pcard:hover{transform:scale(1.015);box-shadow:var(--shadow-2);border-color:var(--g5)}
.pcard:active{transform:scale(1.005)}
@media(prefers-reduced-motion:reduce){
  .pcard,.pcard:hover{transition:none;transform:none}
}
/* The preview is the hero of the card — roughly 70–75% of its height — so
   the catalogue reads as a wall of previews, not a wall of text. Landscape
   proportions suit what actually lives here: document covers, slide
   previews, screenshots, dashboards. */
.pthumb{position:relative;aspect-ratio:4/3;background:var(--g7);display:flex;align-items:center;justify-content:center;
  overflow:hidden;border-radius:var(--r-lg) var(--r-lg) 0 0}
.pthumb img{width:100%;height:100%;object-fit:cover;transition:transform .2s cubic-bezier(.2,.7,.2,1)}
.pcard:hover .pthumb img{transform:scale(1.02)}
.pthumb .ph{width:34%;opacity:.14;transition:opacity .2s}
.pcard:hover .pthumb .ph{opacity:.2}

/* Save/bookmark toggle — top-right of the thumbnail, mirrors badges on the left */
.pfav{position:absolute;top:10px;right:10px;z-index:2;width:30px;height:30px;border-radius:999px;border:none;
  background:rgba(255,255,255,.92);backdrop-filter:blur(6px);display:flex;align-items:center;justify-content:center;
  color:var(--g3);cursor:pointer;box-shadow:var(--shadow-1);transition:.2s cubic-bezier(.2,.7,.2,1)}
.pfav:hover{color:var(--ink);transform:scale(1.08)}
.pfav.on{color:var(--ink)}
.pfav svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:1.7;transition:fill .2s}
.pfav.on svg{fill:currentColor}

/* Elegant metadata badges — scan instantly across a catalogue of thousands */
.pbadges{position:absolute;top:10px;left:10px;z-index:1;display:flex;flex-direction:column;gap:6px;align-items:flex-start}
.pbadge{height:24px;padding:0 10px;border-radius:999px;
  font-size:11px;font-weight:700;letter-spacing:.01em;display:inline-flex;align-items:center;
  background:rgba(255,255,255,.92);backdrop-filter:blur(6px);color:var(--ink);box-shadow:var(--shadow-1)}
.pbadge-new{background:var(--ink);color:#fff}

/* Floating price capsule — the price lives on the preview now, not in a
   footer row, so the body below can stay to category/title/description
   only, with nothing duplicated. */
.pprice-cap{position:absolute;bottom:10px;right:10px;z-index:2;height:28px;padding:0 12px;border-radius:999px;
  background:rgba(255,255,255,.92);backdrop-filter:blur(6px);box-shadow:var(--shadow-1);
  display:inline-flex;align-items:center;font-size:13px;font-weight:700;color:var(--ink)}

.pbody{padding:18px 18px 20px;display:flex;flex-direction:column;gap:4px;flex:1}
.pcat{font-size:11px;font-weight:600;letter-spacing:.09em;text-transform:uppercase;color:var(--g4)}
.ptitle{font-size:14.5px;font-weight:600;letter-spacing:-.01em;line-height:1.35}

/* BERCI's identity: two quiet, always-visible editorial lines — the work
   that's already done, then the recurring frustration that disappears.
   Never specifications, never an editing instruction, never hover-gated.
   Generous space above so the pair reads as a natural continuation of the
   title, not as metadata bolted underneath it. The promise is the point of
   the card, so it carries real weight — closer in size to the title than
   to a caption, ink rather than a muted grey — and the preview above it
   stays in support, not competition. */
.pworkflow{margin-top:12px;display:flex;flex-direction:column;gap:4px}
.pworkflow-state{font-size:14px;font-weight:600;line-height:1.45;color:var(--ink)}
.pworkflow-action{font-size:13.5px;line-height:1.45;color:var(--g3)}

/* Mobile card — a small discovery tile, not a shrunk desktop card and not
   the one-at-a-time full-width card from the previous pass either. The
   homepage is for discovery, not evaluation: browsing should feel like the
   App Store (many products per screen, each easy to scan while scrolling),
   with previews/ratings/pricing detail saved for product.html. So on
   mobile the card drops to cover + title + one sentence — nothing else.
   The cover is deliberately inset and smaller than the card (not full-
   bleed) and now smaller still: it introduces the product, but typography
   is the strongest element on the card, not the image — the title reads
   first, bold and a touch larger, and the promise gets real body-text
   weight and colour (var(--g2), not a muted caption grey) instead of
   competing with a large picture for attention. Body padding must stay a
   real value (not a sliver) — anything too thin here, combined with the
   card's own rounded-corner overflow:hidden clip, is what was cropping
   the first letter of some titles. */
@media(max-width:760px){
  .pbadges,.pfav,.pprice-cap,.rating-badge{display:none}
  .pthumb{aspect-ratio:1/1;width:44%;margin:14px 14px 0;border-radius:var(--r)}
  .pbody{padding:12px 14px 16px;gap:5px}
  .pcat{display:none}
  .ptitle{font-size:15px;font-weight:700;line-height:1.3;letter-spacing:-.015em}
  .pworkflow{margin-top:2px}
  .pworkflow-state{display:none}
  .pworkflow-action{font-size:13.5px;line-height:1.48;color:var(--g2)}
}

/* Ratings — only ever rendered when real, verified-purchase data exists
   (see ratingBadge() in berci.js). Monochrome, on-brand — no yellow stars,
   just the existing ink/muted palette. */
.rating-badge{display:inline-flex;align-items:center;gap:5px;font-size:12px;color:var(--g3)}
.rating-stars{color:var(--ink);font-size:12px;letter-spacing:1px}

/* States */
.state{text-align:center;padding:90px 20px;color:var(--g3)}
.state .mark{width:52px;height:52px;margin:0 auto 18px;opacity:.9}
.state h3{color:var(--ink);font-size:18px;font-weight:600;margin-bottom:6px}
.skel{border:1px solid var(--edge);border-radius:var(--r-lg);overflow:hidden;background:#fff}
.skel .b{background:linear-gradient(90deg,#f2f3f4 25%,#e9eaec 37%,#f2f3f4 63%);background-size:400% 100%;animation:sh 1.3s infinite}
@keyframes sh{0%{background-position:100% 0}100%{background-position:-100% 0}}

/* Modal */
.overlay{position:fixed;inset:0;z-index:60;background:rgba(10,10,10,.42);backdrop-filter:blur(3px);
  display:flex;align-items:center;justify-content:center;padding:20px;opacity:0;pointer-events:none;transition:.2s}
.overlay.show{opacity:1;pointer-events:auto}
.modal{background:#fff;border-radius:22px;box-shadow:var(--shadow-3);width:100%;max-width:640px;max-height:88vh;overflow:auto;
  transform:translateY(8px) scale(.99);transition:.2s}
.overlay.show .modal{transform:none}
.modal-wide{max-width:760px}
.modal .x{position:absolute;top:14px;right:14px}

/* Notice banners */
.notice{border:1px solid var(--edge);border-radius:var(--r);padding:14px 16px;font-size:14px;display:flex;gap:10px;align-items:flex-start}
.notice-info{background:var(--g7);color:var(--g2)}
.notice-err{background:var(--err-bg);color:var(--err);border-color:#f3c9c7}
.notice-ok{background:var(--ok-bg);color:var(--ok);border-color:#c7e6d4}

/* Footer */
.ft{border-top:1px solid var(--edge);margin-top:80px;padding-top:44px;padding-bottom:44px;color:var(--g4);font-size:13px;
  display:flex;justify-content:space-between;align-items:center;gap:16px;flex-wrap:wrap}

/* Admin table */
.table{width:100%;border-collapse:collapse}
.table th{text-align:left;font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--g4);font-weight:600;padding:0 12px 12px}
.table td{padding:12px;border-top:1px solid var(--edge);vertical-align:middle;font-size:14px}
.table tr:hover td{background:var(--g7)}
.tthumb{width:52px;height:40px;border-radius:8px;background:var(--g6);object-fit:cover;overflow:hidden;display:flex;align-items:center;justify-content:center}
.tthumb .ph{width:40%;opacity:.2}
.rowact{display:flex;gap:6px;justify-content:flex-end}

/* Auth card */
.authwrap{min-height:100vh;min-height:100dvh;display:flex;align-items:center;justify-content:center;padding:24px;background:
  radial-gradient(120% 80% at 50% -10%, #fafbfc, #fff 60%)}
.authcard{width:100%;max-width:380px;text-align:center}
.authcard .mark{width:52px;height:52px;margin:0 auto 18px}
.authcard h1{font-size:26px;font-weight:600;letter-spacing:-.02em}
.authcard p.sub{color:var(--g3);font-size:14px;margin-top:6px;margin-bottom:30px}
.authcard form{text-align:left}

/* Auth forms get their own, slightly more generous rhythm than the site's
   compact utility forms (admin fields, checkout) — this is the first and
   last screen most people see, so labels, fields and spacing all read a
   size up from the rest of BERCI. */
.authcard .field{margin-bottom:20px}
.authcard .field > label{font-size:14px;font-weight:600;letter-spacing:-.005em;margin-bottom:8px}
/* 16px, not 15 — the same iOS Safari auto-zoom-on-focus threshold that
   caused the search field's "page shifts when typing" bug (anything under
   16px triggers a visual zoom on focus, independent of any scroll/keyboard
   handling). See wireScrollLockWithinForm() in berci.js for the second,
   independent layer against actual scroll movement. */
.authcard .input{height:48px;padding:0 16px;font-size:16px;border-radius:14px}
.authcard .pw-field .input{padding-right:48px}
.authcard .hint{margin-top:8px}

/* toast */
.toast{position:fixed;left:50%;bottom:26px;transform:translateX(-50%) translateY(20px);z-index:80;
  background:var(--ink);color:#fff;font-size:14px;font-weight:500;padding:12px 18px;border-radius:999px;
  box-shadow:var(--shadow-3);opacity:0;pointer-events:none;transition:.24s}
.toast.show{opacity:1;transform:translateX(-50%)}

/* file dropzones */
.drop{border:1.5px dashed var(--g5);border-radius:12px;padding:16px;display:flex;align-items:center;gap:12px;
  font-size:13px;color:var(--g3);cursor:pointer;transition:.15s;background:#fff}
.drop:hover{border-color:var(--ink);color:var(--g2)}
.drop b{color:var(--ink);font-weight:600}
.drop .prev{width:44px;height:44px;border-radius:9px;background:var(--g6);object-fit:cover;flex:none;display:flex;align-items:center;justify-content:center}
.drop .prev .ph{width:44%;opacity:.25}

/* ==========================================================================
   Homepage — hero, sections, category cards, why-cards, empty states
   ========================================================================== */
.btn-lg{height:50px;padding:0 26px;font-size:15px;border-radius:999px}

.eyebrow{font-size:12px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:var(--g4)}

.hero{padding-top:96px;padding-bottom:88px;text-align:center}
.hero .eyebrow{margin-bottom:18px}
.hero-title{font-size:clamp(40px,7vw,74px);font-weight:700;letter-spacing:-.04em;line-height:1.02}
.hero-sub{color:var(--g3);font-weight:400;font-size:clamp(16px,2vw,19px);line-height:1.6;max-width:52ch;margin:22px auto 0}
.hero-cta{display:flex;gap:12px;justify-content:center;flex-wrap:wrap;margin-top:36px}

.section{padding-top:56px;padding-bottom:56px}
@media(max-width:760px){.section{padding-top:68px;padding-bottom:68px}}
.section-head{margin-bottom:32px}
.section-head .eyebrow{margin-bottom:10px}
.section-title{font-size:clamp(26px,3.6vw,36px);font-weight:700;letter-spacing:-.028em;line-height:1.12;max-width:26ch}
#categories,#nouveautes,#populaires,#pourquoi{scroll-margin-top:84px}

/* Category cards — deliberately square-cornered, never circular */
.cat-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}
@media(max-width:900px){.cat-grid{grid-template-columns:repeat(3,1fr)}}
@media(max-width:620px){.cat-grid{grid-template-columns:repeat(2,1fr)}}
.cat-card{display:flex;flex-direction:column;align-items:flex-start;gap:16px;padding:22px 20px;
  border:1px solid var(--edge);border-radius:var(--r-lg);background:#fff;cursor:pointer;text-align:left;
  font-family:inherit;transition:transform .2s cubic-bezier(.2,.7,.2,1),box-shadow .2s cubic-bezier(.2,.7,.2,1),border-color .2s,background .2s}
.cat-card:hover{transform:translateY(-4px);box-shadow:var(--shadow-2);border-color:var(--g4);background:var(--g7)}
.cat-card:active{transform:translateY(-1px)}
.cat-icon{width:26px;height:26px;color:var(--g2);transition:transform .2s cubic-bezier(.34,1.4,.64,1),color .2s}
.cat-card:hover .cat-icon{color:var(--ink);transform:scale(1.12) rotate(-4deg)}
.cat-name{font-size:14.5px;font-weight:600;letter-spacing:-.01em;color:var(--ink)}

/* Why-BERCI cards */
.why-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:28px}
@media(max-width:900px){.why-grid{grid-template-columns:repeat(2,1fr)}}
@media(max-width:560px){.why-grid{grid-template-columns:1fr}}
.why-grid-3{display:grid;grid-template-columns:repeat(3,1fr);gap:28px}
@media(max-width:760px){.why-grid-3{grid-template-columns:1fr}}
.why-card{display:flex;flex-direction:column;gap:14px}
.why-icon{width:44px;height:44px;padding:11px;border-radius:var(--r);background:var(--g7);color:var(--ink);
  transition:transform .2s cubic-bezier(.2,.7,.2,1),background .2s,color .2s}
.why-card:hover .why-icon{transform:translateY(-3px);background:var(--ink);color:#fff}
.why-card h3{font-size:16px;font-weight:600;letter-spacing:-.01em}
.why-card p{font-size:14px;line-height:1.6;color:var(--g3)}

/* Premium empty-catalogue placeholders — same outer shape as a real product
   card, so the moment real products exist, they slot into exactly this
   layout with zero redesign. Everything the placeholder needs to say lives
   INSIDE the artwork area: the BERCI mark as a large, quiet watermark with
   "Bientôt disponible" stacked directly beneath it, both centered as one
   unit — nothing added below the thumbnail, nothing loud. */
.pcard-ph{cursor:default}
.pcard-ph:hover{transform:none;box-shadow:none;border-color:var(--edge)}
.pcard-ph .pthumb{background:linear-gradient(145deg,var(--g7),var(--g6));flex-direction:column;gap:10px}
.pcard-ph.ph-2 .pthumb{background:linear-gradient(145deg,#FAFBFB,var(--g7))}
.pcard-ph.ph-3 .pthumb{background:linear-gradient(160deg,var(--g6),#F2F3F4)}
.pcard-ph.ph-4 .pthumb{background:linear-gradient(120deg,var(--g7),#EDEEEF)}
.ph-watermark{width:30%;aspect-ratio:1/1;color:var(--g4);opacity:.1}
.ph-caption{font-size:11.5px;font-weight:500;letter-spacing:.02em;color:var(--g4)}

/* Placeholder body — the exact same markup and classes as a real card's
   category/title/description (same font sizes, weights, line heights —
   nothing re-declared), just quieted a shade further with color alone.
   Elegant placeholder copy, never loading bars: the card should already
   look like a finished layout, only the specific product and its artwork
   are missing. The price capsule stays but shows nothing invented. */
.pcard-ph .ptitle{color:var(--g4)}
.pcard-ph .pprice-cap{color:var(--g4);font-weight:500}

.section-note{text-align:center;color:var(--g4);font-size:13.5px;margin-top:26px}

/* Favorites / downloads drawer — a quiet slide-over panel, not a modal
   takeover, for a lightweight "check on this real quick" interaction. */
.drawer-overlay{position:fixed;inset:0;z-index:70;background:rgba(10,10,10,.32);backdrop-filter:blur(2px);
  opacity:0;pointer-events:none;transition:.22s}
.drawer-overlay.show{opacity:1;pointer-events:auto}
.drawer{position:fixed;top:0;right:0;bottom:0;z-index:71;width:100%;max-width:400px;background:#fff;
  box-shadow:var(--shadow-3);transform:translateX(100%);transition:transform .28s cubic-bezier(.2,.7,.2,1);
  display:flex;flex-direction:column}
.drawer.show{transform:none}
.drawer-head{display:flex;align-items:center;justify-content:space-between;padding:20px 22px 16px;border-bottom:1px solid var(--edge);flex:none}
.drawer-head h3{font-size:16.5px;font-weight:600;letter-spacing:-.01em}
.drawer-body{flex:1;overflow:auto;padding:8px 22px 22px}
.drawer-empty{text-align:center;color:var(--g4);font-size:13.5px;line-height:1.6;padding:70px 14px}
.drawer-item{display:flex;gap:12px;align-items:center;padding:14px 0;border-bottom:1px solid var(--edge)}
.drawer-item:last-child{border-bottom:none}
.drawer-item .dthumb{width:42px;height:52px;border-radius:8px;background:var(--g7);overflow:hidden;flex:none;display:flex;align-items:center;justify-content:center}
.drawer-item .dthumb img{width:100%;height:100%;object-fit:cover}
.drawer-item .dthumb .ph{width:40%;opacity:.16}
.drawer-item .dinfo{flex:1;min-width:0}
.drawer-item .dtitle{font-size:13.5px;font-weight:600;line-height:1.3;letter-spacing:-.005em}
.drawer-item .dmeta{font-size:12px;color:var(--g4);margin-top:3px}

/* Password visibility toggle — same control on every password field across
   sign-in and sign-up. The slash fades in/out rather than swapping icons,
   so the transition stays smooth. */
.pw-field{position:relative}
.pw-field .input{padding-right:44px}
.pw-toggle{position:absolute;right:4px;top:4px;bottom:4px;width:36px;display:flex;align-items:center;justify-content:center;
  border:none;background:none;color:var(--g4);cursor:pointer;border-radius:8px;transition:color .2s}
.pw-toggle:hover{color:var(--g2)}
.pw-toggle svg{width:19px;height:19px;fill:none;stroke:currentColor;stroke-width:1.5}
.pw-toggle .pw-slash{opacity:0;transition:opacity .2s}
.pw-toggle.on{color:var(--ink)}
.pw-toggle.on .pw-slash{opacity:1}

/* Account "Accueil" — a control-center home, not a stats dashboard. Quick
   tiles reuse the same rounded-card/hover language as category cards on
   the storefront so the account area reads as a continuation of it. */
.acc-quick-grid{display:grid;grid-template-columns:repeat(6,1fr);gap:12px}
@media(max-width:900px){.acc-quick-grid{grid-template-columns:repeat(3,1fr)}}
@media(max-width:520px){.acc-quick-grid{grid-template-columns:repeat(2,1fr)}}
.acc-tile{display:flex;flex-direction:column;align-items:flex-start;gap:10px;padding:16px;border:1px solid var(--edge);
  border-radius:var(--r-lg);background:#fff;cursor:pointer;text-align:left;font-family:inherit;
  transition:transform .2s cubic-bezier(.2,.7,.2,1),box-shadow .2s,border-color .2s,background .2s}
.acc-tile:hover{transform:translateY(-3px);box-shadow:var(--shadow-2);border-color:var(--g4);background:var(--g7)}
.acc-tile svg{width:21px;height:21px;color:var(--g2);fill:none;stroke:currentColor;stroke-width:1.5}
.acc-tile span{font-size:13px;font-weight:600;color:var(--ink);letter-spacing:-.005em}

.acc-browse-banner{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:22px 26px;margin-top:26px;
  border:1px solid var(--edge);border-radius:var(--r-lg);background:var(--g7);cursor:pointer;
  transition:transform .2s cubic-bezier(.2,.7,.2,1),box-shadow .2s,border-color .2s}
.acc-browse-banner:hover{transform:translateY(-2px);box-shadow:var(--shadow-2);border-color:var(--g4)}
.acc-browse-banner h3{font-size:16px;font-weight:600;letter-spacing:-.01em}
.acc-browse-banner p{font-size:13px;color:var(--g3);margin-top:2px}

.acc-section-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:14px}
.acc-section-head h2{font-size:16px;font-weight:600;letter-spacing:-.01em}
.acc-columns{display:grid;grid-template-columns:1fr 1fr;gap:32px}
@media(max-width:760px){.acc-columns{grid-template-columns:1fr}}
.acc-mini-grid{grid-template-columns:repeat(4,1fr)}
@media(max-width:900px){.acc-mini-grid{grid-template-columns:repeat(3,1fr)}}
@media(max-width:620px){.acc-mini-grid{grid-template-columns:repeat(2,1fr)}}
.acc-empty-row{color:var(--g4);font-size:13.5px;padding:18px 0}
.acc-tab-count{display:inline-flex;align-items:center;justify-content:center;min-width:16px;height:16px;padding:0 4px;
  margin-left:5px;border-radius:999px;background:var(--ink);color:#fff;font-size:10px;font-weight:700}
.chip.on .acc-tab-count{background:#fff;color:var(--ink)}

/* ============================================================================
   Product page — a dedicated destination, not a modal. Two columns: the
   left answers "what is this, exactly," the right stays sticky so the
   purchase decision is never more than a glance away while reading. ---- */
.product-layout{display:grid;grid-template-columns:1fr 360px;gap:48px;align-items:start}
@media(max-width:860px){.product-layout{grid-template-columns:1fr}}

/* Navigation memory — a contextual "back", never a generic one. Quiet by
   design: it's an orientation cue, not a call to action, so it stays out
   of the way of the actual product content just below it. */
.product-back{display:inline-flex;align-items:center;gap:6px;font-size:13px;font-weight:500;
  color:var(--g3);text-decoration:none;margin-bottom:18px;transition:color .15s}
.product-back:hover{color:var(--ink)}

.product-hero{aspect-ratio:16/9;border-radius:var(--r-lg);background:var(--g7)}
/* A quiet capsule, not a loud badge — same instinct as a Nouveau tag but
   deliberately understated, since this is orientation, not a call-out. */
.category-pill{display:inline-flex;align-items:center;height:26px;padding:0 14px;border-radius:999px;
  background:var(--g7);color:var(--g2);font-size:11.5px;font-weight:600;letter-spacing:.04em}
.product-title{font-size:30px;font-weight:600;letter-spacing:-.02em;margin-top:10px;line-height:1.2}
/* Recognition: one strong introductory sentence, nothing more — "what is
   this," answered plainly, right under the title. */
.product-desc{margin-top:14px;line-height:1.65;color:var(--g2);white-space:pre-wrap}

/* Relief: the recurring frustration and how this product removes it —
   the transformation, never the file. No heading, so it reads as a
   natural continuation of the intro sentence rather than a labeled field;
   a touch larger and more generously spaced than the paragraphs below it,
   since this is the page's real point of conviction. */
.product-story{margin-top:22px;font-size:16px;line-height:1.75;color:var(--g2)}
.info-note{font-size:13px;line-height:1.6;color:var(--g4);margin-top:10px}

/* Visual Proof, kept curated rather than exhaustive — a compact row of
   small preview cards, not a full-width gallery competing with the
   reading flow. Each card is one real page/slide; the quiet "Voir un
   aperçu" affordance is the only extra element, answering exactly one
   question ("what am I actually buying") without becoming a section of
   its own. Opens the same image large in a lightbox on click. */
.product-previews{margin-top:40px}
.preview-row{display:flex;gap:16px;flex-wrap:wrap}
.preview-card{position:relative;width:140px;aspect-ratio:4/5;border:1px solid var(--edge);border-radius:var(--r);
  overflow:hidden;cursor:pointer;padding:0;background:var(--g7);transition:border-color .15s,box-shadow .15s}
.preview-card:hover{border-color:var(--g4);box-shadow:var(--shadow-1)}
.preview-card img{width:100%;height:100%;object-fit:cover;object-position:top;display:block}
.preview-card-label{position:absolute;left:0;right:0;bottom:0;padding:8px 10px;font-size:11.5px;font-weight:600;
  color:#fff;background:linear-gradient(to top,rgba(10,10,10,.55),transparent);text-align:left}

/* Lightbox — a focused viewer, not a second page. Same overlay language
   as the cart/favorites drawer (quiet dark scrim), centred instead of
   slid in from the side since this is about looking, not choosing. */
.lightbox-overlay{position:fixed;inset:0;z-index:80;background:rgba(10,10,10,.7);
  opacity:0;pointer-events:none;transition:.22s;display:flex;align-items:center;justify-content:center;padding:40px}
.lightbox-overlay.show{opacity:1;pointer-events:auto}
.lightbox{max-width:min(560px,90vw);max-height:90vh;display:flex;flex-direction:column;align-items:center;gap:16px}
.lightbox img{max-width:100%;max-height:78vh;border-radius:var(--r-lg);box-shadow:var(--shadow-3);display:block}
.lightbox-controls{display:flex;align-items:center;gap:18px}
.lightbox-nav{background:rgba(255,255,255,.14);border:none;color:#fff;width:36px;height:36px;border-radius:999px;
  display:flex;align-items:center;justify-content:center;cursor:pointer;transition:background .15s}
.lightbox-nav:hover{background:rgba(255,255,255,.24)}
.lightbox-nav:disabled{opacity:.3;cursor:default}
.lightbox-nav svg{width:18px;height:18px;fill:none;stroke:#fff;stroke-width:2}
.lightbox-close{position:absolute;top:22px;right:26px;background:none;border:none;color:#fff;font-size:22px;
  cursor:pointer;line-height:1;padding:6px}

/* Validation ("Contenu") and, further down, Practical information — both
   short, plain, never a labeled form field. Generous space between
   sections communicates separation; nothing here needs a border to prove
   it's a section. */
.info-section{margin-top:40px}
.info-heading{font-size:15px;font-weight:600;letter-spacing:-.005em;color:var(--ink);margin-bottom:10px}

/* What's included, as a plain list — whitespace separates each line, not
   a bullet glyph or a bordered card. The list itself communicates quality. */
.content-list{list-style:none;display:flex;flex-direction:column;gap:14px}
.content-list li{font-size:14.5px;line-height:1.55;color:var(--g2)}

/* Practical information — format, language, editable, updated — light,
   label-free reassurance that sits after Validation, never interrupting
   the story above it. */
.info-row{margin-top:40px;padding-top:24px;border-top:1px solid var(--edge);font-size:14px;line-height:1.6;color:var(--g3)}

/* The sticky panel — price, rating, one dominant purchase action, then
   quiet secondary actions, then trust indicators. Nothing else — every
   other element on this page exists to help you decide; this one exists
   so, once decided, you never have to scroll to act. */
.product-panel{position:sticky;top:88px;border:1px solid var(--edge);border-radius:var(--r-lg);
  padding:24px;display:flex;flex-direction:column;gap:14px;background:#fff}
.product-price{font-size:28px;font-weight:700;letter-spacing:-.01em}
.product-panel-rating{margin-top:-8px}
.product-buy{display:flex;flex-direction:column;gap:8px}
.product-buy .btn{width:100%}
.product-secondary{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.product-fav-btn{display:inline-flex;align-items:center;gap:6px}
.product-fav-icon{display:inline-flex;width:14px;height:14px;color:var(--g3)}
.product-fav-icon svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:1.8}
.product-fav-icon.on{color:var(--ink)}
.product-fav-icon.on svg{fill:currentColor}
.trust-list{list-style:none;margin-top:6px;padding-top:14px;border-top:1px solid var(--edge);
  display:flex;flex-direction:column;gap:8px;font-size:13px;color:var(--g3)}
.trust-list li{padding-left:20px;position:relative}
.trust-list li::before{content:"✓";position:absolute;left:0;color:var(--ink);font-weight:700}

/* Ratings prompt — Ma bibliothèque (account.html). Kindness-framed, never
   marketing-framed: see ratingPromptHtml() in account.js. */
.rate-star{background:none;border:none;cursor:pointer;font-size:18px;line-height:1;color:var(--ink);
  padding:2px;transition:transform .12s cubic-bezier(.2,.7,.2,1)}
.rate-star:hover{transform:scale(1.15)}
