/* Oishii Takoyaki POS & Stock Control
   Stylesheet extracted verbatim from the original single-file prototype
   (oishii_takoyaki_pos_stock_control.html, <style> block). */
:root{
  --bg:#130D0B;
  --bg-grad:radial-gradient(1200px 600px at 15% -10%, rgba(232,57,42,.22), transparent 60%), radial-gradient(900px 500px at 90% 0%, rgba(255,194,26,.10), transparent 55%);
  --surface:#1E1512;
  --surface2:#291D19;
  --surface3:#352620;
  --line:#3E2D26;
  --line-bright:#573F36;
  /* The edge of a control that nothing else marks as pressable. --line-bright
     is the worn edge of a table: it is meant to be soft. */
  --line-control:#8F6A56;
  --fg:#FAF2ED;
  --muted:#B3A199;
  /* Bonito red (the washes below) is the shop's identity. It is 4.16 under
     white, which is not enough for a button face, so the action fill is a step
     deeper and the identity red keeps the washes and the edges, where nothing
     has to be read on top of it. Red used as text is lighter again, or it
     disappears into the charcoal. */
  --brand:#D62E20;
  --brand-dark:#B92215;
  --brand-text:#FF6A57;
  --brand-ink:#FFFFFF;
  --price:#FFC21A;
  --price-ink:#17110F;
  /* A price set on photography keeps the bright tape in both themes: the bed
     under it is the shop's own dark scrim, not the page. */
  --price-scrim:#FFC21A;
  --price-bed:rgba(0,0,0,.28);
  /* The bed under a value that sits on the selected red gradient. Bronze on
     paper and gold on charcoal are both invisible there — the fill is dark in
     both themes, so the bed is one ink wash in both. */
  --fill-bed:rgba(0,0,0,.28);
  /* The bed under selected text. A plain deepening of the charcoal here; the
     light theme tints its own, because a neutral grey selection reads as a
     different shop's UI pasted onto the counter. */
  --select-bg:rgba(0,0,0,.35);
  --price-glow:rgba(255,194,26,.18);
  --ok:#3AD29F;
  --low:#F7A83B;
  --out:#FF6E5E;
  /* The stock vocabulary as it appears on the photo scrim. The dark-theme
     values already live there; in the light theme the same three colours are
     darkened for cream, and would sink to 2.2:1 on the scrim, so the scrim
     keeps the bright set in both themes and the pills read the pair. */
  --ok-scrim:#3AD29F;
  --low-scrim:#F7A83B;
  --out-scrim:#FF6E5E;
  --card-shadow:0 10px 28px -8px rgba(0,0,0,.55);
  /* A sheet that floats over the pantry paper rather than sitting in the grid.
     One value per theme, because the wash under it changes with the paper. */
  --pop-shadow:0 20px 44px rgba(0,0,0,.5),0 2px 8px rgba(0,0,0,.35);
  --font-display:'Bungee','Arial Black',Impact,sans-serif;
  --font-body:'Hanken Grotesk',system-ui,-apple-system,'Segoe UI',sans-serif;
  --font-data:'JetBrains Mono',ui-monospace,Menlo,Consolas,monospace;
  color-scheme:dark;
}
:root[data-theme="light"]{
  --bg:#F6F1EE;
  --bg-grad:radial-gradient(1100px 500px at 15% -10%, rgba(188,35,21,.10), transparent 60%), radial-gradient(800px 450px at 90% 0%, rgba(107,66,0,.10), transparent 55%);
  --surface:#FFFFFF;
  --surface2:#F2EAE6;
  --surface3:#E6DBD5;
  --line:#DED1CA;
  --line-bright:#C7B5AC;
  --line-control:#8A7264;
  --fg:#1C1310;
  --muted:#6E5D55;
  --brand:#BC2315;
  --brand-dark:#A81E11;
  --brand-text:#BC2315;
  --brand-ink:#FFFFFF;
  /* On paper the price tape is bronze: the bright gold is a light-on-dark
     colour and cannot be read on white at any weight worth using. */
  --price:#6B4200;
  --price-ink:#FFFFFF;
  --price-scrim:#FFC21A;
  --price-bed:rgba(107,66,0,.10);
  --fill-bed:rgba(0,0,0,.28);
  --select-bg:rgba(188,35,21,.16);
  --price-glow:rgba(107,66,0,.14);
  --ok:#0D6B4A;
  --low:#915000;
  --out:#B82315;
  --ok-scrim:#3AD29F;
  --low-scrim:#F7A83B;
  --out-scrim:#FF6E5E;
  --card-shadow:0 8px 24px -6px rgba(30,21,18,.10);
  --pop-shadow:0 20px 44px rgba(74,42,20,.22),0 2px 8px rgba(74,42,20,.12);
  color-scheme:light;
}
*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{
  background-color:var(--bg);
  background-image:var(--bg-grad);
  background-attachment:fixed;
  color:var(--fg);
  font-family:var(--font-body);
  font-size:15px;
  line-height:1.45;
  padding-block:16px 36px;
  padding-left:max(16px,env(safe-area-inset-left,0px));
  padding-right:max(16px,env(safe-area-inset-right,0px));
}
img{max-width:100%;display:block}
/* Selecting a figure to retype it is the most common thing that happens to a
   number on this screen, and the OS blue belongs to a different shop. */
::selection{background:var(--select-bg);color:var(--fg)}
/* The editor sheet carries its own selection: a deep ink-red wash over waxed paper,
   a lifted ember wash over the dark sheet. The text colour has to follow the sheet
   too - pinning it to the paper ink made selected text vanish the moment the dark
   theme stopped drawing paper. */
.pn ::selection,.pn-paper ::selection{background:var(--paper-select);color:var(--ink)}
[hidden]:not([hidden=until-found i]){display:none!important}
button{font:inherit;color:inherit;cursor:pointer;transition:transform .12s ease, background-color .15s ease, border-color .15s ease, box-shadow .15s ease}
button:active:not(:disabled){transform:scale(.98)}
button:focus-visible,input:focus-visible{outline:2px solid var(--price);outline-offset:2px}
/* Browser surfaces carry the design too: the caret is the brand red rather than
   the OS accent, so typing a quantity looks like the shop and not like a form. */
input,textarea,select{caret-color:var(--price)}
/* A keyboard user reaches the panel without walking the tab strip first. The
   link waits above the top edge and lands over the masthead when it takes
   focus, styled as one of the app's own controls. */
.skip{
  position:fixed;top:8px;left:8px;z-index:90;
  padding:12px 16px;border-radius:10px;border:1px solid var(--price);
  background:var(--surface);color:var(--fg);font-size:13px;font-weight:700;
  text-decoration:none;transform:translateY(-180%);transition:transform .16s ease;
}
.skip:focus{transform:translateY(0);outline:2px solid var(--price);outline-offset:2px}
.app{max-width:1240px;margin:0 auto;display:flex;flex-direction:column;gap:16px}

/* Top bar */
.top{
  display:flex;flex-wrap:wrap;align-items:center;gap:14px 20px;
  padding:14px 18px;
  background:var(--surface);
  border:1px solid var(--line);
  border-radius:18px;
  box-shadow:var(--card-shadow);
}
.brand{display:flex;align-items:center;gap:13px}
.logo-img{
  width:52px;height:52px;border-radius:50%;object-fit:cover;
  border:2px solid var(--brand);
  box-shadow:0 4px 14px rgba(232,57,42,.35);
  flex:none;
}
.brand-text h1{
  font-family:var(--font-display);font-weight:400;font-size:23px;letter-spacing:.06em;margin:0;line-height:1;
  display:flex;align-items:center;gap:8px;
}
.brand-badge{
  font-family:var(--font-body);font-size:10px;font-weight:800;letter-spacing:.12em;
  background:var(--brand);color:var(--brand-ink);padding:3px 7px;border-radius:6px;text-transform:uppercase;
}
.brand-text p{margin:4px 0 0;font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.14em;font-weight:600}

.tabs{
  display:flex;gap:4px;background:var(--bg);padding:5px;border-radius:13px;border:1px solid var(--line);
  /* A flex item shrinks to its content by default. The strip is wider than the
     header card on a phone, so without this it overflowed the card and pushed
     the whole page sideways instead of tightening. */
  max-width:100%;min-width:0;
}
.tabs button{
  border:0;background:transparent;min-height:40px;padding:0 16px;border-radius:9px;
  font-weight:700;font-size:14px;color:var(--muted);display:inline-flex;align-items:center;gap:7px;
}
.tabs button:hover:not(.on){color:var(--fg);background:var(--surface2)}
.tabs button.on{
  background:linear-gradient(135deg,var(--brand),var(--brand-dark));
  color:var(--brand-ink);
  /* The red fill is only 1.45:1 against the strip it sits in, so on a bright
     morning the selected tab and its neighbours differ mainly in hue. A lit top
     edge and an ink rule along the bottom make the selection survive that
     without adding a colour to the palette. */
  box-shadow:0 4px 12px rgba(214,46,32,.35), inset 0 1px 0 rgba(255,255,255,.22);
  position:relative;
}
.tabs button.on::after{
  content:'';position:absolute;left:11px;right:11px;bottom:3px;height:2px;
  border-radius:2px;background:var(--brand-ink);opacity:.9;
}
.top-right{margin-left:auto;display:flex;align-items:center;gap:10px;flex-wrap:wrap}
/* The kitchen board is a different screen, not a sixth tab: a cook needs no
   navigation to mis-tap and a cashier needs no extra tab to skip past. This
   link is the only door from the till, and it stays put in the header. */
