/* ==========================================================================
   ClickBite — Premium Glass Skin  (v2)
   Loaded on every page via header.php, layered on top of the Tailwind utility
   classes. Pure presentation: no markup or behaviour depends on this file.

   Design vocabulary lifted from the ClickBite marketing site:
     canvas  #0b1220   elevated #0f172a   surface #1e293b
     brand   #fb7185 → #e11d48 (the paleta rose)
     radii   12 / 16 / 22        ease  cubic-bezier(.2,.8,.3,1)
   ========================================================================== */

:root {
  --cb-ease: cubic-bezier(0.2, 0.8, 0.3, 1);
  --cb-r-sm: 10px;
  --cb-r: 14px;
  --cb-r-lg: 20px;

  /* Hover should read as "this came toward you", not "this jumped up": a small
     scale in place, no vertical travel. Two sizes, because one factor covers
     very different distances — 2% of a product tile is a couple of pixels, 2%
     of a full-width admin panel is twenty. */
  --cb-pop: 1.02;        /* product tiles and other small cards */
  --cb-pop-wide: 1.006;  /* full-width panels, primary action buttons */

  /* Tenant color, made safe for the two contexts it has to survive in.
     `ink`   — legible as TEXT on a white/near-white surface, whatever hue the
               tenant picked (a pale yellow brand would vanish otherwise).
     `solid` — the fill under white button labels; floored toward navy so a
               light brand color can still carry white text. */
  --cb-tenant-ink: color-mix(in srgb, var(--tenant-primary-color) 58%, #0b1220);
  --cb-tenant-solid: color-mix(in srgb, var(--tenant-primary-color) 86%, #0b1220);
  --cb-tenant-lift: color-mix(in srgb, var(--tenant-primary-color) 92%, #ffffff);
}

* {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3 {
  letter-spacing: -0.02em;
}

/* Money, counts, timers: never let digits jitter as they update. */
[id$="-total"], [id$="-subtotal"], [id$="-change"], [id$="-tax"],
[id$="-expected"], [id$="-counted"], [id$="-overshort"], [id$="-remaining"],
[id^="kpi-"], [id^="live-"], [id^="ds-"], [id^="sr-"], [id^="sm-"],
#drawer-cash-chip, #kds-count {
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

/* Native widgets (scrollbars, date pickers, selects) follow the surface. */
body.bg-slate-900 { color-scheme: dark; }
body.bg-slate-50, body.bg-slate-900.pos-light { color-scheme: light; }

/* Visible keyboard focus everywhere — the old skin only styled :focus. */
:focus-visible {
  outline: 2px solid color-mix(in srgb, var(--cb-brand) 80%, transparent);
  outline-offset: 2px;
}

/* ---- Ambient layered backgrounds (tinted by the tenant color) ---------- */
body.bg-slate-900 {
  background-color: #0b1220 !important;
  background-image:
    radial-gradient(1200px 800px at 85% -10%, color-mix(in srgb, var(--tenant-primary-color) 16%, transparent), transparent 60%),
    radial-gradient(700px 520px at 108% 68%, color-mix(in srgb, var(--cb-brand) 10%, transparent), transparent 62%),
    radial-gradient(900px 700px at -10% 110%, color-mix(in srgb, var(--tenant-primary-color) 10%, transparent), transparent 55%),
    linear-gradient(180deg, #0b1220 0%, #0f172a 100%);
  background-attachment: fixed;
}

body.bg-slate-50 {
  background-color: #eef1f6 !important;
  background-image:
    radial-gradient(1000px 700px at 90% -20%, color-mix(in srgb, var(--tenant-primary-color) 8%, transparent), transparent 60%),
    radial-gradient(760px 540px at -8% -10%, color-mix(in srgb, var(--cb-brand) 6%, transparent), transparent 60%),
    radial-gradient(800px 600px at -10% 120%, rgba(15, 23, 42, 0.05), transparent 55%),
    linear-gradient(180deg, #f5f7fb 0%, #eceff5 100%);
  background-attachment: fixed;
}

/* ==========================================================================
   Surfaces
   The old skin ran panels at 55% opacity over a drifting gradient, so body
   text sat on a background that changed brightness as the blobs moved. These
   are opaque enough to hold text steadily and still read as glass.
   ========================================================================== */

body.bg-slate-900 .bg-slate-800 {
  background-color: rgba(23, 33, 51, 0.82) !important;
}
body.bg-slate-900 .border-slate-700 {
  border-color: rgba(255, 255, 255, 0.09) !important;
}
body.bg-slate-900 .bg-slate-900 {
  background-color: rgba(6, 11, 24, 0.62) !important;
}

/* Heavy glass only on the big fixed panels (cheap enough for tablets) */
body.bg-slate-900 header,
body.bg-slate-900 aside {
  backdrop-filter: blur(20px) saturate(150%);
  -webkit-backdrop-filter: blur(20px) saturate(150%);
}

/* POS chrome: a hairline of light along the top edge of each panel, the way
   the marketing site separates its stacked surfaces. */
body.bg-slate-900 > div > div > header {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05), 0 1px 24px rgba(2, 6, 23, 0.4);
}
body.bg-slate-900 aside {
  box-shadow: -12px 0 40px rgba(2, 6, 23, 0.35);
}

/* The ticket total block: raised, so the numbers that matter feel anchored. */
body.bg-slate-900 aside .sticky.bottom-0 {
  background-color: rgba(20, 29, 46, 0.94) !important;
  box-shadow: 0 -1px 0 rgba(255, 255, 255, 0.06), 0 -18px 40px rgba(2, 6, 23, 0.5);
  backdrop-filter: blur(20px) saturate(140%);
  -webkit-backdrop-filter: blur(20px) saturate(140%);
}

/* ---- Admin: dark glass sidebar over the light workspace ---------------- */
body.bg-slate-50 aside {
  background: linear-gradient(180deg, rgba(15, 23, 42, 0.97), rgba(11, 18, 32, 0.95)) !important;
  backdrop-filter: blur(18px) saturate(140%);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  border-color: rgba(255, 255, 255, 0.06) !important;
  box-shadow: 10px 0 40px rgba(15, 23, 42, 0.14);
}

/* ---- Admin cards: soft floating glass ----------------------------------- */
body.bg-slate-50 .rounded-xl.bg-white,
body.bg-slate-50 .rounded-2xl.bg-white,
body.bg-slate-50 main section.bg-white {
  background-color: rgba(255, 255, 255, 0.9) !important;
  backdrop-filter: blur(14px) saturate(125%);
  -webkit-backdrop-filter: blur(14px) saturate(125%);
  border-color: rgba(15, 23, 42, 0.07) !important;
  box-shadow:
    0 1px 2px rgba(15, 23, 42, 0.04),
    0 14px 36px rgba(15, 23, 42, 0.07) !important;
}

body.bg-slate-50 tbody tr {
  transition: background-color 0.15s ease;
}
body.bg-slate-50 tbody tr:hover {
  background-color: color-mix(in srgb, var(--cb-brand) 5%, transparent);
}

/* ---- Modals: true Apple glass with a pop-in ----------------------------- */
div[id$="-modal"] {
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
div[id$="-modal"] > div {
  border-radius: var(--cb-r-lg) !important;
  backdrop-filter: blur(28px) saturate(160%);
  -webkit-backdrop-filter: blur(28px) saturate(160%);
  box-shadow:
    0 28px 90px rgba(0, 0, 0, 0.5),
    inset 0 1px 0 rgba(255, 255, 255, 0.1);
  animation: cb-pop 0.22s var(--cb-ease);
}
body.bg-slate-900 div[id$="-modal"] > div {
  background-color: rgba(21, 30, 48, 0.9) !important;
  border: 1px solid rgba(255, 255, 255, 0.1) !important;
}
body.bg-slate-50 div[id$="-modal"] > div {
  background-color: rgba(255, 255, 255, 0.94) !important;
  border: 1px solid rgba(15, 23, 42, 0.08);
}
@keyframes cb-pop {
  from { opacity: 0; transform: translateY(12px) scale(0.96); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

/* Modal headings get the brand hairline, matching the admin h1 treatment. */
div[id$="-modal"] > div > h3:first-child,
div[id$="-modal"] > div > div:first-child > h3 {
  letter-spacing: -0.02em;
}

/* ==========================================================================
   Buttons
   ========================================================================== */

button, a {
  transition:
    transform 0.12s var(--cb-ease),
    box-shadow 0.2s ease,
    filter 0.2s ease,
    background-color 0.2s ease,
    border-color 0.2s ease,
    color 0.2s ease,
    opacity 0.2s ease;
}
button:active:not(:disabled) {
  transform: scale(0.975);
}

/* Every tenant-colored action gets a premium gradient + soft glow. The dark
   stop is floored toward navy so white labels hold up even on a pale brand
   color, and the text shadow buys another notch of legibility. */
[class*="bg-[var(--tenant-primary-color)]"]:not([class*="/1"]):not([class*="/2"]) {
  background-image: linear-gradient(160deg, var(--cb-tenant-lift), var(--cb-tenant-solid));
  box-shadow:
    0 6px 20px color-mix(in srgb, var(--tenant-primary-color) 28%, transparent),
    inset 0 1px 0 rgba(255, 255, 255, 0.22);
}
button[class*="bg-[var(--tenant-primary-color)]"],
a[class*="bg-[var(--tenant-primary-color)]"] {
  text-shadow: 0 1px 2px rgba(2, 6, 23, 0.32);
}
[class*="bg-[var(--tenant-primary-color)]"]:hover:not(:disabled) {
  filter: brightness(1.08) saturate(1.05);
}

/* A slow sheen on hover only — the old skin animated every primary button
   forever, which read as noise on a screen staff stare at all day. */
[class*="bg-[var(--tenant-primary-color)]"] {
  background-size: 170% 170%;
  background-position: 0% 30%;
}
[class*="bg-[var(--tenant-primary-color)]"]:hover:not(:disabled) {
  background-position: 100% 70%;
  transition: background-position 0.9s var(--cb-ease), filter 0.2s ease, box-shadow 0.2s ease;
}

#pay-button, #pm-charge, #split-charge {
  letter-spacing: 0.06em;
  border-radius: 16px !important;
  box-shadow:
    0 12px 36px color-mix(in srgb, var(--tenant-primary-color) 42%, transparent),
    inset 0 1px 0 rgba(255, 255, 255, 0.26);
}
#pay-button:hover:not(:disabled),
#pm-charge:hover:not(:disabled),
#split-charge:hover:not(:disabled) {
  transform: scale(var(--cb-pop-wide));
}
#pay-button:disabled, #pm-charge:disabled, #split-charge:disabled {
  box-shadow: none;
  text-shadow: none;
}

/* Secondary / ghost buttons in the POS chrome */
body.bg-slate-900 .bg-slate-700\/60 {
  background-color: rgba(51, 65, 85, 0.5) !important;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
}
body.bg-slate-900 .bg-slate-700\/60:hover {
  background-color: rgba(71, 85, 105, 0.6) !important;
  border-color: color-mix(in srgb, var(--cb-brand) 45%, transparent) !important;
}

/* Destructive actions read as destructive, not as a red rectangle. */
#close-shift-submit, #confirm-ok {
  background-image: linear-gradient(160deg, #f0556d, #d3243f);
  box-shadow: 0 8px 24px rgba(220, 38, 38, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.18);
  text-shadow: 0 1px 2px rgba(2, 6, 23, 0.3);
}

/* ---- Inputs: tenant-tinted focus ring ----------------------------------- */
input, select, textarea {
  transition: border-color 0.18s ease, box-shadow 0.18s ease, background-color 0.18s ease;
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: color-mix(in srgb, var(--tenant-primary-color) 65%, transparent) !important;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--tenant-primary-color) 20%, transparent);
}
body.bg-slate-900 input::placeholder,
body.bg-slate-900 textarea::placeholder {
  color: #64748b;
}
/* Kill the spinner arrows on the dozens of numeric counters — they crowd the
   denomination cells and are useless on a touch register. */
#open-denom-grid input[type="number"]::-webkit-outer-spin-button,
#open-denom-grid input[type="number"]::-webkit-inner-spin-button,
#close-denom-grid input[type="number"]::-webkit-outer-spin-button,
#close-denom-grid input[type="number"]::-webkit-inner-spin-button,
#movement-denom-grid input[type="number"]::-webkit-outer-spin-button,
#movement-denom-grid input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* ==========================================================================
   POS product grid
   ========================================================================== */

#category-pills {
  scrollbar-width: none;
}
#category-pills::-webkit-scrollbar { height: 0; }

.category-pill {
  white-space: nowrap;
  user-select: none;
  letter-spacing: -0.01em;
}
.category-pill:not([class*="bg-[var(--tenant-primary-color)]"]) {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
}
.category-pill[class*="bg-[var(--tenant-primary-color)]"] {
  box-shadow:
    0 4px 16px color-mix(in srgb, var(--tenant-primary-color) 38%, transparent),
    inset 0 1px 0 rgba(255, 255, 255, 0.25);
}

.product-card {
  position: relative;
  border-radius: var(--cb-r) !important;
  transition: transform 0.16s var(--cb-ease), box-shadow 0.25s ease, border-color 0.2s ease;
  overflow: hidden;
  box-shadow: 0 1px 2px rgba(2, 6, 23, 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.04);
}
.product-card:hover {
  transform: scale(var(--cb-pop));
  box-shadow: 0 8px 26px rgba(2, 6, 23, 0.42);
  border-color: color-mix(in srgb, var(--tenant-primary-color) 50%, transparent) !important;
}
.product-card:active {
  transform: scale(0.975);
}
.product-card img {
  transition: transform 0.35s var(--cb-ease);
}
.product-card:hover img {
  transform: scale(1.06);
}
/* Scrim under the name/price row so text stays readable over busy photos. */
.product-card > div:last-child {
  position: relative;
}
.product-card .aspect-square {
  position: relative;
}
.product-card .aspect-square::after {
  content: '';
  position: absolute;
  inset: auto 0 0 0;
  height: 42%;
  background: linear-gradient(180deg, transparent, rgba(2, 6, 23, 0.35));
  pointer-events: none;
}
/* The price is the thing a cashier scans for. */
.product-card p:last-child {
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
}

/* ==========================================================================
   Kitchen Display
   Status was carried only by a 2px border. Now each card gets a full-width
   status edge and a matching glow, readable across a hot kitchen at a glance.
   ========================================================================== */

#kds-board > div {
  position: relative;
  border-radius: var(--cb-r) !important;
  overflow: hidden;
  box-shadow: 0 10px 30px rgba(2, 6, 23, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.05);
  animation: cb-pop 0.22s var(--cb-ease);
}
#kds-board > div::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 4px;
  z-index: 1;
}
#kds-board > div.border-red-500\/60::before     { background: linear-gradient(90deg, #f87171, #dc2626); }
#kds-board > div.border-amber-500\/60::before   { background: linear-gradient(90deg, #fbbf24, #d97706); }
#kds-board > div.border-emerald-500\/60::before { background: linear-gradient(90deg, #34d399, #059669); }

