/* ==========================================================================
   CafePOS — light design system.

   TWO COLOURS. Pinakexa blue #0007B0 and Pinakexa red #F20000, each opened out
   into a scale of tints and shades, over a neutral grey ground. Nothing else.

   With one hue for "good" and one for "wrong", the two states can never be
   confused at a glance across a counter, and the screen stops competing with
   the food for attention. It also happens to be the accessible choice: the
   red/green pairing this replaces is invisible to roughly one man in twelve.

   Blue carries everything positive or active — where you are, what is live,
   what was paid. Red carries everything that wants a person: late tickets,
   overdue bills, low stock, refunds. Weight separates the two red states:
   a tint means "look at this", a solid fill means "this is wrong".

   Two greens survive, and only two, both for reasons outside design:
   --veg is the FSSAI vegetarian mark, which is a legal symbol in India and
   cannot be recoloured, and the aggregator brand colours identify somebody
   else's company on the order queue.

   Light by default, because a counter screen sits under bright strip lighting
   all day and staff read it from a metre away. A dark set is available for the
   places that are not like that — a kitchen screen on a night shift, a
   manager's laptop in an office — and is chosen in Settings.

   The dark set redefines surfaces, lines and text and nothing else. The two
   brand hues stay the brand, lifted only far enough to carry white text on a
   dark ground: #0007B0 is almost black against #171A22 and would disappear.
   ========================================================================== */

:root {
  /* ---- blue: the brand, and everything good or active ------------------ */
  --brand:        #0007B0;   /* the Pinakexa mark; fills, active states      */
  --brand-700:    #000589;   /* pressed                                      */
  --brand-600:    #000A8F;
  --brand-500:    #1A22C7;   /* hover on a filled surface                    */
  --brand-400:    #4A52DC;   /* second chart series                          */
  --brand-300:    #8E93E8;   /* third chart series                           */
  --brand-200:    #C2C5F3;
  --brand-100:    #DEE0F9;
  --brand-050:    #EEEEFB;   /* tinted backgrounds, chips, quiet bars        */

  /* ---- red: the brand's second colour, and everything wrong ------------ */
  --red:          #F20000;   /* errors, refunds, voids, late                 */
  --red-700:      #B00000;   /* red text on a light tint, for contrast       */
  --red-600:      #D40000;
  --red-400:      #FF4D4D;
  --red-300:      #FF9494;
  --red-100:      #FFDCDC;
  --red-050:      #FEECEC;   /* "needs attention" ground                     */

  /* ---- the FSSAI marks. Not palette; food law. ------------------------- */
  --veg:          #12A150;
  --nonveg:       #B00000;

  /* surfaces */
  --page:         #F5F6FB;
  --surface:      #FFFFFF;
  --surface-2:    #F4F5F9;
  --surface-3:    #EBEDF4;
  --line:         #E8EAF1;
  --line-soft:    #F0F1F6;

  /* type */
  --text:         #12141C;
  --text-2:       #5A6274;
  --text-3:       #939BAC;

  --radius:       18px;
  --radius-sm:    12px;
  --radius-xs:    9px;
  /* Two shadows stacked: a tight one for the edge, a wide soft one for the
     lift. One shadow alone reads either hard or muddy. */
  --shadow:       0 1px 2px rgba(18, 20, 28, .04), 0 8px 26px rgba(18, 20, 28, .05);
  --shadow-sm:    0 1px 2px rgba(18, 20, 28, .05), 0 3px 10px rgba(18, 20, 28, .04);
  --shadow-lg:    0 2px 6px rgba(18, 20, 28, .06), 0 26px 60px rgba(18, 20, 28, .16);
  --shadow-pill:  0 6px 18px rgba(0, 7, 176, .30);

  --sidebar-w:    248px;
  /* Jost is an open licence revival of Futura — the geometric, minimal face
     asked for. Futura itself and Garet are both commercial, so a machine that
     happens to have either uses it and everyone else gets Jost, which was
     drawn from the same skeleton. */
  --font: "Jost", "Futura", "Garet", "Century Gothic", -apple-system, BlinkMacSystemFont,
          "Segoe UI", Roboto, Arial, sans-serif;
  --mono: ui-monospace, "SF Mono", "Cascadia Mono", Consolas, monospace;
}

/* ---- the dark set ------------------------------------------------------

   Written once and applied two ways: on [data-theme="dark"] when the shop has
   chosen dark, and under prefers-color-scheme when it has chosen to follow the
   device. The light set above stays the default, so anything this does not
   name keeps working.

   Only surfaces, lines, text and shadows move. The brand hues are lifted just
   far enough to carry white text on a dark ground and no further: the point of
   two colours is that a cashier can tell "good" from "wrong" across a counter,
   and a dark theme that quietly recolours them would break that. */

/* Chosen outright. */
:root[data-theme="dark"] {
  /* Blue, lifted. #0007B0 on #171A22 is very nearly black on black. */
  --brand:        #5B63E3;
  --brand-700:    #4249CE;
  --brand-600:    #4E56D8;
  --brand-500:    #6C74E9;
  --brand-400:    #848BEE;
  --brand-300:    #A4AAF3;
  --brand-200:    #C3C7F7;
  --brand-100:    #1F2450;
  --brand-050:    #191D3E;   /* tinted grounds go dark, not pale            */

  /* Red, lifted the same way. Still unmistakably the other colour.        */
  --red:          #FF5A5A;
  --red-700:      #FF8A8A;   /* red text on a dark tint wants to be lighter */
  --red-600:      #FF6B6B;
  --red-400:      #E24A4A;
  --red-300:      #8E3434;
  --red-100:      #4A1F22;
  --red-050:      #2C1619;

  /* The FSSAI marks are food law and do not move with a theme. They are
     redeclared only to lift the non-veg brown off a dark ground enough to
     be seen; the hues themselves are unchanged. */
  --veg:          #16B95C;
  --nonveg:       #E05252;

  --page:         #0E1016;
  --surface:      #171A22;
  --surface-2:    #1E222C;
  --surface-3:    #262B36;
  --line:         #2B303C;
  --line-soft:    #222733;

  --text:         #E9EBF1;
  --text-2:       #A7AFC1;
  --text-3:       #7B8497;

  /* On a dark ground a shadow is not a shadow: light does not fall that way.
     What reads as depth is a darker pool plus a faint lit edge. */
  --shadow:       0 1px 2px rgba(0, 0, 0, .45), 0 8px 26px rgba(0, 0, 0, .40);
  --shadow-sm:    0 1px 2px rgba(0, 0, 0, .40), 0 3px 10px rgba(0, 0, 0, .30);
  --shadow-lg:    0 2px 6px rgba(0, 0, 0, .50), 0 26px 60px rgba(0, 0, 0, .55);
  --shadow-pill:  0 6px 18px rgba(91, 99, 227, .35);
}

/* Chosen "follow the device", and the device says dark. */
@media (prefers-color-scheme: dark) {
  :root[data-theme="system"] {
    /* Blue, lifted. #0007B0 on #171A22 is very nearly black on black. */
    --brand:        #5B63E3;
    --brand-700:    #4249CE;
    --brand-600:    #4E56D8;
    --brand-500:    #6C74E9;
    --brand-400:    #848BEE;
    --brand-300:    #A4AAF3;
    --brand-200:    #C3C7F7;
    --brand-100:    #1F2450;
    --brand-050:    #191D3E;   /* tinted grounds go dark, not pale            */

    /* Red, lifted the same way. Still unmistakably the other colour.        */
    --red:          #FF5A5A;
    --red-700:      #FF8A8A;   /* red text on a dark tint wants to be lighter */
    --red-600:      #FF6B6B;
    --red-400:      #E24A4A;
    --red-300:      #8E3434;
    --red-100:      #4A1F22;
    --red-050:      #2C1619;

    /* The FSSAI marks are food law and do not move with a theme. They are
       redeclared only to lift the non-veg brown off a dark ground enough to
       be seen; the hues themselves are unchanged. */
    --veg:          #16B95C;
    --nonveg:       #E05252;

    --page:         #0E1016;
    --surface:      #171A22;
    --surface-2:    #1E222C;
    --surface-3:    #262B36;
    --line:         #2B303C;
    --line-soft:    #222733;

    --text:         #E9EBF1;
    --text-2:       #A7AFC1;
    --text-3:       #7B8497;

    /* On a dark ground a shadow is not a shadow: light does not fall that way.
       What reads as depth is a darker pool plus a faint lit edge. */
    --shadow:       0 1px 2px rgba(0, 0, 0, .45), 0 8px 26px rgba(0, 0, 0, .40);
    --shadow-sm:    0 1px 2px rgba(0, 0, 0, .40), 0 3px 10px rgba(0, 0, 0, .30);
    --shadow-lg:    0 2px 6px rgba(0, 0, 0, .50), 0 26px 60px rgba(0, 0, 0, .55);
    --shadow-pill:  0 6px 18px rgba(91, 99, 227, .35);
  }
}

/* A few places state a colour rather than take one, because they are the same
   colour in both themes. On dark they need saying again. */