.kds-link{
  display:inline-flex;align-items:center;gap:7px;
  min-height:44px;padding:0 14px;border-radius:10px;
  border:1px solid var(--line-bright);background:var(--surface2);
  color:var(--fg);font-size:12px;font-weight:800;letter-spacing:.04em;
  text-decoration:none;white-space:nowrap;
}
.kds-link:hover{background:var(--surface3);border-color:var(--line-control)}
.kds-dot{width:7px;height:7px;border-radius:50%;background:var(--ok);box-shadow:0 0 7px var(--ok);flex:none}
.icon-btn{
  border:1px solid var(--line);background:var(--surface2);border-radius:10px;
  min-height:44px;padding:0 14px;font-size:13px;font-weight:600;display:inline-flex;align-items:center;gap:6px;
}
.icon-btn:hover{border-color:var(--line-control);background:var(--surface3)}
/* The theme control draws both marks and shows the one you are switching to: a
   sun in the dark, a moon in the light. Same 2px stroke on a 24 grid as the
   rest of the chrome. The word carries the control above 920px. */
.theme-ico{
  width:17px;height:17px;flex:none;
  fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;
}
.theme-ico-moon{display:none}
:root[data-theme="light"] .theme-ico-sun{display:none}
:root[data-theme="light"] .theme-ico-moon{display:block}

/* Promo & Demo Strip */
.promo-strip{
  display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:10px 16px;
  padding:10px 16px;
  border-radius:14px;
  background:linear-gradient(90deg, rgba(214,46,32,.18), rgba(255,194,26,.12), rgba(214,46,32,.14));
  border:1px solid rgba(214,46,32,.35);
  font-size:13px;
}
.promo-left{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.promo-pill{
  background:var(--price);color:var(--price-ink);font-family:var(--font-display);font-size:11px;
  letter-spacing:.06em;padding:4px 10px;border-radius:999px;text-transform:uppercase;
}
.promo-text{font-weight:600;color:var(--fg)}
.promo-text span{color:var(--muted);font-weight:500}
.promo-actions{display:flex;align-items:center;gap:8px}
.promo-actions button{
  border:1px solid var(--line-bright);background:var(--surface);border-radius:8px;
  min-height:40px;padding:0 12px;font-size:12px;font-weight:700;
}
.promo-actions button:hover{border-color:var(--price)}

/* Shared typography & status badges */
.sec-head{display:flex;align-items:baseline;justify-content:space-between;gap:10px;margin:0 0 10px;flex-wrap:wrap}
.lbl{
  font-size:12px;font-weight:800;text-transform:uppercase;letter-spacing:.14em;color:var(--muted);
  margin:0;display:flex;flex-wrap:wrap;gap:6px 10px;align-items:center;
}
.lbl .step-num{
  width:20px;height:20px;border-radius:6px;background:var(--brand);color:var(--brand-ink);
  font-family:var(--font-data);font-size:11px;display:inline-grid;place-items:center;letter-spacing:0;
}
.lbl .hint{text-transform:none;letter-spacing:0;font-weight:500;font-size:12px;color:var(--muted)}
.num,.mono{font-family:var(--font-data);font-variant-numeric:tabular-nums}
.st{
  display:inline-flex;align-items:center;gap:4px;padding:3px 9px;border-radius:999px;
  font-size:11px;font-weight:800;letter-spacing:.03em;text-transform:uppercase;
  color:var(--c);background:color-mix(in srgb,var(--c) 16%,transparent);
  border:1px solid color-mix(in srgb,var(--c) 35%,transparent);
  white-space:nowrap;
  /* The 16% tint is a wash, not a ground. On a card it is enough; anywhere the
     pill has to sit on photography it needs a bed of its own (see
     .vcard-stock), and a soft shadow carries it over a busy photo edge. */
  box-shadow:0 1px 4px rgba(0,0,0,.35);
}
.st.ok{--c:var(--ok);--cs:var(--ok-scrim)}
.st.low{--c:var(--low);--cs:var(--low-scrim)}
.st.out{--c:var(--out);--cs:var(--out-scrim)}

/* POS Layout */
.pos{display:grid;grid-template-columns:minmax(0,1fr);gap:22px;align-items:start}
@media (min-width:920px){
  .pos{grid-template-columns:minmax(0,1fr) 380px}
  .ticket{position:sticky;top:16px}
}
.build{display:flex;flex-direction:column;gap:22px;min-width:0}
.panel-box{
  background:var(--surface);border:1px solid var(--line);border-radius:18px;
  padding:16px;box-shadow:var(--card-shadow);
}

/* First run: the shop has no paid order yet. The panel sits above the builder
   and leaves on that first sale, so it is never part of the steady state. */
.setup{
  background:var(--surface);border:1px solid var(--line-bright);border-radius:18px;
  padding:14px 18px 16px;box-shadow:var(--card-shadow);margin-bottom:22px;
}
.setup-head{display:flex;align-items:center;justify-content:space-between;gap:12px}
.setup h2{margin:0;font-size:17px;font-weight:800;letter-spacing:-.01em}
.setup-hide{
  border:0;background:none;color:var(--muted);font:inherit;font-size:12px;font-weight:700;
  min-height:44px;min-width:44px;padding:0 6px;margin:-10px -6px -10px 0;border-radius:8px;cursor:pointer;
}
.setup-hide:hover{color:var(--fg)}
.setup-list{list-style:none;margin:6px 0 0;padding:0}
.setup-list li+li{border-top:1px solid var(--line)}
.setup-row{
  display:flex;align-items:center;justify-content:space-between;gap:14px;
  padding:11px 0;min-height:44px;text-decoration:none;color:inherit;
}
.setup-what{display:grid;gap:2px;min-width:0}
.setup-what b{font-size:14px;font-weight:800}
.setup-what span{font-size:12.5px;color:var(--muted);line-height:1.45}
.setup-go{
  display:inline-flex;align-items:center;gap:6px;flex:none;
  font-family:var(--font-data);font-size:11px;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:var(--price);white-space:nowrap;
}
.setup-arrow{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;transition:transform var(--t-state) var(--ease-out)}
.setup-row:hover b{text-decoration:underline;text-underline-offset:3px}
.setup-row:hover .setup-arrow{transform:translateX(2px)}
html.setup-off .setup{display:none}

/* Empty states: what will appear here, and the tab that fills it. */
.empty-state{display:flex;flex-direction:column;align-items:flex-start;gap:4px}
.empty-state b{font-size:15px;font-weight:800}
.empty-state p{margin:0;color:var(--muted);font-size:13.5px;line-height:1.5;max-width:56ch}
.empty-state .go{margin-top:8px}

/* Variant Cards with Food Photography */
.variants{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(158px,1fr));gap:12px;
}
.vcard{
  display:flex;flex-direction:column;align-items:stretch;text-align:left;
  padding:0;border-radius:15px;border:1.5px solid var(--line);
  background:var(--surface2);overflow:hidden;position:relative;
  transition:transform .16s ease, border-color .16s ease, box-shadow .16s ease;
}
.vcard:hover{
  transform:translateY(-2px);
  border-color:var(--line-control);
}
.vcard.on{
  border-color:var(--brand);
  background:linear-gradient(180deg, var(--surface2), color-mix(in srgb, var(--brand) 12%, var(--surface)));
  box-shadow:0 0 0 2px var(--brand), 0 12px 24px -8px rgba(214,46,32,.4);
}
.vcard-media{
  position:relative;width:100%;aspect-ratio:4/3;overflow:hidden;background:#120B09;
}
.vcard-media img{
  width:100%;height:100%;object-fit:cover;
  transition:transform .3s ease;
}
.vcard:hover .vcard-media img{transform:scale(1.05)}
.vcard-media::after{
  content:"";position:absolute;inset:0;
  background:linear-gradient(180deg, rgba(0,0,0,.05) 45%, rgba(19,13,11,.85) 100%);
}
.vcard-price-pill{
  position:absolute;bottom:8px;right:8px;z-index:2;
  background:rgba(19,13,11,.88);backdrop-filter:blur(6px);
  border:1px solid rgba(255,194,26,.7);
  color:var(--price-scrim);font-family:var(--font-data);font-weight:700;font-size:12px;
  padding:3px 8px;border-radius:8px;
}
.vcard-badge{
  position:absolute;top:8px;left:8px;z-index:2;
  background:rgba(19,13,11,.82);backdrop-filter:blur(4px);
  color:#fff;font-size:10px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;
  padding:3px 8px;border-radius:6px;border:1px solid rgba(255,255,255,.15);
}
.vcard.on .vcard-badge{background:var(--brand);border-color:var(--brand)}
/* The stock pill is the one status tag that lands on a photograph, and a 16%
   tint over a bright tray of takoyaki is not a background. It takes the same
   deep scrim the price and flavor chips on this card already use, keeping the
   stock colour in its ink and its ring, so the three states stay apart at a
   glance without hue carrying the meaning alone. */
.vcard-stock{
  position:absolute;top:8px;right:8px;z-index:2;box-shadow:none;
  background:rgba(19,13,11,.88);backdrop-filter:blur(6px);
  /* The colour is stated at full strength rather than as a tint: a whitened
     amber and a whitened coral land within 5% of each other in luminance, and
     this pill's job is to say which of the three states it is. --cs is the
     scrim-side value of the same stock colour. */
  border-color:color-mix(in srgb,var(--cs,var(--c)) 70%,transparent);
  color:var(--cs,var(--c));
}
.vcard-body{padding:11px 12px 12px;display:flex;flex-direction:column;gap:3px;flex:1}
.vcard .vn{font-family:var(--font-display);font-size:15px;line-height:1.15;letter-spacing:.02em}
.vcard .vt{font-size:12px;color:var(--muted);line-height:1.3}

/* Pack Sizes */
.packs{display:grid;grid-template-columns:repeat(auto-fit,minmax(108px,1fr));gap:10px}
.pk{
  position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;
  min-height:66px;padding:10px 12px;border-radius:13px;border:1.5px solid var(--line);
  background:var(--surface2);gap:3px;font-weight:700;
}
.pk:hover{border-color:var(--line-control);background:var(--surface3)}
.pk .pk-lbl{font-size:15px}
.pk .pr{font-family:var(--font-data);font-size:14px;color:var(--price);font-weight:700}
.pk .promo-tag{
  position:absolute;top:-8px;right:8px;
  background:var(--price);color:var(--price-ink);font-family:var(--font-display);
  font-size:10px;letter-spacing:.05em;padding:2px 6px;border-radius:999px;text-transform:uppercase;
  box-shadow:0 2px 6px rgba(0,0,0,.3);
}
.pk.on{
  background:linear-gradient(135deg,var(--brand),var(--brand-dark));
  border-color:var(--brand);color:var(--brand-ink);
  box-shadow:0 6px 16px -4px rgba(214,46,32,.5);
}
/* The selected pack's price stays gold — it is still a price — but on the red
   gradient the gold needs the bed it has everywhere else, or it drops to 3.9. */