#kds-board > div.border-red-500\/60     { box-shadow: 0 10px 30px rgba(220, 38, 38, 0.18), inset 0 1px 0 rgba(255,255,255,.05); }
#kds-board > div.border-amber-500\/60   { box-shadow: 0 10px 30px rgba(217, 119, 6, 0.16), inset 0 1px 0 rgba(255,255,255,.05); }
#kds-board > div.border-emerald-500\/60 { box-shadow: 0 10px 30px rgba(5, 150, 105, 0.14), inset 0 1px 0 rgba(255,255,255,.05); }

/* Ticket number: the card's headline. */
#kds-board > div > div:first-child > span:first-child {
  font-size: 1.35rem;
  font-weight: 800;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}
/* Status badge + timer */
#kds-board > div > div:first-child span[class*="rounded-full"] {
  letter-spacing: 0.08em;
  font-weight: 700;
}
/* The NEW card pulses gently until someone starts it. */
#kds-board > div.border-red-500\/60 > div:first-child span[class*="rounded-full"] {
  animation: cb-kds-pulse 1.8s ease-in-out infinite;
}
@keyframes cb-kds-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.55; }
}
/* Item lines: quantity reads first */
#kds-board > div > div:nth-child(2) p.font-semibold {
  font-size: 0.95rem;
  line-height: 1.35;
}
/* Advance button: full-width footer, generous touch target */
#kds-board button[data-advance] {
  letter-spacing: 0.03em;
  min-height: 52px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}
