﻿/* =========================================================
   CORTHAY — Volney Boutique
   Brand identity aligned on the crm-volney charter (see
   brand/design-tokens.css, brand/charte-graphique.txt): Roboto
   throughout, near-black CTAs with a cognac/copper accent, and a
   light/dark theme pair toggled via [data-theme] on <html>
   (see .theme-toggle in Navbar). The historic Cormorant-Garamond/
   anthracite-only palette was retired 2026-08-14 in favour of this one.
   ========================================================= */

/* Self-hosted UI fonts (V2.80.0). Copied from @fontsource-variable by
   frontend/scripts/sync-fonts.mjs — never linked from Google: a till makes
   no third-party request to paint its first screen, hands no IP to a third
   party on every page load, and skips the HTML → CSS → Google CSS → woff2
   chain. The directory carries the package version, so main.py can serve
   /static/fonts/ as immutable for a year: a bump is a new path, and the
   sync script refuses to run while these urls point at an old one. Latin +
   Latin Extended only; unicode-range keeps a page from downloading a face
   it does not render (the italic and the extended block stay on the shelf
   until a glyph needs them). Weights 100–900 come from ONE variable file,
   so the 600 the components use is a real instance, no longer synthesised
   from 500 and 700. */

@font-face {
  font-family: "Roboto Variable";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/static/fonts/roboto-5.3.0/roboto-latin-wght-normal.woff2) format("woff2-variations");
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

@font-face {
  font-family: "Roboto Variable";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/static/fonts/roboto-5.3.0/roboto-latin-ext-wght-normal.woff2) format("woff2-variations");
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}

@font-face {
  font-family: "Roboto Variable";
  font-style: italic;
  font-weight: 100 900;
  font-display: swap;
  src: url(/static/fonts/roboto-5.3.0/roboto-latin-wght-italic.woff2) format("woff2-variations");
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

@font-face {
  font-family: "Roboto Variable";
  font-style: italic;
  font-weight: 100 900;
  font-display: swap;
  src: url(/static/fonts/roboto-5.3.0/roboto-latin-ext-wght-italic.woff2) format("woff2-variations");
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}

/* The wordmark's serif. brand/charte-graphique.txt names Bodoni Moda for
   the one word "CORTHAY" in the topbar and Georgia as the fallback — and
   until V2.80.0 the fallback was all anyone saw, because the face was
   declared and never loaded. Optical-size axis kept (the browser picks the
   cut for the size it renders at); upright and Latin only, it sets one
   word. */

@font-face {
  font-family: "Bodoni Moda Variable";
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url(/static/fonts/bodoni-moda-5.3.0/bodoni-moda-latin-opsz-normal.woff2) format("woff2-variations");
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

:root,
[data-theme='light'] {
  --bg-1: #F8F6F2;
  --bg-2: #FFFFFF;
  --bg-3: #FFFFFF;
  --bg-4: #F1EEE8;
  --line: #E0E2E5;
  --line-strong: #CED2D6;
  --text-1: #212529;
  --text-2: #343A40;
  --text-3: #6C757D;
  --text-4: #8C939B;
  --accent: #212529;
  --accent-soft: #343A40;
  --accent-bright: #181B1F;
  --accent-rgb: 33, 37, 41;
  --on-accent: #FFFFFF;
  --chart: #A85D2E;         /* cognac/copper — charts + rare highlight moments */
  --chart-strong: #FF9A52;
  --green: #1F8A52;
  --green-rgb: 31, 138, 82;
  --green-bg: #A8DABB;
  --red: #B83325;
  --red-rgb: 184, 51, 37;
  --red-bg: #F0B8AE;
  --warn: #9C6A10;
  --warn-bg: #F0D08A;
  --info: #1858A0;
  --shadow-rgb: 20, 22, 26;
  --shadow: 0 8px 24px rgba(20, 22, 26, 0.12);
  --ease-liquid: cubic-bezier(.2, .8, .3, 1);   /* shared “drawer” easing — smooth, settles softly */
  --radius-pill: 30px;
  /* V2.86.0 — la forme de l'app : trois rayons, une ombre douce. Jusque-là
     61 blocs à 2 px (cartes, panneaux, champs) contre des boutons en
     pilule : le mélange faisait une app « carrée » (propriétaire,
     2026-09-26). Les couleurs ne bougent pas. */
  --r-sm: 10px;   /* champs, petits blocs */
  --r-md: 14px;   /* tuiles, lignes, fenêtres légères */
  --r-lg: 18px;   /* cartes, panneaux, ticket, catalogue */
  --soft-shadow: 0 1px 2px rgba(var(--shadow-rgb), .04), 0 8px 24px rgba(var(--shadow-rgb), .07);
  --font-wordmark: "Bodoni Moda Variable", "Bodoni Moda", Georgia, "Times New Roman", serif;
  --sans: "Roboto Variable", "Roboto", -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
}

[data-theme='dark'] {
  --bg-1: #121417;
  --bg-2: #1C1F24;
  --bg-3: #1C1F24;
  --bg-4: #22252A;
  --line: #2C3036;
  --line-strong: #3C4249;
  --text-1: #E9EAEC;
  --text-2: #CED2D6;
  --text-3: #8C939B;
  --text-4: #6C757D;
  --accent: #E68246;
  --accent-soft: #C86E38;
  --accent-bright: #AA5C2E;
  --accent-rgb: 230, 130, 70;
  --on-accent: #14161A;
  --chart: #E68C54;
  --chart-strong: #FFAF78;
  --green: #329E66;
  --green-rgb: 50, 158, 102;
  --green-bg: #326046;
  --red: #D86858;
  --red-rgb: 216, 104, 88;
  --red-bg: #5C2820;
  --warn: #D89040;
  --warn-bg: #5C4218;
  --info: #82B8E8;
  --shadow-rgb: 0, 0, 0;
  --shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
}

/* -- reset -- */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--bg-1);
  color: var(--text-1);
  font-family: var(--sans);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
  min-height: 100dvh;   /* iOS Safari: the toolbar collapses, 100vh does not */
  transition: background-color .2s ease, color .2s ease;
}
@media (prefers-reduced-motion: reduce) {
  body { transition: none; }
}
button { font-family: inherit; }
a { color: var(--accent); text-decoration: none; }
/* A button that reads as a link: the Receipt links of the sales tables.
   They were <a href="/api/receipt/…"> with a click handler; a middle-click or
   "open in a new tab" went round the handler and reached the endpoint with
   no bearer. A button has no href to go round (V2.52.3). */
.link-btn {
  background: none; border: 0; padding: 0; margin: 0;
  font: inherit; color: var(--accent); cursor: pointer;
}
.link-btn:hover { text-decoration: underline; }

/* Keyboard focus must stay visible everywhere — components may restyle
   :focus, but the :focus-visible ring is the global floor (V2.21.2). */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Links inside prose must not rely on colour alone (WCAG 1.4.1) — nav
   pills and .btn links style themselves, running text gets an underline. */
p a, .muted a {
  text-decoration: underline;
  text-underline-offset: 2px;
}
a:hover { color: var(--accent-bright); }
em { color: var(--text-2); font-style: italic; }

/* -- top bar -- */
.topbar {
  display: grid;
  /* 3rd column is content-sized, not a fixed 280px: it only had to fit
     vendor + date originally, but now also carries the store/role pills
     (added later) — a fixed width made them overlap the nav links. */
  grid-template-columns: 220px 1fr auto;
  align-items: center;
  padding: 14px 24px;
  background: var(--bg-2);
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: 100;
}
/* The floating bar (V2.90.0, owner 2026-09-28: « la barre horizontale
   adoucie »): from the tablet up, the bar is a rounded band held 14 px off
   the edges, the way the drawers float. The phone keeps it edge to edge —
   every pixel there goes to the catalogue. `--shell-gap` is read by the
   ticket's sticky offset (.cart). */
@media (min-width: 600px) {
  :root { --shell-gap: 14px; }
  .topbar {
    margin: var(--shell-gap) var(--shell-gap) 0;
    top: var(--shell-gap);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    box-shadow: var(--soft-shadow);
  }
  /* Stuck 14 px from the top, the bar would let the page scroll past in the
     strip above it; that strip is painted with the page's own background. */
  .topbar::before {
    content: "";
    position: absolute;
    left: calc(-1px - var(--shell-gap));
    right: calc(-1px - var(--shell-gap));
    bottom: 100%;
    height: calc(1px + var(--shell-gap));
    background: var(--bg-1);
  }
}
/* The star beside the wordmark. The brand is a row so the star stays
   vertically centred on the two-line text block, and min-width lets the
   grid column shrink it on narrow screens instead of overflowing. */
.brand { display: flex; align-items: center; gap: 10px; min-width: 0; }
.brand-mark { display: block; flex: 0 0 auto; height: 22px; width: auto; }
.brand-text { min-width: 0; }
.brand .logo {
  font-family: var(--font-wordmark);
  font-size: 26px;
  letter-spacing: 6px;
  font-weight: 400;
  color: var(--accent);
}
.brand .sublabel {
  font-size: 10px;
  letter-spacing: 3px;
  text-transform: uppercase;
  color: var(--text-3);
  margin-top: 2px;
}
.nav { display: flex; gap: 6px; justify-content: center; }
/* Pills since V2.86.0, like every button of the app: the active category
   is filled, the others show their shape on hover. */
.nav-link {
  font-size: 13px;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-2);
  padding: 8px 16px;
  border-radius: var(--radius-pill);
  transition: color .2s, background .2s;
}
.nav-link:hover { color: var(--text-1); background: var(--bg-4); }
.nav-link.active { color: var(--on-accent); background: var(--accent); }

.meta { display: flex; gap: 16px; align-items: center; justify-content: flex-end; font-size: 12px; }
/* The two groups inside .meta are invisible wrappers here; the phone tier
   (end of file) turns them into topbar grid rows of their own. */
.meta-pills, .meta-tools { display: contents; }
/* The three topbar pills (.store-pill, .role-pill, .staff-pill) share one
   set of metrics — see the shared rule next to .role-pill. Anything specific
   to the vendor pill lives here. */
.staff-pill .muted { color: var(--text-3); }
/* The vendor picker carries real names ("EMILIEN JOYEUX"), so it sizes to
   its content instead of the fixed width the old free-text field used. */
.staff-pill .staff-select { max-width: 190px; }
.staff-pill .staff-select:disabled {
  cursor: default;
  color: var(--text-3);
  opacity: 1;   /* Safari greys disabled selects into near-invisibility. */
}
.today { color: var(--text-2); font-variant-numeric: tabular-nums; }

/* Settings gear in the topbar — always-visible shortcut to Office → Settings */
.settings-gear {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  color: var(--text-3);
  border: 1px solid var(--line);
  border-radius: 50%;
  background: transparent;
  transition: all .15s;
  text-decoration: none;
}
.settings-gear:hover {
  color: var(--accent);
  border-color: var(--accent);
  transform: rotate(45deg);
}
.settings-gear.active {
  color: var(--accent);
  border-color: var(--accent);
  background: rgba(var(--accent-rgb), 0.08);
}

/* Light/dark toggle — same pill-circle affordance as the settings gear */
.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  color: var(--text-3);
  border: 1px solid var(--line);
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  transition: all .15s;
}
.theme-toggle:hover {
  color: var(--accent);
  border-color: var(--accent);
}

/* -- the ☰ menu (V2.87.0) --
   Phone and tablet portrait only: the tier rule near the end of the file
   shows the button and folds the topbar to one row. The panel exists only
   while open (components/NavMenu.tsx). */
.nav-burger { display: none; }
.nav-menu-overlay {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.35);
  z-index: 600;
  animation: nav-menu-fade .18s ease;
}
.nav-menu {
  position: fixed;
  top: max(10px, env(safe-area-inset-top));
  bottom: max(10px, env(safe-area-inset-bottom));
  left: max(10px, env(safe-area-inset-left));
  width: min(86vw, 340px);
  z-index: 601;
  display: flex; flex-direction: column;
  padding: 14px 12px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--soft-shadow);
  overflow-y: auto;
  overscroll-behavior: contain;
  animation: nav-menu-in .25s var(--ease-liquid);
}
.nav-menu:focus { outline: none; }
@keyframes nav-menu-in {
  from { transform: translateX(calc(-100% - 20px)); }
  to   { transform: translateX(0); }
}
@keyframes nav-menu-fade { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .nav-menu, .nav-menu-overlay { animation: none; }
}
.nav-menu-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 4px 12px 10px;
  margin-bottom: 8px;
  border-bottom: 1px solid var(--line);
}
.nav-menu-mark {
  font-family: var(--font-wordmark);
  font-size: 20px;
  letter-spacing: 5px;
  color: var(--accent);
}
.nav-menu-close {
  width: 40px; height: 40px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--text-2);
  font-size: 20px; line-height: 1;
  cursor: pointer;
}
.nav-menu-close:hover { color: var(--accent); border-color: var(--accent); }
.nav-menu-list { display: flex; flex-direction: column; gap: 2px; }
.nav-menu-item {
  display: flex; align-items: center; justify-content: space-between;
  min-height: 48px;
  padding: 0 16px;
  border-radius: var(--r-md);
  font-size: 13px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--text-1);
  text-decoration: none;
}
.nav-menu-item:hover { background: var(--bg-4); color: var(--text-1); }
.nav-menu-item.active { background: var(--accent); color: var(--on-accent); }
.nav-menu-ext { color: var(--text-3); }
.nav-menu-pages {
  display: flex; flex-direction: column;
  margin: 4px 0 8px 18px;
  padding-left: 4px;
  border-left: 1px solid var(--line);
}
.nav-menu-page {
  display: flex; align-items: center;
  min-height: 44px;
  padding: 0 14px;
  border-radius: var(--r-sm);
  font-size: 11.5px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-3);
  text-decoration: none;
}
.nav-menu-page:hover { color: var(--text-1); background: var(--bg-4); }
.nav-menu-page.active { color: var(--accent); font-weight: 600; }
.nav-menu-foot {
  margin-top: auto;
  padding-top: 12px;
  border-top: 1px solid var(--line);
  display: flex; flex-direction: column; gap: 8px;
}
.nav-menu-row {
  display: flex; align-items: center; gap: 10px;
  min-height: 48px;
  padding: 0 6px 0 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  font-size: 12px;
  letter-spacing: 1px;
}
.nav-menu-row .muted { color: var(--text-3); text-transform: uppercase; font-size: 10.5px; letter-spacing: 1.5px; }
.nav-menu-row strong { color: var(--text-1); letter-spacing: 1px; }
.nav-menu .nav-menu-row .store-select { flex: 1 1 auto; min-width: 0; border-color: transparent; background-color: transparent; }
.nav-menu-signout { margin-left: auto; padding: 8px 14px; letter-spacing: 1.5px; }
.nav-menu-tools { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.nav-menu-tool {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 44px;
  padding: 0 10px;
  font-size: 11px;
  letter-spacing: 1.2px;
  white-space: nowrap;
  text-decoration: none;
}
.nav-menu-tool.active { color: var(--accent); border-color: var(--accent); }

/* -- sub-nav --
   Since V2.90.0 the pages of the section are pills laid on the page's own
   background, under the floating bar — no band of their own. */
.subnav {
  background: transparent;
  padding: 0 32px;
  display: flex;
  gap: 6px;
  align-items: center;
  height: 0;
  overflow: hidden;
  transition: height .18s ease, padding .18s ease;
}
.subnav.open {
  height: 50px;
  padding: 10px 32px 0;
}
.subnav a {
  font-size: 11px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--text-3);
  padding: 6px 14px;
  border: 1px solid var(--line);
  background: var(--bg-2);
  border-radius: var(--radius-pill);
  transition: color .15s, border-color .15s, background .15s;
}
.subnav a:hover { color: var(--text-1); border-color: var(--line-strong); }
.subnav a.active {
  color: var(--accent);
  background: var(--bg-4);
  border-color: var(--line-strong);
}
/* The pills separate themselves; the hairline between them went with the
   underline (V2.86.0). */
.subnav .sub-sep { display: none; }

/* -- pages -- */
main { max-width: 1380px; margin: 0 auto; padding: 24px 32px 64px; }
.page { display: none; }
.page.active { display: block; }

/* Liquid navigation — each top-level block of a page eases in with a fade +
   upward glide, lightly staggered, on the same curve as the side drawers, so a
   page assembles progressively instead of hard-swapping. The inline
   drawers/overlays/modals (position:fixed) are excluded so they stay
   viewport-anchored; `backwards` fill keeps a block hidden through its delay
   and leaves NO retained transform once it settles. */