.pk.on .pr{color:var(--price-scrim);background:var(--fill-bed);padding:2px 7px;border-radius:8px}

/* Flavor Cards with Ingredient Thumbnails */
/* 158px, not 135px: at 135 the longest names - Octopus, Scallop, Cheese - overran
   their track by up to 10px and the last letter was cut. Four columns still fit at
   this width, so the grid is unchanged and the names are whole. */
.flavor-grid{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(158px,1fr));gap:10px;
}
.fcard{
  display:flex;align-items:center;gap:10px;padding:8px 11px;
  border-radius:14px;border:1.5px solid var(--line);background:var(--surface2);
  text-align:left;position:relative;
}
.fcard:hover:not(:disabled){border-color:var(--line-control);background:var(--surface3)}
.fcard img{
  width:46px;height:46px;border-radius:50%;object-fit:cover;
  border:2px solid var(--line-bright);flex:none;background:#120B09;
}
.fcard-info{display:flex;flex-direction:column;min-width:0;gap:2px}
.fcard-name{font-weight:700;font-size:14px;line-height:1.15;overflow-wrap:anywhere}
.fcard-stock{font-family:var(--font-data);font-size:11px;color:var(--muted);font-weight:500}
.fcard.on{
  background:color-mix(in srgb, var(--brand) 18%, var(--surface2));
  border-color:var(--brand);
  box-shadow:0 0 0 1px var(--brand);
}
.fcard.on img{border-color:var(--price)}
.fcard.on .fcard-stock{color:var(--fg)}
.fcard-check{
  margin-left:auto;width:20px;height:20px;border-radius:50%;
  border:1.5px solid var(--line-control);display:grid;place-items:center;
  font-size:11px;font-weight:800;flex:none;color:transparent;
}
.fcard.on .fcard-check{background:var(--brand);border-color:var(--brand);color:var(--brand-ink)}
.fcard:disabled{opacity:.38;cursor:not-allowed}

/* Add-ons & Cheese Sauce Showcase */
.addons-wrap{display:grid;grid-template-columns:minmax(0,1fr);gap:12px}
@media (min-width:600px){
  .addons-wrap{grid-template-columns:1.25fr 1fr}
}
.chips{display:flex;flex-wrap:wrap;gap:8px;align-content:start}
.chip{
  min-height:46px;padding:6px 14px;border-radius:12px;border:1.5px solid var(--line);
  background:var(--surface2);font-weight:700;font-size:13.5px;
  display:inline-flex;align-items:center;gap:8px;
}
.chip:hover{border-color:var(--line-control);background:var(--surface3)}
.chip small{
  font-family:var(--font-data);font-size:12px;color:var(--price);font-weight:700;
  background:var(--price-glow);padding:2px 7px;border-radius:6px;
}
.chip.on{
  background:linear-gradient(135deg,var(--brand),var(--brand-dark));
  border-color:var(--brand);color:var(--brand-ink);
}
.chip.on small{background:var(--fill-bed);color:var(--price-scrim)}

.csauce-card{
  display:flex;align-items:center;gap:12px;padding:10px 14px;
  border-radius:14px;border:1.5px solid rgba(255,194,26,.35);
  background:linear-gradient(135deg, rgba(255,194,26,.12), rgba(232,57,42,.10));
  text-align:left;
}
.csauce-card:hover{border-color:var(--price)}
.csauce-card img{
  width:54px;height:54px;border-radius:12px;object-fit:cover;
  border:2px solid var(--price);flex:none;
}
.csauce-info{display:flex;flex-direction:column;gap:2px;min-width:0}
.csauce-title{font-family:var(--font-display);font-size:13px;letter-spacing:.03em;color:var(--fg)}
.csauce-sub{font-size:12px;color:var(--muted)}
.csauce-price{
  margin-left:auto;font-family:var(--font-data);font-weight:700;font-size:15px;
  color:var(--price);background:var(--price-bed);padding:5px 10px;border-radius:9px;flex:none;
}
.csauce-card.on{
  border-color:var(--price);
  background:linear-gradient(135deg, rgba(255,194,26,.28), rgba(232,57,42,.22));
  box-shadow:0 0 0 2px var(--price);
}
.csauce-card.on .csauce-price{background:var(--price);color:var(--price-ink)}

/* Add Row */
.addrow{display:flex;flex-wrap:wrap;gap:12px;align-items:stretch}
.stepper{
  display:flex;align-items:center;border:1.5px solid var(--line-control);
  border-radius:14px;background:var(--surface2);overflow:hidden;
}
.stepper button{width:50px;min-height:54px;border:0;background:transparent;font-size:22px;font-weight:700;line-height:1}
.stepper button:hover:not(:disabled){background:var(--surface3)}
.stepper button:disabled{opacity:.35;cursor:not-allowed}
.stepper output{min-width:42px;text-align:center;font-family:var(--font-data);font-weight:700;font-size:18px}
.primary{
  flex:1;min-width:210px;min-height:54px;border:0;border-radius:14px;
  background:linear-gradient(135deg,var(--brand),var(--brand-dark));
  color:var(--brand-ink);font-weight:800;font-size:16px;padding:0 20px;
  box-shadow:0 8px 20px -6px rgba(214,46,32,.55);
  display:inline-flex;align-items:center;justify-content:center;gap:10px;
}
.primary:hover:not(:disabled){filter:brightness(1.06)}
.primary:disabled{background:var(--surface2);color:var(--muted);box-shadow:none;cursor:not-allowed}