#kds-count {
  letter-spacing: 0.02em;
  font-weight: 600;
}

/* ==========================================================================
   Ticket & toasts
   ========================================================================== */

.ticket-item-enter {
  animation: ticket-item-fade-in 160ms var(--cb-ease);
}
@keyframes ticket-item-fade-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}

#ticket-total {
  font-size: 1.15rem;
}

#toast-container > div {
  border-radius: var(--cb-r) !important;
  backdrop-filter: blur(18px) saturate(150%);
  -webkit-backdrop-filter: blur(18px) saturate(150%);
  box-shadow: 0 16px 44px rgba(2, 6, 23, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.08);
  animation: cb-pop 0.18s var(--cb-ease);
}

/* ==========================================================================
   Login
   ========================================================================== */

body.bg-slate-900.h-screen.flex > div {
  border-radius: 22px !important;
  background-color: rgba(21, 30, 48, 0.82) !important;
  border-color: rgba(255, 255, 255, 0.1) !important;
  backdrop-filter: blur(26px) saturate(150%);
  -webkit-backdrop-filter: blur(26px) saturate(150%);
  box-shadow:
    0 30px 80px rgba(2, 6, 23, 0.6),
    inset 0 1px 0 rgba(255, 255, 255, 0.09);
}
body.bg-slate-900.h-screen.flex > div > div:first-child h1 {
  font-size: 2rem;
  letter-spacing: -0.035em;
}