:root[data-theme="dark"] .login-card input,
:root[data-theme="system"] .login-card input {
  background: var(--surface-2);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  min-height: 100%;
  background: var(--page);
  color: var(--text);
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--brand); text-decoration: none; }
a:hover { text-decoration: underline; }
h1, h2, h3, h4 { margin: 0 0 .45rem; font-weight: 700; letter-spacing: -.02em; color: var(--text); }
h1 { font-size: 1.75rem; }
h2 { font-size: 1.05rem; }
h3 { font-size: .92rem; }
p  { margin: 0 0 .7rem; }
small { font-size: .78rem; color: var(--text-2); }
code, .mono { font-family: var(--mono); font-size: .85em; }
hr { border: 0; border-top: 1px solid var(--line); margin: 1rem 0; }

/* ============================================================== app shell */

.app { display: flex; min-height: 100vh; }

.sidebar {
  width: var(--sidebar-w);
  flex: 0 0 var(--sidebar-w);
  background: var(--surface);
  border-right: 1px solid var(--line-soft);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

.brand {
  display: flex; align-items: center; gap: .6rem;
  padding: 1.15rem 1.1rem .9rem;
  font-weight: 800; font-size: 1.12rem; letter-spacing: -.03em;
}
.brand img { width: 34px; height: 34px; object-fit: contain; display: block; }
.brand .wordmark { line-height: 1.1; }
.brand .wordmark b { color: var(--text); }
.brand .wordmark i { color: var(--brand); font-style: normal; }
.brand .wordmark small {
  display: block; font-size: .62rem; font-weight: 600; letter-spacing: .04em;
  color: var(--text-3); text-transform: uppercase;
}

.nav { padding: .35rem .7rem; flex: 1; }
.nav-label {
  padding: 1.05rem .6rem .4rem;
  font-size: .66rem; color: var(--text-3); font-weight: 700;
  text-transform: uppercase; letter-spacing: .08em;
}
.nav a {
  display: flex; align-items: center; gap: .7rem;
  padding: .64rem .75rem; margin-bottom: 3px;
  border-radius: var(--radius-sm);
  color: var(--text-2); font-weight: 600; font-size: .875rem;
  text-decoration: none;
  transition: background .14s ease, color .14s ease;
}
.nav a:hover { background: var(--surface-2); color: var(--text); text-decoration: none; }
/* One saturated fill marks where you are: the brand blue itself, not a tint of
   it. Red is never used for navigation — it is kept for things that are wrong,
   and a menu item is not wrong. */
.nav a.active {
  background: var(--brand); color: #fff;
  box-shadow: var(--shadow-pill);
}
/* Every icon has a size, whether or not the place it lands thought to give it
   one. Each context below still sets its own, and those win; this is only so
   an icon in a spot nobody styled yet comes out the size of the text beside it
   instead of the browser's default 300 by 150. */
.ico { width: 18px; height: 18px; flex: none; }

.nav a.active .ico { opacity: 1; }
.nav a .ico {
  width: 20px; height: 20px; flex: none;
  display: grid; place-items: center;
  color: var(--text-3);
}
.nav a:hover .ico { color: var(--text-2); }
.nav a.active .ico { color: #fff; }
.icon-btn svg, .search-pill .dim svg { display: block; }
.search-pill .dim { display: grid; place-items: center; color: var(--text-3); }
.nav a .count {
  margin-left: auto; background: var(--brand-050); color: var(--brand);
  font-size: .7rem; font-weight: 800; min-width: 22px; text-align: center;
  padding: .05rem .4rem; border-radius: 999px;
}
.nav a.active .count { background: rgba(255,255,255,.22); color: #fff; }
.nav a .count.hot { background: var(--red); color: #fff; }

.side-profile {
  margin: .5rem .8rem 0; padding: 1rem .8rem;
  background: var(--surface-2); border-radius: var(--radius);
  text-align: center;
}
.side-profile .avatar {
  width: 52px; height: 52px; border-radius: 50%; margin: 0 auto .5rem;
  background: linear-gradient(135deg, var(--brand), #3b46d6);
  color: #fff; display: grid; place-items: center;
  font-weight: 800; font-size: 1.1rem; letter-spacing: -.02em;
}
.side-profile .nm { font-weight: 700; font-size: .9rem; }
.side-profile .rl { font-size: .74rem; color: var(--text-3); margin-bottom: .6rem; }
.side-foot { padding: .9rem 1.1rem; font-size: .7rem; color: var(--text-3); }

.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.topbar {
  display: flex; align-items: center; gap: .7rem;
  padding: .85rem 1.4rem;
  background: var(--page);
  position: sticky; top: 0; z-index: 30;
}
.icon-btn {
  width: 38px; height: 38px; flex: none;
  border-radius: 12px; border: 0; background: var(--surface);
  color: var(--text-2); font-size: 1rem; cursor: pointer;
  display: grid; place-items: center; position: relative;
  box-shadow: var(--shadow);
}
.icon-btn:hover { color: var(--text); }
.icon-btn .dot {
  position: absolute; top: 5px; right: 5px;
  min-width: 16px; height: 16px; padding: 0 3px;
  border-radius: 999px; background: var(--red); color: #fff;
  font-size: .62rem; font-weight: 800; display: grid; place-items: center;
}
.crumbs { display: flex; align-items: center; gap: .45rem; font-size: .875rem; color: var(--text-3); font-weight: 600; }
.crumbs .sep { opacity: .5; }
.crumbs .here { color: var(--text); }
.search-pill {
  display: flex; align-items: center; gap: .5rem;
  background: var(--surface); border-radius: 999px; padding: 0 1rem;
  height: 40px; min-width: 260px; box-shadow: var(--shadow);
}
.search-pill input { border: 0; background: none; box-shadow: none; padding: 0; height: 38px; min-height: 0; font-size: .875rem; }
.search-pill input:focus { box-shadow: none; }
.who { display: flex; align-items: center; gap: .55rem; }
.who .av {
  width: 38px; height: 38px; border-radius: 50%;
  background: linear-gradient(135deg, var(--brand), #3b46d6); color: #fff;
  display: grid; place-items: center; font-weight: 800; font-size: .85rem;
}
.who .txt { line-height: 1.15; }
.who strong { display: block; font-size: .85rem; }
.who small { font-size: .7rem; color: var(--text-3); }

.content { padding: .4rem 1.4rem 2rem; flex: 1; }
.page-head { display: flex; align-items: flex-start; gap: 1rem; margin-bottom: 1.1rem; flex-wrap: wrap; }
.page-head .spacer { flex: 1; }
.page-head p { color: var(--text-2); margin: .15rem 0 0; max-width: 62ch; }

/* ============================================================ components */

.card {
  background: var(--surface);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1.2rem 1.25rem;
}
.card + .card { margin-top: 1rem; }
.card-head {
  display: flex; align-items: center; gap: .6rem;
  margin: -1.15rem -1.15rem .9rem; padding: 1rem 1.15rem .8rem;
  border-bottom: 1px solid var(--line-soft);
}
.card-head h2, .card-head h3 { margin: 0; }
.card-head .spacer { flex: 1; }
.card.pad-0 { padding: 0; }
.card.pad-0 .card-head { margin: 0; }
.card.pad-0 > .table-wrap:last-child { border-radius: 0 0 var(--radius) var(--radius); overflow: hidden; }

.grid { display: grid; gap: 1rem; }
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.grid-auto { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
.span-2 { grid-column: span 2; }
@media (max-width: 1180px) {
  .grid-4 { grid-template-columns: repeat(2, 1fr); }
  .grid-3 { grid-template-columns: repeat(2, 1fr); }
  .span-2 { grid-column: span 2; }
}
@media (max-width: 760px) {
  .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; }
  .span-2 { grid-column: auto; }
  .sidebar { display: none; }
}

.row { display: flex; gap: .55rem; align-items: center; flex-wrap: wrap; }
.row.tight { gap: .3rem; }
.spacer { flex: 1; }
.muted { color: var(--text-2); }
.dim   { color: var(--text-3); }
.right { text-align: right; }
.center { text-align: center; }
.nowrap { white-space: nowrap; }
.hide { display: none !important; }

/* ---- stat tiles (reference: icon chip, delta, big number, colour bar) --- */

.stat {
  background: var(--surface); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: 1.05rem 1.15rem 1.2rem;
  display: flex; flex-direction: column; gap: .1rem;
  position: relative;
}
.stat .head { display: flex; align-items: center; gap: .55rem; }
.stat .chip-ico {
  width: 34px; height: 34px; border-radius: 11px; flex: none;
  display: grid; place-items: center; font-size: .95rem;
  background: var(--brand-050); color: var(--brand-600);
}

/* The one card on a screen that carries the headline number. Filled, so the
   eye lands on it first and every other card stays quiet. */
.stat.hero { background: linear-gradient(140deg, var(--brand-500), var(--brand-700)); color: #fff; }
.stat.hero .label, .stat.hero .value { color: #fff; }
.stat.hero .delta { color: rgba(255,255,255,.82); }
.stat.hero .chip-ico { background: rgba(255,255,255,.18); color: #fff; }
.stat .chip-ico.warn { background: var(--red-050);   color: var(--red-700); }
.stat .chip-ico.bad  { background: var(--red-050);   color: var(--red); }
.stat .chip-ico.ok   { background: var(--brand-050); color: var(--brand); }
.stat .label { font-size: .8rem; font-weight: 700; color: var(--text-2); }
.stat .delta { font-size: .75rem; font-weight: 600; color: var(--text-3); margin-top: .1rem; }
/* A movement worth noticing gets a tinted pill, the way a stock ticker does:
   the sign is legible from a metre away without reading the number. */
.stat .delta.up, .stat .delta.down {
  display: inline-flex; align-items: center; gap: .2rem; align-self: flex-start;
  padding: .12rem .45rem; border-radius: 999px; font-weight: 700;
}
.stat .delta.up { color: var(--brand); background: var(--brand-050); }
.stat .delta.down { color: var(--red); background: var(--red-050); }
.stat .value { font-size: 1.9rem; font-weight: 800; letter-spacing: -.04em; margin-top: .4rem; color: var(--text); }
.stat .value.sm { font-size: 1.3rem; }
.stat .bar { height: 6px; border-radius: 99px; background: var(--surface-3); margin-top: .7rem; overflow: hidden; }
.stat .bar > span { display: block; height: 100%; border-radius: 99px; background: var(--brand); }
/* Red is reserved for trouble. A bar that is merely showing a count should
   not look like an alarm, so the blue tints carry ordinary numbers and only
   a real warning gets the red. */
.stat .bar.ok > span   { background: var(--brand); }
.stat .bar.alt > span  { background: var(--brand-400); }
.stat .bar.soft > span { background: var(--brand-300); }
.stat .bar.warn > span { background: var(--red-400); }
.stat .bar.bad > span  { background: var(--red); }
/* The one tile per screen that carries the headline number. */
.stat.accent { box-shadow: 0 6px 24px rgba(61,75,240,.14); outline: 1px solid var(--brand-100); }
.stat.accent .value { color: var(--brand-700); }

/* ---- buttons ---------------------------------------------------------- */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  padding: .55rem .95rem; min-height: 40px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface); color: var(--text);
  font: inherit; font-weight: 700; font-size: .85rem;
  cursor: pointer; user-select: none;
  transition: background .12s, border-color .12s, box-shadow .12s, transform .04s;
}
.btn:hover { background: var(--surface-2); text-decoration: none; }
.btn:active { transform: translateY(1px); }
.btn:disabled, .btn[disabled] { opacity: .45; cursor: not-allowed; }
.btn-primary { background: var(--brand); border-color: var(--brand); color: #fff; box-shadow: var(--shadow-pill); }
.btn-primary:hover { background: var(--brand-500); border-color: var(--brand-500); }
/* Three intents, no colour names: primary is the action the screen is for, ok
   confirms something, danger destroys or refuses something. */
.btn-ok { background: var(--brand); border-color: var(--brand); color: #fff; }
.btn-ok:hover { background: var(--brand-500); border-color: var(--brand-500); }
.btn-danger { background: var(--red); border-color: var(--red); color: #fff; }
.btn-danger:hover { background: var(--red-600); border-color: var(--red-600); }
.btn-ghost { background: transparent; border-color: transparent; color: var(--text-2); box-shadow: none; }
.btn-ghost:hover { background: var(--surface-2); }
.btn-sm { min-height: 32px; padding: .28rem .6rem; font-size: .78rem; border-radius: var(--radius-xs); }
.btn-lg { min-height: 54px; padding: .8rem 1.4rem; font-size: .95rem; border-radius: 13px; }
.btn-block { width: 100%; }

/* ---- forms ------------------------------------------------------------ */

label { display: block; font-size: .78rem; font-weight: 700; color: var(--text-2); margin-bottom: .3rem; }
/* Written as "every input except the ones that are really controls" rather
   than as a list of the types we happened to think of.

   `<input>` with no type attribute is a text box — the browser says so — but
   it matches no `input[type=text]` selector, so it came out as an unstyled
   1996 text field next to properly dressed ones. There were sixty-three of
   them across the system, and the next hand-written form would have added
   another. Excluding the controls is a closed list; listing the text types is
   not. */
input:not([type=checkbox]):not([type=radio]):not([type=file]):not([type=range]):not([type=color]):not([type=submit]):not([type=button]):not([type=reset]):not([type=image]):not([type=hidden]),
select, textarea {
  width: 100%; padding: .55rem .8rem; min-height: 42px;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  font: inherit; font-size: .875rem;
}
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--brand);
  box-shadow: 0 0 0 3px rgba(0, 7, 176, .12);
}
input[type=checkbox], input[type=radio] { width: auto; min-height: 0; accent-color: var(--brand); }
/* A file picker is a button with a filename beside it; forcing a text-box
   shape on it only makes the browser's own control look broken. */
input[type=file] { font: inherit; font-size: .875rem; color: var(--text-2); }
.field { margin-bottom: .8rem; }
.field-error { color: var(--red); font-size: .78rem; margin-top: .2rem; }

/* ---- tables ----------------------------------------------------------- */

table { width: 100%; border-collapse: collapse; font-size: .86rem; }
thead th {
  text-align: left; padding: .7rem .9rem;
  font-size: .75rem; color: var(--text-3); font-weight: 600;
  border-bottom: 1px solid var(--line);
  position: sticky; top: 0; background: var(--surface); z-index: 1;
}
tbody td { padding: .7rem .9rem; border-bottom: 1px solid var(--line-soft); vertical-align: middle; }
tbody tr:hover { background: var(--surface-2); }
tbody tr:last-child td { border-bottom: 0; }
.table-wrap { overflow-x: auto; }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }

/* ---- badges & chips --------------------------------------------------- */

.badge {
  display: inline-block; padding: .18rem .5rem;
  border-radius: 7px; font-size: .7rem; font-weight: 700;
  white-space: nowrap; text-transform: capitalize;
}
.badge-mute  { background: var(--surface-3); color: var(--text-2); }
.badge-info  { background: var(--brand-050); color: var(--brand); }
/* Blue is good, red wants a person. A tint asks to be looked at; a solid
   fill says something is actually wrong. */
.badge-ok    { background: var(--brand-050); color: var(--brand); }
.badge-warn  { background: var(--red-050);   color: var(--red-700); }
.badge-bad   { background: var(--red);       color: #fff; }

.chip {
  display: inline-flex; align-items: center; gap: .38rem;
  padding: .26rem .65rem; border-radius: 999px;
  background: var(--surface-2); color: var(--text-2);
  font-size: .76rem; font-weight: 700;
}
.chip .swatch { width: 8px; height: 8px; border-radius: 50%; flex: none; }

.veg, .nonveg {
  display: inline-block; width: 12px; height: 12px; flex: none;
  border: 1.5px solid var(--veg); border-radius: 3px; position: relative;
}
.nonveg { border-color: var(--red); }
.veg::after, .nonveg::after { content: ''; position: absolute; inset: 2px; border-radius: 50%; background: var(--veg); }
.nonveg::after { background: var(--red); }

/* ---- alerts ----------------------------------------------------------- */

.alert { padding: .8rem 1rem; border-radius: var(--radius-sm); margin-bottom: .85rem; font-size: .86rem; }
.alert-success { background: var(--brand-050); color: var(--brand-700); }
.alert-error   { background: var(--red-050);   color: #A50B0B; }
.alert-info    { background: var(--brand-050); color: var(--brand); }
.alert-warning { background: var(--red-050); color: var(--red-700); }

.empty { padding: 2.4rem 1rem; text-align: center; color: var(--text-3); }
.empty .big { font-size: 2rem; opacity: .5; margin-bottom: .4rem; }

/* ---- period tabs ------------------------------------------------------ */

.period {
  display: inline-flex; gap: .2rem; border-bottom: 1px solid var(--line);
}
.period a, .period button {
  padding: .45rem .9rem; border: 0; background: none; cursor: pointer;
  font: inherit; font-size: .85rem; font-weight: 600; color: var(--text-3);
  border-bottom: 2px solid transparent; margin-bottom: -1px; text-decoration: none;
}
.period a.active, .period button.active { color: var(--brand); border-bottom-color: var(--brand); }

.tabs { display: flex; gap: .2rem; border-bottom: 1px solid var(--line); margin-bottom: 1.1rem; flex-wrap: wrap; }
.tabs a, .tabs button {
  padding: .55rem .9rem; border: 0; background: none; color: var(--text-3);
  font: inherit; font-weight: 600; font-size: .85rem; cursor: pointer;
  border-bottom: 2px solid transparent; margin-bottom: -1px; text-decoration: none;
}
.tabs a.active, .tabs button.active { color: var(--brand); border-bottom-color: var(--brand); }

/* ---- toast / modal ---------------------------------------------------- */

#toasts { position: fixed; right: 18px; bottom: 18px; z-index: 3000; display: flex; flex-direction: column; gap: .5rem; }
.toast {
  background: var(--surface); border-left: 4px solid var(--brand);
  border-radius: var(--radius-sm); padding: .7rem 1rem; box-shadow: var(--shadow-lg);
  min-width: 260px; max-width: 400px; font-size: .86rem; font-weight: 500;
  animation: slideIn .18s ease-out;
}
.toast.ok  { border-left-color: var(--brand); }
.toast.err { border-left-color: var(--red); }
@keyframes slideIn { from { opacity: 0; transform: translateX(16px); } to { opacity: 1; transform: none; } }

.modal-backdrop {
  position: fixed; inset: 0; background: rgba(21, 24, 31, .38);
  display: none; align-items: center; justify-content: center; z-index: 2000; padding: 1rem;
  backdrop-filter: blur(3px);
}
.modal-backdrop.open { display: flex; }
.modal {
  background: var(--surface); border-radius: var(--radius);
  box-shadow: var(--shadow-lg); width: 100%; max-width: 560px; max-height: 92vh;
  display: flex; flex-direction: column;
}
.modal.wide { max-width: 940px; }
.modal-head { padding: 1rem 1.15rem; border-bottom: 1px solid var(--line-soft); display: flex; align-items: center; gap: .6rem; }
.modal-head h2 { margin: 0; }
.modal-body { padding: 1.15rem; overflow-y: auto; }
.modal-foot { padding: .9rem 1.15rem; border-top: 1px solid var(--line-soft); display: flex; gap: .5rem; justify-content: flex-end; }
.modal-close { background: none; border: 0; color: var(--text-3); font-size: 1.5rem; cursor: pointer; line-height: 1; }

/* ---- charts ----------------------------------------------------------- */

.chart { width: 100%; display: block; overflow: visible; }
.chart .grid-line { stroke: var(--line); stroke-width: 1; stroke-dasharray: 3 4; }
.chart .axis { font-size: 10px; fill: var(--text-3); font-weight: 600; }
.chart .area  { fill: url(#areaFill); }
.chart .line  { fill: none; stroke: var(--brand); stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; }
.chart .pt    { fill: var(--brand); }
.chart .peak-pill { fill: var(--brand); }
.chart .peak-text { font-size: 11px; font-weight: 800; fill: #2A2000; }

.donut-wrap { display: flex; align-items: center; justify-content: center; position: relative; }
.donut-center { position: absolute; text-align: center; }
.donut-center .v { font-size: 1.5rem; font-weight: 800; letter-spacing: -.03em; }
.donut-center .l { font-size: .72rem; color: var(--text-3); font-weight: 600; }
.legend { display: flex; gap: 1rem; justify-content: center; flex-wrap: wrap; margin-top: .6rem; }
.legend span { display: inline-flex; align-items: center; gap: .35rem; font-size: .76rem; font-weight: 600; color: var(--text-2); }
.legend i { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }

.bar-row { display: flex; align-items: center; gap: .6rem; margin-bottom: .45rem; }
.bar-row .lbl { width: 132px; font-size: .8rem; color: var(--text-2); font-weight: 600; }
.bar-row .bar { flex: 1; height: 10px; background: var(--surface-3); border-radius: 99px; overflow: hidden; }
.bar-row .bar > span { display: block; height: 100%; border-radius: 99px; background: var(--brand); }
.bar-row .bar.warn > span { background: var(--red-400); }
.bar-row .val { width: 96px; text-align: right; font-size: .8rem; font-weight: 700; font-variant-numeric: tabular-nums; }

/* ---- mini bar chart --------------------------------------------------- */
/* Bars keep a sane width however few months there are: a single month
   stretched across the whole card reads as a filled box, not a chart. */
.mini-bars { display: flex; align-items: flex-end; gap: .5rem; height: 168px; margin-top: .7rem; }
.mini-bar { flex: 1 1 0; max-width: 54px; display: flex; flex-direction: column; align-items: center; height: 100%; }
.mini-bar .track {
  flex: 1; width: 100%; max-width: 34px; display: flex; align-items: flex-end;
  background: var(--surface-2); border-radius: 8px; overflow: hidden;
}
.mini-bar .fill {
  width: 100%; border-radius: 8px;
  background: linear-gradient(180deg, var(--brand-400), var(--brand));
  transition: height .25s ease;
}
.mini-bar small { font-size: .62rem; color: var(--text-3); margin-top: .35rem; white-space: nowrap; }
.mini-bar:hover .fill { background: linear-gradient(180deg, var(--brand), var(--brand-700)); }

/* ---- list rows (trending dishes / best employees) --------------------- */

.list-row { display: flex; align-items: center; gap: .75rem; padding: .55rem 0; border-bottom: 1px solid var(--line-soft); }
.list-row:last-child { border-bottom: 0; }
.list-row .thumb {
  width: 42px; height: 42px; border-radius: 50%; flex: none;
  background: var(--surface-2); display: grid; place-items: center; font-size: 1.2rem;
  overflow: hidden;
}
.list-row .thumb img { width: 100%; height: 100%; object-fit: cover; }
.list-row .nm { font-weight: 700; font-size: .88rem; }
.list-row .sub { font-size: .74rem; color: var(--text-3); }
.list-row .val { margin-left: auto; font-weight: 800; font-variant-numeric: tabular-nums; }

.rank {
  width: 24px; height: 24px; border-radius: 8px; flex: none;
  display: grid; place-items: center; font-size: .72rem; font-weight: 800;
  background: var(--surface-3); color: var(--text-2);
}
.rank.r1 { background: var(--brand); color: #fff; }
.rank.r2 { background: var(--brand-050); color: var(--brand); }
.rank.r3 { background: var(--red-050); color: var(--red); }

/* ---- category tiles & product cards (reference screen 2) -------------- */

.tile-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 1rem; }
.tile {
  background: var(--surface); border-radius: var(--radius); box-shadow: var(--shadow);
  padding: 1.3rem 1rem 1.1rem; text-align: center; cursor: pointer;
  border: 2px solid transparent; color: inherit; font: inherit; text-decoration: none;
  display: flex; flex-direction: column; align-items: center; gap: .7rem;
  transition: transform .12s, box-shadow .12s, background .12s;
}
.tile:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); text-decoration: none; }
.tile.active { background: var(--brand); color: #fff; box-shadow: var(--shadow-pill); }
.tile .emoji { font-size: 2.6rem; line-height: 1; }
.tile .nm { font-weight: 800; font-size: 1rem; }
.tile .ct { font-size: .74rem; color: var(--text-3); font-weight: 600; }
.tile.active .ct { color: #5A4400; }

.prod-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(178px, 1fr)); gap: .9rem; }
.prod-card {
  background: var(--surface); border-radius: var(--radius); box-shadow: var(--shadow);
  padding: 1rem .9rem; text-align: center; cursor: pointer; position: relative;
  border: 2px solid transparent; color: inherit; font: inherit;
  display: flex; flex-direction: column; align-items: center; gap: .35rem;
  transition: transform .1s, box-shadow .12s, border-color .12s;
}
.prod-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); border-color: var(--brand-300); }
.prod-card:active { transform: scale(.985); }
/* An icon tile rather than a bare glyph: it gives the card a consistent
   optical weight whatever the category, and it is the same shape a photograph
   will be once the cafe uploads one. */
.prod-card .thumb {
  width: 54px; height: 54px; border-radius: 15px;
  display: grid; place-items: center;
  background: var(--brand-050); color: var(--brand);
  transition: background .14s ease, color .14s ease;
}
.prod-card .thumb .ico { width: 27px; height: 27px; }
.prod-card:hover .thumb { background: var(--brand); color: #fff; }

/* A photograph fills the thumb rather than sitting in it, and loses the tinted
   ground behind it: a picture of a dish with a blue square peeking out from
   under one corner looks like a mistake. */
.prod-card .thumb:has(img) { background: none; }
.prod-card .thumb img {
  width: 100%; height: 100%; object-fit: cover;
  border-radius: inherit; display: block;
}
.prod-card:hover .thumb:has(img) { background: none; }
.prod-card .nm { font-weight: 700; font-size: .9rem; line-height: 1.25; }
.prod-card .meta { font-size: .72rem; color: var(--text-3); font-weight: 600; min-height: .95rem; }
.prod-card .price { margin-top: auto; font-weight: 800; font-size: 1.05rem; color: var(--brand); }
.prod-card .flag { position: absolute; top: 9px; left: 9px; }

/* Sizes and add-ons, asked for rather than forced.

   A tap on the tile adds the usual one; this opens the sheet. Kept small and
   in the corner because it is the rarer of the two actions, and given a
   generous invisible margin so a thumb finds it without a fingernail. */
.prod-card .opts {
  position: absolute; top: 6px; right: 6px;
  width: 26px; height: 26px; border-radius: 9px;
  display: grid; place-items: center;
  background: var(--surface-2); color: var(--text-3);
  transition: background .12s ease, color .12s ease;
}
.prod-card .opts::after {
  content: ''; position: absolute; inset: -8px;   /* the bit a thumb hits */
}
.prod-card .opts .ico { width: 15px; height: 15px; }
.prod-card:hover .opts { background: var(--brand-050); color: var(--brand); }
.prod-card .opts:hover { background: var(--brand); color: #fff; }
.prod-card .opts:active { transform: scale(.9); }
.prod-card.out { opacity: .45; }

/* ---- the photo cell on the menu screen -------------------------------- */

.photo-cell {
  width: 56px; height: 56px; padding: 0; flex: none;
  border: 1px dashed var(--line); border-radius: 12px;
  background: var(--surface-2); color: var(--text-3);
  display: grid; place-items: center; overflow: hidden; cursor: pointer;
}
.photo-cell.has { border-style: solid; border-color: var(--line-soft); }
.photo-cell:hover { border-color: var(--brand); color: var(--brand); }
.photo-cell img { width: 100%; height: 100%; object-fit: cover; display: block; }
.photo-cell.busy { opacity: .5; pointer-events: none; }
.photo-cell .ico { width: 20px; height: 20px; }
.prod-card.out::after {
  content: '86'; position: absolute; top: 8px; right: 8px;
  background: var(--red); color: #fff; font-size: .62rem; font-weight: 800;
  padding: .1rem .35rem; border-radius: 6px;
}

/* ============================================================ POS screen */

.pos { display: grid; grid-template-columns: 176px 1fr 392px; height: 100vh; overflow: hidden; background: var(--page); }
@media (max-width: 1320px) { .pos { grid-template-columns: 150px 1fr 350px; } }
@media (max-width: 1000px)  { .pos { grid-template-columns: 1fr; grid-template-rows: auto 1fr auto; height: auto; } }

.pos-cats { background: var(--surface); border-right: 1px solid var(--line); overflow-y: auto; padding: .7rem .6rem; }
.pos-cat {
  display: flex; align-items: center; gap: .6rem;
  display: block; width: 100%; text-align: left;
  padding: .65rem .75rem; margin-bottom: .35rem;
  background: var(--surface-2); border: 0;
  border-radius: var(--radius-sm); color: var(--text-2);
  font: inherit; font-weight: 700; font-size: .82rem; cursor: pointer;
}
.pos-cat:hover { background: var(--surface-3); color: var(--text); }
.pos-cat.active { background: var(--brand); color: #fff; box-shadow: var(--shadow-pill); }
.pos-cat small { display: block; font-weight: 600; font-size: .68rem; opacity: .7; }

.pos-center { display: flex; flex-direction: column; overflow: hidden; }
.pos-toolbar {
  display: flex; gap: .55rem; align-items: center; flex-wrap: wrap;
  padding: .75rem .9rem; background: var(--surface); border-bottom: 1px solid var(--line);
}
.pos-search { flex: 1; min-width: 170px; }
.pos-items { flex: 1; overflow-y: auto; padding: .9rem; }

.pos-cart { background: var(--surface); border-left: 1px solid var(--line); display: flex; flex-direction: column; overflow: hidden; }
.cart-head { padding: .8rem .9rem; border-bottom: 1px solid var(--line-soft); }
.cart-type { display: grid; grid-template-columns: repeat(3, 1fr); gap: .35rem; margin-bottom: .6rem; }
.cart-type button {
  padding: .5rem; border: 0; background: var(--surface-2);
  color: var(--text-2); border-radius: var(--radius-sm);
  font: inherit; font-size: .78rem; font-weight: 700; cursor: pointer;
}
.cart-type button.active { background: var(--brand); color: #fff; box-shadow: var(--shadow-pill); }

.cart-lines { flex: 1; overflow-y: auto; padding: .55rem .7rem; background: var(--page); }
.cart-line { background: var(--surface); border-radius: var(--radius-sm); padding: .6rem .7rem; margin-bottom: .45rem; box-shadow: var(--shadow); }
.cart-line .top { display: flex; gap: .5rem; align-items: flex-start; }
.cart-line .nm { flex: 1; font-weight: 700; font-size: .85rem; line-height: 1.3; }
.cart-line .amt { font-weight: 800; font-variant-numeric: tabular-nums; font-size: .86rem; }
.cart-line .sub  { font-size: .73rem; color: var(--text-3); margin-top: .1rem; }
.cart-line .mods { font-size: .73rem; color: var(--brand-500); font-weight: 600; margin-top: .12rem; }
.cart-line .note { font-size: .73rem; color: var(--brand); margin-top: .12rem; font-style: italic; }
.cart-line .fired { font-size: .65rem; color: var(--brand); font-weight: 800; text-transform: uppercase; }

/* A tap that raised a quantity must read as clearly as one that added a line —
   otherwise the cashier taps again thinking nothing happened. */
.cart-line.bump  { animation: cartBump .5s ease; }
.cart-line.added { animation: cartAdd .45s ease; }
@keyframes cartBump {
  0%   { transform: scale(1);     box-shadow: var(--shadow); }
  35%  { transform: scale(1.035); box-shadow: 0 0 0 3px var(--brand-300); }
  100% { transform: scale(1);     box-shadow: var(--shadow); }
}
@keyframes cartAdd {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .cart-line.bump, .cart-line.added { animation: none; }
}

.qty { display: inline-flex; align-items: center; gap: .3rem; margin-top: .4rem; }
.qty button {
  width: 28px; height: 28px; border-radius: 8px;
  border: 1px solid var(--line); background: var(--surface-2); color: var(--text);
  font: inherit; font-weight: 800; cursor: pointer; line-height: 1;
}
.qty button:hover { background: var(--surface-3); }
.qty span { min-width: 26px; text-align: center; font-weight: 800; font-variant-numeric: tabular-nums; }

.cart-totals { padding: .75rem .9rem; border-top: 1px solid var(--line-soft); background: var(--surface); font-size: .85rem; }
.cart-totals .ln { display: flex; justify-content: space-between; padding: .12rem 0; color: var(--text-2); }
.cart-totals .ln span:last-child { font-variant-numeric: tabular-nums; color: var(--text); font-weight: 600; }
.cart-totals .ln.total {
  margin-top: .45rem; padding-top: .5rem; border-top: 1px dashed var(--line);
  font-size: 1.25rem; font-weight: 800; color: var(--text);
}
.cart-actions { padding: .7rem .8rem .9rem; display: grid; grid-template-columns: 1fr 1fr; gap: .45rem; }
.cart-actions .wide { grid-column: 1 / -1; }

.mod-group { border: 1px solid var(--line); border-radius: var(--radius-sm); padding: .75rem .85rem; margin-bottom: .7rem; }
.mod-group h4 { margin: 0 0 .5rem; font-size: .84rem; display: flex; gap: .4rem; align-items: center; }
.mod-opts { display: flex; flex-wrap: wrap; gap: .4rem; }
.mod-opt {
  padding: .4rem .75rem; border: 1px solid var(--line); border-radius: 999px;
  background: var(--surface); font: inherit; font-size: .8rem; font-weight: 700;
  color: var(--text-2); cursor: pointer; display: inline-flex; gap: .3rem; align-items: center;
}
.mod-opt:hover { border-color: var(--brand-300); }
.mod-opt.on { background: var(--brand); border-color: var(--brand); color: #fff; }
.mod-opt:disabled { opacity: .4; cursor: not-allowed; }
.mod-opt .px { font-size: .74rem; opacity: .85; }

/* --- cash pad: notes and coins the drawer holds ------------------------- */
.denoms { display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: .45rem; }
.denom {
  position: relative; display: flex; flex-direction: column; align-items: center; gap: .1rem;
  padding: .5rem .3rem; min-height: 56px; cursor: pointer;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--surface); font: inherit; color: var(--text);
}
.denom:hover  { border-color: var(--brand); background: var(--brand-050); }
.denom:active { transform: translateY(1px); }
.denom .v { font-size: 1rem; font-weight: 800; letter-spacing: -.02em; }
.denom .k { font-size: .66rem; text-transform: uppercase; letter-spacing: .06em; color: var(--text-3); }
.denom.is-coin { border-radius: 999px; }
.denom .n {
  position: absolute; top: -7px; right: -7px; min-width: 22px; padding: 0 .3rem;
  border-radius: 999px; background: var(--brand); color: #fff;
  font-size: .72rem; font-weight: 800; line-height: 22px; text-align: center;
}
.denom .n:empty { display: none; }

.cash-tally { margin-top: .5rem; font-size: .8rem; color: var(--text-2); }

.cash-parts { display: flex; flex-wrap: wrap; gap: .35rem; margin-top: .45rem; }
.cash-parts span {
  padding: .18rem .5rem; border-radius: var(--radius-xs);
  background: var(--surface); border: 1px solid var(--line);
  font-size: .8rem; font-weight: 700; color: var(--text);
}
.cash-parts span.is-coin { border-radius: 999px; }

/* --- modules switchboard ------------------------------------------------ */
.module-row {
  display: flex; gap: .7rem; align-items: flex-start; cursor: pointer;
  padding: .75rem .85rem; border: 1px solid var(--line); border-radius: var(--radius-sm);
  margin-bottom: .5rem; background: var(--surface);
}
.module-row:hover { border-color: var(--brand); background: var(--brand-050); }
.module-row input { margin-top: .2rem; width: 18px; height: 18px; flex: none; accent-color: var(--brand); }
.module-row > span { display: flex; flex-direction: column; gap: .15rem; }
.module-row strong { font-size: .92rem; }
.module-row small { font-size: .78rem; color: var(--text-2); }
.module-row small.dim { color: var(--text-3); }
.module-row .chip {
  align-self: flex-start; margin: .1rem 0; padding: .05rem .45rem;
  font-size: .68rem; font-weight: 800; text-transform: uppercase; letter-spacing: .06em;
  background: var(--surface-2); color: var(--text-3);
}
.module-row .chip.on { background: var(--brand-050); color: var(--brand); }
.module-row.is-blocked { opacity: .68; cursor: not-allowed; background: var(--surface-2); }
.module-row.is-blocked:hover { border-color: var(--line); background: var(--surface-2); }
.module-row small.needs { color: var(--red-700); font-weight: 700; }

/* ============================================================ KDS screen */

.kds { min-height: 100vh; background: var(--page); display: flex; flex-direction: column; }
.kds-bar {
  display: flex; align-items: center; gap: .55rem; flex-wrap: wrap;
  padding: .8rem 1.1rem; background: var(--surface); border-bottom: 1px solid var(--line);
}
.kds-bar .station {
  padding: .45rem .9rem; border-radius: var(--radius-sm);
  background: var(--surface-2); color: var(--text-2);
  font-weight: 700; font-size: .84rem; cursor: pointer; text-decoration: none;
}
.kds-bar .station.active { background: var(--brand); color: #fff; box-shadow: var(--shadow-pill); }
.kds-clock { font-family: var(--mono); font-size: 1.05rem; font-weight: 700; }

.kds-board { flex: 1; padding: .9rem 1.1rem; display: grid; grid-template-columns: repeat(auto-fill, minmax(290px, 1fr)); gap: .9rem; align-content: start; }

/* ---- the kitchen board -------------------------------------------------

   Tickets of wildly different heights — a flat white is one line, a family
   order is fifteen — so they are packed in columns rather than laid on a
   grid. A grid row is as tall as its tallest card, which on a real service
   means half the screen is whitespace and the cook is scrolling.

   The colour on the head says what the ticket is waiting for, and it is the
   first thing visible from across a kitchen. Late overrides everything: a
   ticket past its station's time is red whatever else is true of it. */

.kot-tabs {
  display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
  padding: .7rem 1.1rem 0;
}
.kot-tab {
  border: 1px solid var(--line); background: var(--surface); color: var(--text-2);
  font: inherit; font-weight: 700; font-size: .82rem; cursor: pointer;
  padding: .45rem .95rem; border-radius: 99px;
  display: inline-flex; align-items: center; gap: .45rem;
}
.kot-tab .n {
  font-family: var(--mono); font-size: .76rem;
  background: var(--surface-2); color: var(--text-3);
  border-radius: 99px; padding: 0 .4rem; min-width: 1.35rem; text-align: center;
}
.kot-tab.on { background: var(--brand); border-color: var(--brand); color: #fff; box-shadow: var(--shadow-pill); }
.kot-tab.on .n { background: rgba(255,255,255,.22); color: #fff; }
.kot-tab.late.on { background: var(--red); border-color: var(--red); }

.kot-board {
  flex: 1; min-height: 0; overflow-y: auto;
  padding: .9rem 1.1rem 1.4rem;
  columns: 4 300px; column-gap: .9rem;
}
.kot-board .empty { color: var(--text-3); padding: 3rem 1rem; text-align: center; }

.kot {
  break-inside: avoid; -webkit-column-break-inside: avoid;
  display: inline-block; width: 100%; margin: 0 0 .9rem;
  background: var(--surface); border-radius: var(--radius);
  box-shadow: var(--shadow); overflow: hidden;
  vertical-align: top;
}

.kot-head {
  display: flex; align-items: center; gap: .5rem;
  padding: .6rem .75rem; color: #fff;
  background: var(--kot-colour, #8A6242);
}
.kot-head .no { font-weight: 800; font-size: .98rem; letter-spacing: -.01em; }
.kot-head .spacer { flex: 1; }
.kot-chip {
  display: inline-flex; align-items: center; gap: .3rem;
  background: rgba(255,255,255,.2); border-radius: 99px;
  padding: .18rem .5rem; font-size: .74rem; font-weight: 700;
  font-family: var(--mono);
}
.kot-chip .ico { width: 13px; height: 13px; }
.kot-seat {
  min-width: 2rem; height: 2rem; padding: 0 .45rem; border-radius: 99px;
  background: #F5A524; color: #3A2A05;
  display: inline-flex; align-items: center; justify-content: center;
  font-weight: 800; font-size: .8rem; flex: none;
}
.kot-where { width: 26px; height: 26px; opacity: .85; flex: none; }

/* What each state looks like. Tan for not started, blue for on, green for
   plated, red for late — and red wins, because a late ticket being any other
   colour is the one thing this screen must never do. */
.kot.is-new      { --kot-colour: #8A6242; }
.kot.is-cooking  { --kot-colour: #0007B0; }
.kot.is-ready    { --kot-colour: #0E7A45; }
.kot.is-late     { --kot-colour: #F20000; }
.kot.is-late { animation: pulse 1.8s ease-in-out infinite; }
.kot.is-priority { outline: 2px solid rgba(242,0,0,.35); outline-offset: -1px; }

.kot-lines { padding: .2rem .75rem .4rem; }
.kot-line {
  display: flex; align-items: flex-start; gap: .55rem;
  padding: .55rem 0; border-bottom: 1px solid var(--line-soft);
}
.kot-line:last-child { border-bottom: 0; }
.kot-line-body { flex: 1; min-width: 0; }
.kot-line .nm { font-weight: 700; font-size: .9rem; line-height: 1.25; }
.kot-line .qty { font-weight: 800; font-size: .84rem; color: var(--text-3); font-family: var(--mono); flex: none; }
.kot-attr { font-size: .74rem; color: var(--text-3); line-height: 1.4; margin-top: .15rem; }
.kot-attr b { font-weight: 700; color: var(--text-2); }
.kot-note { font-size: .76rem; color: var(--red); font-weight: 600; margin-top: .15rem; }

/* The tick. Big enough for a thumb with a cloth in the other hand. */
.kot-tick {
  width: 22px; height: 22px; flex: none; margin-top: .1rem;
  border: 1.8px solid var(--line); border-radius: 6px;
  background: var(--surface); cursor: pointer;
  display: grid; place-items: center; padding: 0;
}
.kot-tick .ico { width: 14px; height: 14px; color: #fff; opacity: 0; }
.kot-tick.on { background: var(--brand); border-color: var(--brand); }
.kot-tick.on .ico { opacity: 1; }
.kot-line.done .nm { text-decoration: line-through; color: var(--text-3); }

.kot-foot { display: flex; gap: .45rem; padding: .6rem .75rem .75rem; }
.kot-foot .icon-btn {
  width: 40px; height: 40px; flex: none; border-radius: var(--radius-sm);
  border: 1px solid var(--line); background: var(--surface); color: var(--text-2);
}
.kot-go {
  flex: 1; border: 0; cursor: pointer; border-radius: var(--radius-sm);
  min-height: 40px; font: inherit; font-weight: 800; font-size: .86rem;
  display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  background: var(--kot-colour, #8A6242); color: #fff;
}
.kot-go .ico { width: 16px; height: 16px; }
.kot-go.finish { background: #17B26A; }
.kot-go:active { transform: translateY(1px); }
.kot-go.ghost { background: var(--surface-2); color: var(--text-2); border: 1px solid var(--line); }

.kot-progress { height: 3px; background: rgba(255,255,255,.25); }
.kot-progress > span { display: block; height: 100%; background: rgba(255,255,255,.85); }

.ticket {
  background: var(--surface); border-radius: var(--radius); box-shadow: var(--shadow);
  border-top: 5px solid var(--brand); display: flex; flex-direction: column; overflow: hidden;
}
.ticket.warn { border-top-color: var(--red-400); }
.ticket.late { border-top-color: var(--red); animation: pulse 1.8s ease-in-out infinite; }
.ticket.priority { outline: 2px solid rgba(242,0,0,.35); outline-offset: -1px; }
@keyframes pulse { 0%,100% { box-shadow: var(--shadow); } 50% { box-shadow: 0 0 0 6px rgba(242,0,0,.10); } }

.ticket-head { padding: .65rem .8rem; border-bottom: 1px solid var(--line-soft); }
.ticket-head .l1 { display: flex; align-items: baseline; gap: .5rem; }
.ticket-head .no { font-weight: 800; font-size: 1rem; }
.ticket-head .age { margin-left: auto; font-family: var(--mono); font-weight: 800; font-size: 1rem; }
.ticket.late .age { color: var(--red); }
.ticket-head .l2 { display: flex; gap: .35rem; align-items: center; margin-top: .25rem; font-size: .74rem; color: var(--text-3); flex-wrap: wrap; font-weight: 600; }

.ticket-items { padding: .6rem .8rem; flex: 1; }
.ticket-item { padding: .35rem 0; border-bottom: 1px dashed var(--line); }
.ticket-item:last-child { border-bottom: 0; }
.ticket-item .line { display: flex; gap: .5rem; font-size: .95rem; font-weight: 700; }
.ticket-item .q { color: var(--brand); font-weight: 800; min-width: 28px; }
.ticket-item .mod { font-size: .79rem; color: var(--brand-500); padding-left: 28px; font-weight: 600; }
.ticket-item .nt  { font-size: .79rem; color: var(--brand); padding-left: 28px; font-style: italic; }

.ticket-foot { display: grid; grid-template-columns: 1fr 1fr; gap: 1px; background: var(--line); }
.ticket-foot button {
  padding: .7rem; border: 0; background: var(--surface); color: var(--text-2);
  font: inherit; font-weight: 700; font-size: .83rem; cursor: pointer;
}
.ticket-foot button:hover { background: var(--surface-2); }
.ticket-foot button.go { background: var(--brand); color: #fff; }
.ticket-foot button.go:hover { background: #0E8944; }
.ticket-foot button.wide { grid-column: 1 / -1; }

.progress { height: 5px; background: var(--surface-3); border-radius: 99px; overflow: hidden; }
.progress > span { display: block; height: 100%; background: var(--brand); border-radius: 99px; }
.progress.warn > span { background: var(--red-400); }
.progress.late > span { background: var(--red); }

/* ========================================================== floor plan */

.floor { position: relative; background: var(--surface-2); border-radius: var(--radius); padding: 1rem; min-height: 340px; overflow: auto; }
.table-box {
  position: absolute; width: 104px; min-height: 80px;
  border-radius: var(--radius-sm); border: 2px solid var(--line);
  background: var(--surface); padding: .5rem;
  display: flex; flex-direction: column; gap: .05rem;
  cursor: pointer; font-size: .76rem; box-shadow: var(--shadow);
}
.table-box:hover { border-color: var(--brand-300); }
.table-box .tn { font-weight: 800; font-size: .98rem; }
.table-box.available { border-color: rgba(18,161,80,.45); }
.table-box.occupied  { border-color: rgba(242,0,0,.5); background: var(--red-050); }
.table-box.reserved  { border-color: var(--brand-300); background: var(--brand-050); }
.table-box.cleaning  { border-color: var(--red-300); background: var(--red-050); }
.table-box.round { border-radius: 50%; }


/* ---- POS: the redesigned bits ---------------------------------------- */

.pos-cat .ico { width: 20px; height: 20px; flex: none; color: var(--text-3); }
.pos-cat.active .ico { color: #fff; }
.pos-cat span { min-width: 0; text-align: left; }
.pos-cat strong { display: block; font-size: .84rem; font-weight: 700; line-height: 1.2; }
.pos-cats-foot { margin-top: 1rem; padding: .5rem; display: grid; gap: .35rem; }
.pos-cats-foot .btn { justify-content: flex-start; gap: .5rem; }
.pos-cats-foot .ico { width: 17px; height: 17px; }

/* Search reads as one object with the magnifier inside it, rather than an
   icon sitting next to a box. */
.pos-search-wrap {
  flex: 1; min-width: 190px; display: flex; align-items: center; gap: .55rem;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 999px; padding: 0 1rem; height: 42px;
}
.pos-search-wrap:focus-within { border-color: var(--brand-300); box-shadow: 0 0 0 3px rgba(0,7,176,.10); }
.pos-search-wrap .ico { width: 18px; height: 18px; color: var(--text-3); flex: none; }
.pos-search { border: 0; background: none; box-shadow: none; padding: 0; height: 40px; min-height: 0; }
.pos-search:focus { box-shadow: none; }

.pos-toolbar .btn { gap: .4rem; }
.pos-toolbar .btn .ico, .cart-actions .btn .ico, .cart-type .ico { width: 16px; height: 16px; }

/* Sound toggle: the icon swaps to a crossed-out speaker when muted, so the
   state is legible without reading anything. */
[data-sound-toggle] { color: var(--brand); }
[data-sound-toggle].is-muted { color: var(--text-3); }
[data-sound-toggle] .ico { width: 18px; height: 18px; }

.cart-type button { display: inline-flex; align-items: center; justify-content: center; gap: .35rem; }
.cart-order-line { display: flex; align-items: center; gap: .4rem; margin-top: .45rem; }
.cart-order-line strong { font-size: .8rem; font-weight: 700; color: var(--text-2); }

/* Where the order is going, once the cashier has said. */
.delivery-bar {
  display: flex; align-items: center; gap: .55rem;
  margin-top: .45rem; padding: .5rem .6rem;
  background: var(--brand-050); border-radius: var(--radius-sm);
}
.delivery-bar .ico { width: 18px; height: 18px; color: var(--brand); flex: none; }
.delivery-bar strong { display: block; font-size: .8rem; line-height: 1.2; }
.delivery-bar small { display: block; color: var(--text-2); font-size: .72rem; line-height: 1.3; }

/* The "who is delivering this" sheet, and any other pick-one-of-these. */
.pick-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: .6rem; }
.pick-card {
  display: flex; flex-direction: column; align-items: flex-start; gap: .3rem;
  padding: .9rem; min-height: 116px; text-align: left; cursor: pointer;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-sm); font: inherit; color: inherit;
}
.pick-card:hover { border-color: var(--brand); background: var(--brand-050); }
.pick-card .ico { width: 24px; height: 24px; color: var(--brand); }
.pick-card strong { font-size: .92rem; }
.pick-card small { color: var(--text-2); font-size: .74rem; line-height: 1.35; }
.swatch.lg { width: 22px; height: 22px; border-radius: 7px; }

/* The pay button carries two things — what it does and what it costs — so
   they get opposite ends of it rather than running together. */
.pay-btn { display: flex; align-items: center; justify-content: space-between; gap: .8rem; }

.cart-lines .empty .ico.big { width: 40px; height: 40px; color: var(--text-3); margin-bottom: .5rem; }
.cart-line .qty button .ico { width: 15px; height: 15px; }


/* ---- the pass (waiter screen) ---------------------------------------- */

/* The same light ground as the KDS beside it — a dark board on one screen and
   a light one on the next reads as two different products. What changes is the
   layout, because the jobs are different: the chef reads a queue in order, the
   waiter picks one card out of several at arm's length while holding a tray.
   So everything here is bigger and there is exactly one button per card. */

.kds-foot {
  padding: .8rem .9rem; border-top: 1px solid var(--line);
  color: var(--text-2); font-size: .84rem; text-align: center; background: var(--surface);
}

.kds-bar .late-chip.is-late {
  background: var(--red); color: #fff;
  animation: latepulse 1.4s ease-in-out infinite;
}
.kds-bar .late-chip.is-late .swatch { background: #fff; }
@keyframes latepulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(242, 0, 0, .50); }
  50%      { box-shadow: 0 0 0 7px rgba(242, 0, 0, 0); }
}
.kds-bar .ico { width: 17px; height: 17px; }

/* The pass shares the kitchen's card, so what is left here is the board
   around it and the lock screen, which the kitchen has no equivalent of.
   The board itself is .kot-board; this only widens the columns, because a
   server is reading it from further away than a cook is. */
.pass-board { columns: 3 340px; }

.pass-card {
  background: var(--surface); border-radius: var(--radius);
  box-shadow: var(--shadow); overflow: hidden;
  border-top: 5px solid var(--brand);
  display: flex; flex-direction: column;
}
/* Food has been under the lamp a while, then too long. The card says so before
   a guest does. */
.pass-card.waiting { border-top-color: var(--red-300); }
.pass-card.cold    { border-top-color: var(--red); }
.pass-card.cold .waited { color: var(--red); }

.pass-card header {
  display: flex; align-items: baseline; gap: .55rem;
  padding: .9rem 1rem .45rem;
}
/* The token is what a waiter shouts across the room, so it is the biggest
   thing on the card by a distance. */
.pass-card .token { font-size: 1.9rem; font-weight: 800; letter-spacing: -.035em; line-height: 1; }
.pass-card .where { font-size: .95rem; font-weight: 700; color: var(--text-2); text-transform: capitalize; }
.pass-card .waited {
  margin-left: auto; font-family: var(--mono); font-size: .92rem;
  font-weight: 700; color: var(--text-3);
}

.pass-card .what { padding: 0 1rem .75rem; }
.pass-card .what div { font-size: 1rem; font-weight: 600; line-height: 1.5; }
.pass-card .what .q { color: var(--brand); font-weight: 800; margin-right: .25rem; }

.pass-card footer {
  margin-top: auto; padding: .7rem 1rem 1rem;
  display: flex; align-items: center; gap: .7rem;
  border-top: 1px solid var(--line-soft);
}
.pass-card footer small { color: var(--text-3); font-size: .72rem; }
/* One big button. A waiter taps this with a thumb, holding a tray in the other
   hand, without looking too closely. */
.pass-card footer .btn {
  margin-left: auto; min-width: 152px; gap: .4rem;
  font-size: .95rem; font-weight: 800;
}
.pass-card footer .btn .ico { width: 18px; height: 18px; }

/* Putting one back lives down here, away from a hurried thumb. */
.pass-undo { padding: .8rem 1.1rem 1rem; border-top: 1px solid var(--line); background: var(--surface); }
.pass-undo-row { display: flex; gap: .45rem; flex-wrap: wrap; }
.pass-undo-chip {
  display: inline-flex; align-items: center; gap: .4rem;
  background: var(--surface-2); color: var(--text-2); border: 0; cursor: pointer;
  font: inherit; font-size: .82rem; font-weight: 700;
  padding: .45rem .75rem; border-radius: 999px;
}
.pass-undo-chip:hover { background: var(--brand-050); color: var(--brand); }
.pass-undo-chip .ico { width: 15px; height: 15px; }
.pass-undo-chip small { color: var(--text-3); font-weight: 600; }

/* KDS ticket buttons carry icons now. */
.ticket-foot button { display: inline-flex; align-items: center; justify-content: center; gap: .35rem; }
.ticket-foot .ico { width: 16px; height: 16px; }


/* ---- the pass: who is on it ------------------------------------------- */

.on-duty {
  display: inline-flex; align-items: center; gap: .5rem;
  background: var(--brand-050); border: 1px solid var(--brand-100);
  border-radius: 999px; padding: .3rem .85rem .3rem .6rem;
  font: inherit; color: var(--brand); cursor: pointer; text-align: left;
}
.on-duty:hover { background: var(--brand-100); }
.on-duty .ico { width: 18px; height: 18px; flex: none; }
.on-duty strong { display: block; font-size: .82rem; line-height: 1.15; }
.on-duty small { display: block; font-size: .68rem; color: var(--text-2); line-height: 1.15; }

/* The lock. It covers the board rather than replacing it: a server walking up
   should see there is food waiting before they have typed anything. */
.pass-lock {
  position: fixed; inset: 0; z-index: 900;
  display: grid; place-items: center; padding: 1.25rem;
  /* Light enough to read the board through. The lock is there to ask who is
     carrying, not to hide the food — a server walking up should already be able
     to see there are three trays waiting before they touch anything. */
  background: rgba(12, 16, 32, .30);
  backdrop-filter: blur(2.5px) saturate(1.1);
  -webkit-backdrop-filter: blur(2.5px) saturate(1.1);
}
.pass-lock[hidden] { display: none; }
.pass-lock-card {
  width: 100%; max-width: 360px; text-align: center;
  background: var(--surface); border-radius: 24px; padding: 1.7rem 1.6rem 1.5rem;
  box-shadow: 0 30px 80px rgba(3, 6, 20, .45);
}
.pass-lock-card .ico.big { width: 38px; height: 38px; color: var(--brand); }
.pass-lock-card h2 { margin: .6rem 0 .2rem; font-size: 1.12rem; }
.pass-lock-card .muted { font-size: .85rem; margin-bottom: .9rem; }
.pass-lock-card .pin-pad .btn { min-height: 56px; font-size: 1.2rem; }
.pass-lock-card .pin-pad .ico { width: 20px; height: 20px; }
.pin-msg { min-height: 1.2rem; color: var(--red); font-size: .82rem; font-weight: 700; }

/* ======================================================== login screen */

/* Glassmorphism, done the way it actually works rather than by turning the
   opacity down: a real photograph behind, a heavy blur through a translucent
   pane, a bright hairline along the top-left edge where light would catch a
   real sheet of glass, and a shadow underneath deep enough to lift it off the
   picture. Take away any one of those four and it stops looking like glass and
   starts looking like a washed-out box.
   ---------------------------------------------------------------------- */

.login-wrap {
  min-height: 100vh; display: grid; place-items: center; padding: 1.25rem;
  position: relative; overflow: hidden;
  background:
    linear-gradient(180deg, rgba(8,10,24,.30), rgba(8,10,24,.58)),
    url("/assets/img/login-bg.jpg") center/cover no-repeat fixed,
    #0B1020;
}

/* Two soft brand-coloured lights behind the glass. Without something with
   structure behind it, a blur has nothing to blur and the pane reads as flat
   grey. These also put our own two colours on the one screen that is otherwise
   entirely somebody's photograph. */
.login-wrap::before,
.login-wrap::after {
  content: ''; position: absolute; border-radius: 50%;
  filter: blur(90px); opacity: .5; pointer-events: none;
}
.login-wrap::before { width: 46vmin; height: 46vmin; left: 12%;  top: 8%;  background: var(--brand); }
.login-wrap::after  { width: 38vmin; height: 38vmin; right: 10%; bottom: 6%; background: var(--red); }

.login-card {
  position: relative; z-index: 1;
  width: 100%; max-width: 408px;
  padding: 2rem 1.9rem 1.7rem;
  border-radius: 26px;

  /* The pane itself: a gradient rather than a flat fill, so the sheet catches
     light unevenly the way glass does. */
  background: linear-gradient(145deg, rgba(255,255,255,.86), rgba(255,255,255,.70));
  backdrop-filter: blur(28px) saturate(1.6);
  -webkit-backdrop-filter: blur(28px) saturate(1.6);

  /* A hairline, brightest where the light comes from. */
  border: 1px solid rgba(255,255,255,.60);
  box-shadow:
    0 32px 80px rgba(3, 6, 20, .50),          /* lift off the photograph      */
    0 2px 10px rgba(3, 6, 20, .18),           /* contact shadow at the edge   */
    inset 0 1px 0 rgba(255,255,255,.85),      /* the lit top edge             */
    inset 0 -1px 0 rgba(255,255,255,.28);     /* a fainter one underneath     */
}

/* The specular streak across the top. A real pane is never evenly lit. */
.login-card::before {
  content: ''; position: absolute; inset: 0 0 auto; height: 46%;
  border-radius: 26px 26px 40% 40% / 26px 26px 14% 14%;
  background: linear-gradient(180deg, rgba(255,255,255,.42), rgba(255,255,255,0));
  pointer-events: none;
}
.login-card > * { position: relative; }

.login-card .brand { padding: 0 0 1.2rem; justify-content: center; }
.login-card .field label { color: var(--text-2); font-weight: 700; }

/* The inputs are glass too, one layer deeper — otherwise they sit on the pane
   like stickers. */
.login-card input {
  background: rgba(255,255,255,.55);
  border: 1px solid rgba(255,255,255,.75);
  box-shadow: inset 0 1px 3px rgba(18,20,28,.06);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.login-card input::placeholder { color: rgba(18,20,28,.38); }
.login-card input:focus {
  background: rgba(255,255,255,.88);
  border-color: var(--brand-300);
  box-shadow: 0 0 0 3px rgba(0, 7, 176, .14);
}
.login-card .btn-primary {
  box-shadow: 0 10px 26px rgba(0, 7, 176, .42), inset 0 1px 0 rgba(255,255,255,.28);
}
.login-card .tabs { border-bottom-color: rgba(18,20,28,.10); }

/* Where backdrop-filter is unsupported there is nothing to blur, so the pane
   would be a translucent smear over a photograph. Go nearly opaque instead:
   plain, but readable, which matters more. */
@supports not ((backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px))) {
  .login-card { background: rgba(255,255,255,.96); }
  .login-card input { background: #fff; }
}

.login-foot {
  margin-top: 1.15rem; text-align: center;
  color: rgba(255,255,255,.88); font-size: .78rem; font-weight: 600;
  text-shadow: 0 1px 14px rgba(0,0,0,.6);
}

.pin-pad { display: grid; grid-template-columns: repeat(3, 1fr); gap: .45rem; margin-top: .7rem; }
.pin-pad button { min-height: 50px; font-size: 1.15rem; font-weight: 800; }
.pin-display { text-align: center; font-size: 1.9rem; letter-spacing: .55rem; font-family: var(--mono); min-height: 46px; color: var(--text-2); }

/* ======================================================= online storefront */

.shop { max-width: 1140px; margin: 0 auto; padding: 1.2rem; }
.shop-hero {
  background: linear-gradient(120deg, var(--brand), #2a34d9 60%, var(--red));
  color: #fff; border-radius: 20px; padding: 1.6rem 1.8rem; margin-bottom: 1.2rem;
}
.shop-hero h1 { color: #fff; margin-bottom: .25rem; }
.shop-hero p { color: rgba(255,255,255,.88); margin: 0; }
.shop-hero .status { display: inline-flex; align-items: center; gap: .4rem; margin-top: .8rem;
  background: rgba(255,255,255,.16); padding: .3rem .8rem; border-radius: 999px; font-weight: 700; font-size: .8rem; }

pre.payload {
  background: var(--surface-2); border-radius: var(--radius-sm);
  padding: .9rem; overflow: auto; max-height: 460px;
  font-family: var(--mono); font-size: .78rem; line-height: 1.5; color: #0B3C2B;
  white-space: pre-wrap; word-break: break-word;
}

.offline-banner {
  position: fixed; left: 50%; transform: translateX(-50%); bottom: 18px; z-index: 2500;
  background: var(--text); color: #fff; padding: .6rem 1.1rem; border-radius: 999px;
  font-size: .82rem; font-weight: 700; box-shadow: var(--shadow-lg); display: none;
  align-items: center; gap: .5rem;
}
.offline-banner.show { display: inline-flex; }
.offline-banner .pulse { width: 8px; height: 8px; border-radius: 50%; background: var(--red-400); }

@media print {
  .sidebar, .topbar, .btn, .tabs, .period, #toasts { display: none !important; }
  .app, .main, .content { display: block; padding: 0; }
  body { background: #fff; }
  .card { box-shadow: none; border: 1px solid var(--line); }
}