.page.active > * { animation: page-enter .42s var(--ease-liquid) backwards; }
.page.active > *:nth-child(1) { animation-delay: 0s; }
.page.active > *:nth-child(2) { animation-delay: .05s; }
.page.active > *:nth-child(3) { animation-delay: .10s; }
.page.active > *:nth-child(4) { animation-delay: .15s; }
.page.active > *:nth-child(5) { animation-delay: .20s; }
.page.active > *:nth-child(n+6) { animation-delay: .24s; }
.page.active > .drawer-overlay,
.page.active > .drawer,
.page.active > .modal-overlay { animation: none; }

@keyframes page-enter {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .page.active > * { animation: none; }
}
.page-head { margin-bottom: 28px; }
h1.display, h2.display {
  font-family: var(--sans);
  font-weight: 400;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  margin: 0 0 6px 0;
}
h1.display { font-size: 44px; }
.lede { color: var(--text-2); margin: 0 0 32px 0; max-width: 720px; }
.muted { color: var(--text-3); font-size: 12px; }

h2 { font-family: var(--sans); font-weight: 400; font-size: 20px; margin: 0; letter-spacing: .5px; text-transform: uppercase; }

/* -- KPI grid -- */
.kpi-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  margin-bottom: 28px;
}
.kpi-card {
  background: var(--bg-2);
  border: 1px solid var(--line);
  padding: 22px 24px;
  border-radius: var(--r-lg);
  position: relative;
  box-shadow: var(--soft-shadow);
}
.kpi-label {
  font-size: 11px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--text-3);
  margin-bottom: 14px;
}
.kpi-value {
  font-family: var(--sans);
  font-size: 32px;
  font-weight: 400;
  color: var(--text-1);
  font-variant-numeric: tabular-nums;
}
.kpi-sub {
  margin-top: 6px;
  font-size: 12px;
  color: var(--text-2);
}
.kpi-card.kpi-accent {
  background: linear-gradient(180deg, rgba(var(--accent-rgb), 0.08) 0%, var(--bg-2) 100%);
  border-color: var(--line-strong);
}
.kpi-card.kpi-accent .kpi-value { color: var(--accent-bright); }
.kpi-card.kpi-clickable {
  cursor: pointer;
  transition: border-color .2s var(--ease-liquid), transform .2s var(--ease-liquid), box-shadow .2s var(--ease-liquid);
}
.kpi-card.kpi-clickable:hover { border-color: var(--accent); transform: translateY(-2px); box-shadow: var(--shadow); }
.kpi-card.kpi-clickable.active {
  border-color: var(--accent);
  background: linear-gradient(180deg, rgba(var(--accent-rgb), 0.10) 0%, var(--bg-2) 100%);
}
/* Compact KPIs for the Stock page (smaller than the Home dashboard) */
.kpi-grid.kpi-stock {
  grid-template-columns: repeat(4, 1fr);
  margin-bottom: 18px;
}
.kpi-grid.kpi-stock .kpi-card { padding: 16px 18px; }
.kpi-grid.kpi-stock .kpi-value { font-size: 24px; }
.kpi-grid.kpi-stock .kpi-label { margin-bottom: 10px; font-size: 10px; }

/* =========================================================
   Jauges d'objectif de l'écran d'accueil (V2.77.0)
   Le propriétaire voulait, à la place des suggestions de réassort, voir
   chaque matin où en est chacun sur son objectif du mois. La forme est
   justifiée en tête de `pages/home/GoalCards.tsx` ; l'essentiel ici :
   - `.goal-pace` est le trait qui marque la part du mois écoulée. C'est
     le repère qui donne son sens au pourcentage, pas un ornement ;
   - aucun `--red` sur la ligne d'une personne. Trois états seulement :
     vert (en avance), cognac (dans le rythme), ambre (à rattraper). Un
     vendeur qui voit rouge tous les matins cesse de regarder l'écran.
   La couleur n'est jamais le seul signal : chaque ligne écrit son statut.
   ========================================================= */
/* CINQ tuiles depuis V2.77.0 (« Same day last year »), d'où `auto-fit`
   plutôt qu'un `repeat(5, 1fr)` : à 1024 px — l'iPad paysage que mesure
   `e2e/responsive.spec.ts` — cinq colonnes fixes écraseraient la tuile
   « Year-to-date », dont la valeur à sept chiffres déborderait. `auto-fit`
   en pose autant que la largeur en autorise, cinq sur un grand écran,
   trois sur un iPad, et le palier téléphone ci-dessous en impose deux. */
.kpi-grid.kpi-home {
  grid-template-columns: repeat(auto-fit, minmax(232px, 1fr));
}

.goal-card { margin-top: 24px; }

.goal-track {
  position: relative;
  height: 10px;
  background: var(--bg-4);
  border: 1px solid var(--line);
  border-radius: 999px;
  overflow: hidden;
}
.goal-fill {
  height: 100%;
  border-radius: 999px;
  background: var(--chart);
  transition: width 0.4s var(--ease-liquid);
}
/* DEUX couleurs, TROIS mots. « En avance » et « dans le rythme » partagent
   le vert : les distinguer par la couleur demandait d'opposer `--chart`
   (cognac, #A85D2E) à `--warn` (ambre, #9C6A10), deux bruns qu'aucun œil ne
   sépare sur une barre de 10 px — vérifié à l'écran. Le mot les distingue,
   la couleur dit seulement « ça va » ou « il faut rattraper ». La bande de
   tolérance de 15 % existe précisément pour qu'un léger retard ne soit pas
   puni : elle doit donc se lire comme bonne. */
.goal-ahead, .goal-on_track { background: var(--green); }
.goal-behind { background: var(--warn); }
.goal-unknown { background: var(--accent-soft); }

/* Le trait de rythme. `transform` le recentre sur sa position pour qu'il
   marque le point exact et non son bord gauche — à 57 % du mois, deux
   pixels de décalage sont visibles à côté d'une barre. */
.goal-pace {
  position: absolute;
  top: -2px;
  bottom: -2px;
  width: 2px;
  transform: translateX(-1px);
  background: var(--text-1);
  opacity: 0.55;
}

/* -- la carte boutique -- */
.goal-store-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}
.goal-store-value {
  font-size: 34px;
  line-height: 1.1;
  color: var(--text-1);
  overflow-wrap: anywhere;
}
.goal-store-of { color: var(--text-3); font-size: 14px; }
.goal-store-pct { margin-left: auto; font-size: 22px; }
.goal-store-foot {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 10px;
  font-size: 13px;
}

/* -- une ligne par vendeur -- */
.goal-note {
  color: var(--text-2);
  font-size: 13px;
  line-height: 1.5;
  background: var(--bg-4);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 10px 12px;
  margin-bottom: 14px;
}
.goal-list { list-style: none; margin: 0; padding: 0; }
.goal-row + .goal-row {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
}
.goal-row-head {
  display: grid;
  grid-template-columns: 24px 1fr auto auto minmax(56px, auto);
  align-items: baseline;
  gap: 10px;
  margin-bottom: 7px;
}
.goal-rank {
  font-size: 12px;
  color: var(--text-3);
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.goal-name {
  font-size: 15px;
  letter-spacing: 0.04em;
  color: var(--text-1);
  overflow-wrap: anywhere;
}
.goal-amount { font-variant-numeric: tabular-nums; color: var(--text-1); }
.goal-target { font-variant-numeric: tabular-nums; color: var(--text-3); font-size: 13px; }
.goal-pct {
  font-variant-numeric: tabular-nums;
  text-align: right;
  font-size: 15px;
}
.goal-row-foot {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 7px;
  font-size: 12px;
}

.goal-text-ahead, .goal-text-on_track { color: var(--green); }
.goal-text-behind { color: var(--warn); }
.goal-text-unknown { color: var(--text-3); }

.goal-chip {
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 3px 10px;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  color: var(--text-2);
  white-space: nowrap;
}
/* Pastilles AJOURÉES et non remplies, comme `.stk-chip` : un fond vert plein
   sous un texte de 11 px tombe sous le rapport de contraste de 4,5:1 exigé
   pour du petit texte, et l'audit axe de `e2e/a11y.spec.ts` le relèverait. */
.goal-chip-ahead, .goal-chip-on_track { border-color: var(--green); color: var(--green); }
.goal-chip-behind { border-color: var(--warn); color: var(--warn); }

/* Family/category chips */
.stock-chips {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}
.stock-chip {
  background: var(--bg-3);
  border: 1px solid var(--line);
  color: var(--text-2);
  padding: 7px 12px;
  font-size: 10px;
  letter-spacing: 1.3px;
  text-transform: uppercase;
  cursor: pointer;
  border-radius: var(--radius-pill);
  font-family: inherit;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  transition: all .12s;
}
.stock-chip:hover { color: var(--text-1); border-color: var(--text-3); }
.stock-chip.active {
  background: rgba(var(--accent-rgb), 0.12);
  border-color: var(--accent);
  color: var(--accent);
}
.stock-chip .chip-count {
  background: rgba(var(--accent-rgb), 0.10);
  padding: 1px 6px;
  border-radius: var(--radius-pill);
  font-size: 10px;
  color: var(--text-2);
}
.stock-chip.active .chip-count { color: var(--accent-bright); background: rgba(var(--accent-rgb), 0.16); }

/* Advanced filter bar (Stock-page-specific tweaks) */
.filter-bar.stock-filters {
  flex-wrap: wrap;
  gap: 8px;
}
.filter-bar.stock-filters select { min-width: 130px; }

/* Stock table clickable rows */
#stock-table tbody tr {
  cursor: pointer;
  transition: background .1s;
}
#stock-table tbody tr:hover {
  background: rgba(var(--accent-rgb), 0.06);
}
#stock-table tbody td.col-type {
  font-size: 10px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-3);
}
#stock-table tbody td.col-type.is-cs       { color: var(--accent); }
#stock-table tbody td.col-type.is-bespoke  { color: var(--accent-bright); }

/* ---- Sales-history page ---- */
.period-chips { margin-bottom: 6px; }
.period-custom {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 14px;
  font-size: 11px;
  letter-spacing: 0.3px;
}
.period-custom input[type="date"] {
  padding: 5px 10px;
  font-size: 12px;
  background: var(--bg-3);
  border: 1px solid var(--line);
  color: var(--text-1);
  border-radius: var(--r-sm);
  font-family: inherit;
}
.period-custom input[type="date"]:focus { border-color: var(--accent); outline: none; }

.group-toggle {
  display: inline-flex;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  overflow: hidden;
}
.group-toggle .group-btn {
  background: var(--bg-3);
  border: none;
  padding: 8px 14px;
  font-size: 10px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-2);
  cursor: pointer;
  font-family: inherit;
  transition: all .12s;
}
.group-toggle .group-btn:hover { color: var(--text-1); }
.group-toggle .group-btn.active {
  background: rgba(var(--accent-rgb), 0.12);
  color: var(--accent);
}
.group-toggle .group-btn + .group-btn { border-left: 1px solid var(--line); }

/* Pagination */
.as-pagination {
  display: flex;
  align-items: center;
  gap: 12px;
  justify-content: center;
  margin: 16px 0 28px;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}
.as-pagination .btn { padding: 6px 14px; font-size: 11px; }
.as-pagination select {
  padding: 6px 10px;
  background: var(--bg-3);
  border: 1px solid var(--line);
  color: var(--text-1);
  border-radius: var(--r-sm);
  font-size: 11px;
  font-family: inherit;
}

/* Tier badge in the All-Sales table */
.tier-badge {
  display: inline-block;
  font-size: 9px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  padding: 2px 7px;
  border-radius: var(--radius-pill);
  font-family: var(--sans);
  border: 1px solid transparent;
}
.tier-badge.tier-signature {
  color: var(--text-2);
  background: var(--bg-4);
  border-color: var(--line);
}
.tier-badge.tier-iconic {
  color: var(--accent);
  background: rgba(var(--accent-rgb), 0.10);
  border-color: rgba(var(--accent-rgb), 0.30);
}
.tier-badge.tier-exotic {
  color: var(--accent-bright);
  background: rgba(var(--accent-rgb), 0.18);
  border-color: var(--accent);
}
.tier-badge.tier-casual {
  color: var(--text-3);
  border-color: var(--line);
}

/* Sales table — clickable rows + client / model links */
#as-table tbody tr {
  cursor: pointer;
  transition: background .1s;
}
#as-table tbody tr:hover {
  background: rgba(var(--accent-rgb), 0.06);
}
#as-table tbody tr.row-return {
  color: var(--red);
}
#as-table tbody .cell-neg { color: var(--red); }
#as-table tbody .as-client {
  color: var(--text-1);
  cursor: pointer;
  border-bottom: 1px dotted var(--line);
}
#as-table tbody .as-client:hover { color: var(--accent); border-color: var(--accent); }
#as-table tbody td.col-type {
  font-size: 10px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-3);
}

/* Insights collapse panel */
.insights-panel {
  margin: 22px 0 28px;
  border-top: 1px solid var(--line);
  padding-top: 14px;
}
.insights-panel summary {
  cursor: pointer;
  list-style: none;
  font-size: 10px;
  letter-spacing: 1.8px;
  text-transform: uppercase;
  color: var(--text-3);
  padding: 6px 0;
  transition: color .12s;
}
.insights-panel summary::-webkit-details-marker { display: none; }
.insights-panel summary:hover { color: var(--text-1); }
.insights-panel[open] summary { color: var(--accent); }
.insights-icon {
  display: inline-block;
  margin-right: 6px;
  transition: transform .15s;
}
.insights-panel[open] .insights-icon { transform: rotate(180deg); }
.insights-body { padding-top: 16px; }
.insights-section { margin-bottom: 24px; }
.insights-row { display: grid; gap: 16px; margin-bottom: 24px; }
.insights-row.insights-two   { grid-template-columns: 1fr 1fr; }
.insights-row.insights-three { grid-template-columns: 1fr 1fr 1fr; }
.insights-block {
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 16px 18px;
}
.insights-h {
  font-size: 10px;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--text-3);
  margin-bottom: 12px;
}

/* Daily volume sparkline (CSS bars) */
.sparkline {
  display: flex;
  align-items: flex-end;
  height: 70px;
  gap: 2px;
  padding: 6px 0;
}
.sparkline-bar {
  flex: 1;
  background: var(--accent);
  opacity: 0.55;
  min-height: 1px;
  border-radius: 1px 1px 0 0;
  transition: opacity .15s;
  position: relative;
}
.sparkline-bar:hover { opacity: 1; }
.sparkline-bar.zero { background: var(--line); opacity: 0.4; min-height: 1px; }
.sparkline-sub { font-size: 11px; margin-top: 8px; }

/* Mix-by horizontal bars */
.mix-row {
  display: grid;
  grid-template-columns: 90px 1fr 70px;
  align-items: center;
  gap: 10px;
  padding: 5px 0;
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}
.mix-row .mix-label {
  font-size: 10px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-2);
}
.mix-row .mix-bar {
  height: 8px;
  background: var(--bg-3);
  border-radius: var(--radius-pill);
  overflow: hidden;
  position: relative;
}
.mix-row .mix-bar-fill {
  height: 100%;
  background: var(--accent-soft);
  border-radius: var(--radius-pill);
  transition: width .25s;
}
.mix-row .mix-bar-fill.tier-iconic    { background: var(--accent); }
.mix-row .mix-bar-fill.tier-exotic    { background: var(--accent-bright); }
.mix-row .mix-bar-fill.tier-signature { background: var(--text-3); }
.mix-row .mix-bar-fill.tier-casual    { background: var(--line-strong); }
.mix-row .mix-amt {
  text-align: right;
  color: var(--text-2);
}
.mix-row .mix-amt .mix-pct {
  display: block;
  color: var(--accent);
  font-size: 11px;
}

/* Top-N lists in the insights blocks */
.top-list { font-size: 12px; }
.top-row {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  padding: 6px 0;
  border-bottom: 1px solid var(--line);
}
.top-row:last-child { border-bottom: none; }
.top-row .top-name {
  font-family: var(--sans);
  font-size: 13px;
  color: var(--text-1);
}
.top-row .top-meta {
  font-variant-numeric: tabular-nums;
  color: var(--text-2);
  text-align: right;
  font-size: 11px;
}
.top-row .top-volume {
  font-family: var(--sans);
  font-size: 13px;
  color: var(--accent);
}