/* ==========================================================================
   Responsive layer — phone & small-tablet support
   ========================================================================== */

body.bg-slate-50 main {
  width: 100%;
  margin-left: auto;
  margin-right: auto;
}

/* Wide tables scroll inside their cards instead of breaking the page */
body.bg-slate-50 main section {
  overflow-x: auto;
}

@media (max-width: 767px) {
  body.bg-slate-50 main {
    padding: 4.5rem 1rem 1.5rem 1rem !important;
  }

  /* POS: stack product area over the ticket panel, restore page scrolling */
  body[data-tenant-name] {
    overflow: auto !important;
    height: auto !important;
  }
  body[data-tenant-name] > div.flex.h-screen {
    flex-direction: column;
    height: auto !important;
    min-height: 100vh;
  }
  body[data-tenant-name] > div.flex.h-screen > aside {
    width: 100% !important;
    min-width: 0 !important;
    max-width: none !important;
    border-left: 0 !important;
    border-top: 1px solid rgba(255, 255, 255, 0.08);
  }
  #product-grid {
    grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)) !important;
    max-height: 46vh;
  }
  #ticket-items {
    max-height: 32vh;
  }

  #open-denom-grid .grid,
  #movement-denom-grid .grid,
  #close-denom-grid .grid {
    grid-template-columns: 1fr !important;
  }

  #kds-board {
    grid-template-columns: 1fr 1fr !important;
    padding: 1rem !important;
  }
}

@media (max-width: 480px) {
  #kds-board {
    grid-template-columns: 1fr !important;
  }
}

/* ==========================================================================
   ClickBite ALIVE layer — drifting color blobs and slow crossing lines
   behind every page. Toned down from v1: the workspace has to hold small
   text over it, so the blobs are dimmer and the line grid is a whisper.
   ========================================================================== */

