:root {
  --pos-primary: #1e3a5f;
  --pos-primary-dark: #13263f;
  --pos-accent: #ab8341;
  --pos-bg: #f3f5f7;
  --pos-surface: #ffffff;
  --pos-border: #dfe3e8;
  --pos-text: #1e2733;
  --pos-muted: #66707c;
  --pos-danger: #b3453d;
  --pos-success: #3c7a5a;
  --radius: 10px;
  /* Height available below the navbar for the full-screen page layouts
     (Drop Off / Menu columns, Customers, Employees, Pickup, Location):
     the window's height, minus the navbar's real height, minus .pos-main's
     top + bottom padding (2 x 1.25rem). --pos-vh and --pos-nav-h are
     measured by the small script right after the navbar in _Layout.cshtml
     (so a taller wrapped navbar or a phone's browser bars are accounted
     for); the fallbacks here only apply before it runs. A hard-coded 100px
     used to be here — the navbar is actually ~64px, so pages came out a
     few pixels too tall and always showed a page scrollbar. */
  --pos-fit-h: calc(var(--pos-vh, 100vh) - var(--pos-nav-h, 64px) - 2.5rem);
}

* { box-sizing: border-box; }

body.pos-body {
  background: var(--pos-bg);
  color: var(--pos-text);
  font-family: "Segoe UI", system-ui, -apple-system, sans-serif;
}

.pos-navbar {
  background: linear-gradient(90deg, var(--pos-primary-dark), var(--pos-primary));
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
  padding-top: .7rem;
  padding-bottom: .7rem;
  /* Stays put at the top of the viewport as the page content below
     scrolls, rather than scrolling away with it — the nav (and Sign Out/
     printer setup/etc. it carries) is always reachable. z-index keeps it
     above ordinary page content (search-result dropdowns sit at 1000)
     but still under Bootstrap's own modals/dropdowns (1050+). */
  position: sticky;
  top: 0;
  z-index: 1030;
}
.pos-navbar .navbar-brand {
  font-size: 1.15rem;
  letter-spacing: .02em;
}
.pos-navbar .navbar-brand i { color: var(--pos-accent); }
.pos-navbar .nav-link {
  color: rgba(255, 255, 255, 0.82);
  font-weight: 500;
  font-size: .92rem;
  padding: .5rem 1rem;
  margin: 0 .1rem;
  border-radius: 6px;
  transition: background-color .15s ease, color .15s ease;
}
.pos-navbar .nav-link:hover {
  color: #fff;
  background: rgba(255, 255, 255, 0.1);
}
.pos-navbar .nav-link.active {
  color: var(--pos-primary-dark);
  background: #fff;
  font-weight: 600;
}
.pos-navbar .nav-divider {
  width: 1px;
  height: 22px;
  background: rgba(255, 255, 255, 0.25);
  margin: 0 .5rem;
}
.pos-navbar .nav-signout {
  color: rgba(255, 255, 255, 0.65);
}
.pos-navbar .nav-signout:hover {
  color: #fff;
  background: rgba(255, 255, 255, 0.1);
}

.pos-main { padding: 1.25rem; }

/* Bootstrap's .container-fluid adds its own left/right gutter on top of
   whatever padding wraps it — for the three page-content containers here
   (Home/DropOff/Menu, all direct children of .pos-main) that stacks with
   the padding above and makes the sides wider than the top/bottom. Zeroed
   out so .pos-main's own padding is the only margin on any side. Scoped to
   .pos-main so the navbar's own .container-fluid (which needs its normal
   gutter) is untouched. */
.pos-main > .container-fluid { padding-left: 0; padding-right: 0; }

/* ---- Cards / surfaces ---- */
.pos-card {
  background: var(--pos-surface);
  border: 1px solid var(--pos-border);
  border-radius: var(--radius);
  box-shadow: 0 1px 2px rgba(0,0,0,.04);
}

.pos-card-header {
  padding: .85rem 1.1rem;
  border-bottom: 1px solid var(--pos-border);
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.pos-card-body { padding: 1.1rem; }

.pos-card-footer {
  background: #fafbfb;
  border-radius: 0 0 var(--radius) var(--radius);
}

/* ---- Ticket column fills available height, cart scrolls internally ---- */
.ticket-column {
  /* see --pos-fit-h in :root */
  height: var(--pos-fit-h);
  min-height: 420px;
}
.ticket-card {
  flex: 1 1 auto;
  min-height: 0; /* required so the flex child can actually shrink and scroll */
  display: flex;
  flex-direction: column;
}
.ticket-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}

/* ---- Customers grid: sized to fill the remaining viewport height instead
   of a fixed vh fraction, so it always fits the screen — header and footer
   (pagination) stay put while the table body scrolls in between. ----
   .grid-fit-card is the same pattern, generically named, for any other
   ticket-list grid that should behave the same way (Pickup, Location). */
.cust-grid-card, .grid-fit-card {
  height: var(--pos-fit-h);
  min-height: 420px;
  display: flex;
  flex-direction: column;
}

/* Customers page left panel (Information/Tickets tabs) — same fits-the-
   screen-and-scrolls treatment as the ticket grids: the card is pinned to
   the viewport height, and whichever tab is active scrolls internally
   instead of growing the whole page (most relevant for the Tickets tab,
   which can run long for a regular customer). */
.cust-form-card {
  height: var(--pos-fit-h);
  min-height: 420px;
  display: flex;
  flex-direction: column;
}
.cust-form-card .tab-content {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
.cust-form-card .tab-content > .tab-pane.active {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
}
.cust-form-card .tab-content > .tab-pane.active .pos-card-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}
/* Employees module reuses .cust-form-card but has no tabs — its
   .pos-card-body is a direct child, so it needs the same flex/scroll
   treatment applied directly rather than through the tab-pane rule above. */
.cust-form-card > .pos-card-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}
.cust-grid-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
}
.cust-grid-scroll thead th {
  position: sticky;
  top: 0;
  z-index: 1;
}

/* ---- Left column: Customer card keeps its natural size, Tickets card
   grows to fill whatever height is left, scrolling internally ---- */
.left-column {
  height: var(--pos-fit-h);
  min-height: 420px;
}
.tickets-card {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
.tickets-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}

/* ---- Tile grid (categories / items / sub-items / modifiers) ---- */
.tile-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--tile-btn-width), 1fr));
  gap: .5rem;
  max-height: 320px;
  overflow-y: auto;
  padding: .25rem;
}

/* Small tiles — used for the Modifiers strip, capped to about two visible
   rows before scrolling. Same layout as the Category/Item/Sub-Item tiles
   above (.tile-grid's column width, .tile's min-height/padding/font) —
   every size here is calc()'d as --tile-modifier-scale (Preferences >
   General > Modifier Size, a plain fraction like 0.7 for 70% — configurable,
   not hardcoded) times the SAME --tile-btn-* variables Items uses, not a
   separate preference and not a different shape (a fixed height or forced
   square fought longer labels, spilling text outside the tile instead of
   wrapping/growing the way Items handles it fine). min-height (not a
   fixed height) is what lets a longer label wrap and grow the tile a bit,
   exactly like Items does. Changing Button Width/Height/Font Size OR
   Modifier Size in Preferences resizes Modifiers accordingly — there's
   nothing else to configure here. */
.tile-grid-sm {
  grid-template-columns: repeat(auto-fill, minmax(calc(var(--tile-btn-width) * var(--tile-modifier-scale)), 1fr));
  gap: .35rem;
  max-height: 190px;
  /* Rows size to the tiles' own height, not stretched to fill whatever
     extra vertical space the (now taller) Modifiers card has — without
     this, grid's default align-content:stretch turns every tile into a
     tall rectangle instead of a fixed-size button. */
  align-content: start;
}
.tile-grid-sm .tile {
  min-height: calc(var(--tile-btn-height) * var(--tile-modifier-scale));
  padding: .28rem .21rem;
  font-size: calc(var(--tile-btn-font) * var(--tile-modifier-scale));
}
.tile-grid-sm .tile-img {
  width: 28px;
  height: 28px;
  object-fit: contain;
  object-position: center;
  margin-bottom: .21rem;
}
.tile-grid-sm .tile-price { font-size: calc(var(--tile-btn-font) * var(--tile-modifier-scale) * 0.9); }

/* Menu Setup only (scoped via #setup-page, since .tile-grid-flat is shared
   with Drop Off/Menu's own category & item tiles, which stay their normal
   size) — every tab's tiles (Categories/Items/Sub-Items/Modifiers) are the
   same size here, a little smaller than Modifiers used to be on its own. */
#setup-page .tile-grid-flat {
  grid-template-columns: repeat(auto-fill, minmax(108px, 1fr));
}
#setup-page .tile-grid-flat .tile {
  min-height: 96px;
  font-size: .82rem;
}

/* Equal-width Modifier type tabs on Drop Off, regardless of label length. */
#modifier-type-tabs .btn {
  width: 80px;
}

/* Items no longer scrolls itself — its own card (.items-scroll) handles
   scrolling instead, so the grid shouldn't also cap/scroll internally. */
.tile-grid-flat {
  max-height: none;
  overflow-y: visible;
}

/* ---- Middle column: Categories (fixed size), Items (grows to fill
   whatever's left, scrolling internally), Modifiers (pinned at the
   bottom, always visible) — each its own card, like Modifiers already was ---- */
.menu-column {
  height: var(--pos-fit-h);
  min-height: 420px;
}
.categories-card {
  flex: 0 0 auto;
}
/* Categories are pinned to a single horizontally-scrolling row instead of
   wrapping onto a second row and growing the whole menu column — the row's
   own tile height now sets the card's height, so it always "fits" one row
   regardless of how many categories there are. */
.categories-card .tile-grid {
  display: flex;
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  max-height: none;
}
.categories-card .tile-grid .tile {
  flex: 0 0 var(--tile-btn-width);
}
.items-card {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
.items-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}
.modifiers-card {
  flex: 0 0 auto;
  height: 245px;
  display: flex;
  flex-direction: column;
}
.modifiers-card .pos-card-body {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
}
.modifiers-card .pos-card-body .tile-grid {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}

.tile {
  position: relative;
  border: 1px solid var(--pos-border);
  border-radius: 8px;
  background: #fff;
  padding: .4rem .3rem;
  min-height: var(--tile-btn-height);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  font-size: var(--tile-btn-font);
  font-weight: 600;
  cursor: pointer;
  transition: transform .08s ease, box-shadow .08s ease;
  user-select: none;
}

.tile-sub-badge {
  position: absolute;
  top: -6px;
  right: -6px;
  min-width: 20px;
  height: 20px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--pos-accent);
  color: #fff;
  font-weight: 700;
  font-size: .75rem;
  line-height: 20px;
  text-align: center;
  box-shadow: 0 1px 3px rgba(0,0,0,.25);
}

.tile-img {
  width: 40px;
  height: 40px;
  object-fit: contain;
  margin-bottom: .3rem;
  pointer-events: none;
}

.tile-label { line-height: 1.15; }

.tile:hover { transform: translateY(-1px); box-shadow: 0 2px 6px rgba(0,0,0,.08); }
.tile:active { transform: translateY(0); }
.tile.selected { outline: 2px solid var(--pos-accent); outline-offset: -2px; }
/* Price follows the tile's own font color (dimmed), so it stays readable on
   dark or colored tiles (e.g. Black/Navy/Red color modifiers). */
.tile .tile-price { display: block; font-weight: 400; font-size: .72rem; color: inherit; opacity: .75; margin-top: 2px; }

/* Tiles with a photo (Category/Item/Sub-Item/Modifier images, on both Drop
   Off/Menu and the Menu Setup admin screens) — the image sits centered at
   --tile-img-size of the tile (object-fit: contain, so the whole picture
   shows rather than getting cropped) over a light neutral background,
   with the label/price in a light 70%-opaque bar over the bottom so they
   stay readable regardless of what's in the picture. --tile-img-size is
   set (as a percentage, e.g. "80%") on <html> by whichever page loaded —
   see dropoff.js/menu.js/setup.js — from Preferences > General > Image
   Size; :root's own value here is just the fallback before that JS runs.
   Tiles with no image at all skip this treatment entirely (no
   .tile-has-image class) and keep the plain colored-tile look; a photo
   that fails to load is just removed, leaving the caption bar showing on
   its own. The image+caption sit in their own inner .tile-photo wrapper
   (not .tile itself) so THAT is what clips to the rounded corners —
   leaves .tile itself un-clipped, so the sub-item "+" badge (which pokes
   slightly outside the tile on purpose) still displays in full instead of
   getting cut off. */
:root {
  --tile-img-size: 80%;
  /* Category/Item/Sub-Item tile size, set on <html> by whichever page
     loaded (dropoff.js/menu.js/setup.js) from Preferences > General >
     Button Width/Height/Font Size — these :root values are just the
     fallback before that JS runs. Modifier tiles (.tile-grid-sm) derive
     their own size from these at 70% via calc(), rather than being a
     separate preference. */
  --tile-btn-width: 88px;
  --tile-btn-height: 78px;
  --tile-btn-font: 12px;
  /* Modifier tiles' size relative to the three above — a plain fraction
     (0.7 = 70%), not a percentage string, so calc() can multiply by it
     directly. Configurable (Preferences > General > Modifier Size), not a
     hardcoded 0.7 — this is just the fallback before that JS runs. */
  --tile-modifier-scale: 0.7;
}
.tile.tile-has-image {
  padding: 0;
}
.tile-photo {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: 7px; /* 1px less than .tile's 8px so it clears the tile's own 1px border cleanly */
  background: transparent; /* lets a transparent PNG show the tile's own background (its custom bg color, or plain white) through instead of forcing a fixed color behind it */
}
.tile.tile-has-image .tile-photo .tile-img {
  position: absolute;
  /* Top-anchored, not vertically centered across the whole tile — the
     image sits near the top with the caption bar's own space below it,
     rather than centering through (and partly behind) that bottom band. */
  top: 6%;
  left: calc((100% - var(--tile-img-size)) / 2);
  width: var(--tile-img-size);
  height: var(--tile-img-size);
  object-fit: contain;
  margin: 0;
}
.tile.tile-has-image .tile-photo .tile-caption {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 40%; /* fixed band across the bottom of the tile, rather than sizing to just the text */
  background: rgba(255, 255, 255, .7);
  padding: .2rem .35rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  line-height: 1.15;
}
.tile.tile-has-image .tile-photo .tile-label { color: var(--pos-text); }
.tile.tile-has-image .tile-photo .tile-price { color: var(--pos-muted); opacity: 1; margin-top: 0; font-size: .64rem; }

/* ---- Setup (menu admin) screens ---- */
.tile.tile-add {
  background: transparent;
  border: 2px dashed var(--pos-border);
  color: var(--pos-muted);
  font-weight: 400;
}
.tile.tile-add:hover { border-color: var(--pos-primary); color: var(--pos-primary); }
.tile.tile-add .bi { font-size: 1.4rem; display: block; margin-bottom: .2rem; }
.tile .tile-code { display: block; font-size: .62rem; opacity: .75; margin-top: 1px; }
.tile[draggable="true"] { cursor: grab; }
.tile.dragging { opacity: .4; }

