/* ============================================================================
   Success Payment Restaurant POS — design system (Phase 3)
   Midnight & Brass · touch-first · light + dark · commercial-grade
   ============================================================================ */
:root{
  --ink:#16233A;--ink-2:#3A4C63;--muted:#69788E;--faint:#93A0B2;
  --bg:#EAEEF3;--panel:#FFFFFF;--panel-2:#F5F7FA;--panel-3:#EDF1F6;--line:#DDE4EC;--line-2:#CBD5E1;
  --brass:#A9772E;--brass-2:#C69B4D;--brass-ink:#7A551F;--midnight:#0E1A2B;--midnight-2:#132743;
  --accent:#1F5C8A;--good:#2E9E6B;--good-2:#E7F4EE;--warn:#C68A1E;--warn-2:#FBF1DC;--crit:#C8432F;--crit-2:#F9E4E0;--info:#2D6E9E;--info-2:#E4EEF6;
  --r-s:8px;--r:12px;--r-l:16px;--r-xl:22px;
  --sh-1:0 1px 2px rgba(16,26,43,.06);--sh-2:0 2px 8px rgba(16,26,43,.08),0 1px 2px rgba(16,26,43,.04);
  --sh-3:0 8px 28px rgba(16,26,43,.14),0 2px 6px rgba(16,26,43,.06);--sh-4:0 20px 50px rgba(16,26,43,.24);
  --tap:52px;--rail:76px;
  --font:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  --display:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
  --mono:ui-monospace,"SFMono-Regular","Cascadia Code",Consolas,monospace;
  --ease:cubic-bezier(.2,.7,.3,1);
}
@media (prefers-color-scheme:dark){:root{
  --ink:#E9EEF5;--ink-2:#BFCBDA;--muted:#8B9BB0;--faint:#647388;
  --bg:#0A121D;--panel:#0F1D30;--panel-2:#14243A;--panel-3:#1A2C46;--line:#243A56;--line-2:#2E486A;
  --brass:#D3A85B;--brass-2:#E6C583;--brass-ink:#E6C583;--accent:#6FB0DE;
  --good:#54BE8C;--good-2:#123528;--warn:#E0B968;--warn-2:#33280F;--crit:#E68472;--crit-2:#3A1C17;--info:#6FB0DE;--info-2:#122A40;
  --sh-1:0 1px 2px rgba(0,0,0,.4);--sh-2:0 2px 10px rgba(0,0,0,.4);--sh-3:0 10px 34px rgba(0,0,0,.55);--sh-4:0 24px 60px rgba(0,0,0,.6);
}}
:root[data-theme="dark"]{--ink:#E9EEF5;--ink-2:#BFCBDA;--muted:#8B9BB0;--faint:#647388;--bg:#0A121D;--panel:#0F1D30;--panel-2:#14243A;--panel-3:#1A2C46;--line:#243A56;--line-2:#2E486A;--brass:#D3A85B;--brass-2:#E6C583;--brass-ink:#E6C583;--accent:#6FB0DE;--good:#54BE8C;--good-2:#123528;--warn:#E0B968;--warn-2:#33280F;--crit:#E68472;--crit-2:#3A1C17;--info:#6FB0DE;--info-2:#122A40;--sh-1:0 1px 2px rgba(0,0,0,.4);--sh-2:0 2px 10px rgba(0,0,0,.4);--sh-3:0 10px 34px rgba(0,0,0,.55);--sh-4:0 24px 60px rgba(0,0,0,.6);}
:root[data-theme="light"]{--ink:#16233A;--ink-2:#3A4C63;--muted:#69788E;--faint:#93A0B2;--bg:#EAEEF3;--panel:#FFFFFF;--panel-2:#F5F7FA;--panel-3:#EDF1F6;--line:#DDE4EC;--line-2:#CBD5E1;--brass:#A9772E;--brass-2:#C69B4D;--brass-ink:#7A551F;--accent:#1F5C8A;--good:#2E9E6B;--good-2:#E7F4EE;--warn:#C68A1E;--warn-2:#FBF1DC;--crit:#C8432F;--crit-2:#F9E4E0;--info:#2D6E9E;--info-2:#E4EEF6;--sh-1:0 1px 2px rgba(16,26,43,.06);--sh-2:0 2px 8px rgba(16,26,43,.08);--sh-3:0 8px 28px rgba(16,26,43,.14);--sh-4:0 20px 50px rgba(16,26,43,.24);}

*{box-sizing:border-box;-webkit-tap-highlight-color:transparent;}
html,body{height:100%;margin:0;}
body{font-family:var(--font);background:var(--bg);color:var(--ink);font-size:15px;overflow:hidden;user-select:none;-webkit-font-smoothing:antialiased;}
button,input,select,textarea{font-family:inherit;font-size:inherit;color:inherit;}
button{border:none;background:none;cursor:pointer;}
::-webkit-scrollbar{width:10px;height:10px;}::-webkit-scrollbar-thumb{background:var(--line-2);border-radius:8px;border:2px solid transparent;background-clip:padding-box;}
.hidden{display:none!important;}
.mono{font-family:var(--mono);font-variant-numeric:tabular-nums;}
.num{font-variant-numeric:tabular-nums;}
.serif{font-family:var(--display);}
.grow{flex:1;}
.muted{color:var(--muted);}

/* ---- app shell ---- */
#app{display:flex;height:100vh;}
.rail{width:var(--rail);flex:none;background:var(--midnight);display:flex;flex-direction:column;align-items:center;padding:14px 0 10px;gap:6px;z-index:20;overflow-y:auto;}
.rail::-webkit-scrollbar{display:none;}
.rail .logo{width:44px;height:44px;border-radius:12px;background:linear-gradient(150deg,var(--brass),var(--brass-2));display:grid;place-items:center;color:#0E1A2B;font-family:var(--display);font-weight:700;font-size:1.1rem;margin-bottom:8px;box-shadow:var(--sh-2);}
/* ---- brand logo (real Success Payment mark) ---- */
/* The mark art sits on white; on dark chrome we frame it as a clean white "coin". */
.logo-mark{display:block;object-fit:contain;}
.railbrand{display:grid;place-items:center;margin-bottom:12px;}
.railbrand .logo-mark{background:#fff;border-radius:11px;padding:5px;box-shadow:var(--sh-2);}
.login .loginmark{margin:0 auto 4px;background:#fff;border-radius:22px;padding:12px;box-shadow:0 10px 28px rgba(0,0,0,.45);}
.rail nav{display:flex;flex-direction:column;gap:4px;width:100%;align-items:center;overflow-y:auto;}
.rail nav::-webkit-scrollbar{display:none;}
/* text-align:center is what centres a WRAPPED label. The link is already a centred flex
   column, so the icon and a single-line label sit on the item's centre axis on their own.
   A label that wraps to two lines (only "Rapports X / Z" does) becomes one anonymous flex
   item whose box fills the 56px width — and without a text-align its two lines fall to the
   left, so "Rapports" and "X / Z" drifted off the icon's axis. Centring the text pulls both
   lines back onto it. It is a no-op for single-line items, whose box already shrink-wraps
   the text, so no other rail entry moves. */
.rail a{width:56px;height:56px;border-radius:14px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;color:#8695AA;text-decoration:none;font-size:.6rem;letter-spacing:.02em;text-align:center;transition:.15s var(--ease);}
.rail a svg{width:22px;height:22px;stroke:currentColor;fill:none;stroke-width:1.8;}
.rail a:hover{background:rgba(255,255,255,.06);color:#DCE4EE;}
.rail a.active{background:rgba(198,155,77,.16);color:var(--brass-2);}
.rail a{position:relative;}
/* ---- inline dashboard design mode ---- */
.rail.editmode nav a{cursor:default;background:rgba(255,255,255,.04);}
.rail.editmode nav a.tabhidden{opacity:.4;}
.navbadge{position:absolute;top:1px;right:5px;width:21px;height:21px;border-radius:50%;display:grid;place-items:center;font-weight:800;font-size:15px;line-height:1;cursor:pointer;color:#fff;box-shadow:0 2px 6px rgba(0,0,0,.45);z-index:2;}
.navbadge.rm{background:#C8432F;}
.navbadge.add{background:#2E9E6B;}
.navbadge:hover{transform:scale(1.12);}
.navdivider{width:44px;font-size:.5rem;text-transform:uppercase;letter-spacing:.1em;color:var(--muted);text-align:center;margin:8px 0 2px;padding-top:7px;border-top:1px dashed var(--line);}
/* ---- design-mode table removal ---- */
.ftable.lp-armed{transform:scale(.96);box-shadow:0 0 0 3px var(--brass);transition:transform .12s ease, box-shadow .12s ease;}
.ftable.designing{cursor:default;}
.ftable.designing.locked{opacity:.65;}
.ftable .tdel{position:absolute;top:-9px;right:-9px;width:26px;height:26px;border-radius:50%;background:#C8432F;color:#fff;border:2px solid var(--panel);font-size:17px;font-weight:800;line-height:1;cursor:pointer;display:grid;place-items:center;z-index:6;box-shadow:0 2px 7px rgba(0,0,0,.4);padding:0;}
.ftable .tdel:hover{transform:scale(1.14);}
.ftable .tlock{position:absolute;top:-8px;right:-8px;color:var(--muted);background:var(--panel);border-radius:50%;padding:4px;z-index:6;display:grid;place-items:center;box-shadow:0 1px 4px rgba(0,0,0,.3);}
.editbanner{display:flex;align-items:center;gap:12px;padding:11px 18px;background:linear-gradient(90deg,rgba(198,155,77,.20),rgba(198,155,77,.03));border-bottom:1px solid var(--brass);}
.editbanner svg{stroke:var(--brass-2);flex:none;}
/* ---- settings hub cards ---- */
.settingcard{display:flex;align-items:center;gap:16px;width:100%;text-align:left;cursor:pointer;border:1px solid var(--line);transition:.15s var(--ease);}
.settingcard:hover{border-color:var(--brass);transform:translateY(-1px);box-shadow:var(--sh-2);}
.settingcard .seticon{width:48px;height:48px;border-radius:13px;background:var(--panel-2);display:grid;place-items:center;color:var(--brass);flex:none;}
.settingcard>svg:last-child{stroke:var(--muted);flex:none;}
.rail .spacer{flex:none;width:30px;height:0;margin:6px 0 2px;}
/* min-height:0 IS THE SCROLL, AND ITS ABSENCE IS WHY PARAMÈTRES LOOKED HALF-EMPTY.
 *
 * .content is a COLUMN flex container holding the top bar and .screen, and .screen is
 * `flex:1; overflow:auto`. A flex item's default min-height is `auto` — it refuses to
 * shrink below its own content — so on any layout where .content does not already have a
 * definite height, .screen grew to its FULL content height instead of becoming a scroll
 * container. Measured on the real stylesheet at the real viewports:
 *
 *   1920x1200  canScroll=true   screen 1136 / 1274      (rail beside the content)
 *    960x600   canScroll=true   screen  536 / 2334
 *    640x960   canScroll=FALSE  screen 2334 / 2334      <- the whole hub, unscrollable
 *
 * At 640px and below the rail moves to the bottom and #app becomes a COLUMN, which is
 * where the missing constraint bites. The CPad lands exactly there: the panel is 1920
 * physical pixels, the page asks for width=device-width, and an xxhdpi tablet reports
 * DPR 3 — 1920/3 = 640 CSS px.
 *
 * So a manager saw the top of Paramètres and nothing else. Carte is in the FIRST group and
 * was visible; Réservations sits in the fourth and was simply below a fold that could not
 * be scrolled past. It reads exactly like "the tabs are missing", which is why the
 * permissions were the first suspect and were never the fault — the production MANAGER
 * role holds MANAGE_CONFIG and every card's `show:` evaluates true.
 */
.content{flex:1;min-height:0;display:flex;flex-direction:column;min-width:0;position:relative;}
/* The same constraint one level up: #app is height:100vh, and its flex child must be
   allowed to shrink to it rather than be sized by the content inside .screen. */
#app > div{min-height:0;}

/* ---- top bar ---- */
.topbar{height:60px;flex:none;display:flex;align-items:center;gap:12px;padding:0 18px;background:var(--panel);border-bottom:1px solid var(--line);z-index:10;}
.topbar h1{font-family:var(--display);font-weight:600;font-size:1.3rem;margin:0;letter-spacing:-.01em;}
.topbar .sub{color:var(--muted);font-size:.82rem;}
.pill{display:inline-flex;align-items:center;gap:7px;height:36px;padding:0 13px;border-radius:999px;background:var(--panel-2);border:1px solid var(--line);font-size:.82rem;font-weight:600;color:var(--ink-2);}
.pill .dot{width:8px;height:8px;border-radius:50%;background:var(--good);}
.pill.offline{background:var(--crit-2);border-color:transparent;color:var(--crit);}
.pill.offline .dot{background:var(--crit);animation:pulse 1.4s infinite;}
/* Remote manager (read-only) — subtle brand-blue chip, never alarming; the app stays active. */
.pill.remote-ro{background:rgba(29,78,216,.14);border-color:rgba(29,78,216,.32);color:#5b9bd5;letter-spacing:.01em;}
/* THE CPAD'S OWN BATTERY. Reuses .pill wholesale — this is device status beside the
   connectivity pill, not a new kind of object — and reuses the SAME crit tokens the
   offline pill uses, so "something is wrong with this tablet" always looks the one way.
   The glyph's fill is drawn in currentColor, so colouring the pill colours the fill with
   it and the two can never disagree. */
.pill.batt{gap:6px;padding:0 11px;}
.pill.batt .num{font-variant-numeric:tabular-nums;letter-spacing:.01em;}
/* AT OR BELOW 20 % THE PILL GOES RED — the same red as « Hors ligne », deliberately: an
   operator should not have to learn a second warning colour. Nothing else on the screen
   changes, so service is never interrupted by the warning itself. */
.pill.batt.low{background:var(--crit-2);border-color:transparent;color:var(--crit);}
/* At or below 10 % the FILL alone pulses. The pill stays still — a blinking chip in the
   corner of a till all evening is noise; a moving sliver inside it is a glance. */
/* THE CHARGING BOLT reads as an overlay, not as part of the fill, because it is knocked out
   of whatever is behind it. `paint-order:stroke` draws the halo BEHIND the glyph, so the
   bolt keeps its full shape instead of being eaten from the edges by its own outline. */
.pill.batt .batt-bolt{stroke:var(--panel-2);stroke-width:1.7;stroke-linejoin:round;paint-order:stroke;}
/* …and in the red low state the halo follows the pill, or the bolt would be outlined in a
   colour that is no longer behind it and would lose its edge exactly when it matters. */
.pill.batt.low .batt-bolt{stroke:var(--crit-2);}
.pill.batt.critical .batt-fill{animation:pulse 1.4s infinite;}
@media (prefers-reduced-motion:reduce){.pill.batt.critical .batt-fill{animation:none;}}
@keyframes pulse{50%{opacity:.35;}}
.avatar{width:36px;height:36px;border-radius:50%;display:grid;place-items:center;color:#fff;font-weight:700;font-size:.86rem;box-shadow:var(--sh-1);flex:none;}
.avatar.lg{width:64px;height:64px;font-size:1.4rem;}
.avatar.sm{width:28px;height:28px;font-size:.72rem;}
.staffchip{display:flex;align-items:center;gap:9px;height:44px;padding:0 6px 0 6px;border-radius:999px;background:var(--panel-2);border:1px solid var(--line);}
.staffchip .nm{font-weight:600;font-size:.86rem;padding-right:6px;line-height:1.05;}
.staffchip .rl{font-size:.66rem;color:var(--brass);text-transform:uppercase;letter-spacing:.06em;}

/* ---- surface ---- */
.screen{flex:1;overflow:auto;padding:18px;}
.screen.pad0{padding:0;}
.card{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-l);box-shadow:var(--sh-1);}
.card.p{padding:16px;}
.section-h{display:flex;align-items:center;gap:12px;margin:2px 0 14px;}
.section-h h2{font-family:var(--display);font-weight:600;font-size:1.35rem;margin:0;letter-spacing:-.01em;}
h3{font-size:1rem;font-weight:700;margin:0 0 8px;}
.hint{color:var(--muted);font-size:.85rem;}

/* ---- buttons ---- */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:var(--tap);padding:0 18px;border-radius:12px;font-weight:600;background:var(--panel);border:1px solid var(--line);color:var(--ink);box-shadow:var(--sh-1);transition:transform .08s var(--ease),background .15s,border-color .15s;white-space:nowrap;}
.btn:hover{border-color:var(--line-2);}
.btn:active{transform:translateY(1px) scale(.99);}
.btn:disabled{opacity:.45;pointer-events:none;}
.btn svg{width:19px;height:19px;stroke:currentColor;fill:none;stroke-width:1.9;}
.btn.primary{background:var(--brass);color:#fff;border-color:var(--brass);box-shadow:0 2px 10px rgba(169,119,46,.3);}
.btn.dark{background:var(--midnight);color:#fff;border-color:var(--midnight);}
.btn.good{background:var(--good);color:#fff;border-color:var(--good);}
.btn.crit{background:var(--crit);color:#fff;border-color:var(--crit);}
.btn.ghost{background:transparent;box-shadow:none;}
.btn.sm{min-height:38px;padding:0 12px;font-size:.85rem;border-radius:9px;}
.btn.icon{width:44px;padding:0;}
.btn.block{width:100%;}
.btn.lg{min-height:60px;font-size:1.05rem;border-radius:14px;}

/* ---- inputs ---- */
.field{width:100%;min-height:48px;border-radius:11px;border:1px solid var(--line);background:var(--panel-2);padding:0 13px;font-size:1rem;transition:border-color .15s,box-shadow .15s;}
.field:focus{outline:none;border-color:var(--brass);box-shadow:0 0 0 3px rgba(169,119,46,.16);}
textarea.field{padding:11px 13px;min-height:80px;resize:vertical;}
label.lbl{display:block;font-size:.78rem;font-weight:600;color:var(--muted);margin:0 0 5px;text-transform:uppercase;letter-spacing:.04em;}
.row{display:flex;gap:10px;}.row.wrap{flex-wrap:wrap;}
.stack{display:flex;flex-direction:column;gap:12px;}
.grid{display:grid;gap:12px;}
.toggle{display:inline-flex;background:var(--panel-2);border:1px solid var(--line);border-radius:10px;padding:3px;gap:2px;}
.toggle button{padding:8px 14px;border-radius:8px;font-weight:600;font-size:.85rem;color:var(--muted);}
.toggle button.on{background:var(--panel);color:var(--ink);box-shadow:var(--sh-1);}
.swatch{width:26px;height:26px;border-radius:8px;border:2px solid transparent;cursor:pointer;}
.swatch.sel{border-color:var(--ink);}

/* ---- badges / status ---- */
.badge{display:inline-flex;align-items:center;gap:5px;font-size:.68rem;font-weight:700;padding:3px 9px;border-radius:999px;text-transform:uppercase;letter-spacing:.04em;}
.b-good{background:var(--good-2);color:var(--good);}.b-warn{background:var(--warn-2);color:var(--warn);}.b-crit{background:var(--crit-2);color:var(--crit);}.b-info{background:var(--info-2);color:var(--info);}.b-mute{background:var(--panel-3);color:var(--muted);}
/* « Annoncé »: the kitchen knows, nobody is cooking yet. Deliberately distinct from
   b-info (already sent for preparation) and b-mute (kitchen knows nothing). */
.b-ann{background:var(--brass-2,#4a3a1a);color:var(--brass,#C9A227);}

/* ---- KPI cards ---- */
.kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:14px;}
.kpi{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-l);padding:15px 17px;box-shadow:var(--sh-1);position:relative;overflow:hidden;}
.kpi .k{font-size:.74rem;font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.05em;}
.kpi .v{font-family:var(--display);font-size:1.9rem;font-weight:600;margin-top:4px;line-height:1;letter-spacing:-.01em;}
.kpi .d{font-size:.78rem;color:var(--muted);margin-top:6px;}
.kpi .ic{position:absolute;top:14px;right:14px;color:var(--brass);opacity:.5;}
.kpi.kpi-warn{border-color:var(--warn);} .kpi.kpi-warn .v{color:var(--warn);}
.kpi .ic svg{width:22px;height:22px;stroke:currentColor;fill:none;stroke-width:1.7;}

/* ---- tables ---- */
table.tbl{width:100%;border-collapse:collapse;font-size:.88rem;}
table.tbl th{text-align:left;padding:9px 12px;font-size:.68rem;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);border-bottom:1px solid var(--line);position:sticky;top:0;background:var(--panel);}
table.tbl td{padding:10px 12px;border-bottom:1px solid var(--line);}
table.tbl tr:hover td{background:var(--panel-2);}
table.tbl td.n,table.tbl th.n{text-align:right;font-variant-numeric:tabular-nums;}

/* ---- login ---- */
.login{flex:1;width:100%;height:100vh;display:grid;place-items:center;background:radial-gradient(1200px 500px at 50% -10%,var(--midnight-2),var(--midnight));}
.login .box{width:min(680px,92vw);text-align:center;color:#E9EEF5;}
.login .logo{width:64px;height:64px;border-radius:18px;background:linear-gradient(150deg,var(--brass),var(--brass-2));display:inline-grid;place-items:center;color:#0E1A2B;font-family:var(--display);font-weight:700;font-size:1.5rem;box-shadow:var(--sh-3);}
.login h1{font-family:var(--display);font-weight:600;font-size:1.9rem;margin:16px 0 4px;}
.login .venue{color:var(--brass-2);text-transform:uppercase;letter-spacing:.16em;font-size:.72rem;}
.staffgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:14px;margin-top:26px;}
.stafftile{background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.09);border-radius:16px;padding:18px 12px;display:flex;flex-direction:column;align-items:center;gap:9px;transition:.15s var(--ease);color:#E9EEF5;}
.stafftile:hover{background:rgba(255,255,255,.1);transform:translateY(-2px);}
.stafftile .role{font-size:.64rem;text-transform:uppercase;letter-spacing:.08em;color:var(--brass-2);}
.pinwrap{width:min(360px,92vw);margin:0 auto;}
.pindots{display:flex;gap:14px;justify-content:center;margin:20px 0;height:20px;}
.pindots i{width:16px;height:16px;border-radius:50%;background:rgba(255,255,255,.18);transition:.15s;}
.pindots i.on{background:var(--brass-2);transform:scale(1.05);}
.pinpad{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;}
.pinpad button{height:70px;border-radius:16px;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.08);color:#E9EEF5;font-size:1.5rem;font-weight:600;transition:.1s;}
.pinpad button:active{background:rgba(255,255,255,.16);}

/* ---- floor plan ---- */
.floorwrap{position:relative;height:100%;overflow:hidden;background:
  radial-gradient(circle at 1px 1px,var(--line) 1px,transparent 0) 0 0/26px 26px,var(--bg);}
.floor-toolbar{position:absolute;top:14px;left:14px;right:14px;display:flex;gap:10px;align-items:center;z-index:5;pointer-events:none;}
.floor-toolbar>*{pointer-events:auto;}
.sectionpills{display:flex;gap:8px;overflow-x:auto;}
.sectionpill{height:40px;padding:0 15px;border-radius:999px;background:var(--panel);border:1px solid var(--line);font-weight:600;font-size:.85rem;box-shadow:var(--sh-1);white-space:nowrap;}
.sectionpill.on{background:var(--brass);color:#fff;border-color:var(--brass);}
.floor-canvas{position:absolute;inset:66px 14px 14px 14px;transform-origin:0 0;overflow:auto;}
.ftable{position:absolute;width:104px;height:104px;border-radius:16px;background:var(--panel);border:2px solid var(--line);box-shadow:var(--sh-2);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;transition:box-shadow .15s,border-color .15s,transform .08s;cursor:pointer;}
.ftable.round{border-radius:50%;}
.ftable.rect{width:150px;}
.ftable.oval{width:150px;border-radius:50%;}
.ftable:active{transform:scale(.98);}
.ftable .lbl{font-family:var(--display);font-size:1.5rem;font-weight:700;line-height:1;}
.ftable .meta{font-size:.66rem;color:var(--muted);}
.ftable .amt{font-weight:700;color:var(--brass);font-size:.92rem;}
.ftable .wa{position:absolute;top:-9px;left:-9px;}
.ftable .st{position:absolute;bottom:-8px;left:50%;transform:translateX(-50%);}
.ftable .tmr{position:absolute;top:6px;right:8px;font-size:.64rem;color:var(--muted);font-variant-numeric:tabular-nums;}
.ftable.occupied{border-color:var(--brass);}
.ftable.bill{border-color:var(--info);}
.ftable.paid{border-color:var(--good);}
.ftable.late{border-color:var(--crit);box-shadow:0 0 0 4px var(--crit-2),var(--sh-2);}
.ftable.editing{cursor:grab;}
.ftable.dragging{cursor:grabbing;box-shadow:var(--sh-4);z-index:100;}

/* ---- order screen ---- */
/* WHY THERE IS A ROW TRACK HERE, AND WHY BOTH CHILDREN SAY min-height:0.
   Measured on the live till at 1280x800: .orderlayout was correctly 732px tall, and its two
   children were 824px — they sized to their CONTENT and overflowed the grid by 92px. The
   document does not scroll, so the overflow was simply CLIPPED: Envoyer ended 11px past the
   fold and Payer (820..882) was off the screen entirely and could not be reached at all.
   A cashier could not take payment without resizing the window.

   A grid item's default min-height is auto, which means "at least my content" and silently
   beats the 1fr track. `grid-template-rows:minmax(0,1fr)` fixes the track and
   `min-height:0` lets the children actually be bounded by it, so the ticket panel's
   own flex layout — scrolling lines, pinned totals, pinned commands — resolves inside the
   viewport instead of below it. */
.orderlayout{display:grid;grid-template-columns:1fr minmax(320px,380px);grid-template-rows:minmax(0,1fr);height:100%;min-height:0;overflow:hidden;}
.orderlayout>*{min-height:0;}
.menuside{display:flex;flex-direction:column;min-width:0;min-height:0;border-right:1px solid var(--line);}
.searchbar{padding:12px 14px;border-bottom:1px solid var(--line);display:flex;gap:10px;align-items:center;}
.searchbar .field{flex:1;}
.catbar{display:flex;gap:8px;padding:12px 14px;overflow-x:auto;border-bottom:1px solid var(--line);}
.catbar::-webkit-scrollbar{display:none;}
.catbar{padding:12px 14px;}
.catchip{height:46px;padding:0 16px;border-radius:12px;background:var(--panel-2);border:1px solid var(--line);font-weight:650;white-space:nowrap;display:flex;align-items:center;gap:8px;font-size:.92rem;transition:transform .08s var(--ease),box-shadow .12s;}
.catchip:active{transform:scale(.96);}
.catchip .dot{width:10px;height:10px;border-radius:4px;}
.catchip.on{background:var(--brass);color:#fff;border-color:var(--brass);box-shadow:0 4px 12px rgba(169,119,46,.35);}
/* Image-forward product cards (Milestone 1) — dense, colourful, large touch targets */
/* CASH-REGISTER DENSE. The photo is gone, so the tile no longer has to reserve a 4:3
   image area, and the height it was spending on a picture becomes article buttons. The
   grid scrolls INSIDE itself (min-height:0 + overflow:auto) so a long carte never pushes
   the ticket's actions off the screen. */
.prodgrid{flex:1;min-height:0;overflow:auto;padding:10px;display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:9px;align-content:start;}
.prodcard{min-height:88px;border-radius:13px;background:var(--panel);border:1px solid var(--line);box-shadow:var(--sh-1);padding:10px 11px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;text-align:center;position:relative;overflow:hidden;transition:transform .09s var(--ease),box-shadow .15s;}
.prodcard:hover{box-shadow:var(--sh-2);border-color:var(--brass-2);}
.prodcard:active{transform:scale(.96);}
/* One drawn glyph from the design system — part of the bundle, so the grid paints at once,
   can never show a broken image, and never waits on the network during a sale. */
/* THE CASHIER READS THE NAME. The icon is a shape to find a group by at a glance — a
   glass, a cup, a plate — and it is sized to support the name and the price rather than to
   compete with them. It is explicitly NOT scaled up with the screen: a bigger till buys
   more articles on screen, not a bigger picture of a coffee. The SVG's own width/height
   attributes are overridden here so one rule governs the size at every profile. */
.prodcard .cardic{color:var(--brass);display:flex;align-items:center;justify-content:center;flex:none;opacity:.85;}
.prodcard .cardic svg{width:18px;height:18px;}
.prodcard .cardbody{display:flex;flex-direction:column;gap:2px;align-items:center;width:100%;min-width:0;}
/* A long name wraps to two lines and then stops, so one verbose article cannot make its
   tile taller than its neighbours and break the row rhythm. */
.prodcard .nm{font-weight:650;font-size:.86rem;line-height:1.2;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;word-break:break-word;width:100%;}
.prodcard .pr{color:var(--brass);font-weight:800;font-variant-numeric:tabular-nums;font-size:1rem;}
.prodcard.fav::after{content:"★";position:absolute;top:5px;left:7px;color:#ffd479;font-size:.85rem;}
.prodcard .cardbadge.alc{position:absolute;top:8px;right:9px;background:#7a2e3a;color:#fff;font-size:.62rem;font-weight:800;padding:2px 7px;border-radius:7px;z-index:2;box-shadow:0 2px 6px rgba(0,0,0,.35);}
.prodcard.soldout{opacity:.5;}
.prodcard.soldout::before{content:"Épuisé";position:absolute;inset:0;display:grid;place-items:center;background:rgba(10,16,26,.55);color:var(--crit);font-weight:800;font-size:.85rem;z-index:1;}
.prodcard .cardqty{position:absolute;top:8px;right:9px;min-width:24px;height:24px;padding:0 6px;display:grid;place-items:center;background:var(--brass);color:#1a1206;font-size:.78rem;font-weight:800;border-radius:12px;z-index:3;box-shadow:0 2px 8px rgba(0,0,0,.45);font-variant-numeric:tabular-nums;}
/* if an alcohol badge already sits top-right, drop the qty pill below it */
.prodcard .cardbadge.alc~.cardqty{top:36px;}
.prodcard.pop{animation:cardbump .22s var(--ease);}
@keyframes cardbump{0%{transform:scale(1);}40%{transform:scale(1.06);}100%{transform:scale(1);}}
.schclear{position:absolute;right:8px;top:50%;transform:translateY(-50%);width:26px;height:26px;display:grid;place-items:center;border:0;border-radius:50%;background:var(--panel-2);color:var(--muted);cursor:pointer;transition:background .12s,color .12s;}
.schclear:hover{background:var(--brass);color:#1a1206;}
/* product-editor image picker + library */
.imgpick{display:flex;flex-direction:column;gap:10px;}
.imgpick-preview{position:relative;width:100%;}
.imgpick-thumb{width:100%;height:140px;border-radius:12px;background:var(--panel-2);background-size:cover;background-position:center;border:1px solid var(--line);display:grid;place-items:center;color:var(--muted);}
.imgpick-thumb.ph{opacity:.7;}
.imgpick-remove{position:absolute;top:8px;right:8px;width:28px;height:28px;display:grid;place-items:center;border:0;border-radius:50%;background:rgba(10,16,26,.72);color:#fff;cursor:pointer;}
.imgpick-remove:hover{background:var(--crit);}
.imgpick-actions{display:flex;gap:8px;flex-wrap:wrap;}
.imgpick-phlabel{display:block;font-size:.72rem;color:var(--muted);margin-top:4px;}
.imgtabs{display:flex;gap:4px;border-bottom:1px solid var(--line);flex-wrap:wrap;}
.imgtab{padding:9px 14px;border:0;background:none;color:var(--muted);font-weight:700;font-size:.85rem;cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px;}
.imgtab:hover{color:var(--ink);}
.imgtab.on{color:var(--brass);border-bottom-color:var(--brass);}
.imgtab-pane{min-height:200px;}
.imgdrop{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;height:180px;border:2px dashed var(--line-2);border-radius:14px;color:var(--muted);cursor:pointer;transition:border-color .12s,color .12s;}
.imgdrop:hover{border-color:var(--brass-2);color:var(--ink);}
.imglib{display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:10px;max-height:60vh;overflow:auto;}
.imglib-item{padding:0;border:2px solid transparent;border-radius:12px;background:none;cursor:pointer;overflow:hidden;}
.imglib-item.sel{border-color:var(--brass);}
.imglib-thumb{width:100%;height:96px;background-size:cover;background-position:center;background-color:var(--panel-2);border-radius:10px;}
.imglib-thumb img{width:100%;height:100%;object-fit:cover;border-radius:10px;display:block;}
/* A thumbnail that could not be fetched says so, rather than being a grey hole. */
.imglib-thumb.failed{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;font-size:.62rem;color:var(--muted);text-align:center;padding:4px;border:1px dashed var(--line);}
.imgpick-thumb.preview-ext{height:280px;display:flex;align-items:center;justify-content:center;background-color:var(--panel-2);}
.imgpick-thumb.preview-ext img{max-width:100%;max-height:280px;object-fit:contain;}
.art-thumb{width:52px;height:52px;flex:none;border-radius:10px;background:var(--panel-2);background-size:cover;background-position:center;display:grid;place-items:center;font-size:1.5rem;}
.ed-sec{font-size:.72rem;text-transform:uppercase;letter-spacing:.06em;font-weight:800;color:var(--brass);margin:6px 0 -2px;padding-top:6px;border-top:1px solid var(--line);}
.ed-sec:first-child{border-top:0;padding-top:0;}
.two textarea.field{resize:vertical;min-height:44px;font-family:inherit;}
.rmk-list{display:flex;flex-direction:column;gap:6px;}
.rmk-row{display:flex;gap:8px;align-items:flex-start;padding:8px;border-radius:10px;background:var(--panel-2);border:1px solid var(--line);}
.rmk-ord{display:flex;flex-direction:column;gap:2px;}
.rmk-ord button{width:24px;height:22px;font-size:.8rem;}
.field.sm{height:32px;padding:2px 8px;}
.art-toolbar{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-bottom:14px;padding:10px 12px;background:var(--panel);border:1px solid var(--line);border-radius:12px;}
.dup-banner{display:flex;align-items:center;gap:8px;padding:10px 12px;margin-bottom:12px;border-radius:10px;background:rgba(201,148,47,.12);border:1px solid var(--brass-2);color:var(--brass);font-size:.85rem;font-weight:600;}
.imglib-item.searchres{display:flex;flex-direction:column;gap:4px;}
.imglib-attr{font-size:.66rem;color:var(--muted);line-height:1.2;text-align:left;padding:0 2px 2px;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;}
.imglib-lic{font-size:.6rem;color:var(--brass);text-align:left;padding:0 2px 3px;text-transform:uppercase;letter-spacing:.03em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
/* client-side crop tool */
.cropwrap{display:grid;place-items:center;background:var(--panel-2);border-radius:12px;padding:14px;max-width:100%;}
.cropstage{position:relative;background-size:contain;background-repeat:no-repeat;background-position:center;border-radius:6px;touch-action:none;max-width:100%;}
.cropbox{position:absolute;border:2px solid var(--brass);box-shadow:0 0 0 9999px rgba(6,10,18,.55);cursor:move;touch-action:none;}
.crophandle{position:absolute;width:18px;height:18px;background:var(--brass);border:2px solid #1a1206;border-radius:4px;touch-action:none;}
.crophandle.br{right:-10px;bottom:-10px;cursor:nwse-resize;}

/* ORDER LINES SCROLL; TOTAL AND THE ACTIONS DO NOT. .tp-items is the only flexible row
   (flex:1 + min-height:0 + overflow:auto); .tp-totals and .tp-cmd are flex:none, so Total,
   Envoyer and Payer stay put however many lines the order grows. No absolute positioning
   and no viewport magic numbers — this holds at every size because it is a real layout. */
.ticket-panel{display:flex;flex-direction:column;background:var(--panel);min-width:0;height:100%;min-height:0;overflow:hidden;border-left:1px solid var(--line);}
.tp-head{padding:12px 14px;border-bottom:1px solid var(--line);display:flex;align-items:center;gap:10px;}
.tp-head .th-ico{width:34px;height:34px;display:grid;place-items:center;border-radius:9px;background:var(--panel-2);color:var(--brass);flex:none;}
.tp-head .th-main{min-width:0;}
.tp-head .t{font-family:var(--display);font-size:1.18rem;font-weight:600;line-height:1.1;}
.tp-head .th-sub{font-size:.72rem;color:var(--muted);margin-top:1px;}
.th-chip{display:inline-flex;align-items:center;gap:5px;height:28px;padding:0 10px;border-radius:14px;background:var(--panel-2);border:1px solid var(--line);color:var(--ink-2);font-size:.78rem;font-weight:700;cursor:pointer;}
.th-chip:hover{border-color:var(--brass-2);color:var(--ink);}
/* The three named chips of the ticket head. Each carries the canonical name the renderer
   branches on, so a flow can be dressed — or measured — without any selector depending on
   a French word. They are `.th-chip` first; these rules are what makes each one itself.
   « Nouvelle vente » STARTS something and is drawn as an action rather than a status;
   « Libellé » holds free text and is bounded so a long name cannot push the version badge
   off the row; « Couverts » holds a number that must not jiggle as it counts up. */
.cmd-newsale{border-color:var(--brass-2);color:var(--ink);}
/* `flex:none` is load-bearing, not tidiness. `overflow:hidden` alone let the chip shrink
   as a flex item, and at COMPACT the head squeezed it to 42px wide — a touch target lost
   to a rule meant to bound a long name. It is capped, and it never shrinks. */
.cmd-label{flex:none;max-width:210px;overflow:hidden;white-space:nowrap;}
.cmd-guests{font-variant-numeric:tabular-nums;}
.tp-note{padding:8px 14px;font-size:.8rem;color:var(--ink-2);background:var(--panel-2);border-bottom:1px solid var(--line);}
.tp-items{flex:1;min-height:0;overflow:auto;padding:4px 8px 8px;}
.tp-totals{flex:none;}
.tp-cmd{flex:none;}
.tp-course{position:sticky;top:0;z-index:1;display:flex;align-items:center;gap:8px;padding:8px 6px 4px;background:linear-gradient(var(--panel),var(--panel) 70%,transparent);}
.tp-course .cl{font-size:.7rem;text-transform:uppercase;letter-spacing:.08em;font-weight:800;color:var(--brass);}
.tp-course .c-count{font-size:.72rem;color:var(--muted);font-weight:700;background:var(--panel-2);border-radius:10px;padding:1px 8px;}
.oitem{padding:8px 8px;border-radius:11px;display:flex;gap:9px;align-items:flex-start;transition:background .1s;border:1px solid transparent;}
.oitem:hover{background:var(--panel-2);}
.oitem.comp{opacity:.9;}
.oitem.held{background:rgba(201,148,47,.08);border-color:rgba(201,148,47,.35);}
.oitem .qty{display:flex;align-items:center;gap:2px;background:var(--panel-2);border:1px solid var(--line);border-radius:9px;height:30px;flex:none;}
.oitem .qty button{width:26px;height:28px;font-weight:700;color:var(--brass);}
.oitem .qty button:disabled{color:var(--muted);opacity:.5;}
.oitem .qty .q{min-width:20px;text-align:center;font-weight:700;font-variant-numeric:tabular-nums;}
.oitem .nm{flex:1;min-width:0;}
.oitem .nm-t{font-weight:650;font-size:.9rem;line-height:1.2;}
.oitem .mods{font-size:.75rem;color:var(--muted);font-weight:400;margin-top:2px;}
.oitem .mods.rmk{color:var(--brass);}
.oitem .mods.note{color:var(--ink-2);font-style:italic;}
.oitem .st{display:flex;flex-wrap:wrap;gap:5px;align-items:center;margin-top:5px;}
.oitem .st .dest{font-size:.66rem;font-weight:700;padding:1px 7px;border-radius:7px;}
.oitem .st .dest.kitchen{background:rgba(201,148,47,.16);color:#e6b866;}
.oitem .st .dest.bar{background:rgba(46,110,122,.2);color:#6fb9c6;}
.oitem .lp{font-weight:700;font-variant-numeric:tabular-nums;white-space:nowrap;}
.oitem .lp .was{color:var(--muted);font-weight:500;margin-right:3px;}
.oitem-more{width:30px;height:30px;flex:none;border-radius:8px;color:var(--muted);font-size:1.3rem;line-height:1;font-weight:800;background:transparent;}
.oitem-more:hover{background:var(--panel-2);color:var(--ink);}
.oitem-new{animation:slidein .25s var(--ease);}
@keyframes slidein{from{opacity:0;transform:translateX(10px);}}
.tp-totals{border-top:1px solid var(--line);padding:10px 16px;}
.tp-totals .r{display:flex;justify-content:space-between;padding:2px 0;color:var(--ink-2);font-variant-numeric:tabular-nums;}
.tp-totals .r.disc{color:var(--good);}
.tp-totals .r.tot{font-size:1.35rem;font-weight:700;color:var(--ink);border-top:1px solid var(--line);margin-top:6px;padding-top:8px;font-family:var(--display);}
/* bottom command bar */
.tp-cmd{border-top:1px solid var(--line);background:var(--panel-2);padding:10px 12px;display:flex;flex-direction:column;gap:9px;}
.cmd-suite{margin-bottom:2px;}
.btn.warn{background:linear-gradient(180deg,#caa24a,#a9772e);color:#1a1206;border-color:#caa24a;font-weight:800;}
/* THE TOUCH FLOOR WINS OVER THE ROW COUNT. Six fixed columns squeezed these buttons to
   43px in a narrow ticket — under the 44px floor, on a control an operator is aiming at
   with a thumb. auto-fit + minmax lets the row WRAP to a second line instead of shrinking
   below the size of a finger: fewer per row, never smaller than usable. */
.cmd-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(46px,1fr));gap:6px;}
.cmd-sec{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;height:52px;border-radius:10px;background:var(--panel);border:1px solid var(--line);color:var(--ink-2);font-size:.68rem;font-weight:700;cursor:pointer;transition:border-color .1s,color .1s;}
.cmd-sec:hover{border-color:var(--brass-2);color:var(--ink);}
.cmd-sec svg{color:var(--brass);}
/* Flex, not a fixed 2-column grid: this row holds two buttons or three depending on
   whether anything is still unannounced, and both layouts have to stay touch-sized. The
   1:1.2 emphasis Envoyer always had is preserved by flex-grow rather than by a column
   template that only describes one of the two cases. */
.cmd-primary{display:flex;gap:8px;}
.cmd-primary .btn{flex:1 1 0;min-width:0;height:46px;font-weight:800;}
.cmd-send{flex-grow:1.2;}
/* Informational, not the action of record: outlined rather than filled, so the eye still
   lands on Envoyer when both are offered. */
.cmd-announce{background:var(--panel);border:1px dashed var(--brass-2);color:var(--ink);}
.cmd-announce:disabled,.cmd-send:disabled{opacity:.5;}
.cmd-save{background:var(--panel);border:1px solid var(--line);}
.cmd-send{background:var(--panel);border:1px solid var(--brass-2);color:var(--ink);}
.cmd-pay{width:100%;height:54px;font-size:1.05rem;display:flex;align-items:center;gap:8px;}
.cmd-pay b{font-variant-numeric:tabular-nums;}
/* line action + generic sheet */
.sheet{min-width:min(88vw,360px);}
.sheet-h{display:flex;align-items:center;gap:8px;padding-bottom:8px;border-bottom:1px solid var(--line);margin-bottom:8px;}
.sheet-sec{margin-bottom:8px;}
.sheet-courses{display:grid;grid-template-columns:repeat(4,1fr);gap:6px;margin-top:4px;}
.sheet-courses .chip{justify-content:center;padding:8px 4px;}
.sheet-list{display:flex;flex-direction:column;gap:4px;}
.sheet-act{display:flex;align-items:center;gap:10px;padding:11px 12px;border-radius:10px;background:var(--panel-2);border:1px solid var(--line);color:var(--ink);font-weight:600;font-size:.9rem;text-align:left;cursor:pointer;}
.sheet-act:hover{border-color:var(--brass-2);}
.sheet-act.on{border-color:var(--brass);color:var(--brass);}
.sheet-act.on svg{color:var(--brass);}
.sheet-act.danger{color:var(--crit);}
.sheet-act:disabled{opacity:.4;}
.sheet-act svg{color:var(--brass);flex:none;}

/* ---- modal / sheet / dialog ---- */
.scrim{position:fixed;inset:0;background:rgba(8,14,24,.5);backdrop-filter:blur(2px);display:flex;z-index:200;animation:fade .18s;}
@keyframes fade{from{opacity:0;}}
.scrim.center{align-items:center;justify-content:center;padding:18px;}
.scrim.right{justify-content:flex-end;}
.dialog{background:var(--panel);border-radius:var(--r-xl);box-shadow:var(--sh-4);width:min(560px,94vw);max-height:90vh;overflow:auto;animation:pop .2s var(--ease);}
@keyframes pop{from{opacity:0;transform:translateY(14px) scale(.98);}}
.sheet{background:var(--panel);box-shadow:var(--sh-4);width:min(560px,96vw);height:100%;overflow:auto;animation:slide .24s var(--ease);}
@keyframes slide{from{transform:translateX(30px);opacity:.6;}}
.dialog-h{display:flex;align-items:center;gap:12px;padding:18px 20px 6px;}
.dialog-h h2{font-family:var(--display);font-size:1.35rem;font-weight:600;margin:0;}
.dialog-h h2{flex:1;}
/* Modal dismissal. Secondary to the primary action but always reachable: a dialog with
   no footer (the image chooser has none) previously had no way out at all. */
.dialog-x{margin-left:auto;flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;
  width:36px;height:36px;border:0;border-radius:10px;background:transparent;color:var(--ink-2);
  cursor:pointer;transition:background .15s,color .15s;}
.dialog-x:hover{background:var(--surface-2,rgba(0,0,0,.06));color:var(--ink);}
.dialog-x:focus-visible{outline:2px solid var(--brand,#A9772E);outline-offset:2px;}
.dialog-b{padding:12px 20px;}
.dialog-f{display:flex;gap:10px;padding:14px 20px 18px;}
.dialog-f .btn{flex:1;}

/* chips (modifiers etc) */
.chips{display:flex;flex-wrap:wrap;gap:9px;}
.chip{min-height:46px;padding:0 15px;border-radius:12px;background:var(--panel-2);border:1px solid var(--line);font-weight:600;display:flex;align-items:center;gap:7px;}
.chip.on{background:var(--brass);color:#fff;border-color:var(--brass);}
.chip .px{opacity:.85;font-size:.82rem;}

/* ---- keypad / pay ---- */
.paylayout{display:grid;grid-template-columns:1fr 400px;height:100%;}
.methodgrid{display:grid;grid-template-columns:1fr 1fr;gap:12px;}
.method{min-height:76px;border-radius:16px;border:1px solid var(--line);background:var(--panel);box-shadow:var(--sh-1);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;font-weight:600;transition:.12s;}
.method svg{width:26px;height:26px;stroke:currentColor;fill:none;stroke-width:1.7;}
.method.on{background:var(--brass);color:#fff;border-color:var(--brass);box-shadow:0 4px 14px rgba(169,119,46,.35);}
.keypad{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;}
.keypad button{height:62px;border-radius:14px;background:var(--panel);border:1px solid var(--line);box-shadow:var(--sh-1);font-size:1.35rem;font-weight:600;}
.keypad button:active{background:var(--panel-2);}
.amount-lcd{font-family:var(--display);font-size:2.6rem;font-weight:600;text-align:right;padding:14px 18px;border-radius:14px;background:var(--panel-2);border:1px solid var(--line);font-variant-numeric:tabular-nums;letter-spacing:-.01em;}
.tippresets{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;}
.tippresets button{height:46px;border-radius:11px;background:var(--panel-2);border:1px solid var(--line);font-weight:600;font-size:.9rem;}
.tippresets button.on{background:var(--brass);color:#fff;border-color:var(--brass);}
.splitseg{display:grid;grid-auto-flow:column;grid-auto-columns:1fr;gap:6px;margin-bottom:8px;}
.splitseg button{height:42px;border-radius:10px;background:var(--panel-2);border:1px solid var(--line);font-weight:600;font-size:.82rem;color:var(--muted);}
.splitseg button.on{background:var(--panel);color:var(--ink);box-shadow:var(--sh-1);border-color:var(--brass);}
/* Primary amount UX (Exact / Autre montant) — larger, unmistakable */
.splitseg.amtmode button{height:54px;font-size:1rem;}
.splitseg.amtmode button.on{background:var(--brass);border-color:var(--brass);color:#fff;}
.paylines{display:flex;flex-direction:column;gap:8px;}
.payline{display:flex;align-items:center;gap:10px;padding:10px 12px;border-radius:11px;background:var(--panel-2);border:1px solid var(--line);}

/* receipt */
.receipt{background:#fff;color:#1a1a1a;border-radius:12px;width:340px;margin:0 auto;padding:20px 22px;font-family:var(--mono);font-size:12.5px;line-height:1.55;box-shadow:var(--sh-3);white-space:pre-wrap;}
:root[data-theme="dark"] .receipt{background:#f7f5f0;}
.receipt .ctr{text-align:center;}
.receipt .hr{border-top:1px dashed #999;margin:8px 0;}
.receipt .rr{display:flex;justify-content:space-between;}

/* toast */
.toasts{position:fixed;bottom:22px;left:50%;transform:translateX(-50%);display:flex;flex-direction:column;gap:10px;z-index:400;align-items:center;}
.toast{background:var(--midnight);color:#fff;padding:12px 18px;border-radius:12px;box-shadow:var(--sh-3);display:flex;gap:10px;align-items:center;font-weight:500;animation:toastin .25s var(--ease);max-width:92vw;}
@keyframes toastin{from{opacity:0;transform:translateY(12px);}}
.toast.ok{background:var(--good);}.toast.err{background:var(--crit);}.toast.warn{background:var(--warn);color:#231a06;}
.toast svg{width:18px;height:18px;stroke:currentColor;fill:none;stroke-width:2;}

/* skeleton / empty */
.skel{background:linear-gradient(90deg,var(--panel-2) 25%,var(--panel-3) 37%,var(--panel-2) 63%);background-size:400% 100%;animation:shimmer 1.3s infinite;border-radius:10px;}
@keyframes shimmer{from{background-position:100% 0;}to{background-position:0 0;}}
.empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:60px 20px;text-align:center;color:var(--muted);}
.empty .ic{width:64px;height:64px;border-radius:20px;background:var(--panel-2);display:grid;place-items:center;color:var(--brass);}
.empty .ic svg{width:30px;height:30px;stroke:currentColor;fill:none;stroke-width:1.6;}
.empty h3{color:var(--ink);font-family:var(--display);font-size:1.15rem;}

/* charts */
.chart{width:100%;height:200px;}
.chart .bar{fill:var(--brass);transition:.3s;}
.chart .bar:hover{fill:var(--brass-2);}
.chart .axis{stroke:var(--line);}
.chart text{fill:var(--muted);font-size:10px;font-family:var(--font);}
.spark path{fill:none;stroke:var(--brass);stroke-width:2;}
.spark .area{fill:var(--brass);opacity:.12;stroke:none;}

/* misc layout */
.two{display:grid;grid-template-columns:1fr 1fr;gap:16px;}
@media (max-width:900px){
  .orderlayout,.paylayout{grid-template-columns:1fr;}
  .ticket-panel,.paylayout>.card:last-child{position:fixed;inset:auto 0 0 0;height:62vh;border-top:1px solid var(--line);border-radius:18px 18px 0 0;box-shadow:var(--sh-4);z-index:30;}
  .two{grid-template-columns:1fr;}
  .prodgrid{grid-template-columns:repeat(auto-fill,minmax(128px,1fr));gap:10px;padding-bottom:64vh;}
}
@media (max-width:640px){
  .rail{width:100%;height:60px;flex-direction:row;position:fixed;bottom:0;left:0;right:0;padding:0 8px;justify-content:space-around;border-top:1px solid var(--line-2);}
  .rail .logo,.rail .spacer{display:none;}
  .rail nav{flex-direction:row;justify-content:space-around;}
  .rail a{width:52px;height:52px;}
  #app{flex-direction:column-reverse;}
  .content{padding-bottom:60px;}
  .prodgrid{grid-template-columns:repeat(auto-fill,minmax(104px,1fr));}
  .prodcard{min-height:84px;}
  .imglib{grid-template-columns:repeat(auto-fill,minmax(96px,1fr));}
  .cropstage{max-width:78vw;}
}
/* Narrow header (PAX / tablet portrait): drop diagnostic + secondary chrome so the
   top bar never overflows — avatar-only staff chip, no venue sub-line, no build badge. */
@media (max-width:820px){
  .topbar{gap:8px;padding:0 12px;}
  .topbar .sub{display:none;}
  .buildbadge{display:none;}
  .staffchip .nm,.staffchip .rl{display:none;}
  .staffchip{padding:0;width:44px;justify-content:center;}
}
.wf-fade{animation:fade .2s;}

/* ==================== Manager dashboard (Phase E) ==================== */
.db-kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px;}
.db-kpi{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:16px 18px;box-shadow:var(--sh-1);}
.db-kpi.accent{border-color:var(--brass-2);}
.db-kpi.warnk{border-color:rgba(201,148,47,.5);}
.dbk-v{font-family:var(--display);font-size:1.7rem;font-weight:700;font-variant-numeric:tabular-nums;line-height:1;}
.db-kpi.accent .dbk-v{color:var(--brass);}
.dbk-l{font-size:.78rem;color:var(--muted);margin-top:6px;text-transform:uppercase;letter-spacing:.04em;}
.dbk-s{font-size:.72rem;color:var(--ink-2);margin-top:2px;}
.db-grid2{display:grid;grid-template-columns:1fr 1fr;gap:16px;}
.db-card{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:14px 16px;box-shadow:var(--sh-1);min-width:0;}
.dbc-h{display:flex;align-items:center;gap:8px;margin-bottom:10px;}
.dbc-h h3{margin:0;font-size:1rem;}.dbc-h .grow{flex:1;}
.dbc-h>*:last-child:not(h3){margin-left:auto;}
.db-bars{display:flex;flex-direction:column;gap:8px;}
.db-bar{display:grid;grid-template-columns:minmax(80px,34%) 1fr auto;align-items:center;gap:10px;font-size:.85rem;}
.dbb-l{color:var(--ink-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.dbb-track{height:10px;background:var(--panel-2);border-radius:6px;overflow:hidden;}
.dbb-fill{height:100%;background:linear-gradient(90deg,var(--brass-2),var(--brass));border-radius:6px;}
.dbb-v{font-weight:700;font-variant-numeric:tabular-nums;white-space:nowrap;}
.db-table{width:100%;border-collapse:collapse;font-size:.86rem;}
.db-table th{text-align:left;color:var(--muted);font-size:.72rem;text-transform:uppercase;letter-spacing:.04em;padding:4px 8px;border-bottom:1px solid var(--line);}
.db-table td{padding:6px 8px;border-bottom:1px solid var(--line-2);font-variant-numeric:tabular-nums;}
.db-table tr.clickable{cursor:pointer;}
.db-table tr.clickable:hover td{background:var(--panel-2);}
.db-ctrls{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px;}
.db-ctrl{display:flex;flex-direction:column;align-items:flex-start;gap:2px;padding:12px 14px;border-radius:12px;border:1px solid var(--line);background:var(--panel-2);cursor:pointer;text-align:left;}
.db-ctrl:disabled{cursor:default;opacity:.85;}
.db-ctrl.ok{border-color:rgba(46,158,107,.35);}
.db-ctrl.warn{border-color:rgba(201,148,47,.55);}
.db-ctrl.crit{border-color:rgba(200,67,47,.6);}
.dbc-n{font-size:1.5rem;font-weight:800;font-variant-numeric:tabular-nums;}
.db-ctrl.ok .dbc-n{color:var(--good);}
.db-ctrl.warn .dbc-n{color:var(--brass);}
.db-ctrl.crit .dbc-n{color:var(--crit);}
.dbc-lb{font-size:.76rem;color:var(--ink-2);}
@media (max-width:900px){.db-grid2{grid-template-columns:1fr;}}
.db-filters{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:10px 14px;}
.db-flabel{font-size:.7rem;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);font-weight:700;margin-left:6px;}
.db-filters .field.sm{height:34px;}
/* ===== manager dashboard ===== */
.dash-screen{display:flex;flex-direction:column;gap:16px;}
/* header */
.dash-head{display:flex;align-items:center;gap:12px;}
.dash-head-ic{color:var(--brass);display:grid;place-items:center;}
.dash-head-t h2{font-family:var(--display);font-weight:600;font-size:1.5rem;margin:0;letter-spacing:-.01em;line-height:1.1;}
.dash-head-sub{color:var(--muted);font-size:.84rem;}
.dash-updated{color:var(--muted);font-size:.76rem;font-variant-numeric:tabular-nums;}
.dash-livepill{display:inline-flex;align-items:center;gap:7px;height:32px;padding:0 12px;border-radius:999px;background:var(--good-2);color:var(--good);font-size:.76rem;font-weight:700;text-transform:uppercase;letter-spacing:.05em;}
.dash-livedot{width:8px;height:8px;border-radius:50%;background:var(--good);animation:pulse 1.6s infinite;}
/* KPI cards */
.dash-kpis{grid-template-columns:repeat(auto-fit,minmax(158px,1fr));}
.dash-kpi{position:relative;overflow:hidden;background:var(--panel);border:1px solid var(--line);border-radius:var(--r-l);padding:15px 16px;box-shadow:var(--sh-1);min-height:92px;}
.dash-kpi-accent{position:absolute;left:0;top:0;bottom:0;width:4px;background:var(--acc,var(--brass));opacity:.9;}
.dash-kpi-ic{position:absolute;top:13px;right:13px;color:var(--acc,var(--brass));opacity:.55;}
.dash-kpi-ic svg{stroke-width:1.7;}
.dash-kpi-k{font-size:.72rem;font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.05em;padding-right:26px;}
.dash-kpi-v{font-family:var(--display);font-size:1.85rem;font-weight:600;line-height:1;margin-top:6px;letter-spacing:-.01em;font-variant-numeric:tabular-nums;}
.dash-kpi-foot{margin-top:9px;min-height:22px;display:flex;align-items:center;}
.dash-kpi-sub{font-size:.76rem;color:var(--muted);}
.dash-kpi-gauge{width:60px;margin-top:-4px;margin-bottom:-8px;}
.dash-trend{display:inline-flex;align-items:center;gap:4px;font-size:.76rem;font-weight:800;padding:3px 9px;border-radius:999px;font-variant-numeric:tabular-nums;}
.dash-trend .ar{font-size:.66rem;}
.dash-trend.up{background:var(--good-2);color:var(--good);}
.dash-trend.down{background:var(--crit-2);color:var(--crit);}
.dash-trend.flat{background:var(--panel-3);color:var(--muted);text-transform:uppercase;letter-spacing:.04em;}
/* card scaffolding */
.dash-card{display:flex;flex-direction:column;gap:12px;min-width:0;}
.dash-card-h{display:flex;align-items:center;gap:9px;}
.dash-card-h h3{margin:0;font-size:1rem;}
.dash-card-ic{color:var(--brass);display:grid;place-items:center;}
.dash-toggle button{padding:7px 11px;font-size:.78rem;min-height:34px;}
.dash-sub-h,.dash-chip-h{font-size:.7rem;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);margin-bottom:6px;display:block;}
/* line chart */
.dash-chart-wrap{width:100%;}
.dash-line{width:100%;height:auto;display:block;}
.dash-grid{stroke:var(--line);stroke-width:1;opacity:.6;}
.dash-axis{fill:var(--muted);font-size:10px;font-family:var(--font);font-variant-numeric:tabular-nums;}
.dash-l-today{fill:none;stroke:var(--brass);stroke-width:2.4;stroke-linejoin:round;stroke-linecap:round;}
.dash-l-yday{fill:none;stroke:var(--muted);stroke-width:1.8;stroke-dasharray:6 6;stroke-linecap:round;opacity:.85;}
.dash-l-week{fill:none;stroke:var(--faint);stroke-width:1.6;stroke-dasharray:1 6;stroke-linecap:round;}
.dash-l-dot{fill:var(--brass);stroke:var(--panel);stroke-width:2;}
.dash-l-lbl{fill:var(--brass);font-size:12px;font-weight:800;font-family:var(--font);font-variant-numeric:tabular-nums;}
.dash-legend-inline{display:flex;gap:16px;flex-wrap:wrap;font-size:.76rem;color:var(--muted);}
.dash-legend-inline span{display:inline-flex;align-items:center;gap:6px;}
.dash-legend-inline i{width:16px;height:0;border-top:2px solid var(--brass);display:inline-block;}
.dash-legend-inline i.lg-yday{border-top:2px dashed var(--muted);}
.dash-legend-inline i.lg-week{border-top:2px dotted var(--faint);}
.dash-chart-note{min-height:20px;}
/* heatmap */
.dash-heat{display:flex;flex-direction:column;gap:10px;}
.dash-heat-row{display:grid;grid-template-columns:repeat(16,1fr);gap:4px;}
.dash-heat-col{display:flex;flex-direction:column;align-items:center;gap:4px;min-width:0;}
.dash-heat-cell{width:100%;height:46px;border-radius:8px;border:1px solid var(--line);transition:transform .1s var(--ease);}
.dash-heat-cell:hover{transform:scale(1.06);}
.dash-heat-cell.peak{border-color:var(--brass);box-shadow:0 0 0 2px var(--brass-2);}
.dash-heat-h{font-size:.64rem;color:var(--muted);font-variant-numeric:tabular-nums;height:12px;}
.dash-heat-legend{display:flex;align-items:center;gap:8px;font-size:.72rem;color:var(--muted);}
.dash-heat-grad{flex:1;height:8px;border-radius:999px;background:linear-gradient(90deg,var(--panel-3),var(--brass));}
/* live status grid */
.dash-live-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:10px;}
.dash-live-item{display:flex;align-items:center;gap:10px;padding:11px 12px;border-radius:12px;background:var(--panel-2);border:1px solid var(--line);min-height:56px;}
.dash-live-ic{width:34px;height:34px;flex:none;border-radius:9px;background:var(--panel);display:grid;place-items:center;color:var(--brass);}
.dash-live-v{font-size:1.15rem;font-weight:800;line-height:1;font-variant-numeric:tabular-nums;}
.dash-live-k{font-size:.72rem;color:var(--muted);margin-top:3px;}
/* attention list */
.dash-attn{display:flex;flex-direction:column;gap:8px;}
.dash-attn-row{display:flex;align-items:center;gap:11px;width:100%;text-align:left;padding:11px 12px;border-radius:12px;background:var(--panel-2);border:1px solid var(--line);min-height:52px;transition:border-color .12s,transform .08s;}
.dash-attn-row:hover{border-color:var(--brass-2);}
.dash-attn-row:active{transform:scale(.99);}
.dash-attn-row>svg{color:var(--muted);flex:none;}
.dash-attn-dot{width:10px;height:10px;border-radius:50%;flex:none;}
.dash-attn-dot.high{background:var(--crit);box-shadow:0 0 0 4px var(--crit-2);}
.dash-attn-dot.med{background:var(--warn);box-shadow:0 0 0 4px var(--warn-2);}
.dash-attn-body{flex:1;min-width:0;}
.dash-attn-lbl{font-weight:700;font-size:.9rem;}
.dash-attn-det{font-size:.78rem;color:var(--muted);margin-top:1px;}
.dash-ok{display:flex;align-items:center;gap:10px;justify-content:center;padding:26px 12px;color:var(--good);font-weight:600;}
.dash-ok svg{color:var(--good);}
/* leaderboard */
.dash-leader{display:flex;flex-direction:column;gap:7px;}
.dash-leader-row{display:flex;align-items:center;gap:10px;padding:9px 10px;border-radius:12px;background:var(--panel-2);border:1px solid var(--line);}
.dash-rank{width:22px;text-align:center;font-weight:800;color:var(--brass);font-family:var(--display);font-size:1.05rem;flex:none;}
.dash-leader-main{flex:1;min-width:0;}
.dash-leader-nm{font-weight:700;font-size:.9rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.dash-leader-sub{font-size:.72rem;color:var(--muted);margin-top:1px;}
.dash-leader-stats{text-align:right;flex:none;}
.dash-leader-rev{font-weight:800;color:var(--brass);font-variant-numeric:tabular-nums;}
.dash-leader-tip{font-size:.7rem;color:var(--muted);margin-top:1px;font-variant-numeric:tabular-nums;}
/* stat trios + load bar */
.dash-stats-row{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;}
.dash-stat{padding:11px 12px;border-radius:12px;background:var(--panel-2);border:1px solid var(--line);text-align:center;}
.dash-stat-v{font-family:var(--display);font-size:1.3rem;font-weight:600;line-height:1;font-variant-numeric:tabular-nums;}
.dash-stat-k{font-size:.68rem;color:var(--muted);text-transform:uppercase;letter-spacing:.04em;margin-top:5px;}
.dash-stat.crit .dash-stat-v{color:var(--crit);}
.dash-load-h{display:flex;justify-content:space-between;font-size:.82rem;margin-bottom:6px;}
.dash-load-h b{font-variant-numeric:tabular-nums;}
.dash-course{margin-top:2px;}
/* horizontal bars */
.dash-bars{display:flex;flex-direction:column;gap:9px;}
.dash-bar-row{display:flex;align-items:center;gap:10px;}
.dash-bar-label{width:34%;min-width:80px;font-size:.82rem;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.dash-bar-track{flex:1;height:12px;background:var(--panel-3);border-radius:999px;overflow:hidden;}
.dash-bar-track.lg{height:14px;}
.dash-bar-fill{height:100%;border-radius:999px;background:var(--brass);transition:width .4s var(--ease);min-width:3px;}
.dash-bar-val{width:74px;text-align:right;font-size:.8rem;font-weight:700;font-variant-numeric:tabular-nums;flex:none;}
/* chips (stock / cancelled) */
.dash-chip-wrap{display:flex;flex-direction:column;gap:10px;margin-top:12px;padding-top:12px;border-top:1px solid var(--line);}
.dash-chips{display:flex;flex-wrap:wrap;gap:6px;}
/* donut */
.dash-donut-wrap{display:flex;align-items:center;gap:18px;flex-wrap:wrap;}
.dash-donut-svg{width:150px;height:150px;flex:none;}
.dash-donut-total{fill:var(--ink);font-family:var(--display);font-size:19px;font-weight:600;font-variant-numeric:tabular-nums;}
.dash-donut-cap{fill:var(--muted);font-size:10px;text-transform:uppercase;letter-spacing:.08em;font-family:var(--font);}
.dash-legend{display:flex;flex-direction:column;gap:7px;flex:1;min-width:140px;}
.dash-legend-row{display:flex;align-items:center;gap:8px;font-size:.84rem;}
.dash-legend-dot{width:11px;height:11px;border-radius:4px;flex:none;}
.dash-legend-nm{flex:1;color:var(--ink-2);}
.dash-legend-v{font-weight:700;font-variant-numeric:tabular-nums;}
.dash-simnote{display:flex;align-items:center;gap:8px;font-size:.78rem;color:var(--warn);background:var(--warn-2);padding:8px 11px;border-radius:10px;}
.dash-simnote svg{color:var(--warn);flex:none;}
/* gauge */
.dash-gauge{width:100%;height:auto;display:block;}
.dash-gauge-v{fill:var(--ink);font-family:var(--display);font-size:20px;font-weight:600;font-variant-numeric:tabular-nums;}
.dash-gauge-cap{fill:var(--muted);font-size:10px;text-transform:uppercase;letter-spacing:.06em;font-family:var(--font);}
/* occupancy */
.dash-occ{display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.dash-occ-gauge{width:158px;flex:none;}
.dash-occ-splits{flex:1;min-width:150px;display:flex;flex-direction:column;gap:12px;}
.dash-split-top{display:flex;justify-content:space-between;font-size:.82rem;margin-bottom:5px;}
.dash-split-top b{font-variant-numeric:tabular-nums;}
/* forecast */
.dash-forecast-big{font-family:var(--display);font-size:2.6rem;font-weight:600;line-height:1;letter-spacing:-.02em;color:var(--brass);font-variant-numeric:tabular-nums;}
.dash-forecast-cap{font-size:.82rem;color:var(--muted);margin-top:4px;}
/* alerts */
.dash-alerts{display:flex;flex-direction:column;gap:8px;}
.dash-alert{display:flex;align-items:center;gap:10px;padding:10px 12px;border-radius:10px;background:var(--panel-2);border:1px solid var(--line);border-left:3px solid var(--muted);font-size:.86rem;font-weight:500;}
.dash-alert-ic{color:var(--muted);flex:none;display:grid;place-items:center;}
.dash-alert.sev-high{border-left-color:var(--crit);background:var(--crit-2);}
.dash-alert.sev-high .dash-alert-ic{color:var(--crit);}
.dash-alert.sev-med{border-left-color:var(--warn);}
.dash-alert.sev-med .dash-alert-ic{color:var(--warn);}
.dash-alert.sev-low{border-left-color:var(--info);}
.dash-alert.sev-low .dash-alert-ic{color:var(--info);}
/* insights */
.dash-insights{display:flex;flex-direction:column;gap:9px;}
.dash-insight{display:flex;gap:10px;padding:11px 13px;border-radius:12px;background:var(--panel-2);border:1px solid var(--line);border-left:3px solid var(--brass);font-size:.86rem;line-height:1.4;}
.dash-insight.tone-good{border-left-color:var(--good);}
.dash-insight.tone-warn{border-left-color:var(--warn);}
.dash-insight.tone-info{border-left-color:var(--info);}
.dash-ai-mark{flex:none;filter:saturate(1.1);}
/* responsive */
@media (max-width:900px){
  .dash-head-t h2{font-size:1.25rem;}
  .dash-kpis{grid-template-columns:repeat(auto-fit,minmax(140px,1fr));}
  .dash-stats-row{gap:8px;}
  .dash-occ-gauge{margin:0 auto;}
}
@media (max-width:640px){
  .dash-kpis{grid-template-columns:repeat(2,1fr);}
  .dash-heat-cell{height:38px;}
  .dash-forecast-big{font-size:2.1rem;}
}

/* ===== reservations (floor-plan first) ===== */
.rz{display:flex;flex-direction:column;gap:14px;}
.rz-dash{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:10px;}
.rz-stat{background:var(--panel);border:1px solid var(--line);border-radius:var(--r);padding:12px 14px;box-shadow:var(--sh-1);}
.rz-stat-v{font-family:var(--display);font-size:1.5rem;font-weight:700;line-height:1;color:var(--ink);}
.rz-stat-k{font-size:.72rem;color:var(--muted);margin-top:5px;text-transform:uppercase;letter-spacing:.03em;}
.rz-stat-s{font-size:.72rem;color:var(--faint);margin-top:2px;}
.rz-stat.good{border-color:var(--good);} .rz-stat.good .rz-stat-v{color:var(--good);}
.rz-stat.warn{border-color:var(--warn);} .rz-stat.warn .rz-stat-v{color:var(--warn);}
.rz-stat.crit{border-color:var(--crit);} .rz-stat.crit .rz-stat-v{color:var(--crit);}
.rz-stat.info{border-color:var(--info);}
.rz-toolbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;}
.rz-pills{display:flex;gap:6px;flex-wrap:wrap;}
.rz-pill{display:inline-flex;align-items:center;gap:7px;padding:7px 12px;border-radius:999px;border:1px solid var(--line);background:var(--panel);color:var(--ink-2);font-weight:600;font-size:.85rem;}
.rz-pill.on{border-color:var(--brass);background:var(--brass);color:#fff;}
.rz-pill.on .rz-pill-t{color:#fff;opacity:.85;}
.rz-pill .dot{width:9px;height:9px;border-radius:50%;}
.rz-pill-t{font-size:.72rem;color:var(--muted);font-weight:600;}
.rz-pill.ghost{color:var(--muted);}
.rz-viewtoggle button{display:inline-flex;align-items:center;gap:6px;}

/* plan */
.rz-plan-wrap{padding:14px;min-height:420px;}
.rz-plan{position:relative;}
.rz-table{position:absolute;width:132px;min-height:80px;background:var(--panel-2);border:1.5px solid var(--line);border-radius:var(--r);padding:7px 8px;cursor:pointer;transition:transform .08s,box-shadow .12s;box-shadow:var(--sh-1);}
.rz-table:hover{transform:translateY(-2px);box-shadow:var(--sh-2);border-color:var(--brass);}
.rz-table.free{border-style:dashed;background:var(--panel);}
.rz-table.occupied{background:var(--info-2);}
.rz-table.late{border-color:var(--crit);box-shadow:0 0 0 2px var(--crit-2);}
.rz-table-h{display:flex;align-items:center;justify-content:space-between;margin-bottom:5px;}
.rz-table-h b{font-size:1.05rem;color:var(--ink);}
.rz-cap{display:inline-flex;align-items:center;gap:3px;font-size:.72rem;color:var(--muted);}
.rz-chip{display:flex;align-items:center;gap:6px;background:var(--panel);border:1px solid var(--line);border-left:3px solid var(--brass);border-radius:6px;padding:3px 6px;margin-bottom:3px;font-size:.74rem;}
.rz-chip-t{font-variant-numeric:tabular-nums;font-weight:700;color:var(--ink);}
.rz-chip-n{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ink-2);}
.rz-chip-g{background:var(--panel-3);border-radius:6px;padding:0 6px;font-weight:700;color:var(--ink-2);}
.rz-flag{color:var(--crit);font-weight:900;}
.rz-free{font-size:.8rem;color:var(--faint);font-style:italic;padding:6px 2px;}
.rz-more{font-size:.72rem;color:var(--muted);text-align:center;}

/* timeline */
.rz-tl-grid{min-width:max-content;}
.rz-tl-axis,.rz-tl-row{display:flex;align-items:stretch;border-bottom:1px solid var(--line);}
.rz-tl-axis{position:sticky;top:0;z-index:3;background:var(--panel);border-bottom:2px solid var(--line-2);}
.rz-tl-gut{width:92px;min-width:92px;position:sticky;left:0;z-index:2;background:var(--panel);border-right:1px solid var(--line);display:flex;flex-direction:column;justify-content:center;padding:4px 10px;}
.rz-tl-gut b{font-size:.9rem;color:var(--ink);} .rz-tl-gut .rz-cap{font-size:.68rem;}
.rz-tl-axis .rz-tl-gut{font-weight:700;color:var(--muted);font-size:.75rem;text-transform:uppercase;}
.rz-tl-track{position:relative;height:34px;flex:1;}
.rz-tl-row .rz-tl-track{height:100%;}
.rz-tl-row.drop .rz-tl-track{background:var(--brass-2);opacity:.9;}
.rz-tick{position:absolute;top:0;bottom:0;padding:8px 0 0 4px;font-size:.72rem;color:var(--muted);border-left:1px solid var(--line);font-variant-numeric:tabular-nums;}
.rz-grid{position:absolute;top:0;bottom:0;width:1px;background:var(--line);opacity:.5;}
.rz-bar{position:absolute;top:5px;bottom:5px;border-radius:6px;color:#fff;padding:3px 8px;cursor:grab;overflow:hidden;box-shadow:var(--sh-1);user-select:none;touch-action:none;}
.rz-bar:active{cursor:grabbing;}
.rz-bar.late{outline:2px solid var(--crit);}
.rz-bar.walkin{background-image:repeating-linear-gradient(45deg,rgba(255,255,255,.14) 0 6px,transparent 6px 12px);}
.rz-bar-l{font-size:.74rem;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.rz-bar-s{font-size:.66rem;opacity:.9;white-space:nowrap;}
.rz-h{position:absolute;top:0;bottom:0;width:8px;cursor:ew-resize;}
.rz-h-l{left:0;} .rz-h-r{right:0;}

/* analytics */
.rz-peak{display:flex;align-items:flex-end;gap:8px;height:150px;padding-top:8px;}
.rz-peak-col{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;height:100%;gap:5px;}
.rz-peak-bar{width:70%;min-height:3px;background:linear-gradient(var(--brass-2),var(--brass));border-radius:5px 5px 0 0;}
.rz-peak-x{font-size:.68rem;color:var(--muted);font-variant-numeric:tabular-nums;}
.rz-rank{display:flex;align-items:center;gap:10px;}
.rz-rank b{width:78px;font-size:.85rem;}
.rz-rank-bar{flex:1;height:12px;background:var(--panel-3);border-radius:6px;overflow:hidden;}
.rz-rank-bar span{display:block;height:100%;background:var(--brass);border-radius:6px;}
.rz-rank-n{width:24px;text-align:right;font-weight:700;color:var(--ink-2);font-variant-numeric:tabular-nums;}

/* dialog rows / badges / suggestion */
.rz-resrow{border:1px solid var(--line);border-radius:var(--r);padding:9px 11px;background:var(--panel-2);}
.rz-resrow-h{display:flex;align-items:center;gap:8px;margin-bottom:4px;}
.rz-resrow-m{font-size:.78rem;color:var(--muted);margin-bottom:7px;}
.rz-badge{display:inline-flex;align-items:center;padding:2px 9px;border-radius:999px;font-size:.72rem;font-weight:700;border:1px solid transparent;}
.rz-badge.walkin{background:var(--panel-3);color:var(--muted);}
.rz-chosen{display:flex;align-items:center;gap:8px;min-height:34px;}
.rz-sugg{margin-top:8px;}
.rz-sugg-row{display:flex;gap:8px;flex-wrap:wrap;}
.rz-sugg-chip{display:inline-flex;flex-direction:column;align-items:flex-start;gap:2px;padding:8px 12px;border:1.5px solid var(--line);border-radius:var(--r-s);background:var(--panel);min-width:96px;}
.rz-sugg-chip.rec{border-color:var(--brass);background:var(--brass-2);}
.rz-sugg-chip.rec .rz-sugg-tag{color:var(--brass-ink);font-weight:800;font-size:.62rem;text-transform:uppercase;letter-spacing:.04em;}
.rz-sugg-cap{font-size:.72rem;color:var(--muted);}


/* ── Reservation FLOOR (canonical geometry) ─────────────────────────────────
   The old .rz-plan cards are gone; this is the real restaurant, drawn with the same
   renderer as the Salle. Two columns on a desk, stacked on a tablet held upright — the
   detail panel must never be a drawer a host has to dismiss to see the floor again. */
/* THE FLOOR GETS THE SCREEN.
   The panel is a second column ONLY while it has a table to describe (.with-side); the
   rest of the time the plan spans the full width and the legend sits under it as a key.
   A permanent 320px column holding "Sélectionnez une table…" is the last thing the one
   screen whose job is to show a room should be spending width on. */
.rzf-wrap{display:grid;grid-template-columns:minmax(0,1fr);grid-template-areas:'stage';gap:12px;align-items:stretch;}
.rzf-wrap.with-side{grid-template-columns:minmax(0,1fr) 320px;grid-template-areas:'stage side';}
.rzf-stagecard{grid-area:stage;position:relative;padding:0;overflow:hidden;}
.rzf-sidecard{grid-area:side;overflow:auto;min-height:0;max-height:calc(100vh - 360px);display:none;}
.rzf-wrap.with-side .rzf-sidecard{display:block;}
.rzf-legendbar{position:absolute;left:12px;top:12px;padding:6px 10px;border-radius:12px;background:color-mix(in srgb, var(--panel) 88%, transparent);border:1px solid var(--line);box-shadow:var(--sh-1);backdrop-filter:blur(6px);pointer-events:none;max-width:calc(100% - 300px);}
.rzf-stagecard.rzf-full{position:fixed;inset:0;z-index:60;border-radius:0;border:0;margin:0;max-width:none;}
.rzf-stagecard.rzf-full .rzf-stage{border-radius:0;}
body.rzf-fullbody{overflow:hidden;}
/* Tall on purpose: the plan is the content, and the surrounding chrome (stat strip, day
   bar, view toggle) already takes the top third of the page. */
.rzf-stage{position:relative;min-height:420px;height:calc(100vh - 360px);max-height:940px;background:var(--panel-2);}
.rzf-svg{display:block;width:100%;height:100%;touch-action:manipulation;}
.rzf-t{cursor:pointer;}
.rzf-t:focus-visible{outline:none;}
.rzf-t:focus-visible .rzf-hit{outline:3px solid var(--brass);outline-offset:-3px;border-radius:12px;}
/* Fit / rotate / zoom, floating OVER the plan so the controls cost it no room. */
.rzf-cam{position:absolute;right:12px;bottom:12px;display:flex;align-items:center;gap:6px;padding:6px;border-radius:12px;background:color-mix(in srgb, var(--panel) 88%, transparent);border:1px solid var(--line);box-shadow:var(--sh-1);backdrop-filter:blur(6px);}
.rzf-cam .btn.icon{min-width:40px;min-height:40px;}
.rzf-zoomv{font-size:.75rem;color:var(--muted);min-width:42px;text-align:center;font-variant-numeric:tabular-nums;}
.rzf-side{display:flex;flex-direction:column;gap:10px;}
.rzf-side-h{display:flex;align-items:flex-start;gap:8px;}
.rzf-side-h>div:first-child{flex:1;min-width:0;}
.rzf-side-empty{display:flex;flex-direction:column;align-items:center;gap:10px;text-align:center;color:var(--muted);padding:18px 6px;}
.rzf-side-empty p{margin:0;font-size:.86rem;}
.rzf-legend{display:flex;flex-wrap:wrap;gap:8px 14px;justify-content:center;}
.rzf-leg{display:inline-flex;align-items:center;gap:6px;font-size:.76rem;color:var(--ink-2);}
.rzf-dot{width:11px;height:11px;border-radius:50%;flex:0 0 auto;}

/* The day + service control. Stated in words, because "what am I looking at?" is the
   first question a reservation floor has to answer. */
/* TOUCH TARGETS ARE NOT A NARROW-SCREEN CONCERN. The Sunmi CPad runs 1280×800 in
   landscape — a WIDE viewport — and these were 34–38 px there because the comfortable
   sizing was hidden behind a max-width media query. A host taps these with a thumb while
   carrying plates, at whatever orientation the stand happens to be in. 44 px everywhere. */
.rz-datebar{display:flex;align-items:center;gap:6px;flex-wrap:wrap;}
.rz-datebar .btn.icon{min-width:44px;min-height:44px;}
/* The day label IS the date picker's button — one control, one date. */
.rz-daylabel{display:flex;align-items:center;gap:8px;min-width:170px;min-height:44px;padding:0 12px;
  justify-content:center;font-size:.95rem;background:var(--panel-2);border:1px solid var(--line);
  border-radius:10px;color:var(--ink);cursor:pointer;}
.rz-daylabel:active{background:var(--panel-3);}
.rz-daylabel svg{opacity:.65;}
.rz-today{min-height:44px;}
/* Present for the picker, never shown: it is opened from the label and nothing else.
   Not display:none — a hidden input cannot be opened by showPicker() or click(). */
.rz-datein-hidden{position:absolute;width:1px;height:1px;opacity:0;border:0;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);}
.rz-pill{min-height:44px;}
.rz-viewtoggle button{min-height:44px;}
.imgtab{min-height:44px;}

@media (max-width:980px){
  .rzf-wrap, .rzf-wrap.with-side{grid-template-columns:minmax(0,1fr);grid-template-areas:'stage' 'legend' 'side';}
  .rzf-stage{height:calc(100vh - 330px);min-height:420px;}
  .rzf-sidecard{max-height:none;}
}
/* Portrait tablet (800×1280 on a Sunmi CPad): the floor gets the height, the panel
   scrolls under it, and every control keeps a 44px touch target. */
@media (max-width:860px) and (orientation:portrait){
  /* Portrait on a CPad: the room is the page. */
  .rzf-stage{height:calc(100vh - 330px);min-height:460px;}
  .rz-daylabel{min-width:0;flex:1;}
}

.rz-dash.compact{display:flex;flex-wrap:wrap;gap:8px;}
.rz-dash.compact .rz-stat{display:flex;align-items:baseline;gap:7px;padding:6px 11px;border-radius:999px;}
.rz-dash.compact .rz-stat-v{font-size:1.02rem;}
.rz-dash.compact .rz-stat-k{margin-top:0;font-size:.67rem;}
.rz-dash.compact .rz-stat-s{display:none;}
@media (max-width:1100px){ .rz-dash{grid-template-columns:repeat(4,1fr);} }
@media (max-width:720px){ .rz-dash{grid-template-columns:repeat(2,1fr);} .rz-toolbar{gap:8px;} .rz-tl-gut{width:64px;min-width:64px;} }

/* Unified dashboard facet tabs (Cockpit | Analyse) — from pos-sandbox-till-enhancements */
.dash-unified{display:flex;flex-direction:column;gap:12px;height:100%;}
.dash-facets{display:flex;gap:6px;padding:2px;background:var(--panel);border:1px solid var(--line);border-radius:12px;align-self:flex-start;}
.dash-facet{padding:8px 20px;border:0;background:none;border-radius:9px;font:600 .9rem system-ui,sans-serif;color:var(--muted);cursor:pointer;}
.dash-facet.on{background:var(--brass);color:#1a1205;}
.dash-tabbody{flex:1;min-height:0;}

/* ===== floor: kitchen-ready status on the table ===== */
.kfood{position:absolute;bottom:-11px;left:50%;transform:translateX(-50%);z-index:5;font-size:.7rem;font-weight:800;border-radius:999px;padding:3px 10px;text-align:center;letter-spacing:.01em;line-height:1.15;white-space:nowrap;max-width:150px;overflow:hidden;text-overflow:ellipsis;border:2px solid var(--panel);}
.kfood.ready{background:var(--good);color:#fff;box-shadow:0 1px 4px rgba(46,158,107,.4);}
.kfood.ready.partial{background:linear-gradient(90deg,var(--good) 60%,var(--warn) 60%);}
.kfood.prep{background:var(--panel-3);color:var(--muted);font-weight:700;}
.kfood.delayed{background:var(--crit);color:#fff;}
.ftable.foodready{border-color:var(--good) !important;box-shadow:0 0 0 3px var(--good-2),0 8px 18px rgba(46,158,107,.28);animation:foodpulse 2.2s ease-in-out infinite;}
.ftable.kdelayed{border-color:var(--crit) !important;box-shadow:0 0 0 2px var(--crit-2);}
@keyframes foodpulse{0%,100%{box-shadow:0 0 0 3px var(--good-2),0 8px 18px rgba(46,158,107,.28);}50%{box-shadow:0 0 0 5px var(--good-2),0 10px 22px rgba(46,158,107,.42);}}
@media (prefers-reduced-motion:reduce){.ftable.foodready{animation:none;}}

/* ===== journal de contrôle (X / Z) ===== */
.jc-filters{display:flex;gap:8px;flex-wrap:wrap;align-items:center;}
.jc-chk{display:inline-flex;align-items:center;gap:6px;font-size:.85rem;color:var(--ink-2);padding:0 6px;}
.jc-tbl th,.jc-tbl td{white-space:nowrap;font-size:.82rem;padding:7px 10px;}
.jc-tbl tbody tr:hover{background:var(--panel-2);}
.jc-tbl tr.jc-reopened{background:var(--warn-2);}
.jc-report{font-size:.86rem;}
.jc-report-h{display:flex;justify-content:space-between;font-family:var(--display);font-weight:700;font-size:1.05rem;border-bottom:2px solid var(--line-2);padding-bottom:8px;margin-bottom:10px;}
.jc-sec{font-weight:700;text-transform:uppercase;letter-spacing:.04em;font-size:.7rem;color:var(--muted);border-top:1px dashed var(--line);margin:12px 0 5px;padding-top:7px;}
.jc-report .rr{display:flex;justify-content:space-between;padding:2px 0;}
.jc-warn{background:var(--warn-2);border:1px solid var(--warn);border-radius:var(--r);padding:10px 12px;font-size:.85rem;}
.jc-warn.good{background:var(--good-2);border-color:var(--good);}
.jc-warn.crit{background:var(--crit-2);border-color:var(--crit);}

/* ===== Floor-plan designer ===== */
.fp-wrap{position:relative;height:100%;display:flex;flex-direction:column;background:var(--bg,#0e1726);overflow:hidden;}
.fp-toolbar{display:flex;align-items:center;gap:6px;padding:8px 12px;border-bottom:1px solid var(--line,#22314a);background:var(--panel,#111d30);flex-wrap:wrap;}
.fp-title{display:flex;align-items:center;gap:8px;font-size:.98rem;}
.fp-toolbar .grow{flex:1;}
.fp-zoom{font-size:.78rem;color:var(--muted,#8a97ab);min-width:38px;text-align:center;}
.fp-level{background:var(--panel-2,#16233a);color:var(--ink,#e7edf5);border:1px solid var(--line,#2a3a52);border-radius:8px;padding:4px 8px;font-size:.82rem;}
.fp-body{flex:1;display:flex;min-height:0;}
.fp-main{flex:1;display:flex;flex-direction:column;min-width:0;}
.fp-modes{display:flex;align-items:center;gap:4px;padding:6px 12px;border-bottom:1px solid var(--line,#22314a);background:var(--panel-2,#0f1a2c);}
.fp-mode{background:transparent;border:1px solid transparent;color:var(--muted,#8a97ab);border-radius:8px;padding:5px 12px;font-size:.85rem;cursor:pointer;}
.fp-mode.on{background:var(--panel,#1a2a44);color:var(--ink,#e7edf5);border-color:var(--line,#2a3a52);}
.fp-tools{display:flex;gap:4px;flex-wrap:wrap;}
.fp-tool{background:var(--panel,#152337);border:1px solid var(--line,#2a3a52);color:var(--ink,#cfd8e6);border-radius:7px;padding:4px 9px;font-size:.78rem;cursor:pointer;}
.fp-tool.on{background:var(--brass,#c4984a);color:#1a1206;border-color:var(--brass,#c4984a);font-weight:600;}
.fp-canvas{flex:1;position:relative;overflow:hidden;background:radial-gradient(circle at 50% 40%,#132139,#0c1524);touch-action:none;}
.fp-canvas.fp-arming{cursor:crosshair;}
.fp-svg{display:block;width:100%;height:100%;}
.fp-obj{cursor:move;}
.fp-obj.locked{cursor:not-allowed;opacity:.85;}
.fp-obj.sel>*:first-child,.fp-tbl.sel>*:first-child{stroke-width:2.4;filter:drop-shadow(0 0 4px rgba(196,152,74,.7));}
.fp-tbl{cursor:move;}
.fp-lbl{fill:#9fb0c6;font-size:12px;font-family:var(--display,inherit);pointer-events:none;}
.fp-tlbl{fill:#e7edf5;font-size:13px;font-weight:600;pointer-events:none;}
.fp-handle{fill:var(--brass,#c4984a);stroke:#1a1206;stroke-width:1;cursor:nwse-resize;rx:3;}
.fp-side{width:290px;border-left:1px solid var(--line,#22314a);background:var(--panel,#111d30);overflow-y:auto;flex:none;}
.fp-inspector{padding:14px;}
.fp-inspector h4{margin:0 0 10px;font-size:.92rem;color:var(--brass,#c4984a);text-transform:uppercase;letter-spacing:.04em;}
.fp-row{display:flex;align-items:center;gap:8px;margin-bottom:8px;}
.fp-row label{flex:0 0 78px;font-size:.8rem;color:var(--muted,#8a97ab);}
.fp-num,.fp-txt{flex:1;background:var(--panel-2,#16233a);color:var(--ink,#e7edf5);border:1px solid var(--line,#2a3a52);border-radius:7px;padding:5px 8px;font-size:.84rem;min-width:0;}
.fp-ro{flex:1;font-size:.84rem;color:var(--ink,#cfd8e6);}
.fp-actions{display:flex;flex-direction:column;gap:6px;margin-top:12px;}
.fp-actions .btn{width:100%;justify-content:center;}
.fp-empty{display:flex;flex-direction:column;align-items:center;gap:8px;text-align:center;color:var(--muted,#8a97ab);padding:30px 12px;font-size:.85rem;}
.fp-empty p{margin:0;}
.fp-list{display:flex;flex-direction:column;gap:6px;margin-top:10px;}
.fp-listitem{display:flex;align-items:center;justify-content:space-between;gap:8px;background:var(--panel-2,#16233a);border:1px solid var(--line,#2a3a52);border-radius:8px;padding:7px 10px;cursor:pointer;color:var(--ink,#e7edf5);text-align:left;}
.fp-listitem.on{border-color:var(--brass,#c4984a);}
.fp-zonecard{background:var(--panel-2,#16233a);border:1px solid var(--line,#2a3a52);border-radius:10px;padding:10px;margin-bottom:8px;}
.fp-zonehd{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px;}
.fp-zonerow{display:flex;flex-wrap:wrap;gap:8px;align-items:center;}
.fp-toggle{display:flex;align-items:center;gap:5px;font-size:.76rem;color:var(--muted,#9fb0c6);}
.fp-vlist{display:flex;flex-direction:column;gap:8px;min-width:280px;}
.fp-vitem{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:8px 10px;border:1px solid var(--line,#2a3a52);border-radius:8px;}
@media(max-width:820px){.fp-side{width:100%;position:fixed;inset:auto 0 0 0;max-height:44vh;border-top:1px solid var(--line);z-index:20;}}

/* Floor-plan structural backdrop behind the operational table cards */
.floor-planlayer{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:0;overflow:visible;}
.floor-planlbl{fill:#9fb0c6;font-size:12px;opacity:.8;}
.floor-canvas>.card,.floor-canvas>.tablecard,.floor-canvas>[class*="table"]{position:relative;z-index:1;}

/* ===== Floor-plan designer v2 (handles, bar segments, preview) ===== */
.fp-outline{fill:none;stroke:var(--brass,#c4984a);stroke-width:1.6;stroke-dasharray:5 4;pointer-events:none;}
.fp-handle{fill:var(--brass,#c4984a);stroke:#1a1206;stroke-width:1;cursor:nwse-resize;rx:3;}
.fp-vtx{fill:#fff;stroke:var(--brass,#c4984a);stroke-width:2;cursor:grab;}
.fp-rot{fill:#fff;stroke:var(--brass,#c4984a);stroke-width:2;cursor:grab;}
.fp-rotarm{stroke:var(--brass,#c4984a);stroke-width:1.4;pointer-events:none;}
.fp-node{cursor:move;}
.fp-node.locked{cursor:not-allowed;opacity:.9;}
.fp-node.sel .fpr-table>*:first-child,.fp-node.sel .fpr-bar polygon{filter:drop-shadow(0 0 5px rgba(196,152,74,.7));}
.fp-svg.preview .fp-handles,.fp-svg.preview .fp-vtx{display:none;}
.fp-tlbl{fill:#eaf0f8;font-size:12.5px;font-weight:600;pointer-events:none;paint-order:stroke;stroke:rgba(10,16,28,.7);stroke-width:3px;}
.fp-tools .fp-tool.bar{background:rgba(196,152,74,.18);border-color:var(--brass,#c4984a);color:var(--brass,#c4984a);}
.fp-seghd{display:flex;align-items:center;justify-content:space-between;margin:12px 0 6px;font-size:.82rem;}
.fp-seg{background:var(--panel-2,#16233a);border:1px solid var(--line,#2a3a52);border-radius:8px;padding:8px 10px;margin-bottom:6px;}
.fp-seg>b{font-size:.75rem;color:var(--brass,#c4984a);display:block;margin-bottom:4px;}
.btn.xs{font-size:.72rem;padding:3px 8px;border-radius:6px;}
.fp-svg{cursor:default;background:radial-gradient(circle at 50% 38%,#14233c,#0b1322);}
.fp-svg.preview{background:radial-gradient(circle at 50% 40%,#16273f,#0c1626);}

/* ===== Service-mode SVG floor (fit-to-screen furniture + compact overlay) ===== */
.floor-svc{position:absolute;inset:0;width:100%;height:100%;display:block;touch-action:none;}
.svc-tbl{cursor:pointer;}
.svc-tbl.dim{opacity:.28;}
.svc-tbl.lp-armed .fpr-table>*:nth-child(2){filter:brightness(1.25);}
.svc-num{fill:#f2f6fb;font-weight:700;font-family:var(--display,inherit);paint-order:stroke;stroke:rgba(8,14,26,.85);stroke-width:3px;pointer-events:none;dominant-baseline:middle;}
.svc-num.bar{fill:#241a08;stroke:rgba(255,240,210,.5);stroke-width:1.5px;}
.svc-amt{fill:#e7c99a;font-weight:700;paint-order:stroke;stroke:rgba(8,14,26,.85);stroke-width:2.5px;pointer-events:none;dominant-baseline:middle;}
.floor-svc .fpr-chairs{opacity:.8;}

/* ===== Floor-plan CATALOGUE editor (3-panel) ===== */
.fp-body.cat{display:flex;min-height:0;}
.fp-catalogue{width:250px;flex:none;border-right:1px solid var(--line,#22314a);background:var(--panel,#111d30);overflow-y:auto;display:none;}
.fp-body.cat.editing .fp-catalogue{display:block;}
.fp-cathead{display:flex;align-items:center;gap:8px;padding:10px 12px;border-bottom:1px solid var(--line,#22314a);font-weight:700;font-size:.9rem;}
.fp-cattabs{display:flex;flex-wrap:wrap;gap:4px;padding:8px 10px;border-bottom:1px solid var(--line,#22314a);}
.fp-cattab{background:var(--panel-2,#16233a);border:1px solid var(--line,#2a3a52);color:var(--muted,#9fb0c6);border-radius:14px;padding:4px 10px;font-size:.72rem;cursor:pointer;}
.fp-cattab.on{background:var(--brass,#c4984a);color:#1a1206;border-color:var(--brass,#c4984a);font-weight:600;}
.fp-catgrid{display:grid;grid-template-columns:1fr 1fr;gap:8px;padding:10px;}
.fp-catcard{display:flex;flex-direction:column;align-items:center;gap:5px;background:var(--panel-2,#16233a);border:1px solid var(--line,#2a3a52);border-radius:10px;padding:8px 6px;cursor:grab;color:var(--ink,#e7edf5);transition:border-color .12s,transform .08s;touch-action:none;}
.fp-catcard:hover{border-color:var(--brass,#c4984a);transform:translateY(-1px);}
.fp-catcard:active{cursor:grabbing;}
.fp-thumb{width:100%;height:52px;display:block;background:radial-gradient(circle at 50% 45%,#17263e,#0e1a2c);border-radius:7px;}
.fp-catname{font-size:.7rem;text-align:center;line-height:1.15;color:var(--ink,#cfd8e6);}
.fp-cathint{padding:8px 12px 14px;font-size:.72rem;color:var(--muted,#8a97ab);}
.fp-ghost{position:fixed;z-index:9999;pointer-events:none;background:var(--brass,#c4984a);color:#1a1206;font-size:.75rem;font-weight:700;padding:4px 9px;border-radius:7px;box-shadow:0 6px 16px rgba(0,0,0,.4);opacity:.92;}
.fp-ghost.over{background:#7bbf7b;color:#0c1a0c;}
.fp-insphead{margin-bottom:10px;}
.fp-insphead h4{margin:0;font-size:.95rem;color:var(--brass,#c4984a);text-transform:uppercase;letter-spacing:.03em;}
.fp-insphead .hint{font-size:.72rem;margin-top:2px;}

/* ===== Architectural planner: full-screen workspace, rulers, dimensions, layers ===== */
.fp-wrap.fp-fullscreen{position:fixed;inset:0;z-index:300;background:var(--bg,#0e1726);}
.fp-canvas{position:relative;}
.fp-rulers{position:absolute;inset:0;pointer-events:none;z-index:5;}
.fp-ruler.top{position:absolute;top:0;left:0;right:0;height:18px;background:rgba(12,20,34,.7);border-bottom:1px solid rgba(255,255,255,.06);}
.fp-ruler.left{position:absolute;top:0;left:0;bottom:0;width:18px;background:rgba(12,20,34,.7);border-right:1px solid rgba(255,255,255,.06);}
.fp-rcorner{position:absolute;top:0;left:0;width:18px;height:18px;background:rgba(12,20,34,.85);display:flex;align-items:center;justify-content:center;color:var(--muted,#7f8ea3);}
.fp-rtick{fill:#9fb0c6;font-size:8px;}
.fp-dim{fill:#e7c99a;font-size:12px;font-weight:600;paint-order:stroke;stroke:rgba(8,14,26,.85);stroke-width:3px;cursor:text;}
.fp-layers{border:1px solid var(--line,#2a3a52);border-radius:10px;background:var(--panel-2,#14202f);margin-bottom:12px;padding:8px 10px;}
.fp-layhd{display:flex;align-items:center;gap:6px;font-size:.78rem;color:var(--brass,#c4984a);margin-bottom:6px;font-weight:700;text-transform:uppercase;letter-spacing:.03em;}
.fp-layrow{display:flex;align-items:center;gap:7px;font-size:.78rem;color:var(--ink,#cfd8e6);padding:2px 0;cursor:pointer;}
.fp-layrow.off{opacity:.5;}

/* ===== Planner v2 — premium light architectural shell (scoped to full-screen edit) ===== */
.fp-wrap.fp-fullscreen{background:#e9ebf0;}
.fp-fullscreen .fp-toolbar{background:#ffffff;color:#22282f;border-bottom:1px solid #e6e2da;box-shadow:0 1px 0 rgba(30,22,10,.03);}
.fp-fullscreen .fp-toolbar .fp-title b{color:#22282f;}
.fp-fullscreen .fp-toolbar .btn.ghost,.fp-fullscreen .fp-toolbar .btn.icon{color:#4a5460;background:transparent;}
.fp-fullscreen .fp-toolbar .btn.ghost:hover{background:#f1eee8;}
.fp-fullscreen .fp-toolbar .btn.sm:not(.primary):not(.ghost){background:#f4f1ea;border:1px solid #e3ddd2;color:#33404f;}
.fp-fullscreen .fp-toolbar .btn.primary{background:#c39a4e;color:#241703;border:0;}
.fp-fullscreen .fp-zoom{color:#5a6472;}
.fp-fullscreen .fp-body{background:#e9ebf0;}
/* left catalogue — dark premium panel */
.fp-fullscreen .fp-catalogue{background:#12161d;border-right:1px solid #0a0d12;width:262px;}
.fp-fullscreen .fp-cathead{color:#f2f5f9;border-bottom-color:#1e2530;}
.fp-fullscreen .fp-cattab{background:#1b222d;border-color:#28313d;color:#9aa7b6;}
.fp-fullscreen .fp-cattab.on{background:#c39a4e;color:#241703;border-color:#c39a4e;}
.fp-fullscreen .fp-catcard{background:#191f28;border:1px solid #262f3b;color:#e6ebf1;border-radius:12px;}
.fp-fullscreen .fp-catcard:hover{border-color:#c39a4e;background:#1d242e;}
.fp-fullscreen .fp-thumb{background:linear-gradient(180deg,#f6f2ea,#e9e3d7);border:1px solid #2b3541;}
.fp-fullscreen .fp-catname{color:#c3cdd9;}
.fp-fullscreen .fp-cathint{color:#7c8a9b;}
/* cream tiled canvas (floor tile drawn in SVG) */
.fp-fullscreen .fp-canvas{background:#f1ece3;}
.fp-fullscreen .fp-svg{background:#f1ece3;}
.fp-fullscreen .fp-ruler.top,.fp-fullscreen .fp-ruler.left{background:rgba(255,255,255,.82);border-color:#e0dacf;}
.fp-fullscreen .fp-rtick{fill:#8a7f6a;}
.fp-fullscreen .fp-rcorner{background:#fff;color:#b3a88f;}
/* right properties — white panel */
.fp-fullscreen .fp-side{background:#ffffff;border-left:1px solid #e6e2da;color:#22282f;width:284px;}
.fp-fullscreen .fp-side .fp-inspector h4,.fp-fullscreen .fp-insphead h4{color:#22282f;letter-spacing:0;text-transform:none;font-size:1rem;}
.fp-fullscreen .fp-side .hint,.fp-fullscreen .fp-side .fp-insphead .hint{color:#8a93a1;}
.fp-fullscreen .fp-side .fp-row label{color:#6a7382;}
.fp-fullscreen .fp-side .fp-txt,.fp-fullscreen .fp-side .fp-num{background:#f6f4ef;border:1px solid #e3ddd2;color:#22282f;}
.fp-fullscreen .fp-side .fp-ro{color:#33404f;}
.fp-fullscreen .fp-side .btn.ghost{background:#f4f1ea;border:1px solid #e3ddd2;color:#3a4653;}
.fp-fullscreen .fp-side .btn.danger{background:#f7ede9;border:1px solid #eccfc6;color:#b1503c;}
.fp-fullscreen .fp-side .btn.primary,.fp-fullscreen .fp-side .btn.block.primary{background:#c39a4e;color:#241703;border:0;}
.fp-fullscreen .fp-seg{background:#f6f4ef;border-color:#e6e0d4;}
.fp-fullscreen .fp-seg>b,.fp-fullscreen .fp-seghd b{color:#7a5a2e;}
.fp-fullscreen .fp-layers{background:#f6f4ef;border-color:#e6e0d4;}
.fp-fullscreen .fp-layhd{color:#7a5a2e;}
.fp-fullscreen .fp-layrow{color:#3a4653;}
.fp-fullscreen .fp-dim{fill:#6a4a1e;stroke:rgba(255,255,255,.75);stroke-width:3px;}
/* status footer */
.fp-status{display:none;}
.fp-fullscreen .fp-status{display:flex;align-items:center;gap:20px;padding:9px 18px;background:#ffffff;border-top:1px solid #e6e2da;color:#5a6472;font-size:.8rem;flex-wrap:wrap;}
.fp-fullscreen .fp-status .grow{flex:1;}
.fp-fullscreen .fp-stat{display:flex;align-items:center;gap:7px;}
.fp-fullscreen .fp-stat .k{color:#98a0ad;font-size:.72rem;text-transform:uppercase;letter-spacing:.05em;}
.fp-fullscreen .fp-stat b{color:#2b333f;font-variant-numeric:tabular-nums;font-weight:700;}
.fp-fullscreen .fp-stat.toggle{color:#5a6472;cursor:pointer;}

/* Carte > QR Menu workspace — responsive layout.
   Wide: [section nav | editor | mobile preview]. Tablet: drop the preview column.
   Narrow (Android POS): stack the section nav above the editor. */
.qr-ws-grid { display: grid; grid-template-columns: 220px 1fr auto; gap: 18px; align-items: start; }
@media (max-width: 1180px) {
  .qr-ws-grid { grid-template-columns: 200px 1fr; }
  .qr-ws-preview { display: none; }
}
@media (max-width: 720px) {
  .qr-ws-grid { grid-template-columns: 1fr; }
  .qr-ws-nav { flex-direction: row; flex-wrap: wrap; }
  .qr-ws-nav .btn { flex: 1 1 auto; }
}

/* QR codes management cards */
.qrgrid-codes { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 12px; }
.qrcard { border: 1px solid var(--line, #2a3a52); border-radius: 12px; padding: 12px 13px; background: var(--panel-2, #14202f); display: flex; flex-direction: column; gap: 10px; }
.qrcard-h { display: flex; align-items: center; gap: 10px; }
.qrcard-ic { font-size: 1.35rem; line-height: 1; }
.qrcard-t { font-weight: 700; }
.qrcard-sub { font-size: .74rem; color: var(--muted, #8a9aad); }
.qrcard-actions { display: flex; flex-wrap: wrap; gap: 6px; }
.qrcard-url { font-size: .72rem; color: var(--muted, #8a9aad); }
.qrcard-url summary { cursor: pointer; user-select: none; }
.qrcard-url code { display: block; margin-top: 5px; word-break: break-all; opacity: .8; font-size: .68rem; }
@media (max-width: 640px) { .qrgrid-codes { grid-template-columns: 1fr; } }

/* Salle > Demandes clients — compact collapsible live panel */
.srq-panel { position: absolute; left: 14px; bottom: 14px; z-index: 6; width: 288px; max-width: calc(100vw - 28px); max-height: 56vh; overflow-y: auto; background: var(--panel-2, #132234); border: 1px solid var(--line, #2a3a52); border-radius: 12px; box-shadow: 0 10px 28px rgba(0,0,0,.42); }
.srq-h { display: flex; align-items: center; gap: 8px; padding: 9px 10px 9px 12px; border-bottom: 1px solid var(--line, #2a3a52); position: sticky; top: 0; background: var(--panel-2, #132234); border-radius: 12px 12px 0 0; cursor: default; }
.srq-list { display: flex; flex-direction: column; }
.srq-item { display: flex; align-items: center; gap: 10px; padding: 9px 12px; border-bottom: 1px solid var(--line, #2a3a52); }
.srq-item:last-child { border-bottom: 0; }
.srq-item.is-new { background: rgba(220,80,80,.09); }
.srq-item.is-stale { background: rgba(214,158,46,.14); }
@keyframes srqflash { 0% { box-shadow: 0 0 0 0 rgba(220,80,80,.55); } 100% { box-shadow: 0 0 0 14px rgba(220,80,80,0); } }
.srq-panel.srq-flash { animation: srqflash .9s ease-out 1; }
@media (prefers-reduced-motion: reduce) { .srq-panel.srq-flash { animation: none; } }

/* ── Activation + startup failure ────────────────────────────────────────────
   Both live on the SAME canvas as the employee login (.login: full-screen
   Midnight radial + brass). They are the first thing anyone sees on a till, so
   they must read as Success POS rather than as a browser dialog. Everything here
   is scoped under .login and reuses the existing tokens — no second design
   system, no one-off colours. */
.login .lead{color:#BFCBDA;margin:12px 0 0;line-height:1.55;font-size:1.05rem;}
.login .sub{color:#8B9BB0;margin:6px 0 0;font-size:.95rem;}
.login .inp{width:100%;margin-top:20px;background:rgba(255,255,255,.06);
  border:1px solid rgba(255,255,255,.16);color:#E9EEF5;border-radius:14px;
  padding:18px 20px;font-size:1.3rem;text-align:center;letter-spacing:.18em;
  font-family:var(--display);transition:.15s var(--ease);}
.login .inp::placeholder{color:#5B6B80;letter-spacing:.12em;}
.login .inp:focus{outline:none;border-color:var(--brass-2);
  box-shadow:0 0 0 3px rgba(198,155,77,.22);background:rgba(255,255,255,.09);}
.login .acts{display:flex;gap:14px;justify-content:center;margin-top:22px;flex-wrap:wrap;}
.login .acts .btn{min-width:200px;min-height:56px;font-size:1.02rem;}
.login .note{color:#8B9BB0;font-size:.92rem;margin-top:18px;min-height:1.35em;}
.login .note.err{color:#E8A79A;}
/* The failure state is the login canvas with a restrained crit-toned mark — an
   error, not an alarm, and never a red page. */
.login .failmark{width:66px;height:66px;border-radius:20px;display:inline-grid;
  place-items:center;background:rgba(200,67,47,.15);
  border:1px solid rgba(200,67,47,.38);margin:0 auto 10px;}
.login .failmark svg{width:30px;height:30px;stroke:#E8A79A;fill:none;stroke-width:1.8;}

/* ── Paramètres workspace ────────────────────────────────────────────────────
   A flat 20-card list rendered 2027px of content in a single 660px column at
   EVERY width: 2.6 screens of scrolling on a 1366×768 laptop while ~1250px of a
   1920px screen went unused. Grouped sections give the hierarchy; the grid uses
   the width that was already there. Two columns from 1000px, one below.

   grid-template-columns with minmax(0,1fr) — never a fixed width and never
   absolute positioning — so cards cannot collide or overflow at any viewport,
   and long French labels wrap inside their own cell. */
.param-hub{display:flex;flex-direction:column;gap:22px;max-width:1040px;}
.param-group{display:flex;flex-direction:column;gap:10px;}
.param-grouph{margin:0;font-family:var(--display);font-size:.82rem;font-weight:700;
  letter-spacing:.08em;text-transform:uppercase;color:var(--ink-2);opacity:.85;}
.param-grid{display:grid;grid-template-columns:1fr;gap:10px;}
@media (min-width:1000px){ .param-grid{grid-template-columns:repeat(2,minmax(0,1fr));} }
/* The card keeps the existing settingcard styling; only its box sizing is
   constrained so a grid cell cannot be pushed wider by its own content. */
.param-grid .settingcard{min-width:0;}
.param-grid .settingcard > div{min-width:0;}

/* ── Visual issue reporter ───────────────────────────────────────────────────
   The reporter is shared across Success Payment products and styles itself from a small
   token contract. Mapping it here is what makes it look like part of THIS product rather
   than a tool sitting on top of it, and it inherits the dark theme for free because these
   are the same tokens every other surface uses.

   The accent is the brass the till already uses for its primary actions, so a merchant
   sees the reporter as one of the product's own controls.                              */
:root{
  --sp-vr-surface: var(--panel);
  --sp-vr-surface-2: var(--panel-2);
  --sp-vr-text: var(--ink);
  --sp-vr-muted: var(--muted);
  --sp-vr-border: var(--line);
  --sp-vr-accent: var(--brass);
  --sp-vr-accent-ink: #fff;
  --sp-vr-radius: var(--r);
  --sp-vr-radius-s: var(--r-s);
  --sp-vr-shadow: var(--sh-3);
  --sp-vr-font: var(--font);
}

/* ============================================================================
   TOUCH-FIRST (Sunmi CPad) — centralised, 2026-08. Raises interactive targets to
   a finger-friendly minimum, removes the tap delay + double-tap-zoom + grey tap
   flash, keeps text inputs selectable, and makes dialogs keyboard-safe. Hover
   styles remain as desktop progressive enhancement; scoped to interactive
   controls so information density and the desktop/operator surfaces are intact.
   ============================================================================ */

/* No 300ms tap delay, no double-tap zoom on controls, no grey flash. Scroll
   containers keep touch-action:auto, so finger scrolling is never disabled. */
button, .btn, .rail a, .stafftile, .ftable, .settingcard, .catchip, .prodcard,
.chip, .sheet-act, .toggle button, .pinpad button, .staffchip, .navbadge,
.dialog-x, .swatch, .pill, input[type=checkbox], input[type=radio], select {
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

/* Text inputs stay selectable even though body sets user-select:none. */
input:not([type=checkbox]):not([type=radio]), textarea {
  -webkit-user-select: text; user-select: text;
}

/* Segmented toggle — was ~34px tall; a finger needs more. */
.toggle button { min-height: 44px; padding: 0 16px; font-size: .9rem; }

/* The staff-menu chip is a primary, frequently-tapped control. */
.staffchip { min-height: 48px; }

/* Small / icon buttons: compact, but never below a finger. */
.btn.sm { min-height: 44px; padding: 0 14px; }
.btn.icon { width: 48px; min-width: 48px; }

/* Native checkboxes/radios are ~16px — too small to hit or see. Enlarge the
   control and make the whole label row a comfortable tap target. */
input[type=checkbox], input[type=radio] {
  width: 24px; height: 24px; accent-color: var(--brass); flex: none; cursor: pointer;
}
label.row { min-height: 44px; align-items: center; cursor: pointer; }

/* Course chips inside the order sheet were cramped. */
.sheet-courses .chip { min-height: 44px; padding: 0 6px; }

/* Colour swatches (role/venue) — above a finger minimum. */
.swatch { width: 34px; height: 34px; }

/* Immediate press feedback where a card/tile is tapped (some had none). */
.settingcard:active, .stafftile:active, .chip:active, .sheet-act:active,
.staffchip:active { transform: scale(.98); }

/* Dialogs stay inside the visible viewport even when the Android soft keyboard
   is open (dynamic viewport height), scrolling their own content. */
.dialog { max-height: 90vh; max-height: 90dvh; }
.sheet { height: 100vh; height: 100dvh; }

/* Custom controls the LIVE CPad audit measured below a finger (2026-08). */
.sectionpill { min-height: 44px; }            /* floor area selector */
.th-chip { min-height: 44px; }                /* order-header guest/cover chip */
.dialog-x { width: 44px; height: 44px; }      /* modal close */

/* ============================================================================
   TOUCH-FIRST v2 (Sunmi CPad, 2026-08) — a VISIBLE finger-first pass, not just
   44px minimums. The v1 layer met the target-size metric but left the layout
   reading desktop; this enlarges the high-frequency P0/P1 controls, the rail,
   type and row heights so the till reads as a tablet POS at arm's length. Still
   landscape 1280x800, still dense enough to show a menu grid and a floor.
   Override block: appended last so it wins the cascade over the base values.
   ============================================================================ */

:root { --tap: 58px; --rail: 92px; }
body { font-size: 16px; }

/* Navigation rail — wider, bigger tiles + icons + label, more breathing room. */
.rail { padding: 16px 0 12px; }
.rail nav { gap: 8px; }
.rail a { width: 72px; height: 66px; border-radius: 16px; font-size: .66rem; gap: 4px; }
.rail a svg { width: 26px; height: 26px; }

/* Top bar + status pills — taller, easier to read/press. */
.topbar { height: 68px; }
.pill { height: 42px; padding: 0 15px; font-size: .88rem; }
.staffchip { min-height: 56px; padding: 0 10px; }
.staffchip .nm { font-size: .95rem; }

/* Buttons — more generous padding + type; primary reads as the obvious action. */
.btn { padding: 0 24px; font-size: 1.02rem; border-radius: 14px; gap: 10px; }
.btn.sm { min-height: 46px; padding: 0 16px; font-size: .95rem; }
.btn.icon { width: 56px; min-width: 56px; }
.btn.lg { min-height: 66px; font-size: 1.12rem; }
.btn.primary { font-weight: 700; }

/* Order pad — the highest-frequency surface: bigger category chips + product
   cards + prices so a waiter aims with a finger, not a cursor. */
.catbar { gap: 10px; padding: 14px 16px; }
.catchip { height: 56px; padding: 0 20px; font-size: 1rem; border-radius: 14px; }
.prodgrid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; padding: 11px; }
.prodcard { min-height: 94px; border-radius: 14px; }
.prodcard .nm { font-size: 1rem; }
.prodcard .pr { font-size: 1.18rem; }

/* Floor area selector + generic chips — clearly tappable. */
.sectionpill { min-height: 54px; padding: 0 20px; font-size: .95rem; }
.chip { min-height: 54px; padding: 0 18px; font-size: .95rem; }
.th-chip { min-height: 46px; padding: 0 14px; font-size: .85rem; }

/* Inputs + segmented toggles — taller, bigger text for the Android keyboard. */
.field { min-height: 54px; font-size: 1.05rem; border-radius: 12px; }
.toggle button { min-height: 50px; padding: 0 18px; font-size: .95rem; }

/* PIN pad — already large, nudged for confident entry. */
.pinpad { gap: 14px; }
.pinpad button { height: 78px; font-size: 1.65rem; border-radius: 18px; }
.stafftile { padding: 22px 14px; border-radius: 18px; }

/* Data rows (movements, transactions, staff) — taller, more legible. */
table.tbl { font-size: .95rem; }
table.tbl td { padding: 15px 14px; }
table.tbl th { padding: 12px 14px; }

/* Cards, setting rows + dialogs — more padding, bigger close + actions. */
.card.p { padding: 20px; }
.settingcard { gap: 18px; padding: 18px; }
.settingcard .seticon { width: 54px; height: 54px; }
.dialog-x { width: 48px; height: 48px; }
.dialog-h { padding: 20px 22px 8px; }
.sheet-act { padding: 15px 14px; font-size: 1rem; }
.section-h h2 { font-size: 1.5rem; }

/* ============================================================================
   SUPPORT · RECEIPT · PRINTERS — CPad pass, 2026-08.

   The Support screen was the only place in the app that styled its controls with
   `.inp`, and `.inp` is defined ONLY under `.login`. Outside the sign-in screen it
   matched nothing at all: every input, textarea and select on that screen rendered
   as a raw native control with the browser's own background and `color: inherit`
   — which under the dark palette is #E9EEF5, near-white text in a white box. That
   is the "typed text is impossible to read" report, and it was one missing rule.

   The second half was `.field` being used as a WRAPPER. `.field` IS the input
   class (width:100%, min-height:54px, padding:0 13px, border, background), so a
   label plus a six-row textarea were being crammed inside a control-shaped box
   with zero vertical padding. That is the overlapping text.

   Both are now the design system: `.field` for controls, `.formrow` for rows.
   ============================================================================ */

/* A labelled control. NOT `.field` — see above. */
.formrow { display: flex; flex-direction: column; gap: 6px; margin-bottom: 16px; }
.formrow > .lbl { font-size: .82rem; font-weight: 600; color: var(--ink-2); letter-spacing: .01em; }
.formrow > .hint { margin-top: 2px; }

/* TYPED TEXT IS INK, IN BOTH THEMES, ALWAYS. A textarea that inherits its colour
   from a card and its background from the browser is the bug above; both are
   stated here so neither can drift. */
.field, textarea.field, select.field, input.field {
  color: var(--ink);
  background: var(--panel-2);
  border: 1px solid var(--line);
  caret-color: var(--brass);
}
.field::placeholder, textarea.field::placeholder { color: var(--faint); opacity: 1; }
.field:focus, textarea.field:focus, select.field:focus {
  outline: none; border-color: var(--brass); box-shadow: 0 0 0 3px var(--brass-soft, rgba(169,119,46,.18));
}
/* Multi-line entry on a tablet: room to type, and a comfortable line height. */
textarea.sup-text {
  min-height: 140px; line-height: 1.5; padding: 12px 14px; resize: vertical;
  font-family: inherit; font-size: 1.02rem;
}

/* The Support column. Was `max-width:760px` inline on every node, which left most
   of the CPad's 1280px landscape screen empty while the content it did have was
   cramped. */
.sup-col { max-width: 860px; width: 100%; }
.sup-ticket { cursor: pointer; margin-bottom: 12px; }
.sup-ticket:active { transform: scale(.995); }
.sup-sent { text-align: center; }
/* Chips and a title in one row must WRAP rather than ride over each other — the
   overlapping words on a narrow viewport. */
.sup-col .row { flex-wrap: wrap; row-gap: 8px; min-width: 0; }
.sup-col .row > * { min-width: 0; }
.sup-col .mono { overflow-wrap: anywhere; }

/* A message. The two authors used to differ by an 8% grey wash — invisible in
   both themes. Ours carries the brass edge; the merchant's own words sit on the
   plain panel. Both in full --ink, never a muted body. */
.sup-msg { margin: 14px 0; padding: 14px 16px; border-radius: 14px; border: 1px solid var(--line); }
.sup-msg.mine { background: var(--panel-2); }
.sup-msg.theirs { background: var(--panel-3); border-left: 4px solid var(--brass); }
.sup-msg-who { font-size: .78rem; font-weight: 600; color: var(--muted); margin-bottom: 8px; }
.sup-msg-body { white-space: pre-wrap; overflow-wrap: anywhere; color: var(--ink); line-height: 1.55; font-size: 1rem; }

/* ---- the receipt screen's guaranteed way out ---- */
.receipt-topbar {
  display: flex; align-items: center; gap: 10px;
  margin: 0 0 10px; padding-bottom: 10px; border-bottom: 1px solid var(--line);
}

/* ---- printers ---- */
.prn-card { display: flex; align-items: flex-start; gap: 16px; flex-wrap: wrap; margin-bottom: 12px; }
.prn-name { font-weight: 700; font-size: 1.05rem; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.prn-sub { font-size: .84rem; margin-top: 4px; overflow-wrap: anywhere; }
.prn-err { color: var(--crit); margin-top: 6px; overflow-wrap: anywhere; }
.prn-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.prn-job { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-bottom: 8px; }
/* Role checkboxes: the one control on this dialog a manager actually changes, so
   the whole row is the target rather than a 24px box. */
.prn-roles { display: flex; flex-direction: column; gap: 2px; }
.prn-role { min-height: 52px; align-items: center; gap: 12px; cursor: pointer; padding: 0 4px; border-radius: 10px; }
.prn-role:active { background: var(--panel-3); }

/* ---- rail: unread count ---- */
/* Distinct from `.navbadge`, which is the design-mode add/remove control. This one
   is not interactive: it reports, it is never pressed. */
.navcount {
  position: absolute; top: 6px; right: 10px; min-width: 20px; height: 20px;
  padding: 0 5px; border-radius: 999px; background: var(--crit); color: #fff;
  font-size: .7rem; font-weight: 700; line-height: 20px; text-align: center;
  box-shadow: 0 0 0 2px var(--midnight); pointer-events: none;
}
.rail a { position: relative; }

/* The ticket reference on the acceptance screen. It carried its size and weight as an
   inline style under a class the stylesheet never defined — the same shape as the
   sign-in-only "inp" class above, one screen along. */
.sup-ref { font-size: 1.3rem; font-weight: 600; letter-spacing: .04em; color: var(--ink);
  font-family: var(--mono); margin: 6px 0 10px; }

/* THE PRINTING ALARM. Only ever rendered when something has genuinely not reached
   paper, so its presence is the message. Styled as a button because it is one —
   a manager taps it and lands on the printer that is failing. */
.pill.crit { background: var(--crit-2); border-color: transparent; color: var(--crit); cursor: pointer; }
.pill.crit:active { transform: scale(.98); }

/* ---- À propos ---- */
.abt-title { font-family: var(--display); font-size: 1.35rem; font-weight: 700; color: var(--ink); }
.abt-row { display: flex; align-items: baseline; gap: 14px; padding: 9px 0; border-bottom: 1px solid var(--line); }
.abt-row:last-child { border-bottom: none; }
.abt-k { flex: 0 0 42%; color: var(--muted); font-size: .88rem; }
.abt-v { flex: 1; color: var(--ink); font-weight: 600; overflow-wrap: anywhere; }

/* ---- printers: what prints where ---- */
.prn-cover { margin: 4px 0 16px; border: 1px solid var(--line); border-radius: 14px; overflow: hidden; }
.prn-cover-row { display: flex; align-items: center; gap: 14px; padding: 14px 16px; border-bottom: 1px solid var(--line); background: var(--panel); }
.prn-cover-row:last-child { border-bottom: none; }
.prn-cover-row.none { background: var(--crit-2); }
.prn-cover-ic { font-size: 1.4rem; line-height: 1; flex: none; }
.prn-cover-n { font-weight: 700; }
.prn-cover-h { font-size: .78rem; }
.prn-cover-v { font-weight: 600; color: var(--ink-2); text-align: right; max-width: 45%; overflow-wrap: anywhere; }
.prn-cover-row.none .prn-cover-v { color: var(--crit); }
.prn-role-ic { font-size: 1.15rem; line-height: 1; flex: none; }
.prn-role-h { font-size: .74rem; margin-top: 1px; }
.prn-role { align-items: flex-start; padding-top: 8px; padding-bottom: 8px; min-height: 58px; }

.imglib-thumb.retrying{opacity:.45;}

/* Version in the persistent chrome: subtle, always present, one tap to the detail. */
.versionpill{cursor:pointer;font-variant-numeric:tabular-nums;opacity:.75;}
.versionpill:hover{opacity:1;}
.versionpill.upd{opacity:1;border-color:var(--warn,#b8860b);color:var(--warn,#b8860b);}
.abt-block{margin-top:14px;padding-top:10px;border-top:1px solid var(--line);}
.abt-bt{font-size:.72rem;text-transform:uppercase;letter-spacing:.08em;color:var(--muted);margin-bottom:6px;}

/* Printer role detail: a key/value line and a history row that reads at a glance. */
.prn-kv{display:flex;gap:10px;align-items:baseline;padding:3px 0;font-size:.86rem;}
.prn-k{flex:0 0 42%;color:var(--muted);}
.prn-v{flex:1;word-break:break-all;}
.prn-hist-t{flex:0 0 auto;min-width:52px;color:var(--muted);font-size:.82rem;}
.prn-cover-row{width:100%;text-align:left;cursor:pointer;background:none;}

/* Liste — the reservation book. A row reads without being opened. */
.rz-list{display:flex;flex-direction:column;gap:8px;padding:4px 0 24px;}
.rz-listsum{display:flex;align-items:baseline;gap:8px;padding:10px 14px;border:1px solid var(--line);border-radius:12px;background:var(--panel-2);font-size:.95rem;}
.rz-dot{opacity:.4;}
.rz-listwarn{color:var(--warn);font-weight:600;}
.rz-lrow{display:flex;align-items:center;gap:12px;width:100%;min-height:64px;padding:10px 14px;border:1px solid var(--line);border-radius:12px;background:var(--panel-2);text-align:left;cursor:pointer;}
.rz-lrow:active{background:var(--panel-3);}
.rz-lrow.noseat{border-left:3px solid var(--warn);}
.rz-ltime{flex:0 0 auto;min-width:56px;font-size:1rem;font-weight:700;}
.rz-lmain{flex:1;display:flex;flex-direction:column;gap:2px;min-width:0;}
.rz-lname{font-weight:650;display:flex;align-items:center;gap:8px;}
.rz-lwhere{font-size:.78rem;color:var(--muted);}
.rz-lppl{flex:0 0 auto;font-size:.85rem;color:var(--ink-2);}

/* Sold and taxed, produced nowhere — no station, so no station colour. */
.oitem .dest.none{color:var(--muted);opacity:.8;}

/* ── The visual-issue entry point is a « ? », not a sentence ─────────────────
   It used to read « Défaut visuel » in full, permanently, over a working till — a
   standing accusation in the corner of every screen, and the widest thing on the Salle
   after the order pad. A help affordance should be quiet until it is wanted.

   Restyled HERE, in the host, rather than in web/shared/sp-visual-reporter.js: that file
   is VENDORED and verified byte-identical by tools/vendor-sync.mjs, so editing it would
   fork a shared component to change one product's appearance. The reporter is built for
   this — it takes its label from the host's i18n (visualIssue.button, now « ? ») and its
   colours from --sp-vr-* tokens.

   The behaviour is untouched: tapping it still opens the reporter, which now titles
   itself « Signaler un problème d'affichage » and explains that the merchant selects the
   area and sends it to Success Payment support. Selection, description, screenshot and
   the signed submit are all exactly as they were. */
button.sp-vr-btn{
  width:44px; min-width:44px; height:44px; min-height:44px;
  padding:0; gap:0; justify-content:center;
  font:700 18px/1 var(--display, inherit);
  background:var(--panel-2); color:var(--brass);
  border:1px solid var(--line);
  box-shadow:0 2px 10px rgba(0,0,0,.28);
}
/* The report icon is the label's partner, and there is no label any more. */
button.sp-vr-btn svg{display:none;}
button.sp-vr-btn:active{background:var(--panel-3);}

/* Remote manager read-only order pad — mutation controls render but are disabled/greyed. */
.ro-disabled{opacity:.4;cursor:not-allowed;filter:grayscale(.35);}
.ro-disabled:hover{transform:none;}
.ro-floor .prodgrid{opacity:.6;}
.order-loaderr{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;height:100%;padding:32px;text-align:center;color:var(--muted);}
.order-loaderr .ole-ic{opacity:.5;}
.order-loaderr .ole-t{font-size:18px;font-weight:600;color:var(--ink);}
.order-loaderr .ole-s{font-size:13px;max-width:360px;}

/* ---- Article form: « Options avancées » -------------------------------------
   Collapsed by default. The essentials above it are what a manager fills in to put a
   Coca-Cola on the till; everything else lives behind this one tap. The summary is a
   48px target because the CPad is used with a thumb, not a mouse. */
details.adv{border:1px solid var(--line);border-radius:12px;background:var(--panel-2);}
details.adv>summary{display:flex;align-items:center;gap:10px;min-height:52px;padding:0 14px;cursor:pointer;font-weight:700;list-style:none;user-select:none;}
details.adv>summary::-webkit-details-marker{display:none;}
details.adv>summary::after{content:'';margin-left:auto;width:9px;height:9px;border-right:2px solid var(--muted);border-bottom:2px solid var(--muted);transform:rotate(45deg) translateY(-2px);transition:transform .15s ease;}
details.adv[open]>summary::after{transform:rotate(225deg) translateY(-2px);}
details.adv>summary>.hint{margin-left:4px;}
details.adv>.two{padding:0 14px 14px;}
/* On the CPad the advanced pane is one column — two 300px columns side by side put the
   save button somewhere a thumb has to hunt for. */
@media (max-width:1100px){details.adv>.two{grid-template-columns:1fr;}
  details.adv>summary>.hint{display:none;}}
/* The article form's essential fields get real touch targets. */
.imgpick{max-width:260px;}

/* ============================================================================
   THE SELLING SURFACES (EN DIRECT / À EMPORTER) — the fast article screen.
   ============================================================================
   The SAME order pad, dressed for a different job. Everything below is scale and
   density: bigger article buttons, bigger prices, a wider ticket. No component is
   replaced and no rule here applies to a FLOOR_PLAN venue — every selector is
   inside `.orderlayout.selling`, which only renderSell() emits.

   WHY BIGGER. This screen is used standing up, at speed, by someone who is also
   pouring a drink and talking to a customer, and it replaces a machine with real
   plastic keys. A 146px card is fine for a waiter holding a CPad at reading
   distance; it is not what you want under a bartender's thumb. */
.orderlayout.selling{grid-template-columns:1fr minmax(340px,420px);}
/* THE NAME AND THE PRICE ARE THE BUTTON, and now they are all of it. The image block that
   used to sit above them is gone from this screen entirely: it set the tile height, and the
   tile height sets how many articles a cashier can see. What is left is read at arm's
   length — a glyph to find the group by shape, the name, the price. */
.orderlayout.selling .prodgrid{grid-template-columns:repeat(auto-fill,minmax(148px,1fr));gap:10px;}
.orderlayout.selling .prodcard{min-height:96px;}
.orderlayout.selling .prodcard .nm{font-size:.95rem;-webkit-line-clamp:2;}
.orderlayout.selling .prodcard .pr{font-size:1.12rem;}
/* One compact row of chips that scrolls sideways, never a stack of category cards. */
.orderlayout.selling .catchip{height:46px;padding:0 15px;font-size:.92rem;}
.orderlayout.selling .catbar{padding:8px 10px;gap:7px;flex:none;overflow-x:auto;flex-wrap:nowrap;}
.orderlayout.selling .searchbar{padding:8px 10px;flex:none;}
/* The total is the number the customer is told out loud. */
.orderlayout.selling .tp-totals .r.tot{font-size:1.24rem;}
/* SEND and PAY are the primary actions of the whole screen and are sized like it. They sit
   in .tp-cmd, which is flex:none inside the ticket panel, so they are pinned: the order
   lines above them scroll, these do not move, and neither can leave the viewport. */
.orderlayout.selling .cmd-send{min-height:56px;font-size:1.02rem;}
.orderlayout.selling .cmd-pay{min-height:56px;font-size:1.02rem;}

/* ── THE QUANTITY CONTROL, AT TILL SIZE ──────────────────────────────────────────────
   Measured, not guessed. The order line is 61px tall on this screen and its content box
   is 45px, of which the stepper used 30 — so the row was ALREADY tall enough to hold a
   proper touch target and was simply not using it. Raising the stepper to 44px therefore
   costs the ticket nothing: the line height is set by the name, its modifiers and its
   status row, not by the buttons beside them.

   This is the one place the 44px floor was being missed on a screen operated by thumb,
   and it is the control an operator touches more than any other except the article
   itself. Scoped to `.selling`: a waiter's table pad keeps its dense line, where the
   trade really would cost a third of the visible ticket.

   NOT AT COMPACT, and that is a measurement rather than a preference. COMPACT gives the
   ticket 320px; a 120px stepper and a 44px menu leave 39px for the article name, which
   wrapped every line of a 24-line ticket, took the line from 61px to 100px and dropped
   the visible sale from five lines to three. Trading a touch-target failure for a
   legibility failure on the same row is not an improvement. COMPACT is the profile an
   operator chooses when they want density above all, it is never what AUTO resolves to
   on a CPad, and it keeps the dense line it has always had. */
:root:not([data-display="COMPACT"]) .orderlayout.selling .oitem .qty{height:44px;border-radius:11px;}
:root:not([data-display="COMPACT"]) .orderlayout.selling .oitem .qty button{width:44px;height:44px;font-size:1.15rem;}
:root:not([data-display="COMPACT"]) .orderlayout.selling .oitem .qty .q{min-width:26px;font-size:.98rem;}
:root:not([data-display="COMPACT"]) .orderlayout.selling .oitem-more{width:44px;height:44px;font-size:1.35rem;}
/* AND THE LINE PAYS FOR ITSELF. The taller stepper took the order line from 61px to 62,
   which crossed a rounding boundary and cost À emporter one visible line of the ticket —
   measured, not theorised. Two pixels of row padding buy it back and leave the line
   shorter than it started, so the touch target is free rather than borrowed. Padding, not
   type size and not the target: the name and the price are untouched. */
:root:not([data-display="COMPACT"]) .orderlayout.selling .oitem{padding:7px 8px;}

/* ── EN DIRECT: A NARROW TICKET, BECAUSE THE LINE STOPPED FIGHTING ITSELF ────────────
   THE ARITHMETIC THAT FORCED THIS. On one row the counter line needs a 114px stepper, a
   44px overflow menu, ~120px of readable name, ~55px of price and ~57px of gaps and
   padding: about 390px, which is what the 420px ticket was. "Halve the column" and "keep
   44px touch targets" are not both satisfiable on a single row — one of them has to give,
   and neither is allowed to.

   So the row gives. The line becomes two rows, and the second one is already 44px tall
   because the stepper is in it — so the destination badge and the overflow menu ride
   along in space that was being paid for anyway:

       Judd mat Gaardebounen                    12,90
       [ −  2  + ]   🍳 Cuisine                    ⋯

   The name now spans the full width instead of competing with the stepper, which is why
   this also FIXES the COMPACT clipping the single-row layout had (39px of name, every
   line of a 24-line ticket wrapped) — and why COMPACT can have the 44px stepper too.
   `display:contents` on .nm lets the name, its modifiers and its status row be placed
   individually instead of being one block. */
.orderlayout.selling[data-flow="COUNTER"] .oitem{
  display:grid;grid-template-columns:auto 1fr auto;
  grid-template-areas:"name name price" "qty st more";
  gap:2px 8px;align-items:center;padding:7px 8px;}
.orderlayout.selling[data-flow="COUNTER"] .oitem .nm{display:contents;}
.orderlayout.selling[data-flow="COUNTER"] .oitem .nm-t{grid-area:name;min-width:0;}
.orderlayout.selling[data-flow="COUNTER"] .oitem .lp{grid-area:price;justify-self:end;}
.orderlayout.selling[data-flow="COUNTER"] .oitem .qty{grid-area:qty;justify-self:start;}
/* The status row RIDES the stepper's row; it must not add height to it. Left to wrap it
   put the destination badge on a second line inside a narrow column and took the order
   line from the ~77px this design implies to 95px — which cost two of the five visible
   lines. It stays on one line and clips rather than growing: the badge is a reminder, and
   the article it belongs to is named in full directly above it. */
.orderlayout.selling[data-flow="COUNTER"] .oitem .st{
  grid-area:st;margin-top:0;min-width:0;flex-wrap:nowrap;overflow:hidden;}
.orderlayout.selling[data-flow="COUNTER"] .oitem .st>*{flex:none;}
.orderlayout.selling[data-flow="COUNTER"] .oitem-more{grid-area:more;justify-self:end;}
/* Modifiers, remarks and the waiter's note are full-width under the name — they are part
   of what the article IS, and squeezing them beside a price is how they stop being read. */
.orderlayout.selling[data-flow="COUNTER"] .oitem .mods{grid-column:1/-1;grid-row:auto;}
/* The stepper is affordable at EVERY profile now, COMPACT included: it sets the height of
   a row it shares only with a badge, and no longer takes width from the article name. */
:root[data-display="COMPACT"] .orderlayout.selling[data-flow="COUNTER"] .oitem .qty{height:44px;border-radius:11px;}
:root[data-display="COMPACT"] .orderlayout.selling[data-flow="COUNTER"] .oitem .qty button{width:44px;height:44px;font-size:1.15rem;}
:root[data-display="COMPACT"] .orderlayout.selling[data-flow="COUNTER"] .oitem-more{width:44px;height:44px;font-size:1.35rem;}

/* THE COLUMN ITSELF. Set from what the two-row line actually needs, not from a target
   percentage: stepper 114 + menu 44 + a gap, and a name that no longer shares its row. */
.orderlayout.selling[data-flow="COUNTER"]{grid-template-columns:1fr minmax(236px,260px);}
:root[data-display="COMPACT"] .orderlayout.selling[data-flow="COUNTER"]{grid-template-columns:1fr minmax(224px,244px);}
:root[data-display="LARGE"] .orderlayout.selling[data-flow="COUNTER"]{grid-template-columns:1fr minmax(260px,296px);}

/* ── EN DIRECT: PAYER IS THE END OF THE FLOW, AND IT LOOKS LIKE IT ───────────────────
   `[data-flow="COUNTER"]`, the canonical order type the renderer already branches on —
   never a French label. À emporter and table service are untouched by everything here.

   A counter sale is rung and paid in one motion by the person standing at the till, so
   Payer is not one action among several: it is where every sale ends. It was the same
   height as Envoyer beside it and read as its equal. The eight pixels come out of the
   ticket deliberately and are the only thing on this screen that grew. */
.orderlayout.selling[data-flow="COUNTER"] .cmd-pay{min-height:64px;font-size:1.08rem;}

/* The parked-sales strip is GONE, rules and all — not collapsed to zero height, which
   would leave a spacer nobody can see and nobody can explain. A sale is recovered by the
   surface remembering its own live order (see views-service.js), so the row that used to
   advertise every open sale no longer costs an article row on every sale. */

/* PORTRAIT AND SMALL LANDSCAPE. The shared rule at 900px already docks the ticket to
   the bottom of the screen; the simplified grid needs its own minimum so the cards do
   not become four narrow columns of clipped names on a 10" CPad held upright. */
@media (max-width:900px){
  .orderlayout.selling{grid-template-columns:1fr;}
  .orderlayout.selling .prodgrid{grid-template-columns:repeat(auto-fill,minmax(150px,1fr));}
}
@media (max-width:640px){
  .orderlayout.selling .prodgrid{grid-template-columns:repeat(auto-fill,minmax(118px,1fr));}
}

/* Stock state on an order tile. Quiet by design: only a tracked article that is low,
   out, or negative says anything at all, so the badge means something when it appears.
   Sits opposite the quantity chip so an article can show both without them colliding. */
.prodcard .cardstock{position:absolute;left:6px;top:6px;z-index:2;
  padding:2px 7px;border-radius:999px;font-size:.68rem;font-weight:700;line-height:1.5;
  letter-spacing:.01em;box-shadow:0 1px 3px rgba(0,0,0,.28);white-space:nowrap;max-width:calc(100% - 12px);
  overflow:hidden;text-overflow:ellipsis}
.prodcard .cardstock.low{background:var(--warn);color:#1a1207}
.prodcard .cardstock.out{background:var(--crit);color:#fff}
.prodcard .cardstock.neg{background:var(--crit);color:#fff;outline:2px solid rgba(255,255,255,.35)}

/* Stock list on a CPad. The five-column table is right for a desk and wrong for a
   tablet: « Ajuster » was the last cell, so it sat past the right edge of a card that
   scrolled sideways, and the one action a manager needs mid-service was unreachable
   without knowing to drag the table. Below 820px the row becomes a stacked card with the
   actions on their own full-width line. Same rows, same handlers, different shape. */
.stockrow.tappable{cursor:pointer}
.stockrow.tappable:active{background:var(--panel-2)}
@media (max-width:820px){
  .tbl:has(.stockrow) thead{display:none}
  .tbl:has(.stockrow) .stockrow{display:grid;grid-template-columns:1fr auto auto;
    gap:4px 10px;align-items:center;padding:10px 12px;border-bottom:1px solid var(--line)}
  .tbl:has(.stockrow) .stockrow td{border:none;padding:0}
  .tbl:has(.stockrow) .stockrow td:nth-child(1){grid-column:1/2;grid-row:1}
  .tbl:has(.stockrow) .stockrow td:nth-child(2){grid-column:2/3;grid-row:1;text-align:right}
  .tbl:has(.stockrow) .stockrow td:nth-child(3){grid-column:3/4;grid-row:1;text-align:right;opacity:.7}
  .tbl:has(.stockrow) .stockrow td:nth-child(4){grid-column:1/2;grid-row:2}
  /* The actions get their own line, full width, always on screen. */
  .tbl:has(.stockrow) .stockrow td:nth-child(5){grid-column:1/4;grid-row:3;margin-top:6px}
  .tbl:has(.stockrow) .stockrow td:nth-child(5) .row{justify-content:stretch!important}
  .tbl:has(.stockrow) .stockrow td:nth-child(5) .btn{flex:1;min-height:44px}
}

/* Éditeur de carte grid cell: the picture. The cell only ever had a coloured icon strip,
   so an article looked pictureless in the grid and pictured in the filtered list, which is
   what made this read as "the image did not save". Same fixed-height band as the icon
   strip it replaces, so the grid keeps its rhythm and nothing shifts. */
.prodcard .top.img{padding:0;overflow:hidden;background:var(--panel-2);display:block;aspect-ratio:4/3;height:auto;min-height:0}
.prodcard .prodcell-img{display:block;width:100%;height:100%;object-fit:cover}

/* The print-status slot is always in the DOM so its contents can change without a
   re-render (see paintPrintPill). Empty it collapses and shows nothing. */
.pillslot{display:inline-flex;align-items:center;}
.pillslot:empty{display:none;}

/* ============================================================================
   VENTE — the choice screen, and the density profiles
   ============================================================================
   The three workflows used to sit in a permanent bar above every selling screen.
   On the real 11" device that bar cost a row of article buttons on every sale,
   all day, to answer a question the operator had already answered. So it is a
   screen now, and the workflows get the space back.

   One question, three targets, nothing else. No statistics, no cards, no
   decoration: the screen exists to be left. */
.saleslanding{height:100%;display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:28px;padding:24px;}
.sl-q{font-size:1.25rem;font-weight:650;color:var(--muted);text-align:center;}
.sl-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:18px;
  width:100%;max-width:1100px;}
.saleschoice{display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:10px;min-height:210px;padding:26px 20px;border-radius:20px;background:var(--panel);
  border:1px solid var(--line);box-shadow:var(--sh-1);text-align:center;
  transition:transform .09s var(--ease),box-shadow .15s,border-color .15s;}
.saleschoice:hover{box-shadow:var(--sh-2);border-color:var(--brass-2);}
.saleschoice:active{transform:scale(.97);}
.saleschoice .sc-ic{color:var(--brass);display:flex;}
.saleschoice .sc-t{font-size:1.15rem;font-weight:750;line-height:1.2;}
.saleschoice .sc-s{font-size:.85rem;color:var(--muted);}

/* « ← Vente ». Deliberately small: it replaced a bar that owned a permanent row,
   and giving it a toolbar of its own would hand that row straight back. */
.backsales{min-height:44px;padding:0 14px;gap:6px;white-space:nowrap;flex:none;}

/* ── DENSITY PROFILES ───────────────────────────────────────────────────────
   Set on <html> as data-display by web/app/display-profile.js — AUTO resolves
   from the viewport, an operator can pin one per DEVICE in AxiumPay.

   A profile is a TARGET, never a promise: the rules below change how much is
   asked to fit, and the viewport still bounds the result. Forcing LARGE on a
   small screen must not push Envoyer off the bottom of it, so the shared
   responsive rules further up still apply and every touch target keeps its
   floor. The worst a wrong profile can do is look loose or tight. */

/* COMPACT — a handheld, or any viewport too short to stack the selling screen
   comfortably. Fewer columns and less non-functional space; touch targets are
   NOT shrunk below the 44px floor, because the whole point is that it stays
   usable in one hand. */
:root[data-display="COMPACT"] .prodgrid{grid-template-columns:repeat(auto-fill,minmax(124px,1fr));gap:8px;padding:8px;}
:root[data-display="COMPACT"] .orderlayout.selling .prodcard{min-height:84px;padding:8px 9px;}
:root[data-display="COMPACT"] .orderlayout.selling .prodcard .cardic svg{width:16px;height:16px;}
:root[data-display="COMPACT"] .orderlayout.selling .prodcard .nm{font-size:.84rem;}
:root[data-display="COMPACT"] .orderlayout.selling .prodcard .pr{font-size:1rem;}
/* Even at the tightest density the ticket keeps a usable width and its actions: a cashier
   on a small screen still has to read the total and reach Payer. */
:root[data-display="COMPACT"] .orderlayout.selling{grid-template-columns:1fr minmax(276px,320px);}
:root[data-display="COMPACT"] .catbar{padding:8px 10px;gap:6px;}
:root[data-display="COMPACT"] .catchip{height:46px;padding:0 13px;font-size:.9rem;}
:root[data-display="COMPACT"] .searchbar{padding:8px 10px;}
:root[data-display="COMPACT"] .sl-grid{grid-template-columns:1fr;max-width:460px;gap:12px;}
:root[data-display="COMPACT"] .saleschoice{min-height:96px;flex-direction:row;gap:16px;
  justify-content:flex-start;text-align:left;padding:16px 20px;}
:root[data-display="COMPACT"] .saleslanding{gap:18px;}

/* STANDARD — the ~10-11" POS class, including 1280x800. The most-used layout on
   this product, so it is the one tuned hardest: as many article buttons as can
   be read at arm's length, a ticket that stays legible, and no wasted vertical
   space above the grid. */
/* THE 11-INCH TARGET, tuned hardest: as many readable article buttons as the screen holds,
   with Total, Envoyer and Payer never leaving the viewport. */
:root[data-display="STANDARD"] .prodgrid{grid-template-columns:repeat(auto-fill,minmax(146px,1fr));gap:10px;padding:10px;}
:root[data-display="STANDARD"] .orderlayout.selling .prodcard{min-height:94px;}
:root[data-display="STANDARD"] .orderlayout.selling .prodcard .cardic svg{width:18px;height:18px;}
:root[data-display="STANDARD"] .catbar{padding:10px 12px;}
:root[data-display="STANDARD"] .searchbar{padding:10px 12px;}
:root[data-display="STANDARD"] .sl-grid{max-width:960px;}

/* LARGE — a fixed till or a desktop. Extra space becomes more articles and a
   roomier ticket, not stretched controls: a button the width of a table is
   harder to aim at, not easier. */
:root[data-display="LARGE"] .orderlayout.selling{grid-template-columns:1fr minmax(380px,460px);}
/* More columns and more cart lines, in the SAME simple tile language: extra room buys more
   articles on screen, never a return to photographs. */
:root[data-display="LARGE"] .prodgrid{grid-template-columns:repeat(auto-fill,minmax(176px,1fr));gap:13px;padding:14px;}
:root[data-display="LARGE"] .orderlayout.selling .prodcard{min-height:108px;}
/* Restrained on purpose: 20px, not 40px. The extra room on a 14" till is for more
   articles and more cart lines, which is what a bigger cash register is for. */
:root[data-display="LARGE"] .orderlayout.selling .prodcard .cardic svg{width:20px;height:20px;}
:root[data-display="LARGE"] .orderlayout.selling .prodcard .nm{font-size:1rem;}
:root[data-display="LARGE"] .orderlayout.selling .prodcard .pr{font-size:1.2rem;}
:root[data-display="LARGE"] .saleschoice{min-height:250px;}
:root[data-display="LARGE"] .sl-grid{max-width:1280px;}

/* The print-status slot is always in the DOM so its contents can change without a
   re-render (see paintPrintPill). Empty it collapses and shows nothing. */
.pillslot{display:inline-flex;align-items:center;}
.pillslot:empty{display:none;}


/* MODES DE VENTE — which kinds of sale this venue makes (venue-level; the display profile
   is a different decision, made per device in AxiumPay). Whole-row targets, because a
   checkbox on its own is a 13px thing to aim at on a touchscreen. */
.modeslist{display:flex;flex-direction:column;gap:8px;}
.modeopt{display:flex;gap:11px;align-items:flex-start;padding:12px 14px;min-height:44px;
  border:1px solid var(--line);border-radius:11px;background:var(--panel-2);cursor:pointer;}
.modeopt:hover{border-color:var(--brass-2);}
.modeopt:has(input:checked){border-color:var(--brass);background:var(--panel);}
.modeopt input{width:20px;height:20px;margin-top:2px;flex:none;accent-color:var(--brass);}
.modeopt .mode-ic{color:var(--brass);display:flex;margin-top:1px;flex:none;}
.modeswarn{margin-top:10px;font-weight:700;}