body::before {
  content: '';
  position: fixed;
  inset: -22%;
  z-index: -2;
  pointer-events: none;
  background:
    radial-gradient(36% 32% at 16% 20%, color-mix(in srgb, var(--cb-brand) 20%, transparent), transparent 70%),
    radial-gradient(32% 30% at 84% 14%, color-mix(in srgb, var(--tenant-primary-color) 19%, transparent), transparent 70%),
    radial-gradient(30% 30% at 72% 86%, color-mix(in srgb, #2dd4bf 14%, transparent), transparent 70%),
    radial-gradient(26% 26% at 22% 88%, color-mix(in srgb, #f59e0b 11%, transparent), transparent 70%);
  filter: blur(56px);
  animation: cb-drift 34s ease-in-out infinite alternate;
}
body.bg-slate-50::before,
body.pos-light::before {
  background:
    radial-gradient(36% 32% at 16% 20%, color-mix(in srgb, var(--cb-brand) 11%, transparent), transparent 70%),
    radial-gradient(32% 30% at 84% 14%, color-mix(in srgb, var(--tenant-primary-color) 10%, transparent), transparent 70%),
    radial-gradient(30% 30% at 72% 86%, color-mix(in srgb, #2dd4bf 8%, transparent), transparent 70%),
    radial-gradient(26% 26% at 22% 88%, color-mix(in srgb, #f59e0b 7%, transparent), transparent 70%);
}
@keyframes cb-drift {
  0%   { transform: translate3d(-2.5%, -2%, 0) scale(1) rotate(0.001deg); }
  50%  { transform: translate3d(1.5%, 2%, 0)  scale(1.05); }
  100% { transform: translate3d(3%, -1.5%, 0) scale(1.02); }
}

body::after {
  content: '';
  position: fixed;
  inset: -60%;
  z-index: -1;
  pointer-events: none;
  background-image:
    repeating-linear-gradient(115deg,
      transparent 0 130px,
      color-mix(in srgb, var(--tenant-primary-color) 60%, transparent) 130px 131px,
      transparent 131px 260px),
    repeating-linear-gradient(63deg,
      transparent 0 170px,
      color-mix(in srgb, var(--cb-brand) 60%, transparent) 170px 171px,
      transparent 171px 340px);
  opacity: 0.05;
  animation: cb-lines 60s linear infinite;
}
body.bg-slate-50::after,
body.pos-light::after {
  opacity: 0.055;
}
@keyframes cb-lines {
  to { transform: translate3d(260px, 170px, 0); }
}

@media (prefers-reduced-motion: reduce) {
  body::before, body::after { animation: none; }
}

/* ==========================================================================
   ClickBite brand layer — the paleta's rose threads through the whole UI
   ========================================================================== */

::selection {
  background: color-mix(in srgb, var(--cb-brand) 30%, transparent);
}

/* Sidebar: soft rose glow behind the ClickBite lockup */
.cb-sidebar-brand {
  background: radial-gradient(150px 80px at 50% 0%,
    color-mix(in srgb, var(--cb-brand) 22%, transparent), transparent 78%);
}

/* Admin headings carry a brand→tenant accent bar */
body.bg-slate-50 main h1 {
  position: relative;
  padding-bottom: 10px;
  letter-spacing: -0.03em;
}
body.bg-slate-50 main h1::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: 0;
  width: 36px;
  height: 4px;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--cb-brand), var(--tenant-primary-color));
}

/* Section headings inside admin cards */
body.bg-slate-50 main h2 {
  letter-spacing: 0.01em;
}

/* Softer, more modern card geometry + the hover lift */
body.bg-slate-50 .rounded-xl.bg-white,
body.bg-slate-50 .rounded-2xl.bg-white,
body.bg-slate-50 main section.bg-white {
  border-radius: 18px !important;
  transition: transform 0.2s var(--cb-ease), box-shadow 0.25s ease, border-color 0.2s ease;
}
body.bg-slate-50 main section:hover,
body.bg-slate-50 main .bg-white.rounded-xl:hover {
  box-shadow:
    0 2px 4px rgba(15, 23, 42, 0.05),
    0 12px 34px rgba(15, 23, 42, 0.11) !important;
  border-color: color-mix(in srgb, var(--cb-brand) 26%, rgba(15, 23, 42, 0.07)) !important;
}
/* Only cards WITHOUT form fields react. Anything holding an input, select,
   textarea or date picker stays perfectly still under the cursor. */
body.bg-slate-50 main section:hover:not(:has(input, select, textarea)),
body.bg-slate-50 main .bg-white.rounded-xl:hover:not(:has(input, select, textarea)) {
  transform: scale(var(--cb-pop-wide));
}

/* Content rises in as pages load */
body.bg-slate-50 main > * {
  animation: cb-rise 0.5s var(--cb-ease) both;
}
body.bg-slate-50 main > *:nth-child(2) { animation-delay: 0.06s; }
body.bg-slate-50 main > *:nth-child(3) { animation-delay: 0.12s; }
body.bg-slate-50 main > *:nth-child(4) { animation-delay: 0.18s; }
body.bg-slate-50 main > *:nth-child(5) { animation-delay: 0.24s; }
body.bg-slate-50 main > *:nth-child(n+6) { animation-delay: 0.3s; }
@keyframes cb-rise {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
  body.bg-slate-50 main > * { animation: none; }
}

/* Table headers: airy tint instead of flat grey */
body.bg-slate-50 thead {
  background: linear-gradient(180deg, rgba(248, 250, 252, 0.96), rgba(241, 245, 249, 0.8)) !important;
}
body.bg-slate-50 thead th {
  letter-spacing: 0.06em;
  font-weight: 600;
}

/* KPI numbers get the display treatment */
body.bg-slate-50 main .text-3xl.font-bold,
body.bg-slate-50 main .text-2xl.font-bold {
  letter-spacing: -0.035em;
  font-variant-numeric: tabular-nums;
}

/* Sidebar nav: pill hover with a rose whisper, active item with a glow */
aside nav a {
  border-radius: 11px !important;
}
aside nav a:hover {
  background: color-mix(in srgb, var(--cb-brand) 12%, rgba(51, 65, 85, 0.65)) !important;
}
aside nav a[class*="bg-[var(--tenant-primary-color)]"] {
  box-shadow:
    0 6px 18px color-mix(in srgb, var(--tenant-primary-color) 34%, transparent),
    inset 0 1px 0 rgba(255, 255, 255, 0.2);
}

/* ---- Scrollbars ----------------------------------------------------------- */
::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}
::-webkit-scrollbar-track {
  background: transparent;
}
::-webkit-scrollbar-thumb {
  background-color: rgba(148, 163, 184, 0.32);
  border-radius: 999px;
}
::-webkit-scrollbar-thumb:hover {
  background-color: rgba(148, 163, 184, 0.55);
}

/* ==========================================================================
   CONTRAST — light workspace (admin, body.bg-slate-50)
   slate-400 body copy on white is ~2.6:1. These are the meta lines under
   every KPI ("0 orders · avg $0.00") and the table captions, so they were
   the least readable text in the product.
   ========================================================================== */

body.bg-slate-50 main .text-slate-400 { color: #64748b !important; }
body.bg-slate-50 main .text-slate-500 { color: #556070 !important; }
body.bg-slate-50 main .text-slate-300 { color: #64748b !important; }

/* Tenant-colored links/labels on white: a pale brand color (yellow, lime,
   sky) was effectively invisible. Darkened toward navy, hue preserved. */
body.bg-slate-50 main .text-\[var\(--tenant-primary-color\)\],
body.bg-slate-50 main [class*="text-[var(--tenant-primary-color)]"] {
  color: var(--cb-tenant-ink) !important;
}
body.bg-slate-50 main a[class*="text-[var(--tenant-primary-color)]"]:hover {
  color: color-mix(in srgb, var(--tenant-primary-color) 40%, #0b1220) !important;
}

/* Status/alert text on white cards: the 400 shades are tuned for dark panels. */
body.bg-slate-50 main .text-emerald-400 { color: #047857 !important; }
body.bg-slate-50 main .text-emerald-500 { color: #059669 !important; }
body.bg-slate-50 main .text-red-400,
body.bg-slate-50 main .text-red-500     { color: #dc2626 !important; }
body.bg-slate-50 main .text-amber-400,
body.bg-slate-50 main .text-amber-500   { color: #b45309 !important; }

/* Sidebar footer text sat at 3.4:1 on the near-black panel. */
body.bg-slate-50 aside .text-slate-500,
body.bg-slate-900 aside .text-slate-500 { color: #94a3b8 !important; }
body.bg-slate-50 aside .text-slate-400  { color: #b6c2d1 !important; }

/* Mobile top bar */
#mobile-topbar {
  background-color: rgba(11, 18, 32, 0.92) !important;
  border-color: rgba(255, 255, 255, 0.08) !important;
}

/* ==========================================================================
   POS Light Mode — toggle for backlit/bright-light registers.
   Scoped to body.bg-slate-900.pos-light: pos.php is the only view that can
   ever carry `pos-light`, and the extra .bg-slate-900 in the compound keeps
   every rule here at least as specific as the dark "glass" rules above that
   key off body.bg-slate-900 — so this always wins on the classes they share,
   with no dependency on source order.
   ========================================================================== */

body.bg-slate-900.pos-light {
  background-color: #eef1f6 !important;
  background-image:
    radial-gradient(1000px 700px at 90% -20%, color-mix(in srgb, var(--tenant-primary-color) 8%, transparent), transparent 60%),
    radial-gradient(760px 540px at -8% -10%, color-mix(in srgb, var(--cb-brand) 6%, transparent), transparent 60%),
    radial-gradient(800px 600px at -10% 120%, rgba(15, 23, 42, 0.05), transparent 55%),
    linear-gradient(180deg, #f5f7fb 0%, #eceff5 100%);
}

/* Surfaces — bg-slate-900 is the canvas, bg-slate-800 is a raised card;
   preserve that same elevation order (lightest = most raised). */
body.bg-slate-900.pos-light .bg-slate-900 { background-color: #eef1f6 !important; }
body.bg-slate-900.pos-light .bg-slate-800 { background-color: #ffffff !important; }
body.bg-slate-900.pos-light .bg-slate-700 { background-color: #e4e9f0 !important; }

/* Translucent variants (/50, /60, /70, ...) matched by attribute rather than
   enumerated one by one. Listing them individually meant a new variant in the
   markup silently stayed dark navy under dark text — exactly how the
   denomination grid's bg-slate-900/60 cells became unreadable in light mode. */
body.bg-slate-900.pos-light [class*="bg-slate-900/"] { background-color: #f8fafc !important; }
body.bg-slate-900.pos-light [class*="bg-slate-800/"] { background-color: rgba(255, 255, 255, 0.88) !important; }
body.bg-slate-900.pos-light [class*="bg-slate-700/"] { background-color: rgba(226, 232, 240, 0.9) !important; }

/* Light-mode elevation: the dark skin used glow + hairlines, which read as
   nothing on white. Swap in real shadows so the panels keep their hierarchy. */
body.bg-slate-900.pos-light > div > div > header {
  background-color: rgba(255, 255, 255, 0.85) !important;
  box-shadow: 0 1px 0 rgba(15, 23, 42, 0.06), 0 6px 24px rgba(15, 23, 42, 0.05);
}
body.bg-slate-900.pos-light aside {
  box-shadow: -12px 0 40px rgba(15, 23, 42, 0.07);
}
body.bg-slate-900.pos-light aside .sticky.bottom-0 {
  background-color: rgba(255, 255, 255, 0.96) !important;
  box-shadow: 0 -1px 0 rgba(15, 23, 42, 0.07), 0 -16px 36px rgba(15, 23, 42, 0.06);
}
body.bg-slate-900.pos-light .product-card {
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.05), 0 8px 22px rgba(15, 23, 42, 0.05);
}
body.bg-slate-900.pos-light .product-card:hover {
  box-shadow: 0 16px 36px rgba(15, 23, 42, 0.12);
}
body.bg-slate-900.pos-light .product-card .aspect-square::after {
  background: linear-gradient(180deg, transparent, rgba(15, 23, 42, 0.14));
}

/* Modal panels: overrides the dark-glass rule above (which targets
   div[id$="-modal"] > div directly and would otherwise out-specificity a
   bare .bg-slate-800 remap). */
body.bg-slate-900.pos-light div[id$="-modal"] > div {
  background-color: rgba(255, 255, 255, 0.96) !important;
  border-color: rgba(15, 23, 42, 0.09) !important;
  box-shadow: 0 28px 80px rgba(15, 23, 42, 0.22), inset 0 1px 0 rgba(255, 255, 255, 0.9);
}
body.bg-slate-900.pos-light div[id$="-modal"] {
  background-color: rgba(15, 23, 42, 0.45) !important;
}

/* Borders */
body.bg-slate-900.pos-light .border-slate-700,
body.bg-slate-900.pos-light .border-slate-600,
body.bg-slate-900.pos-light .border-slate-800 {
  border-color: #cfd8e3 !important;
}
body.bg-slate-900.pos-light .hover\:border-slate-400:hover,
body.bg-slate-900.pos-light .hover\:border-slate-500:hover {
  border-color: color-mix(in srgb, var(--tenant-primary-color) 55%, #94a3b8) !important;
}

/* Text — :not(.text-white) so toggled "active" states (e.g. the selected
   discount-type button) that pair a base slate class with .text-white keep
   their intended white text instead of being forced dark. */
body.bg-slate-900.pos-light .text-slate-100:not(.text-white),
body.bg-slate-900.pos-light .text-slate-200:not(.text-white) { color: #0f172a !important; }
body.bg-slate-900.pos-light .text-slate-300:not(.text-white) { color: #334155 !important; }
body.bg-slate-900.pos-light .text-slate-400:not(.text-white),
body.bg-slate-900.pos-light .text-slate-500:not(.text-white) { color: #5b6779 !important; }
body.bg-slate-900.pos-light .text-slate-600:not(.text-white) { color: #475569 !important; }
body.bg-slate-900.pos-light .hover\:text-slate-200:hover,
body.bg-slate-900.pos-light .hover\:text-slate-300:hover { color: #0f172a !important; }
body.bg-slate-900.pos-light input::placeholder,
body.bg-slate-900.pos-light textarea::placeholder { color: #94a3b8; }

/* Body text sits on white now — reset the inherited slate-100 on <body>. */
body.bg-slate-900.pos-light { color: #0f172a !important; }

/* Tenant-colored TEXT on the light POS. Covers the product price, the
   "send to kitchen" active label, the loyalty icon — all of which turned
   near-invisible on white with a pale brand color. */
body.bg-slate-900.pos-light [class*="text-[var(--tenant-primary-color)]"] {
  color: var(--cb-tenant-ink) !important;
}
/* Tenant-tinted fills (bg-…/15, /20) sit on white here; keep them faint so
   the darkened ink on top stays legible. */
body.bg-slate-900.pos-light [class*="bg-[var(--tenant-primary-color)]/15"],
body.bg-slate-900.pos-light [class*="bg-[var(--tenant-primary-color)]/20"] {
  background-color: color-mix(in srgb, var(--tenant-primary-color) 12%, #ffffff) !important;
  background-image: none;
  box-shadow: none;
}
/* …including the kitchen toggle's active border. */
body.bg-slate-900.pos-light #kitchen-toggle[class*="border-[var(--tenant-primary-color)]"] {
  border-color: var(--cb-tenant-ink) !important;
}

/* The active discount-type button keeps .text-white by design (white label
   on its dark bg-slate-900 surface) — but that surface remaps to near-white
   in light mode, which would leave white-on-white. Recolor just its label. */
body.bg-slate-900.pos-light .disc-type-btn.text-white {
  color: var(--cb-tenant-ink) !important;
}
body.bg-slate-900.pos-light .disc-type-btn[class*="border-[var(--tenant-primary-color)]"] {
  border-color: var(--cb-tenant-ink) !important;
  background-color: color-mix(in srgb, var(--tenant-primary-color) 10%, #ffffff) !important;
}

/* Accent colors: the bright 300/400 shades read fine on a dark panel but
   lose most of their contrast once that same panel turns white. */
body.bg-slate-900.pos-light .text-emerald-400,
body.bg-slate-900.pos-light .text-emerald-300 { color: #047857 !important; }
body.bg-slate-900.pos-light .text-red-400,
body.bg-slate-900.pos-light .text-red-300,
body.bg-slate-900.pos-light .hover\:text-red-400:hover { color: #dc2626 !important; }
body.bg-slate-900.pos-light .text-amber-300,
body.bg-slate-900.pos-light .text-amber-400,
body.bg-slate-900.pos-light .text-amber-300\/80 { color: #a1550a !important; }
body.bg-slate-900.pos-light .text-rose-400 { color: #be123c !important; }

/* Amber warning chips: the /20 fill is nearly white on a white panel, so the
   offline badge and drawer-limit banner lost their urgency. Give them a real
   tint and border. */
body.bg-slate-900.pos-light .bg-amber-500\/20,
body.bg-slate-900.pos-light .bg-amber-500\/15 {
  background-color: #fef3c7 !important;
}
body.bg-slate-900.pos-light .border-amber-600\/50,
body.bg-slate-900.pos-light .border-amber-600\/40 {
  border-color: #f0b429 !important;
}
body.bg-slate-900.pos-light .bg-emerald-500\/15 { background-color: #d1fae5 !important; }
body.bg-slate-900.pos-light .border-emerald-500\/40 { border-color: #34d399 !important; }

/* The transfer-request banner (item 22) is blue on purpose — amber is the
   drawer warning. Same problem as the amber chips: the /15 fill vanishes on a
   white panel and the pale text with it. */
body.bg-slate-900.pos-light .bg-sky-500\/15,
body.bg-slate-900.pos-light .bg-sky-500\/25 { background-color: #e0f2fe !important; }
body.bg-slate-900.pos-light .border-sky-600\/40,
body.bg-slate-900.pos-light .border-sky-500\/60 { border-color: #7dd3fc !important; }
body.bg-slate-900.pos-light .text-sky-200,
body.bg-slate-900.pos-light .text-sky-100 { color: #075985 !important; }

/* Destructive buttons keep white labels on a saturated red in both themes. */
body.bg-slate-900.pos-light .bg-red-600\/90,
body.bg-slate-900.pos-light .bg-red-600\/80 {
  background-color: #dc2626 !important;
}

/* Toasts stay on the dark skin regardless of POS theme — brief, floating,
   already legible; re-assert over the generic remap above (ID beats it on
   specificity so this doesn't depend on rule order). */
body.pos-light #toast-container .bg-slate-700     { background-color: #334155 !important; }
body.pos-light #toast-container .border-slate-600 { border-color: #475569 !important; }
body.pos-light #toast-container .text-slate-100   { color: #f1f5f9 !important; }

/* Theme and full-screen toggles: hint at what they do. */
#theme-toggle:hover,
#fullscreen-toggle:hover {
  border-color: color-mix(in srgb, var(--cb-brand) 55%, transparent) !important;
  color: var(--cb-brand) !important;
}

/* ==========================================================================
   WIDE TABLES — fit first, scroll only when it genuinely cannot fit.
   ========================================================================== */

/* Compaction for the tables with many columns (reports: recent orders, shift
   history). Eleven columns of px-5 spend ~440px on padding alone inside a
   1152px page, which is what pushed them off-screen; tightening the gutters
   and dropping a step of type size buys most of that back without hiding any
   data from the accountant.
   Applied with class="cb-compact" so the row templates need no per-cell edits. */
table.cb-compact { font-size: 0.75rem; line-height: 1.15rem; }
table.cb-compact th,
table.cb-compact td { padding-left: 0.6rem; padding-right: 0.6rem; }

/* A readability floor. Without it these tables never overflow — they just keep
   wrapping until eleven columns are one word wide each, which is technically
   "fitting" and completely unreadable. 60rem fits inside the 1088px the reports
   page actually has, so a desktop shows the whole table and no scroll
   affordance; anything narrower overflows on purpose and the edge zones earn
   their place. */
table.cb-compact { min-width: 60rem; }

/* A blanket whitespace-nowrap on the table is the other reason these overflow:
   it forces long free text (audit details, shift notes) onto one endless line.
   Let text wrap, and mark only the cells that must not break mid-value. */
table.cb-wrap { white-space: normal; }
table.cb-wrap .cb-nw { white-space: nowrap; }

/* Long free-text cells get a ceiling so one verbose note cannot widen the
   whole table. */
table.cb-wrap .cb-clamp {
  max-width: 22rem;
  overflow-wrap: anywhere;
}

/* --------------------------------------------------------------------------
   Edge-hover horizontal scrolling.

   The native scrollbar is hidden but the container still scrolls, so the wheel,
   trackpad and touch all keep working — using overflow:hidden here would break
   dragging on the tablets. Two zones sit over the left and right edges,
   invisible until hovered, and each is shown only when there is actually more
   content that way. Geometry is recomputed on hover, so it cannot go stale when
   rows are filtered out from under it.
   -------------------------------------------------------------------------- */
.cb-hscroll-outer { position: relative; }

[data-hscroll] {
  overflow-x: auto;
  scrollbar-width: none;          /* Firefox */
  -ms-overflow-style: none;       /* legacy Edge */
  scroll-behavior: smooth;
}
[data-hscroll]::-webkit-scrollbar { display: none; }

.cb-hscroll-zone {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 2.4rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  padding: 0;
  cursor: pointer;
  opacity: 0;
  transition: opacity 140ms ease;
  pointer-events: none;           /* never steal a click from a cell beneath */
  z-index: 5;
  color: #0f172a;
}
.cb-hscroll-zone[data-active="1"] { pointer-events: auto; }
.cb-hscroll-outer:hover .cb-hscroll-zone[data-active="1"],
.cb-hscroll-zone[data-active="1"]:focus-visible { opacity: 1; }

.cb-hscroll-left  { left: 0;  background: linear-gradient(to right, rgba(255,255,255,.97), rgba(255,255,255,0)); }
.cb-hscroll-right { right: 0; background: linear-gradient(to left,  rgba(255,255,255,.97), rgba(255,255,255,0)); }
.cb-hscroll-zone:hover { color: var(--cb-brand, #fb7185); }
.cb-hscroll-zone svg { width: 1.15rem; height: 1.15rem; }

/* The POS runs on a dark skin, so the scrim has to match or it looks like a
   white smear over the grid. */
body.bg-slate-900 .cb-hscroll-zone { color: #e2e8f0; }
body.bg-slate-900 .cb-hscroll-left  { background: linear-gradient(to right, rgba(15,23,42,.97), rgba(15,23,42,0)); }
body.bg-slate-900 .cb-hscroll-right { background: linear-gradient(to left,  rgba(15,23,42,.97), rgba(15,23,42,0)); }
body.bg-slate-900.pos-light .cb-hscroll-zone { color: #0f172a; }
body.bg-slate-900.pos-light .cb-hscroll-left  { background: linear-gradient(to right, rgba(255,255,255,.97), rgba(255,255,255,0)); }
body.bg-slate-900.pos-light .cb-hscroll-right { background: linear-gradient(to left,  rgba(255,255,255,.97), rgba(255,255,255,0)); }

/* Printing a report should never show a half-scrolled table or an arrow. */
@media print {
  [data-hscroll] { overflow: visible !important; }
  .cb-hscroll-zone { display: none !important; }
}

/* --------------------------------------------------------------------------
   Tall tables — cap the height instead of making the page endless.

   A 100-row shift history pushed everything below it twenty screens down. These
   lists are for scanning, not for reading end to end, so they get their own
   scroll box and the page stays navigable.

   The header MUST stick, or scrolling a capped table means scrolling away the
   only thing that says which column is which.
   -------------------------------------------------------------------------- */
.cb-vscroll {
  overflow-y: auto;
  /* Roughly a dozen rows on a laptop: enough to see the shape of the data
     without burying the next section. Viewport-relative so a big monitor
     genuinely gets more rows rather than the same fixed box. */
  max-height: min(60vh, 34rem);
}
.cb-vscroll table thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  /* thead has a bg class in the markup, but sticky cells paint independently —
     without an explicit background the rows scroll visibly underneath. */
  background-color: #f8fafc;
}
.cb-vscroll table thead tr:first-child th { box-shadow: inset 0 -1px 0 #e2e8f0; }

/* A capped list has to say so, or "50 rows" reads as "that is everything". */
.cb-list-meta {
  font-size: 0.7rem;
  color: #94a3b8;
  padding: 0.4rem 1.25rem 0.75rem;
}

/* The POS runs dark; the sticky header has to match its own table. */
body.bg-slate-900 .cb-vscroll table thead th { background-color: #1e293b; }
body.bg-slate-900.pos-light .cb-vscroll table thead th { background-color: #f8fafc; }

/* Printing a report should show the whole table, not one scrolled pane. */
@media print {
  .cb-vscroll { max-height: none !important; overflow: visible !important; }
}

/* Range toggle: one control that every section on the dashboard obeys. */
.cb-range-btn {
  padding: 0.3rem 0.75rem;
  font-size: 0.75rem;
  font-weight: 600;
  border-radius: 0.5rem;
  color: #64748b;
  transition: background-color 120ms ease, color 120ms ease;
}
.cb-range-btn:hover { background-color: #f1f5f9; }
.cb-range-btn[aria-pressed="true"] {
  background-color: var(--tenant-primary-color, #3b82f6);
  color: #fff;
}