/* Ticket / client drawer sections */
.tkt-d-section { margin-top: 22px; }
.tkt-d-h {
  font-size: 10px;
  letter-spacing: 1.8px;
  text-transform: uppercase;
  color: var(--text-3);
  margin-bottom: 10px;
  border-bottom: 1px solid var(--line);
  padding-bottom: 6px;
}
.tkt-line-card {
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 10px 14px;
  margin-bottom: 8px;
}
.tkt-line-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 4px;
}
.tkt-line-name {
  font-family: var(--sans);
  font-size: 14px;
  color: var(--text-1);
}
.tkt-line-amt {
  font-family: var(--sans);
  font-size: 14px;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.tkt-line-spec {
  font-size: 11px;
  color: var(--text-2);
  letter-spacing: 0.3px;
}
.tkt-line-meta {
  font-size: 10px;
  color: var(--text-3);
  margin-top: 4px;
  letter-spacing: 0.4px;
}

.tkt-tender-row, .kv-row, .cd-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 5px 0;
  font-size: 12px;
  color: var(--text-2);
  border-bottom: 1px solid var(--line);
}
.tkt-tender-row:last-child, .kv-row:last-child, .cd-row:last-child {
  border-bottom: none;
}
.tkt-tender-row .ten-mode {
  font-size: 10px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-2);
}
.tkt-tender-row .ten-amt,
.kv-row .kv-val,
.cd-row .cd-val {
  font-variant-numeric: tabular-nums;
  color: var(--text-1);
}
.kv-row.kv-strong { padding: 10px 0; font-size: 13px; }
.kv-row.kv-strong .kv-val {
  font-family: var(--sans);
  font-size: 18px;
  color: var(--accent-bright);
}

/* Client drawer specifics */
#cd-favmodels .top-row,
#cd-history .top-row { padding: 8px 0; }
#cd-history .top-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2px;
}

/* ---- CS / Bespoke Orders page ---- */
.ord-status-badge {
  display: inline-block;
  font-size: 9px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  padding: 3px 9px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--line);
  background: var(--bg-3);
  color: var(--text-2);
}
.ord-status-badge.s-awaiting-production { color: var(--warn);  border-color: var(--warn); }
.ord-status-badge.s-ready-for-pickup    { color: var(--green); border-color: var(--green); }
.ord-status-badge.s-partially-ready,
.ord-status-badge.s-partially-delivered { color: var(--accent);  border-color: var(--accent); }
.ord-status-badge.s-fully-delivered     { color: var(--text-3); border-color: var(--line); }
.ord-status-badge.s-closed              { color: var(--text-3); border-color: var(--line); }
.ord-status-badge.s-cancelled           { color: var(--red);   border-color: var(--red); }

/* ---- Transfers: the request's status, same shape as the order badge ---- */
.tr-status-badge {
  display: inline-block;
  font-size: 9px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  padding: 3px 9px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--line);
  background: var(--bg-3);
  color: var(--text-2);
  white-space: nowrap;
}
.tr-status-badge.s-asked     { color: var(--warn);   border-color: var(--warn); }
.tr-status-badge.s-accepted  { color: var(--accent); border-color: var(--accent); }
.tr-status-badge.s-transit   { color: var(--accent); border-color: var(--accent); }
.tr-status-badge.s-received  { color: var(--green);  border-color: var(--green); }
.tr-status-badge.s-refused   { color: var(--red);    border-color: var(--red); }
.tr-status-badge.s-cancelled { color: var(--text-3); border-color: var(--line); }

#ord-table tbody tr { cursor: pointer; transition: background .1s; }
#ord-table tbody tr:hover { background: rgba(var(--accent-rgb), 0.06); }

/* Order line cards in the drawer — same style as ticket lines + per-line actions */
.ord-line-card {
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 12px 14px;
  margin-bottom: 10px;
}
.ord-line-head {
  display: flex; justify-content: space-between; align-items: baseline;
  margin-bottom: 4px;
}
.ord-line-name {
  font-family: var(--sans);
  font-size: 14px;
  color: var(--text-1);
}
.ord-line-amt {
  font-family: var(--sans);
  font-size: 14px;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.ord-line-spec { font-size: 11px; color: var(--text-2); }
.ord-line-meta { font-size: 10px; color: var(--text-3); margin-top: 4px; }
.ord-line-actions {
  margin-top: 10px;
  display: flex; gap: 8px; flex-wrap: wrap;
}
.ord-line-actions .btn { padding: 6px 12px; font-size: 11px; }

/* Deliver-modal line picker */
.ord-deliver-line {
  display: grid;
  grid-template-columns: 24px 1fr auto;
  gap: 10px;
  padding: 10px 0;
  align-items: center;
  border-bottom: 1px solid var(--line);
  font-size: 12px;
}
.ord-deliver-line:last-child { border-bottom: none; }
.ord-deliver-line input[type="checkbox"] {
  width: 18px; height: 18px;
  accent-color: var(--accent);
}
.ord-deliver-line .ord-deliver-balance-line {
  font-variant-numeric: tabular-nums;
  color: var(--accent);
}

/* ---- Settings page ---- */
.settings-layout {
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: 28px;
  align-items: start;
}
.settings-nav {
  position: sticky;
  /* Under the bar at its measured height, like the ticket (V2.90.0). */
  top: calc(var(--shell-gap, 0px) + var(--topbar-h, 86px) + 12px);
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-top: 4px;
}
.settings-nav-link {
  padding: 8px 12px;
  font-size: 11px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--text-2);
  border-left: 2px solid transparent;
  text-decoration: none;
  transition: all .12s;
}
.settings-nav-link:hover {
  color: var(--text-1);
  background: var(--bg-2);
}
.settings-nav-link.active {
  color: var(--accent);
  border-left-color: var(--accent);
  background: rgba(var(--accent-rgb), 0.06);
}

.settings-content {
  display: flex;
  flex-direction: column;
  gap: 18px;
  min-width: 0;   /* allow grid item to shrink */
}
.settings-card {
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  scroll-margin-top: 90px;
  box-shadow: var(--soft-shadow);
}
.settings-card.is-editing {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px rgba(var(--accent-rgb), 0.20);
}
.settings-card-head {
  padding: 14px 22px;
  border-bottom: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.settings-card-head h2 {
  margin: 0;
  font-family: var(--sans);
  font-size: 18px;
  font-weight: 400;
  letter-spacing: 0.5px;
  color: var(--text-1);
}
.settings-actions { display: flex; gap: 8px; }
.settings-actions .btn { padding: 5px 14px; font-size: 11px; }
.settings-card-body {
  padding: 16px 22px 18px 22px;
}

/* Field rows inside a settings card */
.set-row {
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: 12px 18px;
  padding: 8px 0;
  align-items: center;
  font-size: 13px;
  border-bottom: 1px solid var(--bg-3);
}
.set-row:last-child { border-bottom: none; }
.set-row .set-label {
  font-size: 10px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--text-3);
}
.set-row .set-value { color: var(--text-1); font-variant-numeric: tabular-nums; }
.set-row .set-value.muted-val { color: var(--text-3); font-style: italic; }
.set-row .set-hint {
  grid-column: 2;
  font-size: 11px;
  color: var(--text-3);
  margin-top: -4px;
  font-style: italic;
}
.set-row input[type="text"],
.set-row input[type="number"],
.set-row input[type="email"],
.set-row input[type="tel"],
.set-row textarea,
.set-row select {
  width: 100%;
  background: var(--bg-3);
  border: 1px solid var(--line-strong);
  color: var(--text-1);
  padding: 8px 12px;
  font-size: 12px;
  border-radius: var(--r-sm);
  font-family: inherit;
}
.set-row textarea {
  resize: vertical;
  min-height: 60px;
  line-height: 1.4;
  font-family: var(--sans);
}
.set-row input:focus,
.set-row textarea:focus,
.set-row select:focus { border-color: var(--accent); outline: none; }
.set-row .set-checkbox-row {
  display: flex; align-items: center; gap: 10px;
  font-size: 12px; color: var(--text-2);
}
.set-row .set-checkbox-row input[type="checkbox"] {
  accent-color: var(--accent);
  width: 16px; height: 16px;
}

/* Label format editor (Office > Labels, V2.51.0; its own page since V2.53.0)

   The generic .set-row puts one control in its second column; these groups
   sit several small fields side by side and let them wrap. A field with no
   type attribute misses `.set-row input[type="text"]` entirely: it keeps its
   intrinsic 20-character width, widens the 1fr track and pushes the whole
   page sideways on a 390px phone. Every input here carries a type. */
/* The label editor is its own page (Office > Labels, V2.53.0). Form on the
   left, preview on the right where it has the width of the real label: the
   whole point of the preview is that it is at true size, and in the 200 px
   field column of a settings card it was 99 px wide and scrolling. */
/* Three columns, the desktop tool's proportions (216 / 1fr / 300): what you
   can add and what is already there, then the label with the whole middle to
   itself, then the properties of whatever is selected. The label is the thing
   being judged, so it gets the room — that is the point of the arrangement. */
.lbl-editor-grid {
  display: grid;
  grid-template-columns: 216px minmax(0, 1fr) 300px;
  gap: 12px;
  align-items: stretch;
  /* Tall enough that the canvas is a workspace rather than a strip; the page
     scrolls, each column scrolls its own content. Bounded by the window: the
     CS card's 47 layers (V2.85.0) otherwise stretched every column to
     1 445 px, and the label, centred in the canvas, sat below the fold. */
  min-height: 560px;
  height: calc(100vh - 240px);
}
.lbl-col {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
  background: var(--bg-2);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-lg);
}
.lbl-col-scroll { overflow: auto; padding: 10px; min-height: 0; }
.lbl-panel-header {
  padding: 9px 12px;
  border-bottom: 1px solid var(--line);
  font-size: 10px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--text-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* The document's commands sit with the title, not in the panels. */
.lbl-head { display: flex; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
.lbl-head > div:first-child { flex: 1 1 320px; min-width: 0; }
.lbl-doc-actions { display: flex; gap: 6px; flex-wrap: wrap; }
.lbl-doc-status { margin: -8px 0 12px; }

.lbl-toolbar {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 10px;
  border-bottom: 1px solid var(--line);
  flex-wrap: wrap;
}
.lbl-spacer { flex: 1 1 auto; }

/* This app's `.btn` is a deliberately grand pill — 11 px by 28 px, uppercase,
   2 px of letter-spacing. It is right for « Save & back up » and wrong for a
   canvas toolbar, where the desktop tool uses 6 by 12. Scoped to the
   container rather than a new modifier class, which is how `.ord-line-actions
   .btn` and `.settings-actions .btn` already do it here. */
.lbl-toolbar .btn,
.lbl-add .btn,
.lbl-doc-actions .btn {
  padding: 6px 12px;
  font-size: 11px;
  letter-spacing: 1px;
}
/* Square, so the icon is not stretched by the text padding above. Specificity
   rather than `!important`, which this repo forbids. */
.lbl-toolbar .btn.lbl-tool { padding: 6px; line-height: 0; }
.lbl-tool svg { width: 16px; height: 16px; display: block; }
.lbl-zoom-btn { min-width: 32px; text-align: center; }
.lbl-zoom-label {
  min-width: 44px;
  text-align: center;
  font-size: 12px;
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}

/* The mat. A checkerboard rather than a flat panel: it reads as "nothing is
   here", which is what surrounds a label, and it makes a white paper edge
   visible without drawing a border that could be mistaken for the label's. */
.lbl-canvas-area {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  place-items: center;
  overflow: auto;
  padding: 32px;
  background: repeating-conic-gradient(var(--bg-4) 0% 25%, var(--bg-2) 0% 50%) 50% / 16px 16px;
}
.lbl-canvas { display: inline-block; }
.lbl-status {
  padding: 8px 10px;
  border-top: 1px solid var(--line);
  font-size: 11px;
  color: var(--text-3);
}

/* A .set-row's second column is a `1fr` track: its automatic minimum is the
   content's min-content width, so the preview at its real 50 mm would widen
   the track and take the whole page sideways with it. Letting the wrapper
   shrink is what makes the .scroll-x around the preview effective — the same
   move the responsive foundations make for .card and the content grids. */
.lbl-editor .set-row > * { min-width: 0; }

.lbl-fields {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.lbl-fields > label {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  color: var(--text-3);
  font-size: 11px;
  letter-spacing: 0.6px;
}
/* Shrinkable, not fixed: on a 390 px phone the second column is ~114 px and
   a rigid field would push its own label off the row. It stays well above the
   44 px tap floor at every tier. */
.lbl-fields > label input[type="number"] { flex: 0 1 5.5rem; min-width: 3rem; }
.lbl-fields .lbl-text { flex: 1 1 12rem; min-width: 0; }
.lbl-fields .set-hint { flex-basis: 100%; margin-top: 0; }
/* The editable preview (V2.54.0).

   The label is white paper, and a white rectangle on a white card is not
   readable as an object — so it sits on a mat. `text-align` centres it rather
   than a flex `justify-content`, which would clip the left side of a label
   wider than its container instead of scrolling to it. */
/* The paper, and the overlay stacked exactly on it. The engine's SVG is sized
   by the wrapper, never by itself: it carries real millimetres, and a zoom
   must not rewrite what prints. */
.lbl-paper {
  position: relative;
  display: block;
  background: #fff;
  box-shadow: 0 0 0 1px var(--line-strong), 0 8px 24px rgb(15 23 42 / 0.14);
  touch-action: none;              /* a drag on a tablet must not scroll the page */
}
.lbl-paper-svg svg { display: block; width: 100%; height: 100%; }
.lbl-overlay { position: absolute; inset: 0; }
.lbl-margin {
  fill: none;
  stroke: var(--accent);
  opacity: 0.45;
  pointer-events: none;
  vector-effect: non-scaling-stroke;
}
.lbl-hit {
  fill: transparent;
  stroke: transparent;
  cursor: move;
  vector-effect: non-scaling-stroke;
}
.lbl-hit:hover { stroke: var(--accent); opacity: 0.6; }
.lbl-hit.is-selected { stroke: var(--accent); opacity: 1; }
.lbl-hit.is-locked { cursor: not-allowed; }
.lbl-handle { fill: var(--bg-2); stroke: var(--accent); vector-effect: non-scaling-stroke; }

/* -- the layer list -- */
.lbl-add { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.lbl-add .btn { display: inline-flex; align-items: center; gap: 6px; }
.lbl-kind { width: 14px; height: 14px; flex: none; }

.lbl-layer-list { list-style: none; margin: 0; padding: 0; }
.lbl-layer {
  display: flex;
  align-items: center;
  gap: 8px;
  border-bottom: 1px solid var(--bg-3);
}
.lbl-layer:last-child { border-bottom: none; }
.lbl-layer.is-selected { background: var(--bg-4); }
.lbl-layer-name {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1 1 auto;
  min-width: 0;
  background: none;
  border: none;
  color: var(--text-1);
  font: inherit;
  font-size: 12px;
  text-align: left;
  padding: 6px 8px;
  cursor: pointer;
}
.lbl-layer-name span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lbl-layer-tools { display: flex; gap: 2px; flex: none; padding-right: 4px; }
.lbl-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  background: none;
  border: none;
  border-radius: var(--r-sm);
  color: var(--text-3);
  cursor: pointer;
}
.lbl-icon svg { width: 15px; height: 15px; }
.lbl-icon:hover:not(:disabled) { color: var(--text-1); background: var(--bg-3); }
.lbl-icon:disabled { opacity: 0.35; cursor: default; }
.lbl-icon[aria-pressed="true"] { color: var(--accent); }

/* -- the properties panel -- */
.lbl-props { display: flex; flex-direction: column; gap: 10px; }
.lbl-section {
  font-size: 10px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--text-3);
  border-bottom: 1px solid var(--bg-3);
  padding-bottom: 4px;
  margin-top: 4px;
}
/* Three across in a 300 px panel: a select needs the room, and a fourth
   column would make every label truncate. Position and size is the exception
   — four short numbers that belong on one line, read as a set. */
.lbl-props .lbl-grid-4 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.lbl-props .lbl-grid-xywh { grid-template-columns: repeat(4, minmax(0, 1fr)); }
/* A long caption would otherwise be squeezed into a third of the panel. */
.lbl-props .lbl-check { grid-column: 1 / -1; }
.lbl-field { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.lbl-field > span, .lbl-mm > span {
  font-size: 10px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-3);
}
.lbl-grid-4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
.lbl-mm { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.lbl-check {
  display: flex;
  align-items: center;
  gap: 8px;
  align-self: end;
  font-size: 12px;
  color: var(--text-2);
  min-width: 0;
}
.lbl-check input { width: 16px; height: 16px; flex: none; }
.lbl-props input[type="text"], .lbl-props input[type="number"], .lbl-props select {
  width: 100%;
  min-width: 0;
  background: var(--bg-3);
  border: 1px solid var(--line-strong);
  color: var(--text-1);
  padding: 8px 10px;
  font-size: 12px;
  border-radius: var(--r-sm);
  font-family: inherit;
}
.lbl-props code {
  background: var(--bg-4);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 0 4px;
}
.lbl-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 12px;
}

/* Tag-style list editor (vendors, payment modes) */
.tag-list { display: flex; flex-wrap: wrap; gap: 6px; }
.tag-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--bg-3);
  border: 1px solid var(--line);
  padding: 5px 10px;
  font-size: 11px;
  letter-spacing: 0.5px;
  border-radius: var(--radius-pill);
  color: var(--text-2);
}
.tag-chip.is-default {
  border-color: var(--accent);
  color: var(--accent);
}
.tag-chip-remove {
  background: transparent;
  border: none;
  color: var(--text-3);
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
  padding: 0 2px;
}
.tag-chip-remove:hover { color: var(--red); }
.tag-add-row {
  display: flex; gap: 6px; margin-top: 8px;
}
.tag-add-row input {
  flex: 1;
  min-width: 0;
  background: var(--bg-3);
  border: 1px solid var(--line);
  color: var(--text-1);
  padding: 6px 10px;
  font-size: 12px;
  border-radius: var(--r-sm);
  font-family: inherit;
}