/* ---- Image picker (Setup modals) ---- */
.image-preview-box {
  width: 120px;
  height: 120px;
  border: 1px dashed var(--pos-border);
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  overflow: hidden;
  background: #fff;
}
.image-preview-box:hover { border-color: var(--pos-primary); }
.image-preview-box img { width: 100%; height: 100%; object-fit: contain; }
.image-preview-placeholder { color: var(--pos-muted); font-size: .72rem; text-align: center; line-height: 1.3; }
.image-preview-placeholder .bi { font-size: 1.4rem; }

.image-picker-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: .6rem;
  max-height: 55vh;
  overflow-y: auto;
}
.image-picker-item {
  border: 1px solid var(--pos-border);
  border-radius: 8px;
  padding: .4rem;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .3rem;
  background: #fff;
  text-align: center;
}
.image-picker-item img { width: 64px; height: 64px; object-fit: contain; }
.image-picker-item span { font-size: .62rem; color: var(--pos-muted); word-break: break-all; line-height: 1.2; }
.image-picker-item:hover { border-color: var(--pos-primary); }
.image-picker-item.selected { outline: 2px solid var(--pos-accent); outline-offset: -2px; }

/* ---- Ticket cart table ---- */
.cart-table { font-size: .9rem; }
.cart-table td, .cart-table th { vertical-align: middle; }
.cart-table tbody tr.cart-row { cursor: pointer; }
.cart-table tbody tr.cart-row:hover { --bs-table-bg: #f6f7f9; }
/* Pickup & Payment grid: the row itself is clickable (toggles that row's
   checkbox), but Ticket# specifically opens the detail popup instead —
   underlined-on-hover marks it as the one cell that does something
   different from the rest of the row. */
.pickup-ticket-link {
  color: var(--pos-accent);
  text-decoration: underline;
  text-decoration-color: transparent;
  transition: text-decoration-color .1s ease;
}
.pickup-ticket-link:hover { text-decoration-color: currentColor; }
/* Drop Off cart grid: clicking a line's own description opens Edit Item
   (replacing the old separate pencil-icon button) — underlined-on-hover
   marks it as clickable, same idea as the Pickup ticket# link above. */
.cart-line-desc-edit {
  cursor: pointer;
  text-decoration: underline;
  text-decoration-color: transparent;
  transition: text-decoration-color .1s ease;
}
.cart-line-desc-edit:hover { text-decoration-color: currentColor; }
/* Modifiers, notes, and linked-alteration lines sit under their item's name
   — indented so they read as a sub-detail of that line rather than a line
   of their own. */
.cart-modifier-text { margin-left: 1.1rem; }

/* Belt-and-suspenders for modal headers with an extra icon button before
   the close button (activity log, etc.) — guarantees the title stays left
   and everything else (icon + close) is pinned to the far right, even if a
   header ever ends up with more than the usual two children. */
.modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

/* ---- Shared app dialog (Dialogs.alert / Dialogs.confirm) — a styled
   stand-in for the browser's native alert()/confirm(), used everywhere in
   the app instead of those. ---- */
.app-dialog {
  border: none;
  border-radius: 16px;
  box-shadow: 0 20px 50px rgba(31, 42, 44, 0.22);
  overflow: hidden;
}
.app-dialog .app-dialog-close {
  position: absolute;
  top: .9rem;
  right: .9rem;
  z-index: 1;
}
.app-dialog-icon {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-left: auto;
  margin-right: auto;
  font-size: 1.9rem;
}
.app-dialog-badge-info { background: #e4edf7; color: #2c5faa; }
.app-dialog-badge-success { background: #e1f3e7; color: var(--pos-success); }
.app-dialog-badge-error { background: #fbe4e1; color: var(--pos-danger); }
.app-dialog-badge-warning { background: #fdf1de; color: #b06a12; }
.app-dialog .app-dialog-title {
  font-weight: 700;
  font-size: 1.15rem;
  color: var(--pos-text);
}
.app-dialog .app-dialog-message {
  color: var(--pos-muted);
  font-size: .95rem;
  line-height: 1.5;
  white-space: pre-line;
}
.app-dialog-footer .btn {
  min-width: 108px;
  font-weight: 600;
}
.cart-table tbody tr.cart-row.selected {
  --bs-table-bg: #d8ebe8;
  box-shadow: inset 3px 0 0 0 var(--pos-primary);
}
.cart-table tbody tr.cart-row.selected td { font-weight: 600; }

/* Drop Off's cart table specifically (not the generic .cart-table used
   elsewhere, e.g. Pickup/Location grids) — Item is the column actually
   worth reading, so it gets noticeably more room than Qty/Price/Total. */
#dropoff-cart-table th:first-child,
#dropoff-cart-table td:first-child {
  width: 46%;
}
.cart-starch-tag { color: var(--pos-primary); font-weight: 600; }

.edit-line { color: var(--pos-muted); vertical-align: middle; }
.edit-line:hover { color: var(--pos-primary); }

.qty-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 28px;
  height: 28px;
  padding: 0 .4rem;
  border-radius: 6px;
  background: var(--pos-primary);
  color: #fff;
  font-weight: 700;
  font-size: .95rem;
}
.cart-empty { color: var(--pos-muted); text-align: center; padding: 2rem 0; }

.totals-panel .row { padding: .15rem 0; }
.totals-panel .label { color: var(--pos-muted); }
.totals-panel .grand-total { font-size: 1.35rem; font-weight: 700; color: var(--pos-primary-dark); }
.totals-panel.pos-card-body { padding: .75rem .9rem; }
.totals-panel hr { margin: .5rem 0; }

/* ---- Totals panel: compact multi-column layout for Sub Total/Tax/Misc
   Charge/Discount/Pieces — label and amount sit on the same line to save
   vertical space, with Total kept full-width and prominent below ---- */
.totals-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: .3rem 1.25rem;
}
.totals-item {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: .5rem;
  font-size: .85rem;
}
.totals-label {
  color: var(--pos-muted);
}
.totals-value {
  font-weight: 600;
  color: var(--pos-text);
  white-space: nowrap;
}

/* Piece count sits right next to the grand total, at comparable visual
   weight — it's the number a cashier reads back to the customer to confirm
   the count at drop-off, so it needs to be seen at a glance, not buried in
   the small Sub Total/Tax/Discount grid above. */
.pieces-value {
  font-size: 1.9rem;
  font-weight: 800;
  color: var(--pos-primary-dark);
  line-height: 1;
}
.pieces-value .pieces-unit {
  font-size: .95rem;
  font-weight: 600;
  color: var(--pos-muted);
  margin-left: .3rem;
}

/* ---- Customer search ---- */
.cust-result {
  padding: .5rem .75rem;
  border-bottom: 1px solid var(--pos-border);
  cursor: pointer;
  background: var(--pos-surface);
}
/* Faint zebra striping so adjacent rows in the dropdown read as separate
   entries at a glance, not one continuous block of text. */
.cust-result:nth-child(even) { background: #f6f7f9; }
.cust-result:hover { background: #eef1f5; }
/* The row currently reached via Up/Down arrow keys — a stronger, distinct
   color plus a left accent so it's unmistakable which row Enter will pick. */
.cust-result.kbd-active {
  background: #e3e9f0;
  box-shadow: inset 3px 0 0 0 var(--pos-primary);
}
.cust-result:last-child { border-bottom: none; }
.cust-result .name { font-weight: 600; }
.cust-result .meta { font-size: .8rem; color: var(--pos-muted); }

/* Ticket row's top line — ticket#/status on the left, balance/log icon on
   the right — must stay on one line rather than wrapping the status badge
   underneath, even in the narrow left column. The right side (balance +
   icon) is fixed-size and never shrinks; the left side truncates with an
   ellipsis in the rare case there still isn't room. */
.ticket-row-line1 {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: nowrap;
  gap: .4rem;
}
.ticket-row-line1 .name {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.ticket-row-line1 .ticket-row-right {
  display: flex;
  align-items: center;
  gap: .35rem;
  flex-shrink: 0;
  white-space: nowrap;
}
.cust-result .balance-highlight { padding: 1px 6px; font-size: .78rem; }

/* Selected customer name in the Drop Off customer panel — bigger than the
   phone/balance lines under it so the cashier can confirm who's on screen
   at a glance. */
.selected-customer-name {
  font-size: 1.3rem;
  font-weight: 700;
  color: var(--pos-primary-dark);
  line-height: 1.2;
  margin-bottom: .15rem;
}

/* ---- Drop Off's "New Ticket" / "Active Ticket #___" banner — bigger and
   bolder than an ordinary status badge since it's the one thing on screen
   telling staff which ticket they're currently editing. */
.ticket-mode-badge {
  font-size: 1.05rem;
  font-weight: 700;
  padding: .45em 1em;
  letter-spacing: .01em;
  border-radius: 999px;
  box-shadow: 0 1px 5px rgba(0, 0, 0, .15);
}

/* ---- Ticket status badges ---- */
.badge-status-A { background: #dff0e4; color: var(--pos-success); }
.badge-status-C { background: #fbe8d3; color: #b06a12; }
.badge-status-D, .badge-status-V { background: #eee; color: var(--pos-muted); }
/* Welcome-card-only Pickup Request statuses (PickedUp/Missed) — Requested/
   Confirmed reuse the A/C colors above. Also reused for a ticket's
   Delivery status badge once a Delivery request takes over that row (see
   deliveryStatusMeta in login.js) — Delivered reuses PickedUp's green,
   a missed delivery reuses Missed's red, and EnRoute gets its own blue. */
.badge-status-PickedUp { background: #dff0e4; color: var(--pos-success); }
.badge-status-Missed { background: #fbe1e1; color: var(--pos-danger, #dc3545); }
.badge-status-EnRoute { background: #dde8fb; color: #2b5fb0; }

/* ---- Dashboard (Home) — shared by the Manager view (Index) and the
   Staff view (Staff). ---- */
.dash-head { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 1rem; margin-bottom: 1rem; }
.dash-head h1 { font-size: 1.5rem; font-weight: 700; margin: 0; }
.dash-head .sub { color: var(--pos-muted); font-size: .85rem; }
.dash-head .employee-chip { padding: .15rem .65rem; font-size: .8rem; }
.dash-section-title { font-size: .75rem; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--pos-muted); margin: 1.25rem 0 .6rem; }
.mix-bar-success { background: var(--pos-success); }

/* Manager: one control bar — range, customer filter, Open Work */
.range-bar { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.range-bar .btn-group .btn { padding: .35rem .8rem; font-size: .875rem; }
.range-dates { font-size: .85rem; color: var(--pos-muted); white-space: nowrap; }
.cust-filter { position: relative; width: 220px; }
.cust-filter > i { position: absolute; left: .65rem; top: 50%; transform: translateY(-50%); color: var(--pos-muted); pointer-events: none; z-index: 1; }
.cust-filter > input { padding-left: 2rem; font-size: .875rem; }
.cust-filter > .pos-card { top: 100%; margin-top: .25rem; }
.cust-chip { background: #eef2f6; border-radius: 999px; padding: .3rem .4rem .3rem .75rem; font-size: .85rem; font-weight: 600; }
.cust-chip .btn-link { color: var(--pos-muted); line-height: 1; }

/* Manager: headline numbers */
.hl-card { padding: 1.1rem 1.25rem; cursor: pointer; position: relative; overflow: hidden; height: 100%; transition: transform .12s, box-shadow .12s; }
.hl-card:hover, .hl-card:focus-visible { transform: translateY(-2px); box-shadow: 0 6px 18px rgba(0,0,0,.08); }
.hl-card::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px; background: var(--pos-primary); }
.hl-card.c-success::before { background: var(--pos-success); }
.hl-card.c-accent::before { background: var(--pos-accent); }
.hl-card.c-info::before { background: #3f7f8f; }
.hl-label { font-size: .8rem; color: var(--pos-muted); font-weight: 600; display: flex; align-items: center; gap: .4rem; }
.hl-value { font-size: 2rem; font-weight: 700; line-height: 1.1; margin: .35rem 0 .2rem; }
.hl-sub { font-size: .8rem; color: var(--pos-muted); }

/* Manager: Needs attention strip */
.attn { display: grid; grid-template-columns: repeat(6, 1fr); }
.attn-item { padding: .85rem 1rem; border-right: 1px solid var(--pos-border); cursor: pointer; transition: opacity .15s; }
.attn-item:last-child { border-right: 0; }
.attn-item:hover, .attn-item:focus-visible { background: #f8f9fb; }
.attn-num { font-size: 1.35rem; font-weight: 700; line-height: 1.1; }
.attn-label { font-size: .78rem; font-weight: 600; }
.attn-sub { font-size: .72rem; color: var(--pos-muted); }
.attn-item.hot .attn-num { color: var(--pos-danger); }
.attn-item.warn .attn-num { color: var(--pos-accent); }
.attn-item.zero { opacity: .45; }
@media (max-width: 991.98px) {
  .attn { grid-template-columns: repeat(3, 1fr); }
  .attn-item:nth-child(3n) { border-right: 0; }
  .attn-item:nth-child(-n+3) { border-bottom: 1px solid var(--pos-border); }
}

/* Manager: Breakdown tabs */
.seg-tabs { display: flex; gap: .25rem; background: var(--pos-bg); padding: .2rem; border-radius: 8px; }
.seg-tabs button { border: 0; background: transparent; font-size: .8rem; font-weight: 600; padding: .25rem .7rem; border-radius: 6px; color: var(--pos-muted); }
.seg-tabs button.active { background: #fff; color: var(--pos-text); box-shadow: 0 1px 3px rgba(0,0,0,.1); }

/* Staff: customer lookup */
.staff-lookup { width: 420px; max-width: 100%; }
.staff-lookup > input { font-size: 1.05rem; padding: .7rem 1rem .7rem 2.6rem; border-radius: 10px; }
.staff-lookup > i { left: 1rem; font-size: 1.1rem; }
.staff-picked { display: flex; align-items: center; gap: .75rem; flex-wrap: wrap; padding: .75rem 1rem; margin-bottom: 1rem; }
.staff-picked .name { font-weight: 700; }

/* Staff: task tiles */
.act-tile { display: flex; align-items: center; gap: 1rem; padding: 1.4rem; border-radius: var(--radius); color: #fff; text-decoration: none; min-height: 110px; height: 100%; transition: transform .12s; }
.act-tile:hover, .act-tile:focus-visible { color: #fff; transform: translateY(-2px); }
.act-tile i { font-size: 2.2rem; }
.act-tile h3 { font-size: 1.25rem; margin: 0; font-weight: 700; }
.act-tile p { margin: 0; font-size: .85rem; opacity: .8; }
.act-tile .act-for { display: block; font-size: .75rem; font-weight: 600; opacity: .95; margin-top: .15rem; }
.act-tile.tile-dropoff { background: linear-gradient(135deg, #2f5d62, #1f3f42); }
.act-tile.tile-pickup { background: linear-gradient(135deg, #6a8f3f, #3f5c26); }
.act-tile.tile-location { background: linear-gradient(135deg, #4a6fa5, #2c4570); }
.act-tile.tile-customers { background: linear-gradient(135deg, #8a5fa0, #5a3a70); }

/* Staff: Today's work cards */
.work-card { padding: 1rem 1.15rem; cursor: pointer; display: flex; align-items: center; gap: .9rem; transition: transform .12s; height: 100%; }
.work-card:hover, .work-card:focus-visible { transform: translateY(-2px); }
.work-ico { width: 44px; height: 44px; border-radius: 10px; display: grid; place-items: center; font-size: 1.3rem; background: #eef2f6; color: var(--pos-primary); flex: 0 0 auto; }
.work-num { font-size: 1.6rem; font-weight: 700; line-height: 1; }
.work-num small { font-size: .9rem; font-weight: 400; color: var(--pos-muted); }
.work-label { font-size: .85rem; font-weight: 600; }
.work-sub { font-size: .75rem; color: var(--pos-muted); }
.work-card.hot .work-ico { background: #f8e5e3; color: var(--pos-danger); }
.work-card.hot .work-num { color: var(--pos-danger); }
.work-card.warn .work-ico { background: #f5ecdc; color: var(--pos-accent); }
.work-card.ok .work-ico { background: #e3efe8; color: var(--pos-success); }
.live-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--pos-success); margin-right: .35rem; box-shadow: 0 0 0 3px rgba(60,122,90,.2); }

/* ---- Location grid: rows past their due date/time ---- */
.row-overdue > td { background: #fbe2e0 !important; color: #8a2a22; }

/* ---- Pickup grid: ticket # and rack stand out at a glance ---- */
.cell-strong { font-weight: 700; font-size: 1.15rem; }

.employee-chip {
  border: 1px solid var(--pos-border);
  border-radius: 999px;
  padding: .35rem .9rem;
  font-size: .85rem;
  background: #fff;
}

/* ---- Dashboard: KPI strip ---- */
.kpi-card {
  padding: 1rem 1.1rem;
  position: relative;
  overflow: hidden;
}
.kpi-clickable {
  cursor: pointer;
  transition: transform .12s ease, box-shadow .12s ease;
}
.kpi-clickable:hover, .kpi-clickable:focus-visible {
  transform: translateY(-2px);
  box-shadow: 0 6px 16px rgba(0, 0, 0, .1);
  outline: none;
}

.kpi-icon {
  position: absolute;
  top: .8rem;
  right: .9rem;
  font-size: 1.4rem;
  opacity: .18;
}
.kpi-value { font-size: 1.6rem; font-weight: 700; line-height: 1.15; }
.kpi-label { font-size: .78rem; color: var(--pos-muted); text-transform: uppercase; letter-spacing: .03em; margin-top: .15rem; }
.kpi-sub { font-size: .74rem; color: var(--pos-muted); margin-top: .35rem; }
.kpi-card::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 4px;
}
.kpi-primary::before { background: var(--pos-primary); }
.kpi-success::before { background: var(--pos-success); }
.kpi-accent::before { background: var(--pos-accent); }
.kpi-info::before { background: #3f7f8f; }
.kpi-danger::before { background: var(--pos-border); }
.kpi-danger.kpi-danger-active::before { background: var(--pos-danger); }
.kpi-danger.kpi-danger-active .kpi-value { color: var(--pos-danger); }

/* ---- Dashboard: 7-day trend chart (plain CSS bars, no chart lib) ---- */
.trend-chart {
  display: flex;
  align-items: flex-end;
  gap: .6rem;
  height: 150px;
  padding-top: .5rem;
}
.trend-col {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  height: 100%;
}
.trend-bar-track {
  flex: 1 1 auto;
  width: 100%;
  display: flex;
  align-items: flex-end;
  max-width: 34px;
  margin: 0 auto;
}
.trend-bar {
  width: 100%;
  background: linear-gradient(180deg, var(--pos-primary), var(--pos-primary-dark));
  border-radius: 4px 4px 0 0;
  min-height: 3px;
  transition: height .25s ease;
}
.trend-label {
  font-size: .72rem;
  color: var(--pos-muted);
  margin-top: .4rem;
}

/* ---- Dashboard: horizontal mix bars (service / payment breakdown) ---- */
.mix-row-top {
  display: flex;
  justify-content: space-between;
  font-size: .82rem;
  margin-bottom: .25rem;
}
.mix-label { font-weight: 600; }
.mix-amount { color: var(--pos-muted); }
.mix-track {
  background: var(--pos-bg);
  border-radius: 999px;
  height: 8px;
  overflow: hidden;
}
.mix-bar { height: 100%; border-radius: 999px; }
.mix-bar-primary { background: var(--pos-primary); }
.mix-bar-accent { background: var(--pos-accent); }

/* ---- Dashboard: recent activity feed ---- */
.activity-card { display: flex; flex-direction: column; }
.activity-scroll { max-height: 320px; overflow-y: auto; }
.activity-list { list-style: none; padding: 0; margin: 0; }
.activity-row {
  display: flex;
  gap: .6rem;
  padding: .55rem 0;
  border-bottom: 1px solid var(--pos-border);
}
.activity-row:last-child { border-bottom: none; }
.activity-icon { font-size: 1rem; margin-top: .15rem; }
.activity-desc { font-size: .85rem; }
.activity-meta { font-size: .72rem; color: var(--pos-muted); }

/* ---- Ticket info modal: pickup location callout ---- */
.location-callout {
  background: linear-gradient(135deg, #2f5d62, #1f3f42);
  color: #fff;
  border-radius: var(--radius);
  padding: 1.1rem 1rem;
  text-align: center;
}
.location-label { font-size: .8rem; opacity: .8; text-transform: uppercase; letter-spacing: .04em; }
.location-value { font-size: 2.4rem; font-weight: 700; line-height: 1.2; }
/* Once a ticket is Done, the rack it was on is just a reference, not
   something staff need to spot from across the counter — the callout
   shrinks down instead of taking up the same prominent space it does for
   an Active/Ready ticket still waiting to be picked up. */
.location-callout.location-callout-sm { padding: .55rem .75rem; }
.location-callout.location-callout-sm .location-label { font-size: .68rem; }
.location-callout.location-callout-sm .location-value { font-size: 1.3rem; }

/* ---- Ticket info modal: multi-column field grid (Customer/Timeline/
   Financials/Other) — several compact "label — value" cells per row
   instead of one long stacked list ---- */
.info-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: .25rem 1.25rem;
}
.info-item {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: .5rem;
  font-size: .85rem;
  padding: .15rem 0;
  border-bottom: 1px dashed var(--pos-border);
}
.info-label { color: var(--pos-muted); }
.info-value { font-weight: 600; color: var(--pos-text); text-align: right; }

/* ---- Change due popup ---- */
.change-due-amount { font-size: 2.6rem; font-weight: 700; color: var(--pos-success); }

/* ---- Payment module: Total Balance / Charge Amount / Balance readouts ----
   Shared by Drop Off's payment modal, Pickup's payment modal, and Pickup's
   inline "pay the customer's balance" card — all three read-only amounts
   get the same caption/value treatment so captions and amounts are always
   visually distinct from each other and from the one editable field
   (Pay Amount) sitting between them. */
.payment-readout { text-align: center; }
.payment-readout-label {
  display: block;
  color: var(--pos-muted);
  font-size: .78rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  margin-bottom: .15rem;
  text-align: left;
}
.payment-readout-value {
  font-size: 1.7rem;
  font-weight: 700;
  color: var(--pos-primary-dark);
  font-variant-numeric: tabular-nums;
  line-height: 1.15;
}
.payment-readout-value.payment-readout-lg { font-size: 2.1rem; }
.payment-readout-balance { color: var(--pos-danger); }
.payment-readout-balance.payment-readout-change { color: var(--pos-success); }

/* Charge Amount's caption line — when a payment surcharge is actually
   included in Charge Amount (as opposed to deferred onto the balance —
   see the confirm popup's own note for that case), this shows the
   surcharge amount inline, right-aligned, in small text next to the
   "Charge Amount" caption itself. */
.payment-readout-caption-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: .5rem;
}
.payment-readout-surcharge-note {
  font-size: .72rem;
  font-weight: 600;
  color: var(--pos-muted);
  white-space: nowrap;
}

/* Confirm Payment popup's who/what/how block — Customer/Ticket/Payment
   Method(/Card on File) sit above the dollar readouts as plain label:value
   rows, distinct from the big centered payment-readout figures below them. */
.payment-confirm-summary {
  background: var(--pos-surface-alt, #f8f9fa);
  border-radius: .5rem;
  padding: .75rem .9rem;
}
.payment-confirm-summary-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: .75rem;
  padding: .2rem 0;
}
.payment-confirm-summary-row + .payment-confirm-summary-row {
  border-top: 1px solid rgba(0, 0, 0, .06);
}
.payment-confirm-summary-label {
  color: var(--pos-muted);
  font-size: .78rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  white-space: nowrap;
}
.payment-confirm-summary-value {
  font-weight: 600;
  text-align: right;
}

/* Pay Amount — the single editable amount in the payment module; styled
   big/bold/centered so it reads at the same visual weight as the read-only
   amounts around it, while a solid border still marks it as an input. */
.payment-amount-input {
  font-size: 1.6rem;
  font-weight: 700;
  text-align: center;
  font-variant-numeric: tabular-nums;
  /* Suppresses the native up/down spinner — Firefox. */
  -moz-appearance: textfield;
}
/* Suppresses the native up/down spinner — Chrome/Safari/Edge (WebKit/Blink). */
.payment-amount-input::-webkit-outer-spin-button,
.payment-amount-input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* Payment Type — Customer's Token / Semi-Integrated / Manual Payment Type
   act as one mutually-exclusive group. "active" marks whichever of the two
   buttons is the currently-selected method; the dropdown shows its own
   selection natively and clears back to its placeholder whenever a button
   takes over instead. */
.payment-method-btn.active {
  background-color: var(--pos-primary);
  border-color: var(--pos-primary);
  color: #fff;
}

/* ---- Process Ticket popup ---- */
.process-ticket-number {
  font-size: 2rem;
  font-weight: 800;
  color: var(--pos-primary-dark);
  margin-bottom: .1rem;
}
/* Same rectangle for all three actions — fixed height rather than
   letting button text/icon decide it, so Done/Take Payment/New Order
   read as equally-weighted choices. */
.process-ticket-btn {
  min-height: 64px;
  font-size: 1.05rem;
  font-weight: 700;
  border-radius: 10px;
}

/* ---- Ticket list row status cues ---- */
.ticket-row-processing { border-left: 3px solid var(--pos-success); }
.ticket-row-ready { border-left: 3px solid var(--pos-accent); }
.ticket-row-unpaid { border-left: 3px solid var(--pos-danger); }
.ticket-row-closed { border-left: 3px solid var(--pos-border); opacity: .8; }

/* ---- Highlighted info chips ---- */
.pcs-highlight, .rack-highlight {
  display: inline-block;
  border-radius: 4px;
  padding: 0 6px;
  font-weight: 700;
  color: #fff;
}
.pcs-highlight { background: var(--pos-primary); }
.rack-highlight { background: var(--pos-accent); }

.balance-highlight {
  font-weight: 700;
  padding: 1px 8px;
  border-radius: 4px;
}
.balance-highlight.due { background: var(--pos-danger); color: #fff; }
.balance-highlight.clear { background: #e7ece9; color: var(--pos-muted); }

/* ---- Due date/time bar in the Ticket panel — bigger, friendlier picker ---- */
.due-date-bar { background: #fafbfc; }

.due-date-input {
  font-size: .9rem;
  font-weight: 600;
  padding: .3rem .5rem;
  border: 1px solid var(--pos-primary);
  border-radius: 6px;
  color: var(--pos-primary-dark);
  background: #fff;
  transition: box-shadow .15s ease, border-color .15s ease;
}
.due-date-input:hover { border-color: var(--pos-accent); }
.due-date-input:focus {
  border-color: var(--pos-accent);
  box-shadow: 0 0 0 .2rem rgba(171, 131, 65, .25);
}

/* Enlarges and tints the little calendar icon (Chrome/Edge only — Safari
   and Firefox don't expose this pseudo-element, so they just get the
   bigger input/border/focus styling above). */
.due-date-input::-webkit-calendar-picker-indicator {
  cursor: pointer;
  padding: 2px;
  margin-left: 3px;
  transform: scale(1.1);
  filter: invert(32%) sepia(15%) saturate(1200%) hue-rotate(140deg) brightness(90%);
}

.due-time-input {
  font-size: .9rem;
  font-weight: 600;
  padding: .3rem 1.5rem .3rem .5rem;
  border: 1px solid var(--pos-primary);
  border-radius: 6px;
  color: var(--pos-primary-dark);
}

/* Starch quick-set buttons next to Due Date & Time — same height as those
   fields (matching padding/font-size/border), right-justified within the
   row via the ms-auto on the button group in the markup. */
#starch-btn-group .starch-btn {
  padding: .3rem .5rem;
  font-size: .78rem;
  font-weight: 600;
  border-color: var(--pos-primary);
  color: var(--pos-primary-dark);
}
#starch-btn-group .starch-btn.active {
  background: var(--pos-primary);
  border-color: var(--pos-primary);
  color: #fff;
}
/* "Save as customer's preference" button right after the starch group —
   icon-only and narrow (kept out of the btn-group itself since it's a
   different action, not another starch choice) but matched to the exact
   same padding/font-size so it lines up at the same height. */
#btn-save-starch-pref {
  padding: .3rem .5rem;
  font-size: .78rem;
}
#btn-save-starch-pref.btn-success {
  border-color: var(--bs-success);
}
.due-time-input:focus {
  border-color: var(--pos-accent);
  box-shadow: 0 0 0 .2rem rgba(171, 131, 65, .25);
}


#ticket-header-customer:not(:empty) {
  display: block;
  font-size: .75rem;
  margin-top: 2px;
}

/* ---- Dashboard drill-down modals ---- */
#dash-detail-modal .modal-content,
#dash-ticket-modal .modal-content {
  border: none;
  border-radius: 14px;
  overflow: hidden;
  box-shadow: 0 20px 50px rgba(0, 0, 0, .18);
}
.dash-modal-header {
  background: linear-gradient(120deg, var(--pos-primary-dark), var(--pos-primary));
  color: #fff;
  padding: 1.1rem 1.4rem;
  border: none;
}
.dash-modal-header .btn-close { filter: invert(1) grayscale(100%) brightness(200%); opacity: .85; }
.dash-modal-header .btn-close:hover { opacity: 1; }
.dash-modal-icon {
  width: 40px;
  height: 40px;
  border-radius: 10px;
  background: rgba(255, 255, 255, .16);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.2rem;
  flex-shrink: 0;
}
.dash-modal-title { font-size: 1.05rem; font-weight: 700; margin: 0; color: #fff; }
.dash-modal-subtitle { font-size: .8rem; color: rgba(255, 255, 255, .78); margin-top: .1rem; }
#dash-ticket-modal .modal-body { padding: 1.1rem 1.3rem; background: var(--pos-bg); }
#dash-detail-modal .modal-body { background: var(--pos-bg); }
#dash-ticket-modal .modal-footer { border-top: 1px solid var(--pos-border); background: var(--pos-surface); }

.dash-loading, .dash-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  padding: 2.75rem 1rem;
  color: var(--pos-muted);
  text-align: center;
}
.dash-loading i, .dash-empty i { font-size: 1.8rem; opacity: .5; }
.dash-loading .spinner-border { width: 1.75rem; height: 1.75rem; color: var(--pos-primary); }

/* Ticket-detail line items — no card border at all now, just a dotted
   divider between rows (matching .info-item's style elsewhere) so a
   ticket with several lines reads as a plain compact list. */
.dash-line-item {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: .75rem;
  border-bottom: 1px dashed var(--pos-border);
  padding: .3rem 0;
  margin-bottom: 0;
}
.dash-line-item:last-child { border-bottom: none; }

/* Logs Viewer — Before/After JSON blocks in the detail popup */
.log-detail-pre {
  background: var(--pos-bg);
  border: 1px solid var(--pos-border);
  border-radius: 6px;
  padding: .5rem .6rem;
  font-size: .78rem;
  max-height: 260px;
  overflow: auto;
  white-space: pre-wrap;
  word-break: break-word;
  margin: 0;
}

/* Pickup Tickets confirmation — each row's ticket#/rack in big type so
   they're readable at a glance before confirming a batch pickup. */
.pickup-confirm-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  border: 1px solid var(--pos-border);
  border-radius: 8px;
  padding: .5rem .9rem;
  background: var(--pos-surface);
}
.pickup-confirm-ticket { font-size: 1.35rem; font-weight: 800; color: var(--pos-primary-dark); }
.pickup-confirm-rack { font-size: 1.35rem; font-weight: 800; color: var(--pos-text); }
.pickup-confirm-rack.no-rack { font-size: 1rem; font-weight: 600; color: var(--pos-muted); }

/* Admin hub tiles */
.admin-tile {
  display: flex;
  flex-direction: column;
  transition: box-shadow .12s ease, transform .12s ease;
  color: var(--pos-text);
}
.admin-tile:hover {
  box-shadow: 0 4px 14px rgba(0,0,0,.08);
  transform: translateY(-2px);
}

/* Assign to Rack grid — rack number is the thing a cashier scans this
   list for, so it reads bigger/bolder than the rest of the row. */
.rack-cell-big {
  font-size: 1.15rem;
  font-weight: 800;
  color: var(--pos-primary-dark);
}

/* Search field highlight on page load — a brief pulse so it's obvious
   where typing will go without having to click first, on Drop Off,
   Pickup & Payment, and Assign to Rack. */
@keyframes search-highlight-pulse {
  0% { box-shadow: 0 0 0 0 rgba(171, 131, 65, .55); border-color: var(--pos-accent); }
  100% { box-shadow: 0 0 0 8px rgba(171, 131, 65, 0); border-color: var(--pos-border); }
}
.search-highlight-on-load {
  animation: search-highlight-pulse 1.2s ease-out;
}

/* Login screen's two big rectangle buttons */
.login-big-btn {
  min-height: 96px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .35rem;
  font-size: 1.05rem;
  font-weight: 700;
  border-radius: 10px;
}
.login-big-btn i { font-size: 1.75rem; }

/* Time Clock admin — employee group headers */
.tc-group-header {
  background: var(--pos-bg);
  border-bottom: 1px solid var(--pos-border);
}
.tc-group:last-child { border-bottom: none !important; }
.tc-day-row td { background: #fafbfc; font-size: .82rem; padding-top: .3rem; padding-bottom: .3rem; }
.dash-line-qty {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 26px;
  height: 22px;
  padding: 0 .4rem;
  border-radius: 6px;
  background: var(--pos-bg);
  color: var(--pos-primary-dark);
  font-weight: 700;
  font-size: .78rem;
  margin-right: .5rem;
}
.dash-ticket-summary-card {
  background: var(--pos-surface);
  border: 1px solid var(--pos-border);
  border-radius: 10px;
  padding: .9rem 1rem;
  margin-bottom: 1rem;
}

/* ---- Login (landing page) ---- */
.landing-body {
  background: var(--pos-bg);
}
.login-card {
  height: 100%;
}

/* Small icon toggle between the generic welcome message and Staff Sign In
   (see login.js) — pinned to the card's corner rather than taking up a
   full-width row of its own. */
.landing-toggle-btn {
  position: absolute;
  top: .75rem;
  right: .75rem;
  width: 2.1rem;
  height: 2.1rem;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  font-size: 1rem;
  line-height: 1;
  z-index: 1;
}

/* Personalized "Welcome back" card (populated from /api/landing/by-token) */
.landing-welcome-header {
  display: flex;
  align-items: center;
  gap: .85rem;
  margin: -1.5rem -1.5rem 1rem;
  padding: 1.1rem 1.5rem;
  background: linear-gradient(135deg, var(--pos-primary), var(--pos-primary-dark));
  border-radius: 12px 12px 0 0;
  color: #fff;
}
.landing-welcome-avatar {
  flex: 0 0 auto;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  background: rgba(255, 255, 255, .22);
  border: 2px solid rgba(255, 255, 255, .55);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: .95rem;
  letter-spacing: .02em;
}
.landing-welcome-header-text h2 {
  color: #fff;
}
.landing-welcome-subtitle {
  font-size: .78rem;
  color: rgba(255, 255, 255, .85);
}

.landing-welcome-info {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
}
.landing-welcome-pill {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  background: var(--pos-bg);
  border: 1px solid var(--pos-border);
  border-radius: 999px;
  padding: .3rem .75rem;
  font-size: .82rem;
  color: var(--pos-muted);
}
.landing-welcome-pill i {
  color: var(--pos-primary);
  font-size: .85rem;
}
.landing-welcome-pill-balance {
  background: #fdeeea;
  border-color: #f3c9bc;
  color: #b3401f;
  font-weight: 600;
}
.landing-welcome-pill-balance i {
  color: #c8502a;
}

/* "Request Pickup" — sits inline with the phone pill in
   #welcome-customer-info (see login.js's renderCustomerWelcome), same
   pill sizing/shape as .landing-welcome-pill but filled/primary so it
   reads as an action, not just more info. */
/* Double height (2026-10-04) and pushed to the right end of the phone's row. */
.landing-welcome-info { align-items: center; }
.landing-welcome-pickup-btn {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  margin-left: auto;
  border-radius: 14px;
  padding: .5rem 1.1rem;
  min-height: 62px;
  font-size: 1.05rem;
  font-weight: 600;
  line-height: 1.2;
  text-decoration: none;
  box-shadow: 0 3px 10px rgba(13, 110, 253, .28);
}
.landing-welcome-pickup-btn i {
  font-size: 1.35rem;
}
/* "Request" over "Pickup", centered. */
.landing-welcome-pickup-label { text-align: center; }

.landing-welcome-tickets-label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .5rem;
  font-size: .78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--pos-muted);
  margin: 1rem 0 .5rem;
}
/* Undo the label's own uppercase/letter-spacing/weight for the "Request
   Delivery" button that now shares this row (see login.js) — it's an
   action, not part of the label text. */
.landing-welcome-tickets-label .landing-welcome-pickup-btn {
  text-transform: none;
  letter-spacing: normal;
}
.landing-welcome-ticket {
  display: flex;
  align-items: flex-start;
  gap: .7rem;
  border: 1px solid var(--pos-border);
  border-left: 4px solid var(--pos-border);
  border-radius: 10px;
  padding: .7rem .85rem;
  margin-bottom: .6rem;
  background: var(--pos-surface);
  box-shadow: 0 1px 3px rgba(0, 0, 0, .04);
  transition: box-shadow .15s ease, transform .15s ease;
}
.landing-welcome-ticket:hover {
  box-shadow: 0 4px 10px rgba(0, 0, 0, .08);
  transform: translateY(-1px);
}
.landing-welcome-ticket:last-child {
  margin-bottom: 0;
}
.landing-welcome-ticket-A { border-left-color: var(--pos-success); }
.landing-welcome-ticket-C { border-left-color: #b06a12; }
.landing-welcome-ticket-D,
.landing-welcome-ticket-V { border-left-color: var(--pos-muted); }
.landing-welcome-ticket-PickedUp { border-left-color: var(--pos-success); }
.landing-welcome-ticket-Missed { border-left-color: var(--pos-danger, #dc3545); }
.landing-welcome-ticket-EnRoute { border-left-color: #2b5fb0; }
.landing-welcome-ticket-icon {
  flex: 0 0 auto;
  width: 2.1rem;
  height: 2.1rem;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--pos-bg);
  color: var(--pos-primary);
  font-size: 1rem;
}
.landing-welcome-ticket-body {
  flex: 1 1 auto;
  min-width: 0;
}
.landing-welcome-ticket-clickable {
  text-decoration: none;
  color: inherit;
  cursor: pointer;
}
.landing-welcome-ticket-clickable:hover {
  border-color: var(--pos-primary);
}
.landing-welcome-ticket-chevron {
  flex: 0 0 auto;
  align-self: center;
  color: var(--pos-muted);
  font-size: 1rem;
}
.landing-welcome-empty {
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .75rem;
  border-radius: 10px;
  background: var(--pos-bg);
  color: var(--pos-muted);
  font-size: .85rem;
}
.landing-welcome-empty i {
  font-size: 1.3rem;
  color: var(--pos-primary);
}

/* Store header bar — deliberately not the full app nav (nothing to
   navigate to before signing in), just the store's own identity. */
.landing-header {
  background: linear-gradient(90deg, var(--pos-primary-dark), var(--pos-primary));
  padding: .9rem 1.5rem;
}
.landing-header-inner {
  display: flex;
  align-items: center;
  gap: .5rem;
  color: #fff;
  font-weight: 600;
  font-size: 1.1rem;
  max-width: 1100px;
  margin: 0 auto;
}
.landing-header-inner i { color: var(--pos-accent); font-size: 1.3rem; }

/* Hero — a banner image (if the store owner set one) behind a translucent
   gradient for legibility, store name/tagline on the left, the login card
   floating on the right so it's never more than a glance away. Stacks to
   a single column on narrow screens, login card first. */
.landing-hero {
  position: relative;
  background: linear-gradient(135deg, var(--pos-primary-dark), var(--pos-primary) 60%, var(--pos-accent));
  overflow: hidden;
  padding: 3rem 1.5rem;
}
.landing-hero-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.landing-hero-overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, rgba(19, 38, 63, .82), rgba(30, 58, 95, .72) 60%, rgba(171, 131, 65, .55));
}
.landing-hero-content {
  position: relative;
  max-width: 1100px;
  margin: 0 auto;
  display: flex;
  justify-content: center;
}
.landing-hero-text {
  flex: 1 1 380px;
  max-width: 600px;
  color: #fff;
  text-align: center;
}
.landing-hero-icon {
  font-size: 2.75rem;
  color: var(--pos-accent);
  margin-bottom: .5rem;
}
.landing-hero-text h1 {
  font-size: 2rem;
  font-weight: 700;
  margin-bottom: .5rem;
}
.landing-tagline {
  font-size: 1.05rem;
  color: rgba(255, 255, 255, 0.88);
  max-width: 480px;
  margin: 0 auto;
}

/* Info sections + gallery below the hero. */
.landing-main {
  max-width: 1100px;
  margin: 0 auto;
  padding: 2.5rem 1.5rem;
}
.landing-sections {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 1.25rem;
  margin-bottom: 2rem;
}
/* New Customer signup page (Views/Account/NewCustomer.cshtml) — a single
   centered card rather than the landing page's multi-column grid, since
   there's just the one form here. */
.landing-newcustomer-wrap {
  max-width: 480px;
  margin: 0 auto;
}
.landing-section-card {
  background: var(--pos-surface);
  border: 1px solid var(--pos-border);
  border-radius: var(--radius);
  padding: 1.5rem;
}
.landing-section-icon {
  font-size: 1.5rem;
  color: var(--pos-accent);
  margin-bottom: .5rem;
}
.landing-section-card h2 {
  font-size: 1.1rem;
  font-weight: 700;
  margin-bottom: .6rem;
}
.landing-section-card p {
  color: var(--pos-muted);
  margin-bottom: 0;
  line-height: 1.55;
}

/* Welcome/About/Services now come from a WYSIWYG editor (Store Profile)
   and are rendered as raw HTML — Quill's own output is one or more <p>
   tags, plus <strong>/<em>/<a>/<ul>/<ol> when the owner uses them. This
   normalizes that block regardless of which of the three sections it's
   in (landing-section-card's own "p" rule above still applies inside it,
   since it's just a nested descendant selector). */
.landing-rich-text p:last-child {
  margin-bottom: 0;
}
.landing-rich-text a {
  color: var(--pos-primary);
}
.landing-rich-text ul,
.landing-rich-text ol {
  padding-left: 1.2rem;
  margin-bottom: 0;
}

.landing-gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1rem;
}
.landing-gallery-tile {
  aspect-ratio: 4 / 3;
  border-radius: var(--radius);
  background: linear-gradient(135deg, var(--pos-primary-dark), var(--pos-primary));
  display: flex;
  align-items: center;
  justify-content: center;
  color: rgba(255, 255, 255, 0.75);
  font-size: 2.5rem;
  background-size: cover;
  background-position: center;
}
.landing-gallery-tile.landing-gallery-photo {
  color: transparent; /* the placeholder icon just rides along invisibly once a real photo covers it */
}
/* A tile with a Store Profile-set link renders as an <a> instead of a
   <div> (see Login.cshtml) — this is purely the "this is clickable" cue;
   the aspect-ratio/background rules above still apply since it's the
   same element, just a different tag. */
.landing-gallery-tile-link {
  text-decoration: none;
  cursor: pointer;
  transition: transform .15s ease, box-shadow .15s ease;
}
.landing-gallery-tile-link:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 16px rgba(0, 0, 0, .15);
}

/* Footer — carries Hours & Contact (moved down here from the section
   grid above) alongside the store name, as plain label/value columns
   rather than a card. */
.landing-footer {
  background: var(--pos-surface);
  border-top: 1px solid var(--pos-border);
  padding: 2rem 1.5rem;
}
.landing-footer-inner {
  max-width: 1100px;
  margin: 0 auto;
  display: flex;
  flex-wrap: wrap;
  gap: 2rem;
  justify-content: space-between;
}
.landing-footer-brand {
  display: flex;
  align-items: center;
  gap: .5rem;
  font-weight: 700;
  color: var(--pos-text);
}
.landing-footer-brand i {
  color: var(--pos-accent);
  font-size: 1.2rem;
}
.landing-footer-col {
  font-size: .85rem;
  color: var(--pos-muted);
  line-height: 1.6;
}
.landing-footer-label {
  font-weight: 600;
  color: var(--pos-text);
  margin-bottom: .2rem;
}

@media (max-width: 767px) {
  .landing-hero-text h1 { font-size: 1.5rem; }
}

/* ---- Reports (admin) — SQL preview in the Run modal ---- */
.run-sql-preview {
  background: var(--pos-bg);
  border: 1px solid var(--pos-border);
  border-radius: 6px;
  padding: .6rem .75rem;
  font-size: .8rem;
  white-space: pre-wrap;
  word-break: break-word;
  color: var(--pos-text);
  max-height: 160px;
  overflow-y: auto;
}
/* Reusable rotating chevron for any collapse toggle (the Run modal's SQL
   preview, and the Edit modal's help-text toggles below) — targets any
   [data-bs-toggle="collapse"] trigger rather than one specific ID, since
   Bootstrap adds/removes .collapsed on whichever trigger you point at it. */
.collapse-toggle-chevron {
  display: inline-block;
  transition: transform .15s ease;
}
[data-bs-toggle="collapse"]:not(.collapsed) .collapse-toggle-chevron {
  transform: rotate(90deg);
}

/* Results grid — the whole popup (params, buttons, SQL preview, toolbar,
   AND the grid) scrolls together as one, so scrolling up always reveals
   everything above the grid. The header row and summary/totals row stick
   to the top/bottom of that same scroll as you pass them — like freezing
   panes in a spreadsheet — instead of only being reachable within a
   separate, boxed-in scroll area for the grid alone.
   position: sticky sticks to the nearest ancestor that actually scrolls,
   so .modal-dialog-scrollable's default (Bootstrap sets overflow-y: auto
   on .modal-body) is exactly the scroll container we want here — no
   overflow override needed on .modal-body itself, and .run-result-scroll
   below must NOT set its own overflow, or it would create a second,
   separate scroll container and the sticky header would stick to the top
   of that inner box instead of the top of the popup.
   overflow-x here is for a grid with more columns than fit on screen — it's
   the same element .modal-dialog-scrollable already made vertically
   scrollable (via its own default overflow-y: auto), just adding
   horizontal too, so there's still only the one scroll container. */
#report-run-modal .modal-body {
  overflow-x: auto;
  /* Bootstrap's own .modal-body padding (1rem) sits ABOVE the sticky
     thead's stick point — position:sticky;top:0 sticks the header flush
     with the padding EDGE of this scroll container, not its content edge,
     so that top padding stays as a permanently visible strip between the
     modal's header bar and the sticky grid header. Because that strip is
     just padding (not a clipped edge), whatever row is currently scrolled
     up underneath is still visible through it — showing a sliver of a
     data row "peeking" above the sticky header instead of a clean gap.
     Moving the padding down onto the first child below (instead of here)
     keeps the same visual spacing above the params row, but means the
     scroll container itself now has zero top padding, so the sticky thead
     sticks perfectly flush against the modal's header bar with nothing
     left behind it to peek through. */
  padding-top: 0;
}
#report-run-modal .modal-body > *:first-child {
  padding-top: var(--bs-modal-padding, 1rem);
}
.run-result-scroll {
  border: 1px solid var(--pos-border);
  border-radius: 6px;
}
.run-result-scroll table {
  margin-bottom: 0;
  /* Bootstrap's .table sets width:100%, which — combined with the default
     table-layout:auto — stretches every column to fill the whole
     (now fullscreen) modal even when the actual data only needs a
     fraction of that. Sized to its own content instead; the scroll
     wrapper above still kicks in normally once real content (lots of
     columns, or just wide ones) needs more room than that. */
  width: auto;
  min-width: 0;
}
.run-result-scroll th,
.run-result-scroll td {
  /* nowrap is what actually makes table-layout:auto size each column to
     its own content — wrapped text confuses that sizing algorithm into
     picking odd in-between widths for every column, not just the wide
     one. A sensible min/max keeps a single-character column from
     collapsing unreadably tight and a long free-text one from ballooning
     the whole table; text-overflow only kicks in past the max, and the
     full value is still available via the title attribute on each cell. */
  white-space: nowrap;
  min-width: 70px;
  max-width: 320px;
  overflow: hidden;
  text-overflow: ellipsis;
}
.run-result-scroll th {
  min-width: 90px; /* headers read worse than data when clipped, so they get a bit more breathing room */
}
.run-result-scroll thead {
  /* Sticks to the top of #report-run-modal .modal-body as it scrolls —
     i.e. the top of the popup, right under the modal's header bar — not
     to the top of .run-result-scroll itself, since that div isn't its own
     scroll container anymore (see the comment above it). */
  position: sticky;
  top: 0;
  z-index: 2;
}
.run-result-scroll thead th {
  background: var(--pos-bg);
  box-shadow: inset 0 -1px 0 var(--pos-border);
}
.run-result-scroll tfoot td {
  /* Same idea, pinned to the bottom of the popup instead of the top. */
  position: sticky;
  bottom: 0;
  z-index: 2;
  background: #fff8e1;
  font-weight: 700;
  box-shadow: inset 0 1px 0 var(--pos-border);
}
.run-sortable-th {
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}
.run-sortable-th:hover {
  background: var(--pos-border) !important;
}
#run-result-filter-row th {
  padding: .25rem .35rem;
}
#run-result-filter-row input {
  font-weight: 400;
  font-size: .78rem;
}
tr.run-group-header td {
  background: var(--pos-bg);
  font-weight: 700;
  border-top: 1px solid var(--pos-border);
  border-bottom: 1px solid var(--pos-border);
}
tr.run-group-subtotal td {
  background: #fffdf5;
  font-weight: 600;
  font-style: italic;
  border-bottom: 1px dashed var(--pos-border);
}

/* ---- Store Profile (admin) ---- */
/* Quill editor container for Welcome/About/Services — Quill mounts its
   own toolbar above this div and the editable area inside it, so this
   just fixes a reasonable height/border so the three editors don't look
   wildly different in size from the plain fields around them. */
.sp-richtext-editor {
  background: var(--pos-surface);
}
.sp-richtext-editor .ql-editor {
  min-height: 90px;
  max-height: 60vh;
  height: 90px;
  font-size: .9rem;
  overflow-y: auto;
  /* Drag the bottom-right corner to grow/shrink the typing area — handy
     for a long Services list or a Welcome message with several
     paragraphs, without permanently taking up that much space for
     stores that just have a line or two. */
  resize: vertical;
}
/* The font-size toolbar dropdown uses a custom px whitelist (see
   store-profile.js) instead of Quill's built-in small/normal/large/huge
   — the snow theme only ships label text for those four (everything
   else falls back to its generic "Normal" label, which is why every
   entry was showing "Normal" instead of a size). Not scoped under
   .sp-richtext-editor: Quill inserts the toolbar as a preceding SIBLING
   of the container div, not a child of it, so it sits outside that
   selector entirely — this targets the toolbar globally instead, which
   is safe since Quill is only used on this page. */
.ql-toolbar.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-toolbar.ql-snow .ql-picker.ql-size .ql-picker-item::before {
  content: attr(data-value) !important;
}
.ql-toolbar.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=""]::before,
.ql-toolbar.ql-snow .ql-picker.ql-size .ql-picker-label:not([data-value])::before {
  content: "Size" !important;
}
.sp-photo-preview {
  width: 72px;
  height: 54px;
  object-fit: cover;
  border-radius: 6px;
  border: 1px solid var(--pos-border);
  flex: 0 0 auto;
}
.sp-preview-hero {
  background: linear-gradient(135deg, var(--pos-primary-dark), var(--pos-primary) 60%, var(--pos-accent));
  color: #fff;
  padding: 1.5rem 1rem;
  text-align: center;
}
.sp-preview-name {
  font-size: 1.3rem;
  font-weight: 700;
}
.sp-preview-tagline {
  font-size: .9rem;
  color: rgba(255, 255, 255, 0.85);
  margin-top: .25rem;
}
.sp-preview-body {
  padding: 1rem;
}
.sp-preview-block {
  padding-bottom: .75rem;
  margin-bottom: .75rem;
  border-bottom: 1px solid var(--pos-border);
}
.sp-preview-block:last-child {
  border-bottom: none;
  margin-bottom: 0;
  padding-bottom: 0;
}

/* Stacked modals (a popup opened on top of another) are layered by
   dialogs.js — see "Stacked modals" there. No fixed z-index rules here:
   a fixed number put a second backdrop ABOVE Drop Off's own Confirm
   Payment popup and made it unclickable. */

/* ── Online Requests > Delivery Customers popup ─────────────────────── */
.dcust-dialog { max-width: 1240px; }
.dcust-dialog .modal-content { height: calc(100vh - 3.5rem); }
.dcust-total {
  display: inline-block; margin-left: 6px; padding: 1px 9px; border-radius: 99px;
  background: #eef1f4; color: var(--pos-muted); font-size: .8rem; font-weight: 700; vertical-align: middle;
}
.dcust-toolbar { padding: 12px 16px 10px; border-bottom: 1px solid var(--pos-border); background: #fafbfc; }
.dcust-tiles { display: flex; flex-wrap: wrap; gap: 8px; }
.dcust-tile {
  display: flex; align-items: center; gap: 8px; padding: 6px 12px 6px 8px;
  border: 1px solid var(--pos-border); border-radius: 10px; background: #fff;
  color: var(--pos-text); font-size: .85rem; font-weight: 600; line-height: 1.1;
}
.dcust-tile:hover { border-color: #b9c4cf; }
.dcust-tile-n {
  min-width: 30px; padding: 3px 6px; border-radius: 7px; text-align: center;
  background: #eef1f4; font-size: .95rem; font-weight: 800; font-variant-numeric: tabular-nums;
}
.dcust-tile-label i { margin-right: 5px; color: var(--pos-muted); }
.dcust-tile.tone-warn .dcust-tile-n { background: #fbf0dc; color: #a86a12; }
.dcust-tile.tone-bad .dcust-tile-n { background: #f8e5e3; color: #b3453d; }
.dcust-tile.tone-good .dcust-tile-n { background: #e3f2ea; color: #2f7a52; }
.dcust-tile.active { border-color: var(--pos-primary); background: var(--pos-primary); color: #fff; box-shadow: 0 2px 6px rgba(19, 38, 63, .25); }
.dcust-tile.active .dcust-tile-label i { color: rgba(255, 255, 255, .8); }
.dcust-tile.active .dcust-tile-n { background: rgba(255, 255, 255, .18); color: #fff; }

.dcust-filters { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 10px; }
.dcust-filters .form-select { width: auto; min-width: 150px; }
.dcust-search { position: relative; flex: 1 1 200px; max-width: 280px; }
.dcust-search i { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); color: var(--pos-muted); font-size: .85rem; }
.dcust-search input { padding-left: 30px; }
.dcust-sort { display: flex; gap: 4px; }

.dcust-bulkbar { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 10px; }
.dcust-showing { font-size: .85rem; color: var(--pos-muted); }
.dcust-showing b { color: var(--pos-text); }
.dcust-progress { display: flex; align-items: center; gap: 10px; margin-top: 8px; font-size: .85rem; color: var(--pos-muted); }
.dcust-progress .progress { flex: 1; height: 8px; }

.dcust-table { font-size: .88rem; }
.dcust-table thead th {
  position: sticky; top: 0; z-index: 2; background: #f3f5f7;
  font-size: .75rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--pos-muted);
  border-bottom: 1px solid var(--pos-border); white-space: nowrap; padding: 8px 10px;
}
.dcust-table thead th.sortable { cursor: pointer; user-select: none; }
.dcust-table thead th.sortable:hover { color: var(--pos-text); }
.dcust-table thead th i { margin-left: 3px; font-size: .7rem; }
.dcust-table td { padding: 8px 10px; vertical-align: middle; border-color: #eceff2; }
.dcust-table tbody tr:hover { background: #f8fafc; }
.dcust-table .num { text-align: center; width: 54px; }
.dcust-table .act { text-align: right; width: 1%; white-space: nowrap; }
.dcust-name { min-width: 200px; }
.dcust-route { font-size: .72rem; font-weight: 600; color: var(--pos-muted); background: #eef1f4; border-radius: 5px; padding: 1px 6px; margin-left: 4px; }
.dcust-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 3px; }
.dcust-tag { font-size: .7rem; font-weight: 700; padding: 1px 7px; border-radius: 99px; background: #eef1f4; color: var(--pos-muted); }
.dcust-tag.t-nocard, .dcust-tag.t-slowing { background: #fbf0dc; color: #a86a12; }
.dcust-tag.t-never, .dcust-tag.t-quiet, .dcust-tag.t-nophone { background: #f8e5e3; color: #b3453d; }
.dcust-tag.t-new { background: #e3f2ea; color: #2f7a52; }
.dcust-token { display: inline-flex; align-items: center; gap: 5px; font-size: .8rem; font-weight: 600; padding: 2px 8px; border-radius: 6px; white-space: nowrap; }
.dcust-token.yes { background: #e3f2ea; color: #2f7a52; }
.dcust-token.no { background: #f3f4f6; color: #8a939c; }
.dcust-sub, .dcust-ago { font-size: .75rem; color: var(--pos-muted); }
.dcust-ago.tone-mild { color: #a86a12; }
.dcust-ago.tone-warn { color: #c2410c; font-weight: 600; }
.dcust-ago.tone-bad { color: #b3453d; font-weight: 700; }
.dcust-muted { color: #9aa4ae; }
.dcust-count { display: inline-block; min-width: 26px; padding: 1px 6px; border-radius: 6px; font-weight: 700; font-variant-numeric: tabular-nums; }
.dcust-count.strong { background: #e6eef7; color: #2f5d8f; }
.dcust-count.zero { background: transparent; color: #b7bec6; font-weight: 500; }
.dcust-invite .btn { white-space: nowrap; }
.dcust-skip { display: flex; align-items: center; gap: 8px; margin-top: 12px; font-size: .85rem; color: var(--pos-muted); cursor: pointer; }
.dcust-skip .form-check-input { flex-shrink: 0; }
.dcust-scroll { overflow: auto; }
.dcust-table { min-width: 1020px; }
@media (max-width: 767.98px) {
  /* Phone: tiles become one swipeable row; filters two per line. */
  .dcust-tiles { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 4px; scrollbar-width: none; }
  .dcust-tile { flex-shrink: 0; }
  .dcust-filters .form-select, .dcust-search { flex: 1 1 calc(50% - 4px); min-width: 0; max-width: none; }
  .dcust-search { flex-basis: 100%; }
}
@media (max-width: 991.98px) { .dcust-dialog .modal-content { height: 100%; } }

/* ── Admin > Site Traffic ──────────────────────────────────────────────
   Series colors: the validated categorical palette, fixed order
   (dataviz reference palette slots 1–4). Color follows the area. */
.traffic {
  --tr-s1: #2a78d6;   /* Customers (identified) */
  --tr-s2: #eb6834;   /* Anonymous visitors */
  --tr-s3: #1baf7a;   /* Staff */
  --tr-s4: #eda100;   /* Drivers */
  --tr-ink: #1e2733;
  --tr-muted: #66707c;
  --tr-grid: #e6e9ed;
}
.traffic.is-loading .tr-kpis, .traffic.is-loading .tr-card { opacity: .55; transition: opacity .15s; }
.tr-filters { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; padding: 10px 12px; margin-bottom: 12px; }
.tr-filters input[type=date] { width: auto; }
.tr-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 12px; margin-bottom: 12px; }
.tr-kpi { padding: 12px 14px; }
.tr-kpi-label { font-size: .78rem; font-weight: 600; color: var(--tr-muted); text-transform: uppercase; letter-spacing: .04em; }
.tr-kpi-value { font-size: 1.8rem; font-weight: 700; color: var(--tr-ink); line-height: 1.2; margin-top: 2px; font-variant-numeric: tabular-nums; }
.tr-kpi-value small { font-size: .9rem; font-weight: 600; color: var(--tr-muted); }
.tr-kpi-sub { margin-top: 2px; }
.tr-delta { font-size: .78rem; color: var(--tr-muted); }
.tr-delta.up { color: #2f7a52; font-weight: 600; }
.tr-delta.down { color: #b3453d; font-weight: 600; }
.tr-delta i { margin-right: 2px; }
.tr-card { padding: 14px 16px; margin-bottom: 12px; }
.row > [class*="col"] > .tr-card { margin-bottom: 0; }
/* Traffic page only — unscoped, this added 12px under every .row.g-3 in the app
   (Drop Off, Menu, Customers, …) and pushed full-height pages past the window. */
.traffic .row.g-3 { margin-bottom: 12px; }
.tr-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 10px; flex-wrap: wrap; }
.tr-card-title { font-weight: 700; color: var(--tr-ink); }
.tr-card-sub { font-size: .8rem; color: var(--tr-muted); }
.tr-legend { display: flex; flex-wrap: wrap; gap: 12px; font-size: .8rem; color: var(--tr-ink); }
.tr-legend-item { display: inline-flex; align-items: center; gap: 6px; }
.tr-swatch { display: inline-block; width: 10px; height: 10px; border-radius: 3px; flex-shrink: 0; }
.tr-chart svg { display: block; overflow: visible; }
.tr-grid { stroke: var(--tr-grid); stroke-width: 1; }
.tr-grid.base { stroke: #c9cfd6; }
.tr-axis { font-size: 11px; fill: var(--tr-muted); font-variant-numeric: tabular-nums; }
.tr-hit { fill: transparent; cursor: crosshair; }
.tr-hit:hover { fill: rgba(30, 58, 95, .05); }
.tr-tooltip {
  position: fixed; z-index: 1080; pointer-events: none; opacity: 0; transition: opacity .08s;
  background: #fff; border: 1px solid var(--pos-border); border-radius: 8px; box-shadow: 0 6px 20px rgba(16, 24, 40, .15);
  padding: 8px 10px; font-size: .8rem; color: var(--tr-ink); min-width: 170px;
}
.tr-tooltip.show { opacity: 1; }
.tr-tip-title { font-weight: 700; margin-bottom: 4px; }
.tr-tip-row { display: flex; align-items: center; gap: 6px; }
.tr-tip-row b { margin-left: auto; padding-left: 12px; font-variant-numeric: tabular-nums; }
.tr-tip-row.total { border-top: 1px solid var(--pos-border); margin-top: 4px; padding-top: 4px; font-weight: 600; }
.tr-table-wrap { overflow-x: auto; }
.tr-table { font-size: .86rem; }
.tr-table th { font-size: .72rem; text-transform: uppercase; letter-spacing: .04em; color: var(--tr-muted); font-weight: 700; border-bottom-color: var(--pos-border); white-space: nowrap; }
.tr-table td { vertical-align: middle; border-color: #eef0f3; }
.tr-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.tr-row { cursor: pointer; }
.tr-row:hover { background: #f6f8fb; }
.tr-muted { color: var(--tr-muted); font-size: .78rem; }
.tr-barcol { width: 22%; min-width: 90px; }
.tr-inline-bar { height: 8px; background: #f0f2f5; border-radius: 4px; overflow: hidden; }
.tr-inline-bar > div { height: 100%; background: var(--tr-s1); border-radius: 0 4px 4px 0; }
.tr-hbars { display: flex; flex-direction: column; gap: 8px; }
.tr-hbar { display: grid; grid-template-columns: minmax(90px, 38%) 1fr auto; align-items: center; gap: 10px; font-size: .84rem; }
.tr-hbar-label { color: var(--tr-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tr-hbar-track { height: 10px; background: #f0f2f5; border-radius: 5px; overflow: hidden; }
.tr-hbar-fill { height: 100%; background: var(--tr-s1); border-radius: 0 4px 4px 0; }
.tr-hbar-value { font-weight: 700; font-variant-numeric: tabular-nums; color: var(--tr-ink); min-width: 70px; text-align: right; }
.tr-hbar-value span { font-weight: 500; color: var(--tr-muted); margin-left: 6px; font-size: .78rem; }
.tr-empty { color: var(--tr-muted); font-size: .85rem; padding: 10px 0; }
.tr-search { width: 220px; }
.tr-visit { border: 1px solid var(--pos-border); border-radius: 10px; padding: 8px 12px; margin-bottom: 10px; }
.tr-visit-head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 4px; font-size: .88rem; }
.tr-visit-row { display: flex; gap: 12px; font-size: .86rem; padding: 2px 0 2px 4px; border-left: 2px solid #e6e9ed; margin-left: 4px; padding-left: 10px; }
.tr-visit-row > .tr-muted { min-width: 64px; }
.tr-pill { font-size: .72rem; font-weight: 700; padding: 1px 8px; border-radius: 99px; background: #eef1f4; color: var(--tr-muted); }
.tr-pill.text { background: #e6eef7; color: #2f5d8f; }
.tr-pill.bad { background: #f8e5e3; color: #b3453d; }


/* ── Driver Log: route order + drag & drop ─────────────────────────── */
#dlog-grid-body .dlog-slot-row td {
  background: var(--bs-tertiary-bg, #f1f3f5);
  font-size: .75rem; font-weight: 600; text-transform: uppercase; letter-spacing: .04em;
  color: var(--bs-secondary-color, #6c757d);
  padding: .3rem .75rem;
}
#dlog-grid-body .dlog-drag-handle {
  display: none; cursor: grab; color: var(--bs-secondary-color, #6c757d);
  margin-right: .35rem; padding: .15rem .1rem; border-radius: .25rem; touch-action: none;
}
#dlog-grid-body.dlog-can-drag .dlog-drag-handle { display: inline-block; }
#dlog-grid-body .dlog-move-btns { display: none; margin-left: .35rem; }
#dlog-grid-body.dlog-can-drag .dlog-move-btns { display: inline-flex; flex-direction: column; vertical-align: middle; line-height: 1; }
#dlog-grid-body .dlog-move-btn { font-size: .8rem; color: var(--bs-secondary-color, #6c757d); }
#dlog-grid-body .dlog-move-btn:hover { color: var(--bs-primary, #0d6efd); }
#btn-dlog-reorder.active { background: var(--bs-secondary, #6c757d); color: #fff; }
#dlog-grid-body .dlog-drag-handle:hover { background: var(--bs-secondary-bg, #e9ecef); color: var(--bs-body-color); }
#dlog-grid-body .dlog-drag-handle:active { cursor: grabbing; }
#dlog-grid-body tr.dlog-dragging { opacity: .45; }
#dlog-grid-body tr.dlog-drop-before > td { box-shadow: inset 0 3px 0 var(--bs-primary, #0d6efd); }
#dlog-grid-body tr.dlog-drop-after > td { box-shadow: inset 0 -3px 0 var(--bs-primary, #0d6efd); }

#dlog-grid-body .dlog-slot-row td { display: table-cell; }
#dlog-grid-body .dlog-slot-row td > span { vertical-align: middle; }
#dlog-grid-body .dlog-slot-progress {
  display: inline-block; width: 90px; height: 6px; margin: 0 .6rem;
  background: var(--bs-secondary-bg, #e9ecef); border-radius: 3px; overflow: hidden;
}
#dlog-grid-body .dlog-slot-progress > span { display: block; height: 100%; background: var(--bs-success, #198754); border-radius: 3px; }
#dlog-grid-body .dlog-slot-count { font-weight: 500; text-transform: none; letter-spacing: 0; }
#dlog-view-tabs .btn.active .badge { background: rgba(255,255,255,.85) !important; }
#dlog-grid-body td { vertical-align: middle; }

/* ── Store logo as the brand mark (Views/Shared/_BrandMark.cshtml) ───── */
.brand-logo { display: inline-block; width: auto; object-fit: contain; flex: 0 0 auto; }
.brand-logo-navbar { height: 30px; max-width: 120px; margin-right: .5rem; vertical-align: middle; }
.landing-header-inner .brand-logo-mark { height: 34px; max-width: 140px; }
.landing-footer-brand .brand-logo-mark { height: 26px; max-width: 110px; }
.brand-logo-mark { height: 30px; max-width: 130px; }
.brand-logo-hero {
  display: block; height: 104px; max-width: 70%; margin: 0 auto .6rem;
  filter: drop-shadow(0 4px 14px rgba(0, 0, 0, .35));
}


/* ── Pickup / Delivery request rows (Online Requests, Driver Log) ──────
   Type sets the hue — Pickup green, Delivery blue — with a solid bar on
   the left edge; status sets the shade: waiting (Requested) light,
   scheduled (Confirmed) a step deeper, on the truck (En Route) deepest,
   and finished (Picked Up / Delivered / Completed / Missed / Cancelled)
   faded back so what's still open stands out. */
.rq-row { --rq-bar: transparent; }
.rq-row > td:first-child { box-shadow: inset 4px 0 0 var(--rq-bar); }
.rq-pickup   { --rq-bar: #2f9e5b; }
.rq-delivery { --rq-bar: #2f7fd6; }

.rq-pickup.rq-st-requested   { --bs-table-bg: #f2faf4; }
.rq-pickup.rq-st-confirmed   { --bs-table-bg: #e3f4e8; }
.rq-pickup.rq-st-pickedup,
.rq-pickup.rq-st-completed   { --bs-table-bg: #f6faf7; }
.rq-pickup.rq-st-missed,
.rq-pickup.rq-st-cancelled   { --bs-table-bg: #f7f8f7; }

.rq-delivery.rq-st-requested { --bs-table-bg: #f1f7fd; }
.rq-delivery.rq-st-confirmed { --bs-table-bg: #e2eefa; }
.rq-delivery.rq-st-enroute   { --bs-table-bg: #d3e5f7; }
.rq-delivery.rq-st-delivered,
.rq-delivery.rq-st-completed { --bs-table-bg: #f5f8fc; }
.rq-delivery.rq-st-missed,
.rq-delivery.rq-st-cancelled { --bs-table-bg: #f7f8f9; }

/* Finished rows fade back; missed/cancelled keep a warning-colored bar. */
.rq-st-pickedup > td, .rq-st-delivered > td, .rq-st-completed > td,
.rq-st-missed > td, .rq-st-cancelled > td { color: var(--bs-secondary-color, #6c757d); }
.rq-row.rq-st-missed    { --rq-bar: #e0a800; }
.rq-row.rq-st-cancelled { --rq-bar: #c9ced4; }
/* Hover shade drawn on the cells, not with filter: a filter on the row
   makes it the containing block for position:fixed children, which threw
   the row's ⋯ menu (Bootstrap dropdown, fixed strategy) far off its button. */
.rq-row:hover > td { background-image: linear-gradient(rgba(0, 0, 0, .025), rgba(0, 0, 0, .025)); }

/* ── Dispatcher / driver hand-off (v37) ───────────────────────────────── */
.dlog-handoff { font-size: .8rem; line-height: 1.25; margin-top: 2px; padding: 2px 6px; border-radius: 4px; color: #212529; }
.dlog-handoff.dlog-missed { background: #fff3cd; border-left: 3px solid #e0a800; }
.dlog-handoff.dlog-flag-open { background: #ffe5d0; border-left: 3px solid #fd7e14; }
.dlog-handoff.dlog-flag-closed { background: #f1f3f5; border-left: 3px solid #adb5bd; }
.dlog-handoff.dlog-reply { background: #e7f1ff; border-left: 3px solid #0d6efd; }
.dlog-driver-chips { display: flex; flex-wrap: wrap; gap: 6px; padding: 8px 12px; border-bottom: 1px solid #e9ecef; background: #fafbfc; }
.dlog-driver-chip { display: inline-flex; align-items: center; gap: 5px; border: 1px solid #ced4da; background: #fff; border-radius: 999px; padding: 2px 10px; font-size: .82rem; color: #343a40; }
.dlog-driver-chip:hover { border-color: #0d6efd; }
.dlog-driver-chip .dlog-chip-count { color: #6c757d; font-variant-numeric: tabular-nums; }
.dlog-driver-chip.is-complete { border-color: #198754; background: #e8f5ee; }
.dlog-driver-chip.is-complete .bi-check-circle-fill { color: #198754; }
.dlog-driver-chip.is-unassigned { border-style: dashed; cursor: default; }

/* Online Requests — dispatcher tools */
.rq-attention { border: 1px solid #f5c2c7; border-radius: 6px; margin: 10px 12px 0; background: #fff8f8; }
.rq-attention-head { display: flex; align-items: center; gap: 8px; padding: 6px 10px; font-weight: 600; color: #842029; cursor: pointer; user-select: none; }
.rq-attention-list { padding: 0 10px 8px; }
.rq-attention-item { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 8px 12px; padding: 6px 0; border-top: 1px solid #f1d4d7; font-size: .88rem; }
.rq-attention-item .rq-att-main { flex: 1 1 320px; min-width: 0; }
.rq-attention-item .rq-att-actions { display: flex; gap: 4px; flex-wrap: wrap; }
.rq-load { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; padding: 6px 12px; font-size: .82rem; border-bottom: 1px solid #e9ecef; background: #fafbfc; }
.rq-load-chip { border: 1px solid #ced4da; border-radius: 6px; padding: 1px 8px; background: #fff; }
.rq-load-chip .rq-load-slot { color: #6c757d; }
.rq-load-chip.is-complete { border-color: #198754; background: #e8f5ee; }
.rq-bulkbar { position: sticky; top: 0; z-index: 5; display: flex; flex-wrap: wrap; gap: 6px; align-items: center; padding: 6px 12px; background: #1e3a5f; color: #fff; }
.rq-bulkbar .form-select, .rq-bulkbar .form-control { width: auto; }
.rq-select-cell { width: 28px; }
/* Forms shown inside the app dialog (Missed reason, Flag, Reschedule…) —
   the message box keeps line breaks for plain text; markup opts out. */
.app-dialog .app-dialog-message .text-start { white-space: normal; color: var(--bs-body-color); }

/* ---- Online Requests: journey step tabs (requests.js) ---- */
.rq-steps { display: flex; flex-wrap: wrap; gap: 4px; padding: 8px 12px 0; margin: 0; list-style: none; border-bottom: 1px solid #dee2e6; background: #fafbfc; }
.rq-steps .rq-step-gap { flex: 1 1 auto; }
.rq-step { display: inline-flex; align-items: center; gap: 6px; border: 1px solid transparent; border-bottom: 0; border-radius: 6px 6px 0 0; background: transparent; padding: 6px 12px; font-size: .9rem; color: #495057; margin-bottom: -1px; }
.rq-step:hover { background: #eef2f6; }
.rq-step.active { background: #fff; border-color: #dee2e6; color: #1e3a5f; font-weight: 600; }
.rq-step .rq-step-n { display: inline-grid; place-items: center; width: 20px; height: 20px; border-radius: 50%; background: #dfe6ee; font-size: .75rem; font-weight: 700; }
.rq-step.active .rq-step-n { background: #1e3a5f; color: #fff; }
.rq-step .badge { background: #6c757d; }
.rq-step-attention { color: #842029; }
.rq-step-attention .badge { background: #dc3545; }
.rq-step-muted { color: #6c757d; }
.rq-step-hint { padding: 6px 12px; font-size: .82rem; color: #6c757d; border-bottom: 1px solid #e9ecef; }
.rq-bag { display: inline-block; padding: 0 5px; border-radius: 4px; background: #fff3cd; border: 1px solid #ffe69c; font-weight: 600; }
.rq-note { color: #6c757d; max-width: 260px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ---- Heat-seal garment barcodes ---- */
.hs-tags { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; margin-top: 3px; }
.hs-chip { font-family: Consolas, "Courier New", monospace; font-size: .72rem; background: #1e3a5f; color: #fff; border-radius: 4px; padding: 0 6px; line-height: 1.5; white-space: nowrap; }
.hs-chip.hs-need { background: #fff3cd; color: #8a5a00; border: 1px solid #f0c36d; font-family: inherit; }
.hs-chip.hs-paper { background: #f1f3f5; color: #6c757d; border: 1px solid #ced4da; font-family: inherit; }
.hs-scan-input { font-family: Consolas, "Courier New", monospace; letter-spacing: .03em; }
.hs-garment-panel { margin-top: 6px; padding: 6px 8px; border: 1px solid #dfe5ec; border-radius: 6px; background: #f8fafc; font-size: .82rem; }
.hs-garment-panel .hs-gp-title { font-weight: 600; }
.hs-garment-panel .hs-gp-notes .badge { font-weight: 600; }
.asm-scan { display: flex; align-items: center; gap: 12px; border: 2px solid #1e3a5f; border-radius: 10px; padding: 10px 14px; background: #fff; }
.asm-scan > i { font-size: 28px; color: #1e3a5f; }
.asm-scan input { border: 0; outline: 0; font-size: 20px; flex: 1; min-width: 0; background: transparent; }
.asm-ticket { border: 1px solid #dee2e6; border-radius: 12px; padding: 16px; min-height: 260px; background: #fff; }
.asm-ticket.is-complete { border-color: #198754; box-shadow: 0 0 0 3px rgba(25,135,84,.15); }
.asm-big { font-size: 44px; font-weight: 800; color: #1e3a5f; line-height: 1; }
.asm-count { font-size: 40px; font-weight: 700; color: #0d6efd; line-height: 1; }
.asm-piece { display: flex; align-items: center; gap: 10px; padding: 7px 8px; border-bottom: 1px solid #eef0f2; font-size: 15px; }
.asm-piece .ok { color: #198754; font-size: 20px; }
.asm-piece .wait { color: #adb5bd; font-size: 20px; }
.asm-piece.just { background: #eef6ff; }
.asm-side { border: 1px solid #dee2e6; border-radius: 12px; padding: 12px 14px; background: #fff; }
.asm-side .asm-wait-row { padding: 4px 0; border-bottom: 1px dashed #e9ecef; cursor: pointer; }
.asm-side .asm-wait-row:hover { background: #f8f9fa; }

/* Assembly hooks */
.asm-hook { flex: 0 0 auto; min-width: 150px; text-align: center; border-radius: 12px; padding: 10px 14px; background: #1e3a5f; color: #fff; }
.asm-hook .lbl { font-size: 13px; letter-spacing: .12em; text-transform: uppercase; opacity: .8; }
.asm-hook .num { font-size: 72px; font-weight: 800; line-height: 1; }
.asm-hook.done { background: #198754; }
.asm-hook.full { background: #b02a37; }
.asm-hook.full .num { font-size: 26px; padding: 14px 0; }
.asm-rail { display: grid; grid-template-columns: repeat(10, 1fr); gap: 4px; }
.asm-rail .h { border: 1px solid #dee2e6; border-radius: 6px; text-align: center; font-size: 12px; padding: 4px 0; color: #adb5bd; background: #f8f9fa; }
.asm-rail .h.used { background: #e7f0fb; color: #1e3a5f; border-color: #9ec5fe; font-weight: 700; cursor: pointer; }
.asm-rail .h.used:hover, .asm-rail .h.cur { background: #1e3a5f; color: #fff; }
.asm-hook-badge { display: inline-block; min-width: 34px; text-align: center; border-radius: 6px; background: #1e3a5f; color: #fff; font-weight: 700; padding: 1px 6px; margin-right: 6px; }
.asm-hook-badge.none { background: #6c757d; }

/* Batch mode: Build Batch, Drop Off batch bar, Assembly */
.bb-table td, .bb-table th { font-size: 13.5px; vertical-align: middle; }
.bb-table tr.just td { background: #eef6ff; }
.bb-table .bb-num { color: #6c757d; font-size: 12px; width: 32px; }
.bb-bar { display: flex; align-items: center; gap: 14px; background: #1e3a5f; color: #fff; border-radius: 10px; padding: 8px 10px; }
.bb-bar .progress-bar.over { background: #dc3545 !important; }
.bb-card { border: 1px solid #dee2e6; border-radius: 10px; padding: 9px 11px; margin-bottom: 9px; background: #fff; }
.bb-card h6 { margin: 0; font-weight: 700; color: #1e3a5f; }
.bt-st { font-size: 11px; font-weight: 700; border-radius: 10px; padding: 1px 8px; white-space: nowrap; }
.bt-st.r { background: #fff3cd; color: #8a5a00; } .bt-st.c { background: #cff4fc; color: #055160; }
.bt-st.a { background: #e7f0fb; color: #1e3a5f; } .bt-st.f { background: #e6f4ea; color: #146c43; }
.bb-pool-btn { min-width: 150px; text-align: left; }
.bb-pool-btn .small { opacity: .8; }
.batch-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; border: 1px solid #c9d7ea; background: #f3f7fc; border-radius: 8px; padding: 6px 10px; font-size: 13px; }
.batch-bar .chip { display: inline-flex; align-items: center; gap: 6px; background: #fff; border: 1px solid #c9d7ea; border-radius: 16px; padding: 2px 4px 2px 10px; }
.batch-bar .chip .progress { width: 70px; height: 6px; }
.asm-rail .h.done { background: #e6f4ea; color: #146c43; border-color: #a3cfbb; }
.asm-rail .h.next { opacity: .45; }
.asm-bhead { display: flex; align-items: center; gap: 14px; background: #1e3a5f; color: #fff; border-radius: 10px; padding: 10px 14px; }
.asm-bhead .progress { background: rgba(255,255,255,.25); }
.asm-batch-tabs .btn { border-radius: 16px; }
.asm-count-btns .btn { min-width: 44px; }

/* Preferences > Production: five mode cards */
.pm-legend { display: flex; flex-wrap: wrap; gap: 12px; color: #44505c; }
.pm-legend span { display: inline-flex; align-items: center; gap: 5px; }
.pm-sw { display: inline-block; width: 12px; height: 12px; border-radius: 3px; border: 2px solid; }
.pm-cards { display: flex; flex-direction: column; gap: 10px; }
.pm-card { display: grid; grid-template-columns: 220px 1fr; gap: 14px; align-items: stretch; border: 2px solid #dee2e6; border-radius: 12px; padding: 12px; background: #fff; cursor: pointer; margin: 0; transition: border-color .12s, box-shadow .12s; position: relative; }
.pm-card:hover { border-color: #9ec5fe; }
.pm-card.selected { border-color: #0d6efd; box-shadow: 0 0 0 4px rgba(13,110,253,.12); background: #f8fbff; }
.pm-radio { position: absolute; opacity: 0; pointer-events: none; }
.pm-card:focus-within { outline: 2px solid #0d6efd; outline-offset: 2px; }
.pm-head { border-right: 1px solid #e9ecef; padding-right: 10px; display: flex; flex-direction: column; gap: 2px; }
.pm-badge { align-self: flex-start; font-size: 10.5px; font-weight: 700; letter-spacing: .06em; background: #1e3a5f; color: #fff; border-radius: 8px; padding: 1px 8px; }
.pm-title { font-size: 16px; font-weight: 700; line-height: 1.2; margin-top: 2px; }
.pm-sub { font-size: 12px; color: #5f6b77; }
.pm-best { font-size: 12px; color: #25744c; font-weight: 600; margin-top: auto; padding-top: 4px; }
.pm-check { display: none; font-size: 12px; font-weight: 700; color: #0d6efd; }
.pm-card.selected .pm-check { display: inline-block; }
.pm-steps { display: flex; align-items: stretch; gap: 0; min-width: 0; }
.pm-arr { flex: 0 0 16px; align-self: center; color: #adb5bd; font-size: 13px; text-align: center; }
.pm-step { flex: 1; min-width: 0; position: relative; border: 2px solid; border-radius: 9px; padding: 9px 8px 7px; }
.pm-n { position: absolute; top: -9px; left: 8px; background: #1e2733; color: #fff; border-radius: 9px; font-size: 10px; font-weight: 700; padding: 0 6px; }
.pm-new { position: absolute; top: -9px; right: 6px; background: #e67e22; color: #fff; border-radius: 9px; font-size: 9.5px; font-weight: 700; padding: 0 6px; }
.pm-t { font-size: 12.5px; font-weight: 700; display: flex; gap: 5px; align-items: center; line-height: 1.2; }
.pm-t i { font-size: 14px; }
.pm-d { font-size: 11.3px; color: #44505c; line-height: 1.3; margin-top: 2px; }
.pm-front { border-color: #4b7bd6; background: #f2f7ff; } .pm-back { border-color: #d99a2b; background: #fff8ec; }
.pm-clean { border-color: #9aa4ae; background: #f6f7f8; } .pm-asm { border-color: #7d5bd0; background: #f6f2ff; }
.pm-rack { border-color: #3c9a6a; background: #effaf4; }
.pm-settings { border: 1px solid #dee2e6; border-radius: 10px; padding: 10px 12px; margin-bottom: 10px; background: #fff; }
.pm-settings-title { font-weight: 700; font-size: 14px; color: #1e3a5f; margin-bottom: 6px; }
@media (max-width: 1100px) { .pm-card { grid-template-columns: 1fr; } .pm-head { border-right: 0; border-bottom: 1px solid #e9ecef; padding: 0 0 8px; } .pm-steps { overflow-x: auto; padding-top: 8px; } .pm-step { min-width: 120px; } }

/* Click feedback for icon-only buttons in popups (ui-feedback.js) */
.modal .ib-press, .offcanvas .ib-press { animation: ibPress .32s ease-out, ibRing .65s ease-out, ibFlash .5s ease-out; border-radius: .5rem; }
@keyframes ibPress { 0% { transform: scale(1); } 35% { transform: scale(.78); } 100% { transform: scale(1); } }
/* Two rings — white and blue — so the pulse shows on light popups and on the dark navy popup headers alike. */
@keyframes ibRing { 0% { box-shadow: 0 0 0 0 rgba(255,255,255,.85), 0 0 0 0 rgba(13,110,253,.55); }
                    100% { box-shadow: 0 0 0 10px rgba(255,255,255,0), 0 0 0 16px rgba(13,110,253,0); } }
@keyframes ibFlash { 0% { background-color: rgba(128,128,128,.35); } 100% { background-color: transparent; } }
.ib-busy { position: relative; pointer-events: none; }
.ib-busy > i { visibility: hidden; }
.ib-busy::after { content: ""; position: absolute; inset: 0; margin: auto; width: 1.05em; height: 1.05em;
  border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: ibSpin .6s linear infinite; }
@keyframes ibSpin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .modal .ib-press, .offcanvas .ib-press { animation: ibRing .5s ease-out, ibFlash .5s ease-out; }
  .ib-busy::after { animation-duration: 1.4s; }
}

/* Online Requests: a driver's routes under the Driver dropdown */
.req-routes { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; }
.req-route-chip { font-size: 11.5px; line-height: 1.5; border: 1px solid #ced4da; background: #fff; color: #495057; border-radius: 10px; padding: 0 8px; }
button.req-route-chip { cursor: pointer; }
button.req-route-chip:hover { border-color: #0d6efd; color: #0d6efd; }
.req-route-chip.on { background: #1e3a5f; border-color: #1e3a5f; color: #fff; font-weight: 600; }

/* Customer Request Pickup: tap-friendly day cards and time slots */
.pk-days { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 6px; padding: 2px 0 4px; }
.pk-day { min-width: 0; min-height: 80px; scroll-snap-align: start; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 1px; border: 2px solid #ced4da; border-radius: 14px; background: #fff; color: #212529; padding: 6px 4px; cursor: pointer; }
.pk-day:active { transform: scale(.96); }
.pk-day-top { font-size: 12px; font-weight: 600; color: #6c757d; text-transform: uppercase; letter-spacing: .02em; }
.pk-day-num { font-size: 24px; font-weight: 700; line-height: 1.1; }
.pk-day-mon { font-size: 12px; color: #6c757d; }
.pk-day.on { border-color: #0d6efd; background: #0d6efd; color: #fff; box-shadow: 0 2px 8px rgba(13,110,253,.35); }
.pk-day.on .pk-day-top, .pk-day.on .pk-day-mon { color: rgba(255,255,255,.85); }
.pk-slots { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 8px; }
.pk-slot { min-height: 52px; display: flex; align-items: center; justify-content: center; font-size: 16px; font-weight: 600; border-radius: 12px; }
@media (max-width: 480px) {
  .pk-days { gap: 4px; }
  .pk-day { min-height: 70px; border-radius: 10px; padding: 4px 0; border-width: 1.5px; }
  .pk-day-top { font-size: 11px; letter-spacing: 0; text-transform: none; }
  .pk-day-num { font-size: 20px; }
  .pk-day-mon { font-size: 10.5px; }
}
@media (max-width: 400px) { .pk-slots { grid-template-columns: repeat(2, minmax(0, 1fr)); } .pk-slot { font-size: 15px; } }
.pk-slot { white-space: nowrap; padding-left: 8px; padding-right: 8px; }
.pk-slot .bi { margin-right: 6px !important; }
/* Online Requests: "Picked Up — No Ticket" tab badge stands out while bags wait */
.rq-step-needticket .badge { background: #fd7e14 !important; color: #fff; }

/* ---- Dashboard: Store Setup card (store-setup.js) ---- */
.ss-head { display: flex; align-items: center; justify-content: flex-start; gap: .75rem; flex-wrap: wrap; }
.ss-head > * { flex: 0 0 auto; }
.ss-card .ss-oneline { flex: 1 1 0; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ss-mode { display: inline-flex; align-items: center; gap: .4rem; background: #eef4ff; color: #1d4ed8; border-radius: 999px; padding: .2rem .7rem; font-weight: 600; font-size: .85rem; white-space: nowrap; }
.ss-card .ss-oneline { display: none; }
.ss-card.ss-collapsed .ss-oneline { display: block; }
.ss-card .ss-last { flex: 1 1 0; min-width: 0; }
.ss-card.ss-collapsed .ss-last { display: none; }
.ss-card.ss-collapsed #ss-body { display: none; }
.ss-card.ss-collapsed .pos-card-header { border-bottom: 0; }
.ss-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: .75rem; }
.ss-tile { border: 1px solid #e6e9ee; border-radius: 10px; padding: .7rem .85rem; background: #fff; min-width: 0; }
.ss-tile h6 { font-size: .8rem; text-transform: uppercase; letter-spacing: .04em; color: #475569; margin: 0 0 .45rem; display: flex; align-items: center; gap: .4rem; }
.ss-tile h6 a { margin-left: auto; font-size: .75rem; text-transform: none; letter-spacing: 0; text-decoration: none; }
.ss-wide { grid-column: span 2; }
.ss-row { display: flex; justify-content: space-between; gap: .5rem; font-size: .85rem; padding: .12rem 0; border-bottom: 1px dashed #eef0f3; }
.ss-row:last-child { border-bottom: 0; }
.ss-row > span:first-child { color: #64748b; }
.ss-row > span:last-child { font-weight: 600; text-align: right; overflow-wrap: anywhere; }
.ss-on { color: #15803d; font-weight: 600; }
.ss-off { color: #94a3b8; font-weight: 500; }
.ss-steps { display: flex; align-items: center; flex-wrap: wrap; gap: .3rem; margin: .2rem 0 .5rem; }
.ss-step { background: #f1f5f9; border-radius: 6px; padding: .2rem .5rem; font-size: .8rem; font-weight: 600; display: inline-flex; gap: .3rem; align-items: center; }
.ss-step i { color: #2563eb; }
.ss-arrow { color: #94a3b8; font-size: .75rem; }
.ss-two { display: grid; grid-template-columns: 1fr 1fr; column-gap: 1.5rem; }
.ss-warn { background: #fff7e6; border: 1px solid #fcd9a0; border-radius: 8px; padding: .45rem .75rem; font-size: .85rem; display: flex; gap: .4rem 1.25rem; flex-wrap: wrap; align-items: center; }
.ss-warn i { color: #d97706; }
.ss-tag { display: inline-block; background: #fff3cd; border-radius: 4px; padding: 0 .35rem; font-size: .75rem; font-weight: 600; }
.ss-local { font-size: .7rem; color: #64748b; font-weight: 500; }
@media (max-width: 1399.98px) { .ss-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 991.98px) { .ss-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } .ss-card .ss-oneline { display: none !important; } .ss-card .ss-last { flex: 1 1 100%; order: 10; } }
@media (max-width: 575.98px) { .ss-grid { grid-template-columns: 1fr; } .ss-wide { grid-column: auto; } .ss-two { grid-template-columns: 1fr; } }

/* ---- Preference change history popup (store-setup.js PrefHistory) ---- */
.ph-set { border: 1px solid #e6e9ee; border-radius: 10px; margin-bottom: .75rem; overflow: hidden; }
.ph-set-head { display: flex; align-items: center; gap: .5rem; padding: .5rem .75rem; background: #f8fafc; border-bottom: 1px solid #e6e9ee; font-size: .9rem; }
.ph-table { table-layout: fixed; }
.ph-table td:nth-child(1) { width: 34%; }
.ph-table td:nth-child(3) { width: 2.25rem; text-align: center; }
.ph-table td { padding: .35rem .75rem; vertical-align: middle; font-size: .85rem; }
.ph-table tr:last-child td { border-bottom: 0; }
.ph-old { color: #94a3b8; text-decoration: line-through; overflow-wrap: anywhere; }
.ph-new { font-weight: 600; overflow-wrap: anywhere; }

/* ---- Dashboard > Open Work popup (open-work.js) ---- */
.ow-dialog { max-width: min(1320px, 96vw); }
#ow-body .ow-section { padding: .75rem 1rem 0; }
#ow-body > .ow-section:last-child, #ow-body > .row:last-child .ow-section { padding-bottom: 1rem; }
#ow-body > .row { margin: 0; }
#ow-body > .row > [class*="col"] { padding: 0; }
.ow-section-h { display: flex; align-items: center; gap: .45rem; font-size: .8rem; text-transform: uppercase; letter-spacing: .05em; color: #475569; font-weight: 700; margin-bottom: .45rem; }
.ow-section-h a { margin-left: auto; text-transform: none; letter-spacing: 0; font-weight: 600; text-decoration: none; font-size: .8rem; }
#ow-body .kpi-card .kpi-value { font-size: 1.6rem; }
.ow-mini { display: flex; justify-content: space-between; gap: .5rem; font-size: .75rem; border-top: 1px dashed #eef0f3; padding-top: .15rem; margin-top: .15rem; }
.ow-table td { vertical-align: middle; }
.ow-addr { display: inline-block; max-width: 260px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; vertical-align: bottom; }
.ow-note { background: #f8fafc; border: 1px solid #e6e9ee; border-radius: 8px; padding: .45rem .65rem; font-size: .9rem; white-space: pre-wrap; }
.ow-flag { background: #fef2f2; border-color: #fecaca; white-space: normal; }
.ow-photo { max-width: 220px; max-height: 220px; border-radius: 8px; border: 1px solid #e6e9ee; }
.ow-log { display: flex; flex-direction: column; gap: .5rem; max-height: 460px; overflow-y: auto; }
.ow-log-item { border-left: 3px solid #cbd5e1; padding: .1rem 0 .1rem .6rem; }
#ow-back { line-height: 1; }
@media (max-width: 575.98px) { #ow-body .ow-section { padding: .6rem .6rem 0; } .ow-addr { max-width: 140px; } }

/* ---- Preferences > Routes & days (route-days-editor.js) ---- */
.rd-table th { font-size: .75rem; text-transform: uppercase; color: #64748b; font-weight: 700; }
.rd-day { width: 34px; height: 30px; border-radius: 7px; border: 1px solid #cbd5e1; background: #fff; color: #94a3b8; font-weight: 700; font-size: .8rem; }
.rd-day.on { background: #1d4ed8; border-color: #1d4ed8; color: #fff; }
.rd-day:focus-visible { outline: 2px solid #93c5fd; outline-offset: 1px; }
.rd-closed { font-weight: 600; display: inline-flex; align-items: center; padding: .35rem .3rem .35rem .65rem; }
.rd-closed .btn-close { font-size: .55rem; }

/* ---- Online Requests: This week by route (requests.js loadRouteWeek) ---- */
.rq-week { padding: 6px 12px 8px; border-bottom: 1px solid #e9ecef; background: #fafbfc; font-size: .82rem; }
.rq-week-head { font-weight: 600; margin-bottom: 4px; }
.rq-week-table { border-collapse: collapse; }
.rq-week-table th, .rq-week-table td { border: 1px solid #e2e8f0; padding: 2px 8px; text-align: center; min-width: 46px; }
.rq-week-table thead th { background: #f1f5f9; cursor: pointer; font-weight: 600; line-height: 1.1; }
.rq-week-date { font-size: .7rem; font-weight: 400; color: #64748b; }
.rq-week-table th.rq-week-route { text-align: left; background: #fff; white-space: nowrap; font-weight: 600; }
.rq-week-days { font-size: .68rem; font-weight: 400; color: #64748b; }
.rq-week-table td { background: #fff; cursor: pointer; font-weight: 700; color: #1d4ed8; }
.rq-week-table td.is-off { background: repeating-linear-gradient(45deg, #f8fafc, #f8fafc 5px, #e9eef5 5px, #e9eef5 10px); color: #94a3b8; }
.rq-week-table td.is-conflict { color: #b45309; box-shadow: inset 0 0 0 2px #f59e0b; }
.rq-week-table .is-picked { outline: 2px solid #1d4ed8; outline-offset: -2px; }

/* ---- Drop Off: due date follows a Delivery customer's route (dropoff.js) ---- */
.due-route-hint { font-size: .75rem; color: #1d4ed8; margin-top: 3px; line-height: 1.2; }
.due-route-hint.is-warn { color: #b45309; }
.rq-week-table thead th.is-today { background: #dbeafe; color: #1d4ed8; }
.rq-week-table .is-past { opacity: .55; }
.rq-week-scope { background: #eef2ff; color: #3730a3; border-radius: 999px; padding: 0 .55rem; font-weight: 400; }

/* Standing pickup badge (Online Requests, Driver Log, driver phone) */
.rq-standing { display: inline-flex; align-items: center; gap: 3px; background: #ede9fe; color: #5b21b6; border-radius: 999px; padding: 0 7px; font-size: .75rem; font-weight: 700; white-space: nowrap; }

/* Online Requests: make the selected step tab stand out (filled, not just outlined) */
.rq-step { transition: background-color .15s, color .15s; }
.rq-step.active { background: #1e3a5f; border-color: #1e3a5f; color: #fff; font-weight: 700; box-shadow: 0 -2px 0 #f59e0b inset, 0 2px 6px rgba(30,58,95,.25); position: relative; z-index: 1; }
.rq-step.active:hover { background: #1e3a5f; }
.rq-step.active .rq-step-n { background: #fff; color: #1e3a5f; }
.rq-step.active .badge { background: #fff !important; color: #1e3a5f !important; }
.rq-step.active i { color: inherit; }
.rq-step-attention.active { background: #b02a37; border-color: #b02a37; box-shadow: 0 -2px 0 #ffc107 inset, 0 2px 6px rgba(176,42,55,.3); }
.rq-step-attention.active:hover { background: #b02a37; }
.rq-step-attention.active .badge { color: #b02a37 !important; }
.rq-step-needticket.active { background: #c2410c; border-color: #c2410c; box-shadow: 0 -2px 0 #fde68a inset, 0 2px 6px rgba(194,65,12,.3); }
.rq-step-needticket.active:hover { background: #c2410c; }
.rq-step-needticket.active .badge { color: #c2410c !important; }
.rq-step-muted.active { background: #495057; border-color: #495057; }

/* "Printing…" / "Opening activity log…" note beside a clicked popup icon button (ui-feedback.js) */
.ib-toast { position: fixed; z-index: 3000; background: #111827; color: #fff; font-size: .82rem; font-weight: 600; padding: .3rem .65rem; border-radius: 999px;
  box-shadow: 0 4px 14px rgba(0,0,0,.25); opacity: 0; transform: translateY(-4px); transition: opacity .15s, transform .15s; pointer-events: none; white-space: nowrap; }
.ib-toast.show { opacity: 1; transform: translateY(0); }

/* Driver Log — row 2 (route) and row 3 (Load truck) under the header. */
.dlog-route-bar { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .75rem; padding: .5rem 1.1rem; border-bottom: 1px solid var(--pos-border, #e9ecef); background: #fafbfc; min-height: 48px; }
.dlog-route-bar .dlog-driver-chips { padding: 0; border: 0; background: transparent; }
.dlog-route-bar #dlog-route-info { margin-left: -.45rem; }
.dlog-route-bar #dlog-route-info:not(:empty)::before { content: "· "; }
.dlog-load-bar { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .85rem; padding: .6rem 1.1rem; background: #eef5ff; border-bottom: 1px solid #d6e4fb; transition: background-color .6s ease; }
.dlog-load-title { font-weight: 600; color: var(--bs-primary, #0d6efd); white-space: nowrap; }
.dlog-load-form { width: auto; flex-wrap: nowrap; }
.dlog-load-form .form-control { width: 220px; font-size: 1rem; }
.dlog-load-progress { display: inline-block; width: 110px; height: 8px; background: #d6e4fb; border-radius: 4px; overflow: hidden; }
.dlog-load-progress > span { display: block; height: 100%; width: 0; background: var(--bs-primary, #0d6efd); transition: width .3s ease; }
.dlog-load-chip { display: inline-flex; align-items: center; border: 1px solid; border-radius: 999px; padding: 1px 10px; font-size: .82rem; background: #fff; white-space: nowrap; }
.dlog-load-chip.ok { border-color: #9bd3ae; background: #ecf8f0; color: #146c43; }
.dlog-load-chip.err { border-color: #f1b0b7; background: #fdf0f1; color: #a52834; }
.dlog-load-chip.old { opacity: .55; }
.dlog-load-bar.dlog-load-flash-ok { animation: dlogFlashOk .9s ease; }
.dlog-load-bar.dlog-load-flash-err { animation: dlogFlashErr .9s ease; }
@keyframes dlogFlashOk { 0% { background: #c9ecd4; } 100% { background: #eef5ff; } }
@keyframes dlogFlashErr { 0% { background: #f8d0d5; } 100% { background: #eef5ff; } }

/* Online Requests › Needs Attention — overdue rows and filter chips. */
.rq-overdue { display: inline-block; background: #fde2e4; color: #a52834; border: 1px solid #f1b0b7; font-weight: 700; font-size: .72rem; border-radius: 4px; padding: 1px 6px; white-space: nowrap; }
.rq-row.rq-overdue-row { --rq-bar: #dc3545; }
.rq-attn-filters { display: flex; flex-wrap: wrap; gap: 6px; padding: 6px 16px; border-bottom: 1px solid #eef1f4; }
.rq-attn-chip { border: 1px solid #ced4da; border-radius: 999px; padding: 2px 11px; background: #fff; font-size: .8rem; color: #343a40; }
.rq-attn-chip b { font-weight: 600; margin-left: 2px; }
.rq-attn-chip:hover { border-color: #0d6efd; }
.rq-attn-chip.on { background: #212b3b; border-color: #212b3b; color: #fff; }

/* Ticket # chips (Online Requests, Driver Log) — as easy to spot as the bag number. */
.rq-tkt { display: inline-block; padding: 0 6px; border-radius: 4px; background: #e7f1ff; border: 1px solid #b6d4fe; color: #084298; font-weight: 600; white-space: nowrap; }
/* Search box next to the date filter. */
.rq-search { position: relative; }
.rq-search > .bi-search { position: absolute; left: 9px; top: 50%; transform: translateY(-50%); color: #6c757d; font-size: .8rem; pointer-events: none; }
.rq-search > input { padding-left: 27px; width: 250px; }