/* Order Ticket */
.ticket{
  background:var(--surface);border:1px solid var(--line);border-radius:18px;
  padding:18px;display:flex;flex-direction:column;gap:14px;min-width:0;
  box-shadow:var(--card-shadow);
}
.tk-scroll{display:flex;flex-direction:column;gap:14px;min-height:0}
.tk-head{display:flex;justify-content:space-between;align-items:center;gap:8px;padding-bottom:10px;border-bottom:1px solid var(--line);flex:0 0 auto}
.tk-head h2{margin:0 auto 0 0;font-family:var(--font-display);font-weight:400;font-size:19px;letter-spacing:.03em}
.tk-toggle{display:none;min-height:40px;padding:0 10px;border:1px solid var(--line-control);border-radius:9px;background:var(--surface2);color:var(--text);font-family:var(--font-body);font-size:11px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;white-space:nowrap}
.tk-badge{
  font-family:var(--font-data);font-size:12px;font-weight:700;color:var(--fg);
  background:var(--surface2);padding:4px 10px;border-radius:999px;border:1px solid var(--line);
}
.tlines{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;max-height:310px;overflow-y:auto}
.tlines li{
  display:grid;grid-template-columns:42px minmax(0,1fr) auto 30px;gap:10px;
  align-items:center;padding:10px 0;border-bottom:1px dashed var(--line);
}
.tlines li.empty{
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  text-align:center;color:var(--muted);font-size:13.5px;padding:22px 12px;
  border:1px dashed var(--line);border-radius:12px;background:var(--surface2);gap:4px;
}
.tl-thumb{width:42px;height:42px;border-radius:10px;object-fit:cover;border:1px solid var(--line-bright)}
.tl{display:flex;flex-direction:column;min-width:0;gap:2px}
.tl b{font-size:14px;line-height:1.2}
.tl span{font-size:12px;color:var(--muted);line-height:1.25}
.tp{font-family:var(--font-data);font-weight:700;font-size:14px;color:var(--price)}
.x{
  width:30px;height:30px;border:0;background:var(--surface2);border-radius:8px;
  color:var(--muted);font-size:18px;line-height:1;display:grid;place-items:center;
}
.x:hover{background:var(--out);color:#fff}
.total{
  display:flex;justify-content:space-between;align-items:baseline;
  background:var(--surface2);padding:12px 14px;border-radius:12px;border:1px solid var(--line);
}
.total span{font-size:12px;text-transform:uppercase;letter-spacing:.14em;color:var(--muted);font-weight:800}
.total b{font-family:var(--font-data);font-size:30px;color:var(--price);line-height:1}
.cashrow label{display:block;font-size:12px;font-weight:700;color:var(--muted);margin-bottom:6px;text-transform:uppercase;letter-spacing:.08em}
.cashrow input{
  width:100%;min-height:48px;border-radius:11px;border:1.5px solid var(--line-control);
  background:var(--bg);color:var(--fg);font-family:var(--font-data);font-size:20px;font-weight:700;padding:0 14px;
}
.quick{display:grid;grid-template-columns:repeat(5,1fr);gap:6px;margin-top:8px}
.quick button{
  min-height:40px;padding:0 6px;border-radius:8px;border:1px solid var(--line-control);
  background:var(--surface2);font-family:var(--font-data);font-size:12.5px;font-weight:700;
}
.quick button:hover{border-color:var(--price);color:var(--price)}
.chgrow{display:flex;justify-content:space-between;align-items:baseline;font-size:14px;color:var(--muted);font-weight:600}
.chg{font-family:var(--font-data);font-weight:700;font-size:18px;color:var(--ok)}
.chg.short{color:var(--out)}
.charge{
  min-height:56px;border:0;border-radius:13px;
  background:linear-gradient(135deg,var(--brand),var(--brand-dark));
  color:var(--brand-ink);font-weight:800;font-size:17px;
  box-shadow:0 8px 20px -6px rgba(214,46,32,.5);
}
.charge:disabled{background:var(--surface2);color:var(--muted);box-shadow:none;cursor:not-allowed}
.rcpt{
  border-top:1px solid var(--line);padding-top:12px;
  background:var(--surface2);padding:12px;border-radius:12px;border:1px solid var(--line);
}
.rcpt h3{margin:0 0 2px;font-size:13.5px;color:var(--ok);display:flex;align-items:center;gap:6px}
.rcpt p{margin:0 0 8px;font-size:12px;color:var(--muted)}
/* The receipt says what the kitchen now owns. It sits directly under the paid
   heading rather than after the deduction list: a receipt with eight
   deductions is taller than the ticket, and its last line is the first one a
   short window clips. */
.rcpt p.rcpt-kds{
  margin:3px 0 10px;padding-top:7px;border-top:1px dashed var(--line-bright);
  font-size:11px;font-weight:600;letter-spacing:.02em;
}
.rcpt-kds a{color:inherit;font-weight:800;text-decoration:underline;text-underline-offset:2px}
.rcpt ul{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:4px 12px;font-family:var(--font-data);font-size:11.5px}
.rcpt li{display:flex;justify-content:space-between;gap:6px}
.rcpt li b{color:var(--out);font-weight:600}

/* Inventory + Shift */
.strip{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:12px;
}
.stat-card{
  background:var(--surface);border:1px solid var(--line);border-radius:15px;
  padding:14px 16px;display:flex;flex-direction:column;gap:4px;box-shadow:var(--card-shadow);
}
.stat-card span{font-size:11px;text-transform:uppercase;letter-spacing:.14em;color:var(--muted);font-weight:800}
.stat-card b{font-family:var(--font-data);font-size:24px;line-height:1.1}
.stat-card small{font-size:12px;color:var(--muted)}
.scroll{overflow-x:auto;border:1px solid var(--line);border-radius:16px;background:var(--surface);box-shadow:var(--card-shadow)}
table{border-collapse:collapse;width:100%;min-width:700px}
th{font-size:11px;text-transform:uppercase;letter-spacing:.12em;color:var(--muted);text-align:left;padding:12px 14px;border-bottom:1px solid var(--line);white-space:nowrap;background:var(--surface2)}
td{padding:11px 14px;border-bottom:1px solid var(--line);vertical-align:middle}
tr:last-child td,tr:last-child th[scope=row]{border-bottom:0}
th[scope=row]{font-size:14px;text-transform:none;letter-spacing:0;color:var(--fg);font-weight:700;border-bottom:1px solid var(--line);background:transparent}
.ing-cell{display:flex;align-items:center;gap:10px}
.ing-cell img{width:36px;height:36px;border-radius:9px;object-fit:cover;border:1px solid var(--line-bright);flex:none}
td.r,th.r{text-align:right}
.lvl{position:relative;height:9px;border-radius:999px;background:var(--surface2);min-width:120px;overflow:hidden}
.lvl i{display:block;height:100%;border-radius:999px;background:var(--ok)}
.lvl.low i{background:var(--low)} .lvl.out i{background:var(--out)}
.lvl b{position:absolute;left:33.33%;top:0;bottom:0;width:2px;background:var(--fg);opacity:.55}
.act{white-space:nowrap;text-align:right}
.act button{min-height:40px;padding:0 12px;border-radius:8px;border:1px solid var(--line-control);background:var(--surface2);font-size:12.5px;font-weight:700;margin-left:6px}
.act button:hover{border-color:var(--price);background:var(--surface3)}
.sub{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px;margin:6px 0 0}
.flt{display:flex;gap:6px;flex-wrap:wrap}
.flt button{min-height:40px;padding:0 14px;border-radius:999px;border:1px solid var(--line-control);background:var(--surface);font-size:13px;font-weight:700}
.flt button.on{background:var(--brand);color:var(--brand-ink);border-color:var(--brand)}

/* Ledger pager. It sits under the table it pages, and the count says where in
   the history you are so a press is never a guess. */
.pager{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-top:-4px}
.pager-count{font-size:12px;color:var(--muted);font-variant-numeric:tabular-nums}
.pager-btns{display:flex;align-items:center;gap:8px}
.pager-btn{
  min-height:40px;padding:0 16px;border-radius:10px;cursor:pointer;
  font-size:12.5px;font-weight:700;font-family:var(--font-body);
  border:1px solid var(--line-control);background:var(--surface);color:var(--fg);
}
.pager-btn:hover:not(:disabled){border-color:var(--brand);color:var(--brand-text)}
.pager-btn:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
.pager-btn:disabled{opacity:.38;cursor:not-allowed}
.pager-pos{font-size:12px;color:var(--muted);font-variant-numeric:tabular-nums;min-width:9ch;text-align:center}
.pos-d{color:var(--ok);font-weight:700} .neg-d{color:var(--out);font-weight:700}

/* Shift Bars & Orders */
.shift-grid{display:grid;grid-template-columns:minmax(0,1fr);gap:18px}
@media (min-width:860px){.shift-grid{grid-template-columns:380px minmax(0,1fr)}}
.bars{display:flex;flex-direction:column;gap:12px}
.bar{display:grid;grid-template-columns:36px 120px minmax(0,1fr) 48px;gap:10px;align-items:center;font-size:13.5px;font-weight:600}
.bar img{width:36px;height:36px;border-radius:8px;object-fit:cover;border:1px solid var(--line-bright)}
.bar .tr{height:12px;border-radius:999px;background:var(--surface2);overflow:hidden}
.bar .tr i{display:block;height:100%;background:linear-gradient(90deg,var(--brand),var(--price));border-radius:999px}
.orders{list-style:none;margin:0;padding:0;border:1px solid var(--line);border-radius:16px;background:var(--surface);overflow:hidden;box-shadow:var(--card-shadow)}
.orders li{display:grid;grid-template-columns:92px minmax(0,1fr) auto;gap:6px 14px;padding:13px 16px;border-bottom:1px solid var(--line);align-items:start}
.orders li:last-child{border-bottom:0}
.orders .oid{font-family:var(--font-data);font-weight:700;font-size:13.5px;color:var(--brand-text)}
.orders .ot{font-size:12px;color:var(--muted)}
.orders .od{min-width:0;font-size:14px;font-weight:600;display:flex;flex-direction:column;gap:4px}
.orders .od span{display:block;font-size:12px;color:var(--muted);font-weight:400}
.orders .am{text-align:right;font-family:var(--font-data);font-weight:700;font-size:15px;color:var(--price)}
.orders .am small{display:block;font-weight:500;color:var(--muted);font-size:11px;margin-top:2px}

/* Menu Board Gallery View */
.menu-view{display:flex;flex-direction:column;gap:20px}
.menu-boards{display:grid;grid-template-columns:minmax(0,1fr);gap:18px;align-items:start}
@media (min-width:860px){.menu-boards{grid-template-columns:1.35fr 1fr}}
.board-card{
  background:var(--surface);border:1px solid var(--line);border-radius:18px;
  padding:16px;display:flex;flex-direction:column;gap:12px;box-shadow:var(--card-shadow);
}
.board-card img{width:100%;border-radius:12px;border:1px solid var(--line-bright)}
.gallery-grid{
  display:grid;grid-template-columns:repeat(auto-fill,minmax(175px,1fr));gap:12px;
}
.gcard{
  background:var(--surface);border:1px solid var(--line);border-radius:14px;
  overflow:hidden;display:flex;flex-direction:column;box-shadow:var(--card-shadow);
}
.gcard img{width:100%;aspect-ratio:4/3;object-fit:cover;background:#120B09}
.gcard-body{padding:10px 12px;display:flex;flex-direction:column;gap:2px}
.gcard-body b{font-family:var(--font-display);font-size:13.5px;letter-spacing:.02em}
.gcard-body span{font-size:12px;color:var(--muted)}

@media (max-width:540px){
  .orders li{grid-template-columns:minmax(0,1fr) auto}
  .orders .oid{grid-column:1}
  .orders .od{grid-column:1 / -1;order:3}
  .bar{grid-template-columns:32px 96px minmax(0,1fr) 40px}
}

/* Modal + Toast */
.modal{
  position:fixed;inset:0;background:rgba(0,0,0,.68);backdrop-filter:blur(4px);
  display:grid;place-items:center;
  padding:max(16px,env(safe-area-inset-top,0px)) max(16px,env(safe-area-inset-right,0px)) max(16px,env(safe-area-inset-bottom,0px)) max(16px,env(safe-area-inset-left,0px));
  z-index:20;
}
.sheet{
  width:min(440px,100%);background:var(--surface);border:1px solid var(--line-bright);
  border-radius:18px;padding:20px;display:flex;flex-direction:column;gap:12px;
  box-shadow:0 20px 50px rgba(0,0,0,.6);
}
.sheet h3{margin:0;font-size:18px;font-family:var(--font-display);font-weight:400;letter-spacing:.02em}
.sheet p{margin:0;font-size:13.5px;color:var(--muted)}
.sheet label{font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.08em;color:var(--muted)}
.sheet input{
  min-height:48px;border-radius:10px;border:1.5px solid var(--line-bright);
  background:var(--bg);color:var(--fg);font-family:var(--font-data);font-size:20px;font-weight:700;padding:0 12px;width:100%;
}
.sheet .row{display:flex;gap:8px;justify-content:flex-end;margin-top:6px}
.sheet .row button{min-height:44px;padding:0 18px;border-radius:10px;border:1px solid var(--line);background:var(--surface2);font-weight:700}
.sheet .row .go{background:var(--brand);border-color:var(--brand);color:var(--brand-ink)}

/* The reset sheet. It is the one dialog in the app that destroys things, so it
   is allowed to look different from the others: the consequences are listed
   before the button, not discovered after it. */
.sheet.sheet-danger{border-color:var(--brand-dark)}
.sheet .sheet-list{margin:0;padding-left:18px;display:flex;flex-direction:column;gap:6px;font-size:13px;color:var(--muted)}
.sheet .sheet-list li::marker{color:var(--brand-text)}
.sheet .sheet-warn{font-size:11.5px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--brand-text)}
.sheet .row .danger{background:var(--brand-dark);border-color:var(--brand-dark);color:var(--brand-ink)}
.sheet .row .danger:hover{background:var(--brand)}

/* A button that is working says so, and cannot be pressed a second time. The
   label is made transparent rather than removed so the button keeps its width
   and the row does not jump while the request is in flight. */
button.is-loading{position:relative;color:transparent!important;pointer-events:none;cursor:progress}
button.is-loading::after{
  content:"";position:absolute;inset:0;margin:auto;width:15px;height:15px;border-radius:50%;
  border:2px solid var(--fg);border-top-color:transparent;animation:spin .7s linear infinite;
}
.sheet .row .go.is-loading::after,
.sheet .row .danger.is-loading::after{border-color:var(--brand-ink);border-top-color:transparent}
/* Working is not "off". The disabled grey belongs to a button that cannot be
   pressed at all; a button that is mid-write keeps its own fill and gives up
   only its label, so the red primary still reads as the thing being done. */
.primary.is-loading:disabled,
.charge.is-loading:disabled{
  background:linear-gradient(135deg,var(--brand),var(--brand-dark));
  color:transparent;opacity:1;cursor:progress;
  box-shadow:0 8px 20px -6px rgba(214,46,32,.3);
}
@keyframes spin{to{transform:rotate(360deg)}}
.toast{
  position:fixed;left:50%;transform:translateX(-50%);
  bottom:calc(18px + env(safe-area-inset-bottom,0px));
  background:var(--fg);color:var(--bg);padding:11px 18px;border-radius:12px;
  font-weight:700;font-size:14px;max-width:calc(100% - 32px);z-index:30;
  opacity:0;pointer-events:none;transition:opacity .15s;
  box-shadow:0 10px 30px rgba(0,0,0,.45);
}
.toast.show{opacity:1}
/* ---------------------------------------------------------------------------
   Motion. This is an Operate surface, so motion confirms what just happened and
   explains where it went; it never performs. Three moves, each with a job:

   1. FEEDBACK — a ticket line arrives from the builder side, so a tap has a
      destination instead of the number simply being larger.
   2. THE STAMP — the receipt lands: a green rule draws left to right and the
      paid line settles onto the page. A sale is the product's atomic fact and
      this is the one authored moment in the app.
   3. A sheet rises 14px while the scrim fades, because a modal is an object
      placed on the counter, not a new page.

   The tab switch is not animated. A view transition there measured 976ms to
   its first frame and 1998ms to finish on a phone, because the snapshot has to
   rasterise five food photographs; an instant swap beats a slow cross-fade on
   the one control a cashier presses all shift.

   Everything here is transform and opacity. No layout property animates, no
   listener is added, and nothing runs unless an interaction caused it.
   --------------------------------------------------------------------------- */
:root{
  --ease-out:cubic-bezier(.16,1,.3,1);
  --t-state:180ms;
  --t-enter:320ms;
}

/* 1. Feedback: a new line slides in from the builder it came from. */
@keyframes o-line-in{from{opacity:0;transform:translateX(-10px)}to{opacity:1;transform:none}}
.tlines li.is-new{animation:o-line-in var(--t-state) var(--ease-out) both}

/* 2. The stamp. The rule draws, the line lands, the deductions follow. */
@keyframes o-rule{from{transform:scaleX(0)}to{transform:scaleX(1)}}
@keyframes o-stamp{from{opacity:0;transform:scale(1.04)}to{opacity:1;transform:none}}
@keyframes o-rcpt-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
.rcpt{animation:o-rcpt-in var(--t-enter) var(--ease-out) both}
.rcpt::before{
  content:'';display:block;height:2px;border-radius:2px;margin:0 0 9px;
  background:var(--ok);transform-origin:left;
  animation:o-rule 460ms var(--ease-out) both;
}
.rcpt h3{animation:o-stamp 380ms var(--ease-out) both}

/* 3. A sheet is placed, not navigated to. */
@keyframes o-scrim{from{opacity:0}to{opacity:1}}
@keyframes o-sheet{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
.modal{animation:o-scrim var(--t-state) ease-out both}
.sheet{animation:o-sheet 240ms var(--ease-out) both}

/* The toast rises 6px as it fades in. It is centred with `transform`, so the
   offset lives on `translate` and the two compose instead of fighting. */
.toast{translate:0 6px;transition:opacity .15s,translate var(--t-state) var(--ease-out)}
.toast.show{translate:0 0}

/* Reduced motion keeps every state change and drops the travel: the line is
   simply there, the receipt is simply stamped, the sheet is simply open. */
@media (prefers-reduced-motion:reduce){
  .toast,button,.vcard,.vcard-media img,.skip{transition:none}
  .toast{translate:0 0}
  .tlines li.is-new,.rcpt,.rcpt h3,.rcpt::before,.modal,.sheet{animation:none}
}

/* ---------------------------------------------------------------------------
   Mobile pass (<=919px). The app was laid out at 1440px and then made to fit a
   phone; these rules give the phone its own layout instead.

   1. The POS ticket becomes the bottom of the screen instead of the last thing
      on a 3,897px page. Charge sat 4.6 screens down and the confirmation toast
      then covered it. Only the line list scrolls, so Total / Cash / Charge never
      leave the viewport.
   2. Inventory's two tables stop being tables below 760px — they were 885px wide
      inside a 356px scroller, which put +Receive and Count 384px past the right
      edge. The pantry ledger has stacked its rows since it shipped.
   3. Tap targets are lifted to the floor DESIGN.md already promises: 40px on the
      POS path, 44px for a chip.
   --------------------------------------------------------------------------- */
@media (max-width:919px){
  .ticket{
    position:fixed;left:0;right:0;bottom:0;z-index:15;
    max-height:min(calc(100vh - 8px),620px);
    max-height:min(calc(100dvh - 8px),620px);
    overflow:hidden;
    display:flex;flex-direction:column;gap:8px;
    padding:12px 14px max(12px,env(safe-area-inset-bottom,0px));
    border-radius:16px 16px 0 0;
    box-shadow:0 -12px 32px -12px rgba(0,0,0,.65);
  }
  /* One scroll region holds the order and payment fields. Charge sits outside
     it, so the primary action stays at thumb height even in landscape. */
  .ticket .tk-scroll{
    flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain;
    -webkit-overflow-scrolling:touch;padding-right:2px;
    scrollbar-width:thin;scrollbar-color:var(--line-control) transparent;
    gap:10px;
  }
  .ticket .tk-head{padding-bottom:8px}
  .ticket .tk-toggle{display:inline-flex;align-items:center;justify-content:center}
  .ticket:has(.tlines li.empty) .tk-toggle{display:none}
  .ticket .tlines{flex:0 0 auto;max-height:none;overflow:visible}
  .ticket .charge{flex:0 0 auto}
  .ticket .total{padding:10px 12px}
  .ticket .total b{font-size:24px}
  .ticket .charge{min-height:52px}
  .ticket .pay-block{margin:2px 0}
  .ticket.is-min{max-height:none}
  .ticket.is-min .tk-head{padding-bottom:0;border-bottom:0}
  .ticket.is-min .tk-head h2{white-space:nowrap}
  .ticket.is-min .tk-badge{display:none}
  .ticket.is-min .tk-scroll,
  .ticket.is-min .charge,
  .ticket.is-min .rcpt{display:none}
  /* The receipt that follows a sale is a full ingredient list. On the till it
     only needs to say which order was paid; the Shift tab keeps the detail.
     It also steps aside once the next order starts, so the lines keep the room. */
  .ticket .rcpt{padding:10px 12px}
  .ticket .rcpt p,.ticket .rcpt ul{display:none}
  .ticket .rcpt h3{font-size:14px;margin:0}
  .ticket:has(.tlines li:not(.empty)) .rcpt{display:none}
  /* The ticket is out of flow now, so the page has to end above it. An empty
     ticket is compact; a live order reserves the same cap the ticket uses. */
  .app:has(.ticket){padding-bottom:calc(240px + env(safe-area-inset-bottom,0px))}
  .app:has(.ticket .tlines li:not(.empty)){
    padding-bottom:calc(min(calc(100vh - 8px),620px) + 16px + env(safe-area-inset-bottom,0px));
    padding-bottom:calc(min(calc(100dvh - 8px),620px) + 16px + env(safe-area-inset-bottom,0px));
  }
  .app:has(.ticket.is-min){padding-bottom:calc(76px + env(safe-area-inset-bottom,0px))}
  /* Nothing can be paid for yet, so payment controls would only crowd out the
     instruction that gets the cashier started. */
  .ticket:has(.tlines li.empty) .total,
  .ticket:has(.tlines li.empty) .pay-block,
  .ticket:has(.tlines li.empty) .cashrow,
  .ticket:has(.tlines li.empty) .chgrow,
  .ticket:has(.tlines li.empty) .charge{display:none}
  /* The receipt takes 53px plus its rule out of a 290px cap, which left the
     empty state's hint clipped to a sliver. Once a sale has posted the receipt
     is the thing worth reading, so the hint steps aside. */
  .ticket:has(.rcpt) .tlines li.empty{padding:12px 12px;gap:2px}
  .ticket:has(.rcpt) .tlines li.empty span{display:none}

  /* 158px + a 12px gap needs 328px and the panel gives 324, so the five variants
     were stacking one per screen into 1,645px of step 1. */
  .variants{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
  .vcard .vn{font-size:13.5px}
  .vcard .vb{font-size:9.5px}

  /* The confirmation must not land on the button it is confirming. */
  .toast{bottom:auto;top:calc(env(safe-area-inset-top,0px) + 12px)}

  .icon-btn{min-height:44px}
  .promo-actions button{min-height:44px}
  .tabs button{min-height:44px}
  .quick button{min-height:44px;font-size:13px}
  .flt button{min-height:40px}
  .x{width:44px;height:44px}
  /* The remove button's grid column has to grow with the target. */
  .tlines li{grid-template-columns:42px minmax(0,1fr) auto 44px}
}

/* A phone held sideways is wide and short. At 844x390 the page under the
   masthead is about 180px, and a sheet pinned to the bottom of the viewport
   fills all of it, so the order covered the food. At 760px wide and 560px tall
   or less the ticket becomes a rail beside the builder again, the composition
   the desk layout uses, and the page scrolls normally. */
@media (min-width:760px) and (max-height:560px){
  .pos{grid-template-columns:minmax(0,1fr) 320px;gap:16px}
  .ticket{
    position:sticky;top:8px;left:auto;right:auto;bottom:auto;z-index:auto;
    max-height:calc(100dvh - 16px);border-radius:18px;
    box-shadow:var(--card-shadow);
  }
  .ticket .tk-toggle{display:none}
  .app:has(.ticket),
  .app:has(.ticket .tlines li:not(.empty)),
  .app:has(.ticket.is-min){padding-bottom:0}
}

/* Inventory below 760px: the same row stacking the pantry ledger already does. */
@media (max-width:760px){
  .scroll{overflow:visible;border:0;background:transparent;box-shadow:none}
  .inv-table,.ledger-table{display:block;min-width:0}
  .inv-table thead,.ledger-table thead{display:none}
  .inv-table tbody,.ledger-table tbody{display:block}
  .inv-table tr,.ledger-table tr{
    display:grid;gap:8px 14px;padding:12px 14px;margin-bottom:8px;
    background:var(--surface);border:1px solid var(--line);border-radius:14px;
    box-shadow:var(--card-shadow);align-content:start;
  }
  .inv-table td,.ledger-table td{display:block;padding:0;border:0;text-align:left}
  .inv-table td.r,.ledger-table td.r{text-align:left}
  /* Every cell names itself once the column heads are gone. */
  .inv-table td[data-th]::before,.ledger-table td[data-th]::before{
    content:attr(data-th);display:block;margin-bottom:2px;
    font-size:10.5px;font-weight:600;color:var(--muted);letter-spacing:.01em;
  }

  /* A grid track takes its minimum from the widest child, so one long cell
     pushed the whole row past the card. The cells may shrink now and wrap. */
  .inv-table tr>*,.ledger-table tr>*,.users-table tr>*,.audit-table tr>*{min-width:0}
  /* One cell standing in for the whole row spans the card instead of one track. */
  .inv-table tr>*:only-child,.ledger-table tr>*:only-child{grid-column:1/-1}
  .inv-table tr{grid-template-columns:1fr 1fr}
  .inv-table th[scope=row]{grid-column:1/-1;padding:0;border:0;background:transparent;text-align:left}
  .inv-table .it-onhand{grid-column:1}
  .inv-table .it-used{grid-column:2}
  .inv-table .it-level{grid-column:1/-1}
  .inv-table .it-level .lvl{min-width:0}
  .inv-table .it-status{grid-column:1;align-self:center}
  .inv-table .it-acts{grid-column:2;display:flex;gap:8px;justify-content:flex-end}
  .inv-table .it-acts button{flex:1;min-height:44px}

  /* Movement row: when and what, then delta beside the resulting balance, then
     why. Rows are placed explicitly so the DOM order can stay the header order. */
  .ledger-table tr{grid-template-columns:1fr 1fr}
  .ledger-table .lt-time{grid-column:1/-1;grid-row:1;font-size:11.5px;color:var(--muted)}
  .ledger-table .lt-name{grid-column:1/-1;grid-row:2}
  .ledger-table .lt-delta{grid-column:1;grid-row:3;white-space:nowrap}
  .ledger-table .lt-after{grid-column:2;grid-row:3;text-align:right;white-space:nowrap}
  .ledger-table .lt-after::before{text-align:right}
  .ledger-table .lt-reason{grid-column:1/-1;grid-row:4;font-size:12.5px;color:var(--muted)}
}


/* ---------------------------------------------------------------------------
   Accounts and access. The Users tab and the account menu are the same shop as
   the till: warm surfaces, a signwriter's section head, tabular dates, and one
   red action per region. The tables become stacked records on a phone rather
   than a sideways-scrolling desktop grid.
   --------------------------------------------------------------------------- */
.sr-only{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0,0,0,0);white-space:nowrap;border:0;
}

/* Account menu */
.account-menu{position:relative}
.account-btn{
  display:flex;align-items:center;gap:10px;min-height:44px;padding:7px 11px 7px 13px;
  border:1px solid var(--line-bright);background:var(--surface2);border-radius:12px;
  color:var(--fg);text-align:left;
}
.account-btn:hover{background:var(--surface3);border-color:var(--line-control)}
.account-btn[aria-expanded="true"]{border-color:var(--price);box-shadow:0 0 0 1px var(--price)}
.account-identity{display:flex;flex-direction:column;gap:1px;min-width:0}
.account-name{
  max-width:16ch;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  font-size:13.5px;font-weight:800;line-height:1.1;
}
.account-role{
  font-size:10px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;
  color:var(--muted);line-height:1.2;
}
.account-chevron{
  width:8px;height:8px;flex:none;margin-left:2px;opacity:.7;
  border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;
  transform:rotate(45deg) translateY(-2px);transition:transform .15s ease;
}
.account-btn[aria-expanded="true"] .account-chevron{transform:rotate(225deg) translateY(-2px)}
.account-pop{
  position:absolute;right:0;top:calc(100% + 8px);z-index:30;
  min-width:min(15rem,calc(100vw - 2rem));
  display:flex;flex-direction:column;gap:2px;padding:6px;
  background:var(--surface);border:1px solid var(--line-bright);border-radius:14px;
  box-shadow:0 16px 40px rgba(0,0,0,.45);
}
.account-pop a,.account-pop button{
  display:flex;align-items:center;width:100%;min-height:44px;padding:0 12px;
  border:0;border-radius:9px;background:transparent;color:var(--fg);
  font:inherit;font-size:14px;font-weight:700;text-align:left;text-decoration:none;
}
.account-pop a:hover,.account-pop button:hover{background:var(--surface2)}
.account-pop a:focus-visible,.account-pop button:focus-visible{outline:2px solid var(--price);outline-offset:0}
.account-pop .signout-form{margin:6px 0 0;padding-top:6px;border-top:1px solid var(--line)}
.account-pop .signout-form button{color:var(--out)}
.account-pop .signout-form button:hover{background:color-mix(in srgb,var(--out) 14%,transparent)}

/* Users masthead and tools */
.users-view{display:flex;flex-direction:column;gap:18px}
.users-mast{
  display:flex;align-items:flex-end;justify-content:space-between;gap:16px;flex-wrap:wrap;
  padding:2px 2px 0;
}
.users-mast h2{
  margin:0;font-family:var(--font-display);font-weight:400;font-size:28px;
  letter-spacing:.03em;line-height:1.1;
}
.users-mast p{margin:5px 0 0;max-width:62ch;color:var(--muted);font-size:13.5px;line-height:1.45}
.go{
  display:inline-flex;align-items:center;justify-content:center;
  min-height:44px;padding:0 18px;border:0;border-radius:12px;
  background:linear-gradient(135deg,var(--brand),var(--brand-dark));
  color:var(--brand-ink);font-size:14px;font-weight:800;
  text-align:center;text-decoration:none;box-shadow:0 8px 20px -6px rgba(214,46,32,.5);
}
.go:hover{filter:brightness(1.06)}
.go:disabled{background:var(--surface2);color:var(--muted);box-shadow:none;cursor:not-allowed}
.users-panel{display:flex;flex-direction:column;gap:10px}
.users-head{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}
.users-head h2.lbl{
  margin:0;font-family:var(--font-display);font-size:18px;font-weight:400;
  letter-spacing:.02em;line-height:1.2;text-transform:none;color:var(--fg);
}
.users-count{font-size:12px;color:var(--muted);font-variant-numeric:tabular-nums}
.users-tools{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.users-search{flex:1 1 240px;min-width:0}
.users-search input,.users-status select{
  width:100%;min-height:44px;border-radius:10px;border:1.5px solid var(--line-control);
  background:var(--bg);color:var(--fg);font:inherit;font-size:14px;padding:0 12px;
}
.users-search input::placeholder{color:var(--muted)}
.users-status{flex:0 1 170px;min-width:0}
.users-table{min-width:940px}
.users-table td,.users-table th[scope=row]{vertical-align:top}
.user-cell{display:flex;flex-direction:column;gap:2px;min-width:0}
.user-cell b{font-size:14.5px;line-height:1.2}
.user-cell .mono{font-size:11.5px;color:var(--muted);font-weight:500}
.user-cell small{font-size:11.5px;color:var(--muted);line-height:1.3;overflow-wrap:anywhere}
.user-role{font-size:13px;font-weight:600}
.user-muted{font-size:12.5px;color:var(--muted)}
.user-date{font-size:11.5px;color:var(--muted);white-space:nowrap}
.user-actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:6px}
.user-actions .u-btn{min-height:44px}
.u-btn{
  display:inline-flex;align-items:center;justify-content:center;
  min-height:44px;padding:0 12px;border-radius:8px;
  border:1px solid var(--line-control);background:var(--surface2);color:var(--fg);
  font-size:12.5px;font-weight:700;text-decoration:none;white-space:nowrap;
}
.u-btn:hover{border-color:var(--price);background:var(--surface3)}
.u-btn.danger{color:var(--out);border-color:color-mix(in srgb,var(--out) 55%,var(--line))}
.u-btn.danger:hover{border-color:var(--out);background:color-mix(in srgb,var(--out) 14%,transparent)}
.audit-table{min-width:880px}
.audit-time{font-size:11.5px;color:var(--muted);white-space:nowrap}
.audit-detail{font-size:12.5px;color:var(--muted)}
.users-empty-cell{padding:18px 14px;color:var(--muted)}
.users-empty{
  margin:0;padding:16px;border:1px dashed var(--line);border-radius:14px;
  color:var(--muted);font-size:13.5px;
}

/* Account sheets and fields */
.account-sheet{width:min(560px,100%);max-height:calc(100vh - 32px);overflow:auto}
.field{display:flex;flex-direction:column;gap:6px}
.field-row{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.field label{font-size:11px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:var(--muted)}
.field input,.field select{
  width:100%;min-height:48px;padding:0 12px;border-radius:10px;
  border:1.5px solid var(--line-bright);background:var(--bg);color:var(--fg);
  font:inherit;font-size:15px;
}
.field input[type="password"]{font-family:var(--font-data);letter-spacing:.04em}
.field input:focus,.field select:focus{outline:2px solid var(--price);outline-offset:2px;border-color:var(--price)}
.field-hint{font-size:11.5px;line-height:1.35;color:var(--muted)}
.field input.is-invalid,.field select.is-invalid{border-color:var(--out);box-shadow:0 0 0 1px var(--out)}
.field-error{margin:0;color:var(--out);font-size:12.5px;font-weight:700;line-height:1.35}
.account-sheet .row{position:sticky;bottom:-20px;background:var(--surface);padding-top:10px}
.temp-password{background:var(--bg);border:1px solid var(--line-control);border-radius:12px;padding:14px}
.temp-password code{
  display:block;font-family:var(--font-data);font-size:clamp(18px,5vw,26px);
  font-weight:700;letter-spacing:.06em;color:var(--price);
  overflow-wrap:anywhere;user-select:all;
}
.temp-password code.is-copied{color:var(--ok)}
.temp-expiry{margin:0;font-size:12.5px;color:var(--muted)}

@media (max-width:760px){
  .users-mast h2{font-size:24px}
  .users-mast .go{width:100%}
  .users-tools{flex-direction:column;align-items:stretch}
  .users-search,.users-status{flex:1 1 auto;width:100%}
  .users-status select{width:100%}
  .users-scroll,.audit-scroll{overflow:visible;border:0;background:transparent;box-shadow:none}
  .users-table,.audit-table{display:block;min-width:0}
  .users-table thead,.audit-table thead{display:none}
  .users-table tbody,.audit-table tbody{display:block}
  .users-table tr,.audit-table tr{
    display:grid;gap:7px 12px;padding:13px 14px;margin-bottom:8px;
    background:var(--surface);border:1px solid var(--line);border-radius:14px;
    box-shadow:var(--card-shadow);
  }
  .users-table th,.users-table td,.audit-table td{display:block;padding:0;border:0;text-align:left}
  .users-table td[data-th]::before,.audit-table td[data-th]::before{
    content:attr(data-th);display:block;margin-bottom:2px;
    font-size:10.5px;font-weight:700;letter-spacing:.02em;color:var(--muted);
  }
  .users-table tr{grid-template-columns:1fr 1fr}
  .users-table th[scope=row]{grid-column:1/-1;padding:0;border:0;background:transparent}
  /* A timestamp held on one line is 423px wide at 200% text, which pushed the
     card past the screen. It wraps here, and still fits on one line normally. */
  .user-date{white-space:normal}
  .users-table td.user-actions{
    grid-column:1/-1;display:grid;grid-template-columns:1fr 1fr;gap:8px;
    justify-content:stretch;white-space:normal;
  }
  .user-actions .u-btn{width:100%;min-height:44px}
  .user-actions .u-btn:only-child{grid-column:1/-1}
  .audit-detail{color:var(--fg)}
  .field-row{grid-template-columns:1fr}
  .account-sheet .row{flex-direction:column-reverse}
  .account-sheet .row button{width:100%}
}

@media (max-width:540px){
  .account-menu{width:100%}
  .account-btn{width:100%;justify-content:space-between}
  .account-pop{left:0;right:0;min-width:0}
  .users-mast h2{font-size:22px}
}

/* ---------------------------------------------------------------- reports */
.reports-view{display:flex;flex-direction:column;gap:18px}
.trend{
  display:flex;align-items:flex-end;gap:10px;overflow-x:auto;padding:18px 6px 6px;
  border-top:1px solid var(--line);
}
/* The column fills the bar's height so the bar is a bar, not a full-width
   slab: a single day at 100% must still read as a measured value. */
.trend-col{display:flex;flex-direction:column;align-items:center;gap:6px;min-width:72px;flex:1;align-self:stretch}
.trend-val{font-size:11.5px;color:var(--price);font-weight:700}
.trend-bar{
  display:flex;align-items:flex-end;width:100%;max-width:76px;min-height:132px;height:132px;
  background:linear-gradient(180deg,transparent,var(--surface2));
  border-radius:10px;overflow:hidden;
}
.trend-bar i{
  display:block;width:100%;
  background:linear-gradient(180deg,var(--brand),var(--brand-dark));
  border-radius:10px 10px 0 0;
}
.trend-lbl{font-size:11.5px;color:var(--muted);text-align:center}
.trend-sub{font-size:10.5px;color:var(--muted);font-family:var(--font-data)}
.report-filters{
  display:grid;grid-template-columns:minmax(180px,2fr) repeat(2,minmax(130px,1fr)) repeat(3,minmax(120px,1fr)) auto auto;
  gap:10px;align-items:end;padding:0 0 14px;
}
.report-filters>*{min-width:0}
.report-filters .users-search{min-width:0}
.report-filters .go,.report-filters .u-btn{min-height:44px}
.report-date{display:flex;flex-direction:column;gap:4px;font-size:11px;color:var(--muted);font-weight:600}
.report-date input{
  min-height:44px;padding:0 10px;border-radius:10px;
  border:1px solid var(--line-control);background:var(--surface2);color:var(--fg);
  font:inherit;font-size:13.5px;
}
.report-table{width:100%;border-collapse:separate;border-spacing:0}
.report-table th,.report-table td{padding:11px 12px;text-align:left;vertical-align:middle}
.report-table th{font-size:11px;letter-spacing:.04em;text-transform:uppercase;color:var(--muted);font-weight:700;border-bottom:1px solid var(--line)}
.report-table td{border-bottom:1px solid var(--line)}
.report-table .r{text-align:right}
.report-table tr.is-voided td{opacity:.62}
.report-table tr.is-voided td[data-th="Order"] b{text-decoration:line-through}
.report-empty{color:var(--muted);text-align:center;padding:28px 12px}
.usage-table{width:100%;border-collapse:separate;border-spacing:0}
.usage-table th,.usage-table td{padding:10px 12px;text-align:left;border-bottom:1px solid var(--line)}
.usage-table th{font-size:11px;letter-spacing:.04em;text-transform:uppercase;color:var(--muted);font-weight:700}
.usage-table .r{text-align:right}
.usage-table tbody tr:last-child td{border-bottom:0}

@media (max-width:1100px){
  .report-filters{grid-template-columns:1fr 1fr 1fr}
  .report-filters .users-search{grid-column:1/-1}
}
@media (max-width:760px){
  .report-filters{grid-template-columns:1fr 1fr}
  .report-filters .go,.report-filters .u-btn{width:100%}
  /* The category select is the last filter, so it takes the row instead of
     sitting beside an empty cell and pushing Clear into one of its own. */
  .report-filters label:last-of-type{grid-column:1/-1}
  .report-table thead{display:none}
  .report-table tr{
    display:grid;grid-template-columns:1fr 1fr;gap:7px 12px;padding:13px 14px;margin-bottom:8px;
    background:var(--surface);border:1px solid var(--line);border-radius:14px;box-shadow:var(--card-shadow);
  }
  .report-table td,.usage-table td{display:block;padding:0;border:0}
  .report-table td[data-th]::before,.usage-table td[data-th]::before{
    content:attr(data-th);display:block;margin-bottom:2px;
    font-size:10.5px;font-weight:700;color:var(--muted);
  }
  .report-table td.user-actions{
    grid-column:1/-1;display:grid;grid-template-columns:1fr 1fr;gap:8px;
    justify-content:stretch;white-space:normal;
  }
  .report-table .user-actions .u-btn{width:100%;min-height:44px}
  .report-table .user-actions .u-btn:only-child{grid-column:1/-1}
  .usage-table{display:block}
  .usage-table thead{display:none}
  .usage-table tbody tr{
    display:grid;grid-template-columns:1fr 1fr;gap:6px 12px;padding:12px 14px;margin-bottom:8px;
    background:var(--surface);border:1px solid var(--line);border-radius:14px;
  }
  .usage-table tbody tr:last-child td{border-bottom:0}
  .trend-col{min-width:64px}
}

/* ----------------------------------------------------- payment & customer */
.pay-block{display:flex;flex-direction:column;gap:7px;margin:10px 0 4px}
.pay-lbl{font-size:11px;letter-spacing:.05em;text-transform:uppercase;color:var(--muted);font-weight:700}
.pay-chips{display:flex;flex-wrap:wrap;gap:6px}
.pay-chip,.customer-chip{
  min-height:40px;padding:0 14px;border-radius:999px;cursor:pointer;
  border:1px solid var(--line-control);background:var(--surface2);color:var(--fg);
  font:inherit;font-size:13px;font-weight:600;
}
.pay-chip:hover,.customer-chip:hover{border-color:var(--brand-text)}
.pay-chip.on,.customer-chip.on{
  background:linear-gradient(180deg,var(--brand),var(--brand-dark));
  border-color:transparent;color:var(--brand-ink);
}
.pay-note{margin:8px 0 0;color:var(--muted);font-size:12.5px}

/* The report log and usage tables stack into records on a phone, the same way
   the roster does. A desktop table here would scroll sideways and hide the
   Void button behind a gesture the owner never discovers. */
@media (max-width:760px){
  .users-panel .scroll.users-scroll:has(.report-table),
  .users-panel .scroll.users-scroll:has(.usage-table){overflow:visible}
  .users-panel .report-table,
  .users-panel .usage-table{display:block;width:100%;min-width:0;border-spacing:0}
  .users-panel .report-table thead,
  .users-panel .usage-table thead{display:none}
  .users-panel .report-table tbody,
  .users-panel .usage-table tbody{display:block}
  .users-panel .report-table tr,
  .users-panel .usage-table tbody tr{
    display:grid;grid-template-columns:1fr 1fr;gap:7px 12px;
    width:100%;padding:13px 14px;margin-bottom:8px;
    background:var(--surface);border:1px solid var(--line);border-radius:14px;
    box-shadow:var(--card-shadow);
  }
  .users-panel .report-table td,
  .users-panel .usage-table td{display:block;padding:0;border:0;text-align:left;width:auto;max-width:100%}
  .users-panel .report-table td[data-th]::before,
  .users-panel .usage-table td[data-th]::before{
    content:attr(data-th);display:block;margin-bottom:2px;
    font-size:10.5px;font-weight:700;letter-spacing:.02em;color:var(--muted);
  }
  .users-panel .report-table td.user-actions{
    grid-column:1/-1;display:grid;grid-template-columns:1fr 1fr;gap:8px;
    justify-content:stretch;white-space:normal;
  }
  .users-panel .report-table .user-actions .u-btn{width:100%;min-height:44px}
  .users-panel .report-table .user-actions .u-btn:only-child{grid-column:1/-1}
  .users-panel .report-table .report-empty{grid-column:1/-1;text-align:center}
  .users-panel .usage-table tbody tr:last-child td{border-bottom:0}
}

/* ------------------------------------------------------------ data exchange */
.data-copy{margin:0 0 12px;color:var(--muted);max-width:68ch;line-height:1.55}
.data-actions{display:flex;flex-wrap:wrap;gap:10px}
.data-actions .u-btn,.data-actions .go{min-height:44px;display:inline-flex;align-items:center;padding:0 18px}
.data-import{display:flex;flex-wrap:wrap;align-items:flex-end;gap:14px;margin-bottom:14px}
.data-file{display:flex;flex-direction:column;gap:6px;font-size:11.5px;font-weight:700;color:var(--muted);letter-spacing:.03em;text-transform:uppercase}
.data-file input{
  min-height:44px;padding:9px 12px;border-radius:10px;border:1px solid var(--line-control);
  background:var(--surface2);color:var(--fg);font:inherit;font-size:13.5px;max-width:100%;
}
.data-check{display:inline-flex;align-items:center;gap:8px;font-size:13.5px;min-height:44px;color:var(--fg)}
.data-check input{width:18px;height:18px;accent-color:var(--brand)}
.data-report{border-top:1px solid var(--line);padding-top:12px}
.data-report b{display:block;margin-bottom:4px}
.data-report p{margin:0 0 6px;color:var(--muted)}
.data-report.is-ok b{color:var(--ok)}
.data-report.is-bad b{color:var(--out)}
.data-problems{margin:8px 0 0;padding-left:18px;color:var(--fg);font-size:13.5px;line-height:1.6;max-height:320px;overflow:auto}
.data-problems li{margin-bottom:2px}
@media (max-width:540px){
  /* The file field, the checkbox and both buttons each take the whole row and
     stack. Left to wrap on their own the two buttons shrank to half the row
     and the form read as three separate alignments down the panel. */
  .data-import{flex-direction:column;align-items:stretch}
  .data-actions{width:100%}
  .data-actions .u-btn,.data-actions .go{flex:1 1 100%;width:100%;justify-content:center}
  .data-file input{width:100%}
}

/* The export/import panels read as cards on the same rhythm as Reports, and a
   heading that groups them needs air above it rather than a bare gap. */
.data-view .users-panel{padding:18px 20px}
.data-view .users-panel + .users-panel{margin-top:0}
.data-view .users-head{margin-bottom:10px}
@media (max-width:760px){
  .data-view .users-panel{padding:16px 14px}
}

/* ------------------------------------------------------ the masthead, rethought
   On a handset the bar stacked three deep: brand, a three-row tab grid, then
   Kitchen, the account and the theme button on a line of its own. It measured
   409px of an 844px screen, and the promo strip under it added 147px, so the
   first takoyaki sat at y=604. The bar had been built for the five tabs it
   shipped with and had grown to eight.

   It is now two rows, or three on the narrowest phone: identity beside the
   controls, then the tabs. Every view keeps its own button, with no hamburger
   and no drawer, and the row reflows by track width: four tabs across a 390px
   screen, three across a 320px one. The tagline is dropped because it is the
   shop's slogan and <title> still carries it.

   Below 600px the brand and the controls no longer share a line, so each takes
   a row of its own with the tabs between them: brand, tabs, controls. */
@media (max-width:919px){
  .top{padding:10px;gap:10px}
  .brand{flex:1 1 auto;min-width:0;gap:9px}
  .logo-img{width:36px;height:36px;border-width:1.5px}
  .brand-text h1{font-size:18px;letter-spacing:.05em;gap:6px}
  .brand-badge{font-size:10px;padding:2px 5px;border-radius:4px;letter-spacing:.1em}
  .brand-text p{display:none}

  /* Each tab takes an equal share of the row and breaks to the next row before
     it would clip its own label: "Menu Board" is 66px at this size and a button
     never goes below 74px, so four fit a 390px screen and three a 320px one. */
  .tabs{order:3;width:100%;flex-wrap:wrap;gap:4px;padding:4px}
  .tabs button{flex:1 1 74px;min-width:0;min-height:44px;padding:0 3px;font-size:12px;justify-content:center;white-space:nowrap}

  /* A 40px control is a mouse target. On a handset every one of them is a thumb
     target, so the floor moves to 44 and the padding carries it. */
  .act button,.flt button,.promo-actions button{min-height:44px}

  .top-right{order:2;margin-left:0;gap:8px;flex-wrap:nowrap;flex:0 0 auto}
  .kds-link{min-height:44px;padding:0 11px;font-size:11.5px}
  .account-menu{width:auto}
  .account-btn{width:auto;gap:8px;padding:0 10px}
  .account-name{font-size:12.5px;max-width:13ch}
  .account-role{display:none}

  /* The theme button keeps its accessible name and gives up its visible label:
     two words of it cost the account menu the width it needs for a name. The
     glyph shows the theme you are not in, the way the words did.
     Scoped to the button itself. .icon-btn is also the Menu Board's "Order in
     POS" button, which needs its label. */
  #themeBtn{width:44px;min-width:44px;padding:0;justify-content:center;color:var(--fg)}
  #themeBtn .theme-word{display:none}
}

@media (max-width:600px){
  .brand{width:100%}
  .tabs{order:2}
  .top-right{order:3;width:100%}
  .account-menu{flex:1 1 auto;min-width:0}
  .account-btn{width:100%;justify-content:space-between}
  .account-pop{left:auto;right:0;min-width:min(15rem,calc(100vw - 2rem))}
}

/* The promo states a menu rule and it repeats on every screen. In a pocket it
   says the same thing on one line: the pack rule and the way to the reference
   menu. The long sentence and the stock note stay on the desk layout, where
   there is room to read them. A phone held sideways is short instead of
   narrow, and the long sentence does not fit there either, so the height joins
   the width as a reason to shorten it. */
@media (max-width:600px),(max-height:560px){
  .promo-strip{padding:8px 10px;gap:8px;border-radius:12px}
  /* A zero basis, so the line breaks inside the sentence rather than dropping
     the Menu button onto a line of its own and leaving a band of empty red. */
  .promo-left{flex:1 1 0;gap:8px;flex-wrap:nowrap;min-width:0}
  .promo-pill{flex:none;font-size:10px;padding:3px 8px}
  .promo-text{min-width:0;font-size:12px;line-height:1.3}
  .promo-actions{width:auto;margin-left:auto;flex:none}
  .promo-actions button{min-height:44px;padding:0 10px;font-size:11.5px}
}

/* Three or four stat cards sit in one row on a desk. In a pocket they stacked
   into 330px of scrolling and pushed the table they summarise below the fold.
   Two across restores them as peers, and an odd last card takes the whole row. */
@media (max-width:600px){
  .strip{grid-template-columns:repeat(2,1fr);gap:10px}
  .stat-card{padding:12px;gap:3px}
  .stat-card span{font-size:10px;letter-spacing:.1em}
  .stat-card b{font-size:20px}
  .stat-card small{font-size:11.5px;line-height:1.3}
  .strip > :last-child:nth-child(odd){grid-column:1/-1}
}

/* One label per width: the long words on a desk, the short ones in a pocket. */
.promo-narrow{display:none}
@media (max-width:600px),(max-height:560px){
  .promo-wide{display:none}
  .promo-narrow{display:inline}
}

/* ---------------------------------------------------------------- print */
@media print{
  :root{--bg:#FFFFFF;--surface:#FFFFFF;--surface2:#FFFFFF;--surface3:#F4F1EF;--line:#CFC6C1;--fg:#111111;--muted:#4A403C;--price:#111111;--brand:#111111;--brand-dark:#111111;--brand-text:#111111;--ok:#0F6B4F;--low:#8A5300;--out:#9B1C11;--card-shadow:none}
  body{background:#FFFFFF;color:#111111}
  .top,.promo,.tabs,.kds-link,.account-menu,.flt,.report-filters,.data-actions,.data-import,#themeBtn,.toast,.modal,.skip,.users-mast .go,.reports-view .users-mast a.go{display:none!important}
  .app,.wrap{max-width:none;margin:0;padding:0}
  .users-panel,.stat-card,.report-table tr,.usage-table tr,.trend{break-inside:avoid;box-shadow:none;border-color:#CFC6C1}
  .stat-card,.users-panel{background:#FFFFFF}
  .trend-bar{background:#F4F1EF}
  .trend-bar i{background:#111111}
  .report-table th,.usage-table th{color:#4A403C}
  .report-table td,.usage-table td{border-color:#E4DED9}
  .users-mast h2,.lbl{color:#111111}
  a{color:#111111;text-decoration:none}
  .reports-view::before{
    content:"Oishii Takoyaki — sales report";display:block;margin-bottom:8px;
    font-family:var(--font-display);font-size:16pt;
  }
  .report-table td.user-actions,.report-table th:last-child{display:none}
  @page{margin:12mm}
}

/* A checkbox is a control too: 18px of box in a 44px row is easy to hit with a
   mouse and hard with a thumb. */
.data-check input[type="checkbox"]{width:22px;height:22px;flex:none}