/* Per-vendor commission overrides table */
.commission-overrides {
  margin-top: 12px;
  border-top: 1px solid var(--line);
  padding-top: 10px;
}
.commission-overrides table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}
.commission-overrides th {
  text-align: left;
  font-size: 9px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-3);
  padding: 6px 8px;
  border-bottom: 1px solid var(--line);
}
.commission-overrides td {
  padding: 6px 8px;
  border-bottom: 1px solid var(--bg-3);
  color: var(--text-2);
}
.commission-overrides input {
  width: 100%;
  background: var(--bg-3);
  border: 1px solid var(--line);
  color: var(--text-1);
  padding: 4px 8px;
  font-size: 12px;
  border-radius: var(--r-sm);
  font-family: inherit;
  text-align: right;
}

/* Tier system explanation card (read-only) */
.tier-explain-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}
@media (max-width: 1023px) {
  .tier-explain-grid { grid-template-columns: 1fr; }
}
.tier-explain-card {
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 14px 16px;
}
.tier-explain-card.tier-iconic-card    { border-color: rgba(var(--accent-rgb), 0.40); }
.tier-explain-card.tier-exotic-card    { border-color: var(--accent); }
.tier-explain-card.tier-signature-card { border-color: var(--text-3); }
.tier-explain-card.tier-casual-card    { border-color: var(--line-strong); }
.tier-explain-name {
  font-family: var(--sans);
  font-size: 16px;
  color: var(--text-1);
  margin-bottom: 8px;
}
.tier-explain-iconic    .tier-explain-name { color: var(--accent); }
.tier-explain-exotic    .tier-explain-name { color: var(--accent-bright); }
.tier-explain-body {
  font-size: 12px;
  color: var(--text-2);
  line-height: 1.6;
}
.tier-explain-list {
  margin: 8px 0 0 0;
  padding-left: 18px;
  font-size: 11px;
  color: var(--text-3);
}

/* Floating dirty-state banner */
.settings-dirty-bar {
  display: none;
  position: fixed;
  bottom: 22px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--bg-2);
  border: 1px solid var(--accent);
  border-radius: var(--r-md);
  box-shadow: 0 8px 32px rgba(var(--accent-rgb), 0.18);
  padding: 12px 18px;
  font-size: 12px;
  color: var(--text-1);
  z-index: 600;
  align-items: center;
  gap: 14px;
}
.settings-dirty-bar.show { display: flex; }
.settings-dirty-bar .btn { padding: 6px 14px; }
.settings-dirty-bar #settings-dirty-section {
  color: var(--accent);
  font-weight: 500;
  text-transform: capitalize;
}

/* Tablet portrait and below: the side nav becomes a wrapping row */
@media (max-width: 1023px) {
  .settings-layout { grid-template-columns: 1fr; }
  /* Below 1024 the three columns cannot each hold a form. They stack, and
     the label keeps the top: it is what the person came to look at. The
     canvas gets a fixed height rather than filling a column that no longer
     has one. */
  .lbl-editor-grid { grid-template-columns: 1fr; min-height: 0; height: auto; }
  .lbl-editor-grid > :nth-child(2) { order: -1; }
  .lbl-canvas-area { height: 340px; padding: 20px; }
  .lbl-col-scroll { overflow: visible; }
  /* Four number fields side by side stop being typeable well before this. */
  .lbl-grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* Under a coarse pointer every one of these buttons is 44 px wide (the tap
     floor), and six of them do not fit beside a name on a phone. The row
     becomes two: what the layer is, then what you can do to it. */
  .lbl-layer { flex-wrap: wrap; padding-bottom: 4px; }
  .lbl-layer-name { flex-basis: 100%; }
  .lbl-layer-tools { flex-wrap: wrap; padding-left: 4px; }
  .settings-nav { position: static; flex-direction: row; flex-wrap: wrap; }
  .settings-nav-link { border-left: none; border-bottom: 2px solid transparent; }
  .settings-nav-link.active { border-bottom-color: var(--accent); border-left: none; }
}

/* ---- Stock drill-down drawer ---- */
.stk-d-section { margin-top: 22px; }
.stk-d-h {
  font-size: 10px;
  letter-spacing: 1.8px;
  text-transform: uppercase;
  color: var(--text-3);
  margin-bottom: 10px;
  border-bottom: 1px solid var(--line);
  padding-bottom: 6px;
}

/* Velocity tiles (4-tile row) */
.velocity-grid {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1fr;
  gap: 10px;
}
.velocity-tile {
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 12px 14px;
}
.velocity-tile.vt-totals {
  background: linear-gradient(180deg, rgba(var(--accent-rgb), 0.08) 0%, var(--bg-3) 100%);
  border-color: var(--line-strong);
}
.vt-label {
  font-size: 9px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--text-3);
  margin-bottom: 6px;
}
.vt-value {
  font-family: var(--sans);
  font-size: 20px;
  color: var(--text-1);
  font-variant-numeric: tabular-nums;
}
.velocity-tile.vt-totals .vt-value { color: var(--accent-bright); }
.vt-sub {
  font-size: 11px;
  color: var(--text-3);
  margin-top: 4px;
  font-variant-numeric: tabular-nums;
}

/* Size matrix — last × size heatmap */
.size-matrix-wrap { overflow-x: auto; padding-bottom: 4px; }
.size-matrix {
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
  font-size: 12px;
}
.size-matrix th, .size-matrix td {
  border: 1px solid var(--line);
  padding: 8px 10px;
  text-align: center;
  min-width: 42px;
}
.size-matrix thead th,
.size-matrix tbody th {
  background: var(--bg-3);
  font-weight: 400;
  color: var(--text-3);
  font-size: 10px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
}
.size-matrix tbody th { text-align: left; padding: 8px 12px; }
.size-matrix tbody td { background: var(--bg-2); color: var(--text-2); }
/* Heatmap intensity (qty = 0 → empty / 1 → soft / 2+ → medium / 3+ → strong) */
.size-matrix tbody td.cell-0 { color: var(--text-3); }
.size-matrix tbody td.cell-1 { background: rgba(var(--green-rgb), 0.10); color: var(--green); }
.size-matrix tbody td.cell-2 { background: rgba(var(--green-rgb), 0.20); color: var(--green); font-weight: 600; }
.size-matrix tbody td.cell-3 { background: rgba(var(--green-rgb), 0.32); color: var(--green); font-weight: 700; }
.size-matrix tbody td.cell-hot {
  background: rgba(var(--accent-rgb), 0.18);
  color: var(--accent-bright);
  font-weight: 700;
}

/* -- quick action tiles -- */
.quick-actions {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  margin-bottom: 28px;
}
.action-tile {
  background: var(--bg-2);
  border: 1px solid var(--line);
  padding: 24px;
  border-radius: var(--r-lg);
  display: block;
  transition: border-color .2s, transform .15s, background .2s;
  box-shadow: var(--soft-shadow);
}
.action-tile:hover {
  border-color: var(--accent);
  background: var(--bg-3);
  transform: translateY(-1px);
}
.tile-title {
  font-family: var(--sans);
  font-size: 22px;
  color: var(--accent);
  margin-bottom: 4px;
}
.tile-sub { font-size: 12px; color: var(--text-3); letter-spacing: 1px; }

/* -- card -- */
.card {
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 24px;
  margin-bottom: 24px;
  box-shadow: var(--soft-shadow);
}
.card-header {
  display: flex; justify-content: space-between; align-items: baseline;
  margin-bottom: 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--line);
}

/* -- form blocks -- */
.sale-form { max-width: 980px; }
.block {
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 20px 24px 24px 24px;
  margin: 0 0 18px 0;
  background: var(--bg-2);
  box-shadow: var(--soft-shadow);
}
.block legend {
  padding: 0 8px;
  font-family: var(--sans);
  font-size: 16px;
  letter-spacing: 1px;
  color: var(--accent);
}
.field { display: flex; flex-direction: column; gap: 6px; }
.field label {
  font-size: 11px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-3);
}
.field input, .field select, textarea, .filter-bar input, .filter-bar select {
  background: var(--bg-1);
  border: 1px solid var(--line);
  color: var(--text-1);
  padding: 9px 12px;
  border-radius: var(--r-sm);
  font-size: 14px;
  font-family: inherit;
  outline: none;
  transition: border-color .15s;
}
.field input:focus, .field select:focus, textarea:focus, .filter-bar input:focus {
  border-color: var(--accent);
}
.field input::placeholder { color: var(--text-3); }
textarea { width: 100%; resize: vertical; }

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

/* -- type cards (radio) -- */
.type-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
.type-card {
  position: relative;
  cursor: pointer;
  text-align: center;
  padding: 16px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  font-family: var(--sans);
  font-size: 17px;
  color: var(--text-2);
  transition: all .15s;
}
.type-card:hover { color: var(--text-1); border-color: var(--line-strong); }
.type-card input[type="radio"] {
  position: absolute; opacity: 0; pointer-events: none;
}
.type-card:has(input:checked) {
  background: rgba(var(--accent-rgb), 0.08);
  border-color: var(--accent);
  color: var(--accent);
}

/* -- autocomplete -- */
.autocomplete { position: relative; }
.suggestions {
  position: absolute;
  top: calc(100% + 4px); left: 0; right: 0;
  background: var(--bg-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  list-style: none;
  margin: 0; padding: 0;
  max-height: 220px;
  overflow-y: auto;
  z-index: 30;
  display: none;
  box-shadow: var(--shadow);
}
.suggestions.open { display: block; }
.suggestions li {
  padding: 8px 12px;
  cursor: pointer;
  font-size: 13px;
  border-bottom: 1px solid var(--line);
}
.suggestions li:hover { background: var(--bg-4); color: var(--accent); }
.suggestions li:last-child { border-bottom: 0; }
.suggestions li.create-new { color: var(--accent); font-style: italic; }

/* -- item lines (multi-item ticket) -- */
.item-line {
  border: 1px solid var(--line);
  background: var(--bg-3);
  border-radius: var(--r-md);
  padding: 16px 20px 18px;
  margin-bottom: 14px;
  position: relative;
}
.item-line-head {
  display: flex; gap: 18px; align-items: center;
  margin-bottom: 14px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--line);
}
.line-num {
  font-family: var(--sans);
  font-size: 17px;
  color: var(--accent);
  min-width: 80px;
}
.type-mini { display: flex; gap: 8px; flex: 1; }
.type-mini label {
  position: relative;
  cursor: pointer;
  padding: 6px 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  font-size: 11px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-2);
  transition: all .15s;
}
.type-mini label:hover { color: var(--text-1); border-color: var(--line-strong); }
.type-mini input[type="radio"] { position: absolute; opacity: 0; pointer-events: none; }
.type-mini label:has(input:checked) {
  background: rgba(var(--accent-rgb), 0.1);
  border-color: var(--accent);
  color: var(--accent);
}
.btn-remove {
  background: transparent; border: 1px solid var(--line); color: var(--text-3);
  width: 28px; height: 28px; border-radius: 50%;
  font-size: 18px; line-height: 1; cursor: pointer;
  transition: all .15s;
  font-family: inherit;
}
.btn-remove:hover { color: var(--red); border-color: var(--red); }
.line-subtotal-tile { justify-content: flex-end; }
.line-subtotal {
  background: var(--bg-2);
  border: 1px solid var(--line);
  padding: 9px 12px;
  border-radius: var(--r-sm);
  font-family: var(--sans);
  font-size: 16px;
  color: var(--accent);
  text-align: right;
  font-variant-numeric: tabular-nums;
  min-height: 38px;
  display: flex; align-items: center; justify-content: flex-end;
}
.item-line .stock-widget {
  margin-top: 14px;
  padding: 12px 16px;
  grid-template-columns: 160px 1fr;
}
.item-line .sw-value { font-size: 22px; }

/* -- stock widget -- */
.stock-widget {
  margin-top: 16px;
  padding: 16px 20px;
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-left: 3px solid var(--text-3);
  border-radius: var(--r-lg);
  display: grid;
  grid-template-columns: 200px 1fr;
  align-items: center;
  gap: 16px;
  transition: border-left-color .25s, border-color .15s;
  position: relative;
}
.stock-widget.in-stock  { border-left-color: var(--green); }
.stock-widget.out-stock { border-left-color: var(--red); }
.stock-widget.clickable { cursor: pointer; }
.stock-widget.clickable:hover { border-color: var(--accent); }
.sw-label {
  font-size: 11px; letter-spacing: 2px; text-transform: uppercase; color: var(--text-3);
}
.sw-value {
  font-family: var(--sans);
  font-size: 28px;
  color: var(--accent);
}
.stock-widget.in-stock .sw-value  { color: var(--green); }
.stock-widget.out-stock .sw-value { color: var(--red); }
.sw-hint { color: var(--text-2); font-size: 12px; grid-column: 1 / -1; }
.sw-caret {
  display: none;
  position: absolute;
  top: 14px; right: 18px;
  font-size: 13px;
  color: var(--text-3);
  transition: transform .15s, color .15s;
  pointer-events: none;
  font-family: var(--sans);
}
.stock-widget.clickable .sw-caret { display: block; }
.stock-widget.expanded   .sw-caret { transform: rotate(180deg); color: var(--accent); }

/* Expandable list of individual stock units (one card per pair). */
.stock-units {
  display: none;
  margin-top: 6px;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--bg-2);
  max-height: 320px;
  overflow-y: auto;
}
.stock-units.show { display: block; }
.stock-units-empty {
  padding: 18px;
  text-align: center;
  color: var(--text-3);
  font-style: italic;
  font-size: 12px;
}
.stock-unit-card {
  padding: 10px 14px;
  border-bottom: 1px solid var(--line);
  cursor: pointer;
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 4px 12px;
  transition: background .12s, border-color .12s;
  align-items: center;
}
.stock-unit-card:last-child { border-bottom: none; }
.stock-unit-card:hover {
  background: var(--bg-3);
}
.stock-unit-card.active {
  background: rgba(var(--accent-rgb), 0.08);
  border-left: 2px solid var(--accent);
  padding-left: 12px;
}
.stock-unit-spec {
  font-family: var(--sans);
  font-size: 12px;
  color: var(--text-1);
  letter-spacing: 0.3px;
  line-height: 1.4;
}
.stock-unit-meta {
  font-size: 10px;
  color: var(--text-3);
  margin-top: 3px;
  letter-spacing: 0.3px;
}
.stock-unit-meta .badge-cs       { color: var(--accent); }
.stock-unit-meta .badge-good     { color: var(--green); }
.stock-unit-meta .badge-defect   { color: var(--red); }
.stock-unit-side {
  text-align: right;
  font-size: 10px;
  color: var(--text-3);
  letter-spacing: 0.3px;
}
.stock-unit-card:hover .stock-unit-pick { color: var(--accent-bright); }
.stock-unit-pick {
  font-size: 9px;
  letter-spacing: 1.3px;
  text-transform: uppercase;
  color: var(--accent);
  margin-top: 4px;
  transition: color .12s;
}
.stock-unit-bc {
  font-family: monospace;
  font-size: 10px;
  letter-spacing: 1.5px;
  color: var(--text-3);
}

/* -- totals -- */
.totals-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-top: 16px; }
.total-tile {
  background: var(--bg-3);
  border: 1px solid var(--line);
  padding: 14px 18px;
  border-radius: var(--r-lg);
}
.t-label { font-size: 11px; letter-spacing: 2px; text-transform: uppercase; color: var(--text-3); margin-bottom: 6px; }
.t-value { font-family: var(--sans); font-size: 24px; color: var(--text-1); font-variant-numeric: tabular-nums; }

/* -- buttons -- */
.actions { display: flex; gap: 12px; justify-content: flex-end; margin-top: 8px; }
.btn {
  padding: 11px 28px;
  border-radius: var(--radius-pill);
  font-size: 12px;
  letter-spacing: 2px;
  text-transform: uppercase;
  cursor: pointer;
  font-family: inherit;
  transition: all .15s;
  border: 1px solid var(--line-strong);
  background: transparent;
  color: var(--text-1);
}
.btn:hover { border-color: var(--accent); color: var(--accent); }
/* .btn-primary/.btn-pay are the app's one deliberate solid-fill button: the
   real CORTHAY site never needs a filled CTA (no transactional urgency),
   but a POS's Pay/Save/Confirm actions do — kept as the single departure
   from the charter's transparent-pill rule. */
.btn-primary {
  background: var(--accent);
  color: var(--on-accent);
  border-color: var(--accent);
  font-weight: 600;
}
.btn-primary:hover { background: var(--accent-bright); border-color: var(--accent-bright); color: var(--on-accent); }
.btn-ghost { background: transparent; color: var(--text-2); }

/* -- filter bar -- */
.filter-bar {
  display: flex; gap: 12px; align-items: center;
  margin-bottom: 16px; flex-wrap: wrap;
}
.filter-bar input { flex: 1 1 300px; }
.filter-bar select { min-width: 180px; }
.filter-bar .check {
  display: flex; gap: 6px; align-items: center;
  font-size: 12px; color: var(--text-2);
}
.filter-bar .inline { display: inline-flex; gap: 8px; align-items: center; font-size: 12px; color: var(--text-2); }
.filter-bar .inline input { width: auto; padding: 6px 10px; }

/* -- tables -- */
.data-table { width: 100%; border-collapse: collapse; }
.data-table th, .data-table td {
  text-align: left;
  padding: 10px 12px;
  border-bottom: 1px solid var(--line);
  font-size: 13px;
}
.data-table th {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 1.2px;
  color: var(--text-3);
  font-weight: 500;
}
.data-table td.num, .data-table th.num { text-align: right; font-variant-numeric: tabular-nums; }
.data-table tbody tr { cursor: pointer; transition: background .12s; }
.data-table tbody tr:hover { background: var(--bg-3); }
.data-table tbody tr.selected { background: var(--bg-4); }

/* -- wide scrollable table (All Sales) -- */
.scroll-x {
  overflow-x: auto;
  padding: 0;
}
/* Dense cells for the source-file-like Detailed view (~30 columns). */
.data-table.dense th, .data-table.dense td {
  padding: 6px 8px;
  font-size: 12px;
  white-space: nowrap;
}
.data-table.dense td.cell-comments {
  max-width: 240px;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* -- BL entry: what the workshop wrote, under each line -- */
/* Doublure, semelle, talon, lacets, options et recette de patine ne
   rentrent dans aucune colonne du stock, et ce sont elles qui distinguent
   la paire. Sous la ligne plutôt que dans une infobulle : une recette de
   patine se relit, elle ne se survole pas. */
.data-table.dense tr.bl-detail td {
  padding: 2px 10px 10px 10px;
  border-top: 0;
}
/* La largeur est bornée par une boîte INTÉRIEURE, pas par la cellule : un
   `colSpan` qui s'étale pousse la table plus large que l'écran, et le
   texte finit hors du champ dans le `.scroll-x`. Une recette de patine
   qu'il faut scroller horizontalement pour lire n'est pas lisible. */
.data-table.dense tr.bl-detail .bl-detail-text {
  max-width: 640px;
  white-space: normal;
  font-size: 11px;
  color: var(--text-3);
  line-height: 1.6;
}

/* -- BL entry: the customer orders the note carries -- */
.bl-orders {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}
.bl-orders-label {
  font-size: 11px; letter-spacing: 1.5px; text-transform: uppercase;
  color: var(--text-3); margin-bottom: 6px;
}
.bl-orders ul { margin: 0; padding-left: 18px; }
.bl-orders li { font-size: 12px; color: var(--text-2); line-height: 1.7; }

/* Column picker for the Detailed view (native <details> popover). */
.col-picker { position: relative; margin-bottom: 10px; display: inline-block; }
.col-picker > summary {
  cursor: pointer;
  list-style: none;
  display: inline-block;
  padding: 6px 14px;
  border: 1px solid var(--line);
  font-size: 10px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-2);
  transition: border-color .15s, color .15s;
}
.col-picker > summary::-webkit-details-marker { display: none; }
.col-picker > summary:hover, .col-picker[open] > summary { border-color: var(--accent); color: var(--accent); }
.col-picker .col-picker-menu {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 40;
  background: var(--bg-2);
  border: 1px solid var(--line-strong);
  padding: 14px 18px;
  display: grid;
  grid-template-columns: repeat(3, minmax(130px, 1fr));
  gap: 5px 18px;
  box-shadow: var(--shadow);
}
.col-picker label {
  font-size: 12px;
  color: var(--text-2);
  display: flex;
  gap: 7px;
  align-items: center;
  cursor: pointer;
  white-space: nowrap;
}
.col-picker label:hover { color: var(--text-1); }
.scroll-x::-webkit-scrollbar { height: 10px; }
.scroll-x::-webkit-scrollbar-track { background: var(--bg-1); }
.scroll-x::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 5px; }
.scroll-x::-webkit-scrollbar-thumb:hover { background: var(--text-3); }
.data-table.wide {
  min-width: 2400px;
  white-space: nowrap;
  font-size: 12px;
}
.data-table.wide th, .data-table.wide td {
  padding: 8px 10px;
}
.data-table.wide td.cell-mute { color: var(--text-3); }
.data-table.wide td.cell-pos  { color: var(--green); }
.data-table.wide td.cell-neg  { color: var(--red); }
.data-table.wide tr.row-return td { background: rgba(var(--red-rgb), 0.05); }
.data-table.wide td.action a { color: var(--accent); font-size: 11px; letter-spacing: 1px; text-transform: uppercase; }

/* -- two-column for clients -- */
.two-col { display: grid; grid-template-columns: 1.4fr 1fr; gap: 24px; align-items: start; }
.client-detail { min-height: 400px; }

/* -- commissions -- */
.commission-grid {
  display: grid;
  grid-template-columns: 1.2fr 1fr;
  gap: 24px;
  margin-bottom: 24px;
}
.big-number {
  font-family: var(--sans);
  font-size: 56px;
  color: var(--accent-bright);
  font-variant-numeric: tabular-nums;
  margin: 12px 0 8px 0;
}
.rule-row {
  display: flex; justify-content: space-between;
  padding: 8px 0;
  border-bottom: 1px solid var(--line);
  font-size: 13px;
}
.rule-row:last-child { border-bottom: 0; }
.rule-row .v { color: var(--accent); font-variant-numeric: tabular-nums; }

/* -- toast -- */
.toast {
  position: fixed;
  /* À GAUCHE depuis le 2026-09-16, et pas par goût : le bas-droit est occupé
     sur TOUS les paliers. Au-dessus de 1024 c'est le pied du ticket (Clear /
     Pay), en dessous de 600 c'est le bouton flottant « aller au ticket ».
     Le toast d'un ajout au panier masquait donc exactement le bouton sur
     lequel on venait de cliquer (propriétaire, 2026-09-16). La colonne de
     gauche est le catalogue à toutes les largeurs : une seule règle, aucune
     requête média, aucun couplage à la largeur du ticket. */
  bottom: 32px; left: 32px;
  background: var(--bg-3);
  border: 1px solid var(--line-strong);
  border-left: 3px solid var(--accent);
  padding: 14px 22px;
  border-radius: var(--r-md);
  font-size: 13px;
  color: var(--text-1);
  /* Above every drawer/modal overlay (max existing z-index is 600) —
     a validation-error toast fired while a drawer is open (the common
     case: e.g. "Add to ticket" with an incomplete composition) must
     stay visible, not render behind the drawer panel. */
  z-index: 700;
  box-shadow: var(--shadow);
  opacity: 0;
  transform: translateY(20px);
  transition: opacity .25s, transform .25s;
  pointer-events: none;
  max-width: 420px;
}
.toast.show { opacity: 1; transform: translateY(0); }
.toast.error { border-left-color: var(--red); }
.toast.warn  { border-left-color: var(--warn); }

/* =========================================================
   CEGID-STYLE COMPONENTS (V2.3)
   ========================================================= */

/* -- Drawer (slide-in from right) -- */
.drawer-overlay {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.5);
  opacity: 0; pointer-events: none;
  transition: opacity .18s ease;
  z-index: 500;
  backdrop-filter: blur(2px);
}
.drawer-overlay.open { opacity: 1; pointer-events: auto; }
.drawer {
  position: fixed; top: 0; right: 0; bottom: 0;
  width: 480px; max-width: 100vw;
  background: var(--bg-2);
  border-left: 1px solid var(--line-strong);
  transform: translateX(100%);
  transition: transform .25s cubic-bezier(.2,.8,.3,1);
  z-index: 510;
  display: flex; flex-direction: column;
  overflow: hidden;
}
.drawer.wide { width: 640px; }
/* The cross-boutique stock search (V2.59.0): a six-column table with its
   own filter bar above it. 640px puts it permanently inside `.scroll-x`;
   this width lets it be read without dragging sideways. */
.drawer.widest { width: 960px; }
/* New Sale's phone ticket drawer (owner, 2026-09-10) can itself open
   another drawer on top of it — editing a line opens the Configurator,
   picking a client opens CustomerDrawer. At the default z-index (510,
   same as every drawer) whichever mounted LATER in the JSX painted on
   top regardless of which the user actually opened, so tapping "Select
   client" while the ticket was open could open CustomerDrawer BEHIND it
   — invisible, looked like nothing happened. Pinning the ticket drawer
   one level below every other (still-default-510) drawer/modal fixes it
   unconditionally, without depending on render order. */
.drawer.ticket-drawer { z-index: 505; }
/* The shadow only on an OPEN drawer: closed, it sits just off the right
   edge and its 32 px shadow spilled back onto the page — a grey veil down
   the right of every phone screen (owner's screenshot, 2026-09-27). */
.drawer.open { transform: translateX(0); box-shadow: -8px 0 32px rgba(var(--accent-rgb), 0.20); }
/* From tablet width up the drawer floats, rounded, off the window's edge
   (V2.86.0). Closed, it moves out by its width AND its margin, or a sliver
   of it would stay on screen. A phone keeps it edge to edge. */
@media (min-width: 600px) {
  .drawer {
    top: 12px; right: 12px; bottom: 12px;
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    transform: translateX(calc(100% + 24px));
  }
  .drawer.open { transform: translateX(0); }
}
.drawer-header {
  padding: 20px 28px;
  border-bottom: 1px solid var(--line);
  display: flex; align-items: center; justify-content: space-between;
}
.drawer-title {
  font-family: var(--sans);
  font-size: 22px;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--accent);
}
.drawer-close {
  background: transparent; border: 1px solid var(--line); color: var(--text-2);
  width: 36px; height: 36px; border-radius: 50%;
  font-size: 18px; line-height: 1; cursor: pointer; font-family: inherit;
  transition: all .15s;
}
.drawer-close:hover { color: var(--accent); border-color: var(--accent); }
/* The header's validating action, beside the close button (V2.86.1): a
   filled round check, the one solid control of the header. */
.drawer-header-actions { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.drawer-confirm {
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; border-radius: 50%;
  background: var(--accent); color: var(--on-accent); border: 1px solid var(--accent);
  cursor: pointer; transition: background .15s, opacity .15s;
}
.drawer-confirm:hover { background: var(--accent-bright); border-color: var(--accent-bright); }
.drawer-confirm:disabled { opacity: .4; cursor: not-allowed; }
.drawer-confirm svg { width: 18px; height: 18px; }
.drawer-body { flex: 1; overflow-y: auto; padding: 24px 28px; }
.drawer-footer {
  padding: 18px 28px;
  border-top: 1px solid var(--line);
  background: var(--bg-3);
  display: flex; gap: 12px; justify-content: flex-end;
}

/* -- Modal (centered) -- */
.modal-overlay {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.6);
  display: none;
  align-items: center; justify-content: center;
  z-index: 600;
  backdrop-filter: blur(3px);
}
.modal-overlay.open { display: flex; }
.modal {
  background: var(--bg-2);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-lg);
  width: 720px; max-width: 92vw;
  max-height: 92vh;
  max-height: 92dvh;
  overflow: hidden;
  display: flex; flex-direction: column;
  box-shadow: 0 24px 64px rgba(var(--accent-rgb), 0.25);
}
.modal-header {
  padding: 22px 32px;
  border-bottom: 1px solid var(--line);
  display: flex; align-items: center; justify-content: space-between;
}
.modal-title {
  font-family: var(--sans);
  font-size: 26px;
  letter-spacing: 1px;
  color: var(--accent);
}
.modal-body { flex: 1; padding: 24px 32px; overflow-y: auto; }
.modal-footer {
  padding: 18px 32px;
  border-top: 1px solid var(--line);
  background: var(--bg-3);
  display: flex; gap: 12px; justify-content: flex-end;
}

/* -- Touch-friendly inputs (V2.3 sizing) -- */
.touch input, .touch select, .touch textarea {
  font-size: 16px;   /* below 16px iOS Safari zooms the page on focus */
  padding: 12px 14px;
  min-height: 44px;
}
.touch .btn { min-height: 44px; padding: 12px 24px; font-size: 12px; }

/* -- Numeric keypad -- */
.keypad {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}
.keypad button {
  background: var(--bg-3);
  border: 1px solid var(--line);
  color: var(--text-1);
  font-family: var(--sans);
  font-size: 22px;
  padding: 18px 0;
  border-radius: var(--r-md);
  cursor: pointer;
  transition: all .12s;
}
.keypad button:hover { background: var(--bg-4); border-color: var(--accent); color: var(--accent); }
.keypad button.kp-action {
  font-family: var(--sans);
  font-size: 12px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--text-2);
}
/* Full width: Clear wipes the whole amount, so it must not sit a
   thumb's width from "0" or from the new backspace key. */
.keypad button.kp-clear { color: var(--red); grid-column: 1 / -1; }

/* -- Tender amount display -- */
.tender-display {
  background: var(--bg-3);
  border: 1px solid var(--line);
  padding: 18px 22px;
  border-radius: var(--r-md);
  margin-bottom: 16px;
  text-align: right;
}
.tender-display .td-label { font-size: 11px; letter-spacing: 1.5px; text-transform: uppercase; color: var(--text-3); }
.tender-display .td-value {
  font-family: var(--sans);
  font-size: 36px;
  color: var(--accent-bright);
  font-variant-numeric: tabular-nums;
  letter-spacing: 1px;
}

/* -- Quick amounts (100% / 50%) -- */
/* Under the figure they write, above the button that confirms it. Each
   carries the sum it will enter, so the vendor reads the deposit instead
   of computing it at the counter. */
.tender-quick {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
}
.tender-quick button {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  padding: 10px 8px;
  background: var(--bg-3);
  border: 1px solid var(--line);
  color: var(--text-2);
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: all .15s;
  font-family: inherit;
}
.tender-quick .tq-pct {
  font-size: 12px; letter-spacing: 1.5px; text-transform: uppercase;
}
.tender-quick .tq-amt {
  font-size: 11px; color: var(--text-3); font-variant-numeric: tabular-nums;
}
.tender-quick button:hover:not(:disabled) { color: var(--accent); border-color: var(--accent); }
.tender-quick button:hover:not(:disabled) .tq-amt { color: var(--accent); }
/* Nothing left to pay: a 0.00 proposal would only earn "Type an amount
   first" — the button says so before it is pressed. */
.tender-quick button:disabled { opacity: .45; cursor: not-allowed; }

/* -- Tender mode chips -- */
.tender-modes {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
  margin-bottom: 16px;
}
.tender-modes button {
  padding: 14px 8px;
  background: var(--bg-3);
  border: 1px solid var(--line);
  color: var(--text-2);
  font-size: 11px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: all .15s;
  font-family: inherit;
}
.tender-modes button:hover { color: var(--text-1); border-color: var(--line-strong); }
.tender-modes button.active {
  background: rgba(var(--accent-rgb), 0.12);
  border-color: var(--accent);
  color: var(--accent);
}

/* -- Tender list (added tenders) -- */
.tender-list {
  margin: 16px 0;
}
.tender-row {
  display: flex; justify-content: space-between; align-items: center;
  padding: 10px 14px;
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  margin-bottom: 6px;
  font-size: 14px;
}
.tender-row .tr-mode { color: var(--text-2); font-size: 11px; letter-spacing: 1.5px; text-transform: uppercase; }
.tender-row .tr-amt  { font-family: var(--sans); font-size: 18px; color: var(--accent); font-variant-numeric: tabular-nums; }
.tender-row .tr-rm   {
  background: transparent; border: 0; color: var(--text-3);
  cursor: pointer; padding: 4px 8px; font-size: 16px;
}
.tender-row .tr-rm:hover { color: var(--red); }

/* -- Balance summary -- */
.balance-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin: 18px 0;
}
.balance-cell {
  background: var(--bg-3);
  border: 1px solid var(--line);
  padding: 10px 14px;
  border-radius: var(--r-md);
}
.balance-cell .bc-label { font-size: 10px; letter-spacing: 1.5px; text-transform: uppercase; color: var(--text-3); }
.balance-cell .bc-value { font-family: var(--sans); font-size: 20px; font-variant-numeric: tabular-nums; }
.balance-cell.due .bc-value { color: var(--red); }
.balance-cell.change .bc-value { color: var(--green); }
.balance-cell.paid .bc-value { color: var(--accent); }

/* =========================================================
   POS Layout (split-screen catalog | cart)
   ========================================================= */
.pos-wrap {
  display: grid;
  grid-template-columns: 1fr 380px;
  gap: 24px;
  min-height: 70vh;
}
/* The three width tiers (see "Touch & responsive foundations" at the end
   of this file): >= 1200 the historic 380px cart, 1024-1199 a 320px cart
   (an iPad in landscape is 1080 wide and must keep the cart on screen),
   below 1024 one column — the side-drawer / bottom-sheet cart is the
   "caisse tactile" lot, not this one. */
@media (max-width: 1199px) { .pos-wrap { grid-template-columns: 1fr 320px; gap: 16px; } }
@media (max-width: 1023px) { .pos-wrap { grid-template-columns: 1fr; } }

/* -- Catalog pane -- */
.catalog {
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 20px 22px;
  display: flex; flex-direction: column;
  box-shadow: var(--soft-shadow);
}
.catalog-tabs {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
  margin-bottom: 12px;
  padding-bottom: 2px;
}
.catalog-tab {
  background: transparent;
  border: 1px solid var(--line);
  color: var(--text-2);
  padding: 10px 16px;
  font-size: 11px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  cursor: pointer;
  border-radius: var(--radius-pill);
  transition: all .15s;
  font-family: inherit;
}
.catalog-tab:hover { color: var(--text-1); }
/* Filled, like the section in the bar (V2.90.0): the tint read as a second,
   fainter kind of « selected ». */
.catalog-tab.active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}
.catalog-search {
  margin-bottom: 16px;
}
.catalog-search input {
  width: 100%;
  padding: 12px 16px;
  font-size: 14px;
  background: var(--bg-1);
  border: 1px solid var(--line);
  color: var(--text-1);
  border-radius: var(--r-sm);
}
.catalog-search input:focus { border-color: var(--accent); outline: none; }

.catalog-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 10px;
  flex: 1;
  overflow-y: auto;
  padding-right: 4px;
  align-content: start;   /* keep rows at content height — don't stretch to fill */
}
.product-card {
  background: var(--bg-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  padding: 16px 14px;
  cursor: pointer;
  box-shadow: 0 1px 3px rgba(var(--accent-rgb), 0.06);
  transition: background .18s var(--ease-liquid), border-color .18s var(--ease-liquid), transform .18s var(--ease-liquid), box-shadow .18s var(--ease-liquid);
  position: relative;
  display: flex; flex-direction: column;
  height: 140px;          /* fixed: all cards identical; casuals get empty space below */
}
.product-card:hover {
  background: var(--bg-4);
  border-color: var(--accent);
  transform: translateY(-2px);
  box-shadow: var(--shadow);
}
.product-card .pc-cat {
  font-size: 9px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--text-3);
  margin-bottom: 6px;
}
.product-card .pc-name {
  font-family: var(--sans);
  font-size: 17px;
  color: var(--text-1);
  letter-spacing: 0.5px;
  flex: 1;
}
.product-card .pc-price {
  margin-top: 10px;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
}
.product-card .pc-price .pc-tier-marker {
  font-size: 9px;
  letter-spacing: 1px;
  color: var(--text-3);
  margin-right: 4px;
}
.product-card .pc-price .pc-iconic {
  color: var(--accent-bright);
  margin-left: 8px;
}
.product-card .pc-meta {
  font-size: 10px;
  color: var(--text-3);
  margin-top: 4px;
  letter-spacing: 0.5px;
}
.product-card .pc-family {
  position: absolute;
  top: 10px; right: 12px;
  font-size: 8px;
  letter-spacing: 1.2px;
  color: var(--text-3);
  text-transform: uppercase;
  opacity: .7;
}

/* -- Tier system (Signature / Iconic / Exotic / Casual) -- */
.tier-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  padding: 14px 0;
  border-bottom: 1px solid var(--line);
  margin-bottom: 16px;
}
.tier-bar-label {
  font-size: 10px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--text-3);
  margin-right: 4px;
}
.tier-pill {
  font-size: 11px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  padding: 6px 12px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--line-strong);
  background: var(--bg-3);
  color: var(--text-2);
  cursor: pointer;
  transition: all .12s;
  font-family: var(--sans);
}
.tier-pill:hover { border-color: var(--text-3); color: var(--text-1); }
.tier-pill.active[data-tier="SIGNATURE"] {
  border-color: var(--text-2);
  color: var(--text-1);
  background: var(--bg-4);
}
.tier-pill.active[data-tier="ICONIC"] {
  border-color: var(--accent);
  color: var(--accent-bright);
  background: var(--bg-4);
}
.tier-pill.active[data-tier="EXOTIC"] {
  border-color: var(--accent-bright);
  color: var(--accent-bright);
  background: rgba(var(--accent-rgb), 0.08);
}
.tier-pill.active[data-tier="CASUAL"] {
  border-color: var(--text-3);
  color: var(--text-2);
  background: var(--bg-4);
}
.tier-pill .tp-price {
  display: block;
  margin-top: 2px;
  font-size: 10px;
  color: var(--text-3);
  letter-spacing: 0.5px;
  font-variant-numeric: tabular-nums;
}
.tier-pill.active .tp-price { color: var(--text-2); }
.tier-hint {
  font-size: 11px;
  color: var(--text-3);
  font-style: italic;
  line-height: 1.5;
  padding: 4px 0 0 4px;
  flex-basis: 100%;
}

/* Description block in configurator */
.cfg-description {
  font-family: var(--sans);
  font-size: 13px;
  color: var(--text-2);
  font-style: italic;
  line-height: 1.6;
  padding-bottom: 14px;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--line);
}

/* ---- Configurator: type pills (Stock / CS / Bespoke / Service) ---- */
.cfg-type-row {
  margin-bottom: 14px;
}
.cfg-type-label {
  font-size: 9px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--text-3);
  margin-bottom: 6px;
}
.cfg-type-pills {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}
.cfg-type-pill {
  flex: 1;
  background: var(--bg-3);
  border: 1px solid var(--line);
  color: var(--text-2);
  padding: 9px 8px;
  font-size: 10px;
  letter-spacing: 1.3px;
  text-transform: uppercase;
  cursor: pointer;
  border-radius: var(--radius-pill);
  font-family: inherit;
  transition: all .12s;
  min-width: 70px;
}
.cfg-type-pill:hover { color: var(--text-1); border-color: var(--text-3); }
.cfg-type-pill.active {
  background: var(--bg-4);
  border-color: var(--accent);
  color: var(--accent-bright);
}

/* ---- Configurator: compact meta row (size / qty / discount) ---- */
.cfg-meta-row {
  display: grid;
  grid-template-columns: 1.2fr 1fr 1fr;
  gap: 12px;
  margin-bottom: 18px;
}

/* ---- Configurator: tab bar for personalisation dimensions ---- */
.cfg-tab-bar {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
  margin-bottom: 10px;
  border-bottom: 1px solid var(--line);
  padding-bottom: 8px;
}
.cfg-tab {
  background: transparent;
  border: 1px solid var(--line);
  color: var(--text-2);
  padding: 7px 11px;
  font-size: 10px;
  letter-spacing: 1.3px;
  text-transform: uppercase;
  cursor: pointer;
  border-radius: var(--radius-pill);
  transition: all .12s;
  font-family: inherit;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  line-height: 1.2;
}
.cfg-tab:hover { color: var(--text-1); border-color: var(--text-3); }
.cfg-tab.active {
  background: rgba(var(--accent-rgb), 0.12);
  border-color: var(--accent);
  color: var(--accent);
}
.cfg-tab .tab-value {
  color: var(--text-3);
  font-size: 9px;
  text-transform: none;
  letter-spacing: 0;
  font-family: var(--sans);
  font-style: italic;
}
.cfg-tab.active .tab-value { color: var(--accent-bright); }

/* ---- Configurator: tile grid (one tab's worth of options) ---- */
.cfg-tile-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(105px, 1fr));
  gap: 8px;
  margin-bottom: 14px;
  min-height: 80px;
}
.cfg-tile {
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 11px 10px;
  cursor: pointer;
  transition: all .12s;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  min-height: 64px;
  text-align: left;
  position: relative;
  font-family: inherit;
}
.cfg-tile:hover {
  background: var(--bg-4);
  border-color: var(--accent);
  transform: translateY(-1px);
}
/* Selected = FILLED, like the primary button, with a check in the corner.
   Until V2.89.0 a selected tile and an in-tier tile shared the same fill
   and border, and a seller could not tell « chosen » from « in my range »
   (owner, 2026-09-28). Fill means chosen; a side bar means in the tier. */
.cfg-tile.active {
  background: var(--accent);
  border-color: var(--accent);
}
.cfg-tile.active::before {
  content: "✓";
  position: absolute;
  top: 6px;
  right: 8px;
  font-size: 12px;
  line-height: 1;
  color: var(--on-accent);
}
.cfg-tile.disabled {
  opacity: .35;
  cursor: not-allowed;
  pointer-events: none;
}
.cfg-tile-name {
  font-family: var(--sans);
  font-size: 12px;
  color: var(--text-1);
  letter-spacing: 0.3px;
  line-height: 1.2;
}
.cfg-tile.active .cfg-tile-name { color: var(--on-accent); padding-right: 14px; }
.cfg-tile-tier {
  font-size: 8px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-3);
  margin-top: 4px;
}
.cfg-tile.tier-iconic  .cfg-tile-tier { color: var(--accent); }
.cfg-tile.tier-exotic  .cfg-tile-tier { color: var(--accent-bright); }
/* After the tier colours: on a filled tile they would vanish. */
.cfg-tile.active .cfg-tile-tier,
.cfg-tile.active .cfg-tile-hint { color: var(--on-accent); opacity: .75; }
/* In the tier currently on the bar (catalogue p. 80: Signature = calf,
   Iconic adds suede/patent/canvas, Exotic its own hides). Emphasis only —
   the chip stays clickable, because under STOCK it is a physical pair and
   the tier decides price, never what may be sold. Hence NO greying of the
   other tiles: a dimmed tile reads as unavailable (`.disabled` is exactly
   that), and an out-of-tier pair on the shelf must stay sellable. The
   mark is a side bar and a bolder tier label, on the tile's own
   background — never the fill, which belongs to the selection. */
.cfg-tile.in-tier .cfg-tile-tier { font-weight: 700; color: var(--text-1); }
.cfg-tile.in-tier::after {
  content: "";
  position: absolute;
  inset: 8px auto 8px 0;
  width: 3px;
  border-radius: 0 2px 2px 0;
  background: var(--accent);
}
.cfg-tile.in-tier.active::after { background: var(--on-accent); opacity: .6; }
.cfg-tile.in-tier.active .cfg-tile-tier { color: var(--on-accent); }
.cfg-tile-swatch {
  width: 100%;
  height: 16px;
  border-radius: var(--r-sm);
  margin-top: 6px;
  border: 1px solid var(--line);
  background: var(--bg-3);
}
/* A heading inside the tile grid — the accent tab groups its tiles by
   material, the options tab by catalogue group (lining, sole, buckle…).
   Text only: not a control, so no tap-target size applies. */
.cfg-tile-group {
  grid-column: 1 / -1;
  font-size: 10px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--text-3);
  padding: 8px 0 0;
  border-bottom: 1px solid var(--line);
}
.cfg-tile-group:first-child { padding-top: 0; }
.cfg-tile-hint {
  font-size: 10px;
  color: var(--text-3);
  margin-top: 4px;
}
.cfg-tile-placeholder {
  grid-column: 1 / -1;
  text-align: center;
  color: var(--text-3);
  font-style: italic;
  font-size: 12px;
  padding: 18px 0;
}

/* ---- Configurator: selected summary ---- */
.cfg-summary {
  font-size: 12px;
  color: var(--text-1);
  padding: 12px 0 4px 0;
  margin-top: 4px;
  border-top: 1px solid var(--line);
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 6px;
}
.cfg-summary-label {
  font-size: 9px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--text-3);
}
.cfg-summary-chip {
  font-family: var(--sans);
  font-size: 12px;
  color: var(--text-1);
  padding: 2px 4px;
}
.cfg-summary-chip + .cfg-summary-chip::before { content: "·"; color: var(--text-3); margin-right: 6px; }
.cfg-summary-empty { color: var(--text-3); font-style: italic; }

/* ---- Configurator: price + line total compact row ---- */
.cfg-price-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  margin-top: 12px;
}

/* Size cross-reference popover (Berluti / Edward Green / Lobb / …) */
.size-xref {
  display: none;
  position: absolute;
  z-index: 50;
  background: var(--bg-4);
  border: 1px solid var(--accent);
  border-radius: var(--r-md);
  padding: 12px 14px;
  box-shadow: var(--shadow);
  min-width: 240px;
  font-size: 11px;
}
.size-xref.show { display: block; }
.size-xref-title {
  font-size: 9px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--text-3);
  margin-bottom: 6px;
}
.size-xref-row {
  display: flex;
  justify-content: space-between;
  padding: 2px 0;
  color: var(--text-2);
}
.size-xref-row .sxr-brand { color: var(--text-3); }
.size-xref-row.corthay { color: var(--accent-bright); border-bottom: 1px solid var(--line); padding-bottom: 4px; margin-bottom: 4px; }
.size-xref-link {
  font-size: 10px;
  color: var(--accent);
  cursor: pointer;
  margin-left: 6px;
}
.size-xref-link:hover { color: var(--accent-bright); }

/* -- Cart pane -- */
.cart {
  /* De la barre au haut du ticket non épinglé (pages de la rubrique, marge,
     titre et sa phrase : 192 px sur ordinateur, 202 sur iPad où les pilules
     font 44 px), plus 16 px de marge sous Pay. Mesuré, V2.90.0. */
  --cart-lead: 218px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  display: flex; flex-direction: column;
  position: sticky;
  /* Sous la barre, à la hauteur qu'elle a VRAIMENT : `--topbar-h` est mesurée
     par Navbar.tsx. Jusqu'à V2.89.0 c'était 100 px en dur, la barre d'un
     ordinateur ; sur un iPad en paysage elle en fait 135, et le haut du ticket
     glissait dessous une fois la page défilée. */
  top: calc(var(--shell-gap, 0px) + var(--topbar-h, 86px) + 12px);
  /* Le budget de hauteur doit tenir AVANT que le collant ne prenne, pas
     seulement après. `100dvh - 130px` supposait la carte épinglée à 100 px du
     haut ; en haut de page elle démarre en réalité sous le titre, vers 285 px,
     et sa hauteur maximale la faisait alors finir à 915 px pour une fenêtre de
     760 — le pied (Clear / Pay) tombait sous la ligne de flottaison
     (propriétaire, 2026-09-16 : « à moitié rognés par le bas de la fenêtre »).
     Mesuré : à 1512 × 760, Pay finissait à 898 px dès la première ligne.

     Le budget est donc celui de la position NON épinglée, la seule des deux
     qui puisse déborder. Coût assumé : une fois la page défilée, le ticket est
     plus court d'environ 160 px qu'il ne pourrait l'être — soit deux lignes de
     moins à l'écran, dans une liste qui défile déjà. Sur une caisse, « Pay est
     toujours cliquable sans défiler » vaut plus que deux lignes visibles.
     Le plancher garde la carte utilisable sur une fenêtre très basse. */
  max-height: max(360px, calc(100vh - var(--shell-gap, 0px) - var(--topbar-h, 86px) - var(--cart-lead)));
  max-height: max(360px, calc(100dvh - var(--shell-gap, 0px) - var(--topbar-h, 86px) - var(--cart-lead)));
  box-shadow: var(--soft-shadow);
}
/* Everything except the header and the Clear/Pay footer scrolls as ONE
   region — the same split as the phone Drawer's `.drawer-body`/
   `.drawer-footer` (Drawer.tsx), which never needed any of the per-child
   shrink tricks below because nothing has to compress: the region just
   grows and scrolls.
   The alternative tried first (giving `.cart-items` and `.upsell-prompt`
   their own `flex: 0 1 auto; min-height: 0`, so each shrinks to fit `.cart`'s
   max-height) stopped the overflow but made both illegible once BOTH had to
   shrink at once — a service catalogue long enough to need the upsell
   prompt's own scroll (a dozen-plus rows) squeezed `.upsell-prompt` down to
   a sliver with every checkbox hidden (owner, 2026-09-17, follow-up to the
   2026-09-16 fix). One scroll region sidesteps the trade-off entirely. */
.cart-scroll { flex: 1; overflow-y: auto; min-height: 0; }
.cart-header {
  padding: 16px 20px;
  border-bottom: 1px solid var(--line);
  display: flex; justify-content: space-between; align-items: baseline;
}
.cart-header h2 {
  font-family: var(--sans);
  font-size: 22px;
  color: var(--accent);
}
.cart-header .cart-count {
  font-size: 11px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--text-3);
}
.cart-client {
  padding: 12px 20px;
  border-bottom: 1px solid var(--line);
  background: var(--bg-3);
  cursor: pointer;
  transition: background .12s;
  display: flex; justify-content: space-between; align-items: center;
  font-size: 13px;
}
.cart-client:hover { background: var(--bg-4); }
.cart-client.unset { color: var(--text-3); font-style: italic; }
.cart-client .cc-arrow { color: var(--accent); font-size: 16px; }

/* New Sale's CITY SHOES upsell prompt — must read as a suggestion, not a
   ticket line or a status message, the instant you see it. The copper
   left-edge + badge is the one deliberate use of --chart as a UI accent
   (CLAUDE.md reserves it for exactly this: a rare, one-off highlight
   moment, never a general control colour). */
.upsell-prompt {
  /* No flex-shrink tricks here — `.cart-scroll` (or `.drawer-body` on
     phone) is the one scroll region for everything below the header, so
     this never has to compress below its own content. A dozen-plus rows in
     `.upsell-list` (its own max-height: 200px, still scrolls internally)
     just makes the page scroll a bit further, never squeezes this box down
     to an unreadable sliver — that WAS what a flex-shrink-based fix did
     here (owner, 2026-09-17). */
  margin: 14px 20px;
  padding: 12px 14px;
  background: var(--bg-4);
  border: 1px solid var(--line);
  border-left: 3px solid var(--chart);
  border-radius: var(--r-lg);
}
.upsell-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
}
.upsell-badge {
  flex-shrink: 0;
  font-size: 10px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--on-accent);
  background: var(--chart);
  padding: 3px 9px;
  border-radius: var(--radius-pill);
}
.upsell-title {
  flex: 1;
  font-size: 13px;
  color: var(--text-2);
}
.upsell-dismiss {
  flex-shrink: 0;
  background: none;
  border: none;
  color: var(--text-3);
  cursor: pointer;
  font-size: 13px;
  line-height: 1;
  padding: 4px;
}
.upsell-dismiss:hover { color: var(--text-1); }
.upsell-list {
  background: var(--bg-1);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  max-height: 200px;
  overflow-y: auto;
}
.upsell-option {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;
  border-bottom: 1px solid var(--line);
  cursor: pointer;
  font-size: 13px;
  color: var(--text-1);
}
.upsell-option:last-child { border-bottom: none; }
.upsell-option:hover { background: var(--bg-4); }
.upsell-option input[type="checkbox"] {
  flex-shrink: 0;
  width: 16px; height: 16px;
  accent-color: var(--chart);
}
.upsell-option-label { flex: 1; }
.upsell-option-price {
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
  color: var(--text-2);
}
.upsell-prompt .upsell-add {
  width: 100%;
  margin-top: 10px;
  min-height: 38px;
  font-size: 13px;
}
.cart-items {
  /* A plain block now — `.cart-scroll` (desktop) / `.drawer-body` (phone)
     is the one scroll region for the whole ticket, so this doesn't need its
     own flex-shrink/overflow to keep the Clear/Pay footer reachable
     (2026-09-16's fix, then 2026-09-17's: shrinking THIS to protect the
     footer squeezed the upsell prompt unreadable instead — see
     `.cart-scroll`). `min-height` is just a comfortable default for the
     empty-ticket placeholder, not a floor to defend. */
  min-height: 200px;
  padding: 12px 20px;
}
.cart-empty {
  text-align: center;
  color: var(--text-3);
  padding: 40px 20px;
  font-style: italic;
  font-size: 13px;
}
.cart-line {
  border-bottom: 1px solid var(--line);
  padding: 12px 0;
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 8px 12px;
}
.cart-line:last-child { border-bottom: 0; }
.cart-line .cl-name {
  font-family: var(--sans);
  font-size: 16px;
  color: var(--text-1);
  letter-spacing: 0.5px;
}
.cart-line .cl-spec {
  font-size: 11px;
  color: var(--text-3);
  margin-top: 2px;
  letter-spacing: 0.3px;
}
.cart-line .cl-amt {
  text-align: right;
  font-family: var(--sans);
  font-size: 16px;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.cart-line .cl-meta {
  grid-column: 1 / -1;
  display: flex; justify-content: space-between; align-items: center;
  font-size: 11px;
  color: var(--text-3);
  margin-top: 4px;
}
.cart-line .cl-actions { display: flex; gap: 6px; }
.cart-line .cl-act {
  background: transparent; border: 0; color: var(--text-3);
  cursor: pointer; padding: 2px 6px; font-size: 12px;
  letter-spacing: 1px; text-transform: uppercase;
}
.cart-line .cl-act:hover { color: var(--accent); }
.cart-line .cl-act.rm:hover { color: var(--red); }

.cart-totals {
  /* Le total et les boutons sont ce qu'on vient chercher : ils ne rétrécissent
     jamais, quoi qu'il arrive au-dessus d'eux. C'est `.cart-items` qui cède. */
  flex: 0 0 auto;
  padding: 14px 20px;
  border-top: 1px solid var(--line);
  background: var(--bg-3);
}
.cart-totals .ct-row {
  display: flex; justify-content: space-between;
  padding: 4px 0;
  font-size: 13px;
}
.cart-totals .ct-row.big {
  font-size: 18px;
  padding-top: 10px;
  margin-top: 6px;
  border-top: 1px solid var(--line);
  font-family: var(--sans);
}
.cart-totals .ct-row.big .ct-amt { color: var(--accent-bright); font-size: 24px; font-variant-numeric: tabular-nums; }
.cart-cta {
  flex: 0 0 auto;
  padding: 16px 20px;
  display: flex; gap: 10px;
}
.cart-cta .btn { flex: 1; min-height: 50px; font-size: 13px; }
.btn-pay {
  background: var(--accent);
  color: var(--on-accent);
  border-color: var(--accent);
  font-weight: 600;
  font-size: 14px !important;
}
.btn-pay:hover { background: var(--accent-bright); border-color: var(--accent-bright); color: var(--on-accent); }
.btn-pay:disabled { background: var(--line); color: var(--text-3); border-color: var(--line); cursor: not-allowed; }

/* Floating "go to ticket" button — phone tier only (below), shown/sized in
   the @media (max-width: 599px) block. On a phone the ticket sits below a
   long catalog grid, so reaching it meant scrolling past every product
   card first (owner, 2026-09-10). Sits under every drawer/modal overlay
   (z-index 500+) so an open drawer naturally covers it. */
.cart-fab { display: none; }

/* -- responsive: content grids collapse at the tablet-portrait tier -- */
@media (max-width: 1023px) {
  .kpi-grid, .kpi-grid.kpi-home { grid-template-columns: repeat(2, 1fr); }
  .quick-actions { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
  .grid-3 { grid-template-columns: 1fr 1fr; }
  .two-col { grid-template-columns: 1fr; }
  .commission-grid { grid-template-columns: 1fr; }
}
/* Below the desktop tier the single-row topbar no longer fits (the six
   category links plus the three pills need ~1 150px): brand + meta share
   the first row, the category nav gets its own full-width scrollable row
   (no wrapped two-line nav, no overflow). */
@media (max-width: 1199px) {
  .topbar {
    grid-template-columns: 1fr auto;
    grid-template-areas: "brand meta" "nav nav";
    gap: 10px 12px;
    padding: 12px 16px;
  }
  .topbar .brand { grid-area: brand; }
  .topbar .meta  { grid-area: meta; }
  .topbar .nav {
    grid-area: nav;
    justify-content: flex-start;
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;          /* the accent underline marks position */
    gap: 4px;
    min-width: 0;   /* a grid item's default min-width:auto is what made the
                       nav 602px wide on a 390px phone instead of scrolling */
  }
  .topbar .meta { flex-wrap: wrap; min-width: 0; row-gap: 6px; }
  .topbar .nav::-webkit-scrollbar { display: none; }
  .topbar .nav .nav-link { white-space: nowrap; }
  .topbar .meta .today { display: none; }  /* secondary info on small screens */
}

/* ============================================================
   RBAC — login gate + role pill (V2.17)
   ============================================================ */
.login-overlay {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background:
    radial-gradient(120% 120% at 50% 0%, var(--bg-3), var(--bg-1) 70%);
  z-index: 200;
}
.login-card {
  width: 100%;
  max-width: 420px;
  padding: 34px 32px 30px;
  text-align: center;
  animation: page-enter .5s var(--ease-liquid) backwards;
}
.login-brand { margin-bottom: 22px; }
.login-brand .logo {
  font-family: "Didot", "Bodoni 72", serif;
  font-size: 30px;
  letter-spacing: 6px;
  color: var(--accent-bright);
}
.login-mark { display: block; height: 24px; width: auto; margin: 0 auto 12px; }
.login-title { font-size: 26px; margin-bottom: 6px; }
.login-hint { font-size: 12.5px; margin-bottom: 22px; }
.login-card .field { text-align: left; margin-bottom: 16px; }
.login-btn { width: 100%; margin-top: 4px; min-height: 46px; }
.login-error {
  color: var(--red);
  font-size: 13px;
  margin-bottom: 14px;
  padding: 8px 12px;
  border: 1px solid var(--red);
  border-radius: 8px;
  background: rgba(var(--red-rgb), 0.08);
}
.login-divider {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 16px 0;
  font-size: 11px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--text-3);
}
.login-divider::before,
.login-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line);
}

/* ---- The three topbar pills ----
   Boutique, Role and Vendor sit side by side, so they must agree on height,
   padding, radius and type scale or the row reads as three unrelated
   controls. They drifted apart once already (the vendor pill kept a 6px
   padding and inherited the generic form-control rule's 9px input padding,
   which made it visibly taller than its neighbours). Keep the shared
   metrics here; put only genuinely per-pill things in the rules below. */
.store-pill, .role-pill, .staff-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 30px;
  padding: 4px 12px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--bg-2);
}
/* The logout button sits flush inside the role pill, so that edge is tighter. */
.role-pill { padding-right: 6px; }
.store-pill .muted, .role-pill .muted, .staff-pill .muted {
  font-size: 10px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
}
.store-pill strong, .role-pill strong {
  font-size: 12.5px;
  letter-spacing: 0.5px;
  white-space: nowrap;
}
.role-pill strong { color: var(--accent); }
.role-logout {
  border: none;
  background: transparent;
  color: var(--text-3);
  cursor: pointer;
  font-size: 15px;
  line-height: 1;
  padding: 4px 6px;
  border-radius: 999px;
  transition: color .18s var(--ease-liquid), background .18s var(--ease-liquid);
}
.role-logout:hover { color: var(--accent-bright); background: var(--bg-4); }

/* Store pill (Phase 2) — same shape as .role-pill, read-only (no switcher
   yet: every session resolves to exactly one boutique). */
.store-pill strong { color: var(--accent); }

/* ============ Stocktake (physical inventory count) ============ */

.mono {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  letter-spacing: 0.04em;
}

.stk-resume {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 14px;
  border-color: var(--accent);
  margin-bottom: 14px;
}
.stk-resume-actions { display: flex; gap: 8px; }
.stk-warn { border-color: var(--red); margin: 12px 0; }
.stk-start-row { display: flex; align-items: center; gap: 16px; margin: 20px 0; }
.stk-start {
  font-size: 14px;
  padding: 14px 32px;
  letter-spacing: 2px;
  text-transform: uppercase;
  background: var(--accent);
  color: var(--on-accent);
  border: none;
}
.stk-start:hover { background: var(--accent-bright); }
.stk-nobc { margin-top: 12px; }
.stk-nobc summary { cursor: pointer; color: var(--accent); }
.stk-neg { color: var(--red); }
.stk-pos { color: var(--green); }

/* -- counting: progress header -- */
.stk-progress-card { margin-bottom: 14px; }
.stk-bignum { display: flex; align-items: baseline; gap: 8px; font-family: var(--sans); }
.stk-bignum .stk-done { font-size: 46px; color: var(--accent-bright); line-height: 1; }
.stk-bignum .stk-slash { font-size: 26px; color: var(--text-3); }
.stk-bignum > span:nth-child(3) { font-size: 26px; color: var(--text-2); }
.stk-bignum-label {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--text-3);
  margin-left: 10px;
}
.stk-bar {
  height: 6px;
  background: var(--bg-4);
  border-radius: 999px;
  overflow: hidden;
  margin: 12px 0;
}
.stk-bar-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--accent-soft), var(--accent-bright));
  border-radius: 999px;
  transition: width 0.25s var(--ease-liquid);
}
.stk-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.stk-chip {
  font-size: 11px;
  letter-spacing: 0.08em;
  padding: 3px 10px;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  color: var(--text-2);
}
.stk-chip-done { border-color: var(--green); color: var(--green); }
.stk-chip-bad { border-color: var(--red); color: var(--red); }

/* -- counting: feed + side column -- */
.stk-columns {
  display: grid;
  grid-template-columns: 1fr 320px;
  gap: 14px;
  align-items: start;
}
@media (max-width: 1023px) { .stk-columns { grid-template-columns: 1fr; } }
.stk-side { display: flex; flex-direction: column; gap: 14px; }
.stk-feed { list-style: none; margin: 0; padding: 0; }
.stk-feed-empty { padding: 26px 8px; text-align: center; }
.stk-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 6px;
  border-bottom: 1px solid var(--line);
}
.stk-row:last-child { border-bottom: none; }
.stk-ico {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  flex: none;
  border: 1px solid var(--line-strong);
  color: var(--text-2);
}
.stk-matched .stk-ico { border-color: var(--green); color: var(--green); }
.stk-duplicate .stk-ico { border-color: var(--warn); color: var(--warn); }
.stk-unexpected .stk-ico { border-color: var(--red); color: var(--red); }
.stk-spec { flex: 1; min-width: 0; }
.stk-spec .stk-code {
  display: block;
  font-size: 11px;
  color: var(--text-3);
}
.stk-undo { padding: 4px 10px; font-size: 11px; }
.stk-hint { margin-top: 8px; }
.stk-actions { display: flex; flex-direction: column; gap: 8px; }
.stk-finish {
  background: var(--accent);
  color: var(--on-accent);
  border: none;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  padding: 12px 18px;
}
.stk-finish:hover { background: var(--accent-bright); }
.stk-finish:disabled { opacity: 0.6; }
.stk-confirm-text { color: var(--warn); font-size: 13px; }

/* -- per-scan flash: a brief tint of the whole section edge -- */
@keyframes stk-flash-frame {
  0% { box-shadow: inset 0 0 0 2px currentColor; }
  100% { box-shadow: inset 0 0 0 0 transparent; }
}
.stk-flash-matched,
.stk-flash-duplicate,
.stk-flash-unexpected { animation: stk-flash-frame 0.65s var(--ease-liquid); }
.stk-flash-matched { color: var(--green); }
.stk-flash-duplicate { color: var(--warn); }
.stk-flash-unexpected { color: var(--red); }

/* -- review -- */
.stk-review-actions { display: flex; gap: 10px; margin-top: 4px; }
.stk-perfect {
  margin-top: 14px;
  border-color: var(--green);
  color: var(--green);
  text-align: center;
  font-family: var(--sans);
  font-size: 17px;
}

/* Boutique picker — only rendered for an account authorised on several
   boutiques (Japan team, HQ global_manager/admin). Styled to sit inside the
   existing .store-pill rather than beside it, so the single-boutique
   majority sees no layout change at all. */
.store-pill .store-select, .staff-pill .staff-select, .nav-menu-row .store-select {
  appearance: none;
  border: 1px solid var(--line);
  background: var(--bg-2);
  color: var(--text-1);
  font: inherit;
  font-weight: 600;
  border-radius: 999px;
  padding: 2px 22px 2px 8px;
  cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, var(--text-2) 50%),
                    linear-gradient(135deg, var(--text-2) 50%, transparent 50%);
  background-position: right 10px center, right 6px center;
  background-size: 4px 4px, 4px 4px;
  background-repeat: no-repeat;
}
.store-pill .store-select:focus-visible,
.staff-pill .staff-select:focus-visible,
.nav-menu-row .store-select:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* -- user management: boutique scope picker (V2.29.1) --
   Composes .field/.grid-3 like every other form on the app; only the
   checkbox row and the table's horizontal scroll needed anything new. */
.store-scope { grid-column: 1 / -1; }
.store-scope-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
  padding: 6px 0;
}
.store-scope-list label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--text-1);
  cursor: pointer;
}
.store-scope-table { overflow-x: auto; }

/* -- shared column chooser + per-column filter row (V2.30.0) --
   The chooser markup itself reuses .col-picker (V2.24); these add the
   toolbar that holds it and the filter inputs, so Stock and All Sales
   render the same control. */
.col-tools {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}
.col-tools .col-picker { margin-bottom: 0; }
.col-picker-actions {
  grid-column: 1 / -1;
  display: flex;
  gap: 8px;
  margin-top: 8px;
}
.col-filter-row th { padding: 4px 6px; }
.col-filter-row input {
  width: 100%;
  min-width: 60px;
  box-sizing: border-box;
  padding: 3px 6px;
  font-size: 11px;
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  color: var(--text-1);
  background: var(--bg-2);
  border: 1px solid var(--line);
}
.col-filter-row input:focus-visible {
  outline: 1px solid var(--accent);
  outline-offset: 0;
}
.col-filter-row.num input { text-align: right; }

/* =========================================================
   Touch & responsive foundations (V2.35.0, 2026-09-05)

   Three width tiers, fixed by the owner on 2026-09-05 after the touch
   audit (docs/ROADMAP.md, "Chantier tablette / smartphone"):
     >= 1200 px   desktop — the historic layout, untouched
     1024-1199    compact desktop and iPad landscape (1 080) — two-row
                  topbar, split POS with a 320 px cart
     600-1023     tablet portrait (iPad, 810) — one-row topbar with the
                  ☰ menu (V2.87.0), one-column content grids, scrollable
                  sub-nav
     < 600        phone (iPhone, 390) — the same ☰ topbar, full-screen
                  drawers and modals, 12 px page gutters
   Custom properties cannot drive @media, so the numbers are literal —
   grep "max-width: 599px|1023px|1199px" to find every tier rule.

   The tap floor is keyed on the POINTER, not the width: Apple HIG and
   WCAG 2.5.5 want 44 x 44 CSS px for anything a finger operates, and a
   laptop with a touchscreen deserves that as much as an iPad. A mouse
   (any-pointer: fine only) sees none of it, so the PC till keeps its
   density. frontend/e2e/responsive.spec.ts replays both measurements —
   no horizontal overflow, every control finger-sized — on every PR.
   ========================================================= */

/* A grid column is `minmax(auto, 1fr)`: its minimum is the content's
   min-content width, and a table's is the sum of its widest cells. That is
   how a 769px stock table pushed a 390px phone to 619px. Letting the cards
   and grid cells shrink is what makes the .scroll-x wrappers effective. */
.card, .pos-wrap > *, .two-col > *, .grid-2 > *, .grid-3 > *,
.commission-grid > *, .settings-layout > *, .stk-columns > *, .kpi-grid > * {
  min-width: 0;
}
.scroll-x {
  max-width: 100%;
  -webkit-overflow-scrolling: touch;
}
/* Native checkboxes/radios default to the platform blue — off-palette. */
input[type="checkbox"], input[type="radio"] { accent-color: var(--accent); }

/* -- Journal (admin) -- */
.log-level {
  display: inline-block;
  font-size: 10px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  padding: 2px 8px;
  border-radius: 30px;
  border: 1px solid var(--line-strong);
  color: var(--text-2);
}
.log-level-warn { color: var(--warn); border-color: var(--warn); }
.log-level-error { color: var(--red); border-color: var(--red); }
.log-detail td { background: var(--bg-4); cursor: default; }
.log-detail pre {
  margin: 0 0 8px;
  padding: 10px 12px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  font-size: 11px;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  max-height: 320px;
  overflow: auto;
}

/* -- the tap floor (any coarse pointer: iPad, phone, touch laptop) -- */
@media (any-pointer: coarse) {
  :root { --tap: 44px; }
  button, .btn, [role="button"], [role="option"], select, textarea,
  input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]) {
    min-height: var(--tap);
  }
  button, .btn, [role="button"], select { min-width: var(--tap); }
  /* Below 16px iOS Safari zooms the whole page when a field takes focus. */
  input, select, textarea { font-size: 16px; }
  /* WCAG 2.5.8 floor for the secondary controls whose label is the real target. */
  input[type="checkbox"], input[type="radio"],
  .set-row .set-checkbox-row input[type="checkbox"],
  .ord-deliver-line input[type="checkbox"] { width: 24px; height: 24px; }
  /* Inline role=button surfaces (a client name in All Sales, the size
     chart link): min-height needs a box that is not inline. */
  .as-client, .size-xref-link { display: inline-flex; align-items: center; }
  .nav-link, .subnav a {
    display: inline-flex; align-items: center;
    min-height: var(--tap);
    min-width: var(--tap);
    justify-content: center;
  }
  .nav-link { padding: 0 10px; }
  .nav { gap: 12px; }
  .subnav a { padding: 0 8px; }
  .subnav.open { height: 60px; }
  .settings-nav-link { display: flex; align-items: center; min-height: var(--tap); }
  .theme-toggle, .settings-gear, .drawer-close, .drawer-confirm, .btn-remove {
    width: var(--tap); height: var(--tap);
  }
  /* The topbar pills: the select fills the pill, so the pill's own border
     is the control's border — two concentric outlines otherwise. */
  .store-pill, .role-pill, .staff-pill { min-height: 46px; padding-top: 0; padding-bottom: 0; }
  /* background-COLOR: the shorthand also wiped the chevron, and the vendor
     pill no longer read as a list on an iPad (V2.87.0). */
  .store-pill .store-select, .staff-pill .staff-select { border-color: transparent; background-color: transparent; }
  .suggestions li { display: flex; align-items: center; }
  .top-row { min-height: var(--tap); align-items: center; }
}

/* -- tablet portrait tier and below -- */
@media (max-width: 1023px) {
  main { padding: 24px 20px 56px; }
  /* One row since V2.87.0 (owner, 2026-09-27): ☰, the wordmark, the vendor
     — the one choice made at every sale. The sections, the boutique, the
     role, the theme and the settings live in the menu (NavMenu.tsx). The
     side columns are equal so the wordmark sits in the middle of the
     screen, not of what the button and the pill leave. */
  .topbar {
    grid-template-columns: 1fr auto 1fr;
    grid-template-areas: "burger brand vendor";
    gap: 10px;
    padding: 8px max(16px, env(safe-area-inset-right)) 8px max(16px, env(safe-area-inset-left));
  }
  .nav-burger {
    grid-area: burger;
    justify-self: start;
    display: inline-flex; align-items: center; justify-content: center;
    width: 44px; height: 44px;
    border-radius: 50%;
    border: 1px solid var(--line);
    background: transparent;
    color: var(--text-1);
    cursor: pointer;
  }
  .nav-burger:hover { color: var(--accent); border-color: var(--accent); }
  .topbar .brand { justify-content: center; }
  .topbar .nav, .topbar .meta-tools, .topbar .today,
  .topbar .store-pill, .topbar .role-pill { display: none; }
  .topbar .meta { display: contents; }
  .topbar .meta-pills { grid-area: vendor; display: flex; justify-content: flex-end; min-width: 0; }
  /* The word « Vendor » stays for a screen reader; on screen the pill's
     place says what it is. */
  .topbar .staff-pill .muted {
    position: absolute;
    width: 1px; height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  /* A shorter page head: the sentence under a title explains the page to
     a newcomer, and on a phone it pushed the first product below the fold
     (V2.87.0). Only a sentence marked .page-lede goes — a loading notice,
     an error or a stocktake's date and author stay. */
  .page-head { margin-bottom: 16px; }
  .page-head > .page-lede { display: none; }
  h1.display { font-size: 30px; }
  /* The till's pillars and categories: one row that scrolls under the
     finger instead of three stacked rows. */
  .catalog-tabs {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    padding-bottom: 12px;
    margin-bottom: 12px;
  }
  .catalog-tabs::-webkit-scrollbar { display: none; }
  .catalog-tab { flex: 0 0 auto; white-space: nowrap; }
  .subnav { padding: 0 20px; }
  .subnav.open { padding: 10px 20px 0; }
  .subnav {
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
  }
  .subnav::-webkit-scrollbar { display: none; }
  .subnav a, .subnav .sub-sep { flex: 0 0 auto; white-space: nowrap; }
  .kpi-grid.kpi-stock { grid-template-columns: repeat(2, 1fr); }
}

/* -- phone tier -- */
@media (max-width: 599px) {
  main { padding: 16px 12px calc(40px + env(safe-area-inset-bottom)); }
  .cart-fab {
    display: flex;
    align-items: center; justify-content: center;
    position: fixed;
    right: max(16px, env(safe-area-inset-right));
    bottom: calc(20px + env(safe-area-inset-bottom));
    width: 56px; height: 56px;
    border-radius: 50%;
    background: var(--accent);
    color: var(--on-accent);
    border: none;
    box-shadow: 0 8px 24px rgba(var(--accent-rgb), 0.35);
    z-index: 450;
    cursor: pointer;
  }
  .cart-fab-badge {
    position: absolute;
    top: -4px; right: -4px;
    min-width: 20px; height: 20px;
    padding: 0 5px;
    border-radius: 10px;
    border: 2px solid var(--bg-1);
    background: var(--red);
    color: #fff;
    font-size: 11px;
    font-weight: 700;
    line-height: 16px;
    text-align: center;
  }
  /* The one-row topbar of the tier above, tightened: a seller's name
     (« EMILIEN JOYEUX ») must not push the wordmark off a 390 px screen. */
  .topbar {
    gap: 8px;
    padding-left: max(12px, env(safe-area-inset-left));
    padding-right: max(12px, env(safe-area-inset-right));
  }
  .brand { gap: 7px; }
  .brand-mark { height: 18px; }
  .brand .logo { font-size: 20px; letter-spacing: 4px; }
  .brand .sublabel { font-size: 9px; letter-spacing: 2.5px; }
  .topbar .staff-pill { padding: 0 10px; }
  .topbar .staff-pill .staff-select { max-width: 104px; text-overflow: ellipsis; }
  .subnav { padding: 0 12px; }
  /* The outlined pills need a little air; 54 px, not the tablet's 60. */
  .subnav.open { height: 54px; padding: 6px 12px 0; }

  h1.display { font-size: 26px; }
  .card { padding: 16px; margin-bottom: 16px; }
  .kpi-grid, .kpi-grid.kpi-stock, .kpi-grid.kpi-home {
    grid-template-columns: 1fr 1fr; gap: 10px;
  }
  .kpi-card { padding: 16px 14px; }
  .kpi-value { font-size: 26px; overflow-wrap: anywhere; }
  .grid-2, .grid-3, .quick-actions, .type-row { grid-template-columns: 1fr; }
  .filter-bar input { flex-basis: 100%; }
  .filter-bar select { min-width: 0; flex: 1 1 140px; }
  .actions { flex-wrap: wrap; }
  .actions .btn { flex: 1 1 auto; }

  /* Overlays go full-screen. A 480px drawer on a 390px phone was already
     clamped by max-width: 100vw; its paddings and the modal were not. */
  .drawer, .drawer.wide, .drawer.widest { width: 100vw; border-left: 0; }
  .drawer-header { padding: 12px 16px; }
  .drawer-title { font-size: 18px; }
  .drawer-body { padding: 16px; }
  .drawer-footer { padding: 12px 16px calc(12px + env(safe-area-inset-bottom)); flex-wrap: wrap; }
  .modal {
    width: 100vw; max-width: 100vw;
    max-height: 100vh; max-height: 100dvh;
    border-radius: 0; border: 0;
  }
  .modal-header { padding: 14px 16px; }
  .modal-title { font-size: 20px; }
  .modal-body { padding: 16px; }
  .modal-footer { padding: 12px 16px calc(12px + env(safe-area-inset-bottom)); flex-wrap: wrap; }
  .settings-dirty-bar {
    left: 12px; right: 12px; transform: none;
    bottom: calc(12px + env(safe-area-inset-bottom));
    flex-wrap: wrap;
  }
}

/* ---- Le bon de commande à la manufacture (V2.65.0) ------------------- */
/* Une grille de champs qui se plie : deux colonnes sur un poste, une seule
   sur un téléphone. Pas de largeur minimale supérieure à l'écran — c'est
   ce qui faisait déborder la page du Stock en V2.59.0. */
.po-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}
.po-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
  gap: 14px 20px;
}
.po-field { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.po-field > span,
.po-field > label:not(.check) {
  font-size: 11px;
  letter-spacing: .6px;
  text-transform: uppercase;
  color: var(--text-3);
}
.po-field select,
.po-field textarea { width: 100%; max-width: 100%; }
.po-field textarea { resize: vertical; }
/* La valeur que la vente a décidée : lisible, et visiblement non modifiable
   — la changer ici voudrait dire vendre autre chose. */
.po-read {
  padding: 7px 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--bg-3);
  color: var(--text-2);
}
.po-req { color: var(--warn); }
.po-hint { display: block; grid-column: 1 / -1; }
.po-note, .po-warn {
  margin: 10px 0 0;
  padding: 9px 12px;
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--bg-3);
  font-size: 12px;
}
.po-warn { border-color: var(--warn); color: var(--warn); }
.po-actions { display: flex; flex-wrap: wrap; gap: 10px; }

/* La cible tactile des contrôles du bon, comme partout ailleurs. */
@media (any-pointer: coarse) {
  .po-field select,
  .po-field textarea,
  .po-actions .btn { min-height: 44px; }
}

/* La pastille « PO à valider » est un bouton : c'est du travail à faire.
   Elle garde l'aspect d'une pastille de statut — un seul vocabulaire
   visuel sur la ligne — et gagne seulement de quoi être cliquée. */
.po-chip {
  cursor: pointer;
  font-family: inherit;
  appearance: none;
}
.po-chip:hover { background: var(--bg-2); }
@media (any-pointer: coarse) { .po-chip { min-height: 44px; padding: 3px 12px; } }

/* Un bouton d'action principale désactivé doit LE PARAÎTRE : plein et noir,
   il invite au clic alors qu'il ne répondra pas. Même traitement que
   `.btn-pay:disabled`, dont c'était déjà le raisonnement. */
.btn-primary:disabled,
.btn-primary:disabled:hover {
  background: var(--line);
  color: var(--text-3);
  border-color: var(--line);
  cursor: not-allowed;
}
/* La valeur décidée par la vente ne doit pas ressembler à un champ : elle
   se lit, elle ne se remplit pas. */
.po-read { cursor: default; border-style: dashed; }

/* --- Commissions (V2.72.0) ------------------------------------------------
   Le total d'un mois et le minimum manqué d'un vendeur : deux lignes que
   l'œil doit trouver sans les chercher. La couleur du manque est celle de
   l'avertissement du thème (`--warn`), jamais une couleur neuve. */
.data-table tr.row-total > td {
  border-top: 2px solid var(--line-strong);
  background: var(--bg-4);
}
.data-table td.cell-missed { color: var(--warn); }

/* Daily sales (V2.74.0) — le dimanche, jour de fermeture à Volney, se lit
   comme une ligne calme plutôt que comme un trou dans le tableau. */
.data-table tr.row-quiet > td { color: var(--text-3); }
