/* olly-ui/components.css — Olly component library (spec §2.5)
 *
 * The reusable vocabulary for the dashboard (§5), the sandboxed canvas (§6),
 * and the view schema (§8): each view-schema block type maps 1:1 to a class
 * family here. Requires tokens.css. NO bespoke visual styles elsewhere.
 *
 * Component index (matches preview cards in olly-ui/components/):
 *   .olly-kpi            KPI card                (block type: kpi)
 *   .olly-rollup         region/district rollup  (block type: region_rollup)
 *   .olly-table          sortable data table     (block type: table)
 *   .olly-pace           pace bar
 *   .olly-alert-row      alert row               (block type: alert)
 *   .olly-section-header section header
 *   .olly-panel          panel                   (layout container)
 *   .olly-drawer         slide-over drawer       (store drill-in, reports)
 *   .olly-fab            help-bot FAB
 *   .olly-chat-*         chat bubbles + panel
 *   .olly-canvas-shell   canvas host chrome
 */

/* -- Panel ----------------------------------------------------------------*/
.olly-panel {
  background: var(--olly-surface);
  border: 1px solid var(--olly-line-2);
  border-radius: var(--olly-r-md);
  padding: var(--olly-sp-4);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

/* -- Section header -------------------------------------------------------*/
.olly-section-header {
  font-size: var(--olly-fs-xs);
  font-weight: var(--olly-fw-semibold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--olly-muted-2);
  margin: 0 0 var(--olly-sp-3);
}

/* -- KPI card -------------------------------------------------------------*/
.olly-kpi {
  background: var(--olly-surface);
  border: 1px solid var(--olly-line-2);
  border-radius: var(--olly-r-md);
  padding: var(--olly-sp-3) var(--olly-sp-4);
  display: flex;
  flex-direction: column;
  gap: var(--olly-sp-1);
  min-width: 130px;
}
.olly-kpi__label {
  font-size: var(--olly-fs-2xs);
  font-weight: var(--olly-fw-medium);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--olly-muted-2);
}
.olly-kpi__value {
  font-size: var(--olly-fs-xl);
  font-weight: var(--olly-fw-bold);
  color: var(--olly-ink);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.olly-kpi__delta { font-size: var(--olly-fs-xs); color: var(--olly-muted); }
.olly-kpi--good .olly-kpi__value { color: var(--olly-good); }
.olly-kpi--warn .olly-kpi__value { color: var(--olly-warn); }
.olly-kpi--bad  .olly-kpi__value { color: var(--olly-bad); }

/* -- Region / district rollup card ---------------------------------------*/
.olly-rollup {
  background: var(--olly-surface);
  border: 1px solid var(--olly-line-2);
  border-radius: var(--olly-r-md);
  padding: var(--olly-sp-3) var(--olly-sp-4);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--olly-sp-3);
}
.olly-rollup__name  { font-size: var(--olly-fs-md); font-weight: var(--olly-fw-semibold); color: var(--olly-ink); }
.olly-rollup__meta  { font-size: var(--olly-fs-xs); color: var(--olly-muted-2); }
.olly-rollup__value { font-size: var(--olly-fs-lg); font-weight: var(--olly-fw-bold);
                      color: var(--olly-ink); font-variant-numeric: tabular-nums; }

/* -- Sortable data table ---------------------------------------------------*/
.olly-table { width: 100%; min-width: 700px; border-collapse: collapse; font-size: var(--olly-fs-sm); }
.olly-table th {
  text-align: left;
  font-size: var(--olly-fs-2xs);
  font-weight: var(--olly-fw-semibold);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--olly-muted-2);
  padding: var(--olly-sp-2) var(--olly-sp-3);
  border-bottom: 1px solid var(--olly-line-3);
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}
.olly-table th.is-sorted-asc::after  { content: ' ▲'; font-size: 0.6em; }
.olly-table th.is-sorted-desc::after { content: ' ▼'; font-size: 0.6em; }
.olly-table td {
  padding: var(--olly-sp-2) var(--olly-sp-3);
  border-bottom: 1px solid var(--olly-line);
  color: var(--olly-ink);
  font-variant-numeric: tabular-nums;
}
.olly-table tbody tr { cursor: pointer; }
.olly-table tbody tr:hover { background: var(--olly-bg); }
.olly-table th:first-child,
.olly-table td:first-child { position: sticky; left: 0; z-index: 1; background: var(--olly-surface); }
.olly-table tbody tr:hover td:first-child { background: var(--olly-bg); }
.olly-table .is-bad  { color: var(--olly-bad);  font-weight: var(--olly-fw-semibold); }
.olly-table .is-warn { color: var(--olly-warn); font-weight: var(--olly-fw-semibold); }
.olly-table .is-good { color: var(--olly-good); }

/* -- Stores table (overview zone 4) ---------------------------------------
   Fixed layout + explicit per-column widths. The shared .olly-table min-width
   of 700px forces ~270px of surplus on a 393px phone, and auto-layout hands
   most of it to the widest column (STORE) — half the table. Widths are in rem
   so they track user font scaling; numeric columns are sized above their
   max-content so figures never wrap, truncate, or ellipsize. Only STORE
   truncates (full name is in the cell's title + the row click-through).
   Scoped to the modifier: .olly-table is shared by tables with different
   column counts (olly-dashboard.js, calls-dashboard.js, canvas-frame.html). */
.olly-table.olly-table--stores {
  table-layout: fixed;
  min-width: 27rem;                /* == sum of the widths below (432px) */
}
/* border-box is load-bearing: the widths below are whole-column, and cells are
   content-box by default — without this the 8px side padding is ADDED to each
   width, fattening every numeric column by 16px and starving STORE to 48px. */
.olly-table--stores th,
.olly-table--stores td {
  box-sizing: border-box;
  padding: var(--olly-sp-2);       /* 12px -> 8px sides: reclaims 40px */
}
.olly-table--stores th { white-space: normal; }   /* "AVG TICKET" wraps to 2 lines instead of
                                                     forcing an 85px header-driven column */
.olly-table--stores td { white-space: nowrap; }   /* figures never wrap */

/* Column widths — under table-layout:fixed these must sit on the FIRST ROW (th),
   not the td. A width on td:first-child would do nothing for column sizing. */
.olly-table--stores th:nth-child(1) { width: 7rem; }      /* STORE  ~15 chars    */
.olly-table--stores th:nth-child(2) { width: 3.75rem; }   /* CARS   hdr+▲        */
.olly-table--stores th:nth-child(3) { width: 5rem; }      /* NET    $152,291     */
.olly-table--stores th:nth-child(4) { width: 5.25rem; }   /* TICKET $1,214.43    */
.olly-table--stores th:nth-child(5) { width: 6rem; }      /* WOW    ▲ +1234.5%   */

/* STORE: the only column allowed to truncate. */
.olly-table--stores td:first-child { overflow: hidden; }
.olly-table--stores .olly-store-name {
  display: inline-block; max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; vertical-align: bottom;
}
/* Reserve room for the no-data asterisk so it survives truncation. */
.olly-table--stores td.has-flag .olly-store-name { max-width: calc(100% - 0.75rem); }

/* Frozen-column seam. box-shadow, NOT border-right: under border-collapse:collapse
   the collapsed border is painted by the table, not the cell, so it does not travel
   with a sticky cell and drops out mid-scroll in Chromium. */
.olly-table--stores th:first-child,
.olly-table--stores td:first-child { box-shadow: 1px 0 0 0 var(--olly-line-2); }

/* Desktop: let STORE absorb the surplus so columns don't bunch left.
   Fixed-layout gives ALL leftover space to the single auto column (CSS2.1). */
@media (min-width: 720px) {
  .olly-table--stores th:nth-child(1) { width: auto; }
}

/* -- Pace bar ---------------------------------------------------------------*/
.olly-pace { display: flex; align-items: center; gap: var(--olly-sp-2); min-width: 110px; }
.olly-pace__track {
  flex: 1; height: 6px; border-radius: 3px;
  background: var(--olly-line-2); overflow: hidden;
}
.olly-pace__fill { height: 100%; border-radius: 3px; background: var(--olly-good); }
.olly-pace--warn .olly-pace__fill { background: var(--olly-warn); }
.olly-pace--bad  .olly-pace__fill { background: var(--olly-bad); }
.olly-pace__label { font-size: var(--olly-fs-xs); color: var(--olly-muted); font-variant-numeric: tabular-nums; }

/* -- Alert row ---------------------------------------------------------------*/
.olly-alert-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--olly-sp-3);
  padding: var(--olly-sp-2) var(--olly-sp-3);
  border-radius: var(--olly-r-sm);
  margin-bottom: var(--olly-sp-2);
  font-size: var(--olly-fs-sm);
  background: var(--olly-tint-info);
  color: var(--olly-ink);
}
.olly-alert-row--good { background: var(--olly-tint-good); }
.olly-alert-row--warn { background: var(--olly-tint-warn); }
.olly-alert-row--bad  { background: #fde8e8; }
.olly-alert-row__title { font-weight: var(--olly-fw-semibold); }
.olly-alert-row__meta  { font-size: var(--olly-fs-xs); color: var(--olly-muted); }

/* -- Drawer -------------------------------------------------------------------*/
.olly-drawer {
  position: fixed; top: 0; right: 0; bottom: 0;
  width: min(480px, 92vw);
  background: var(--olly-surface);
  border-left: 1px solid var(--olly-line-2);
  box-shadow: var(--olly-shadow-3);
  transform: translateX(100%);
  transition: transform 0.22s ease;
  z-index: 150;
  display: flex; flex-direction: column;
}
.olly-drawer.is-open { transform: translateX(0); }
.olly-drawer__head {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--olly-sp-4);
  border-bottom: 1px solid var(--olly-line-2);
}
.olly-drawer__title { font-size: var(--olly-fs-lg); font-weight: var(--olly-fw-bold); color: var(--olly-ink); }
.olly-drawer__body  { flex: 1; min-height: 0; overflow-y: auto; padding: var(--olly-sp-4); }

/* -- Buttons / chips (pill language from the live tabs) -----------------------*/
.olly-btn {
  font: var(--olly-fw-medium) var(--olly-fs-sm) var(--olly-font-sans);
  color: var(--olly-ink);
  background: var(--olly-surface);
  border: 1px solid var(--olly-line-3);
  border-radius: var(--olly-r-pill);
  padding: 6px 14px;
  cursor: pointer;
}
.olly-btn:hover { background: var(--olly-bg); }
.olly-btn--primary {
  background: var(--olly-primary); color: var(--olly-on-primary); border-color: var(--olly-primary);
}
.olly-btn--primary:hover { opacity: 0.88; background: var(--olly-primary); }
.olly-chip {
  display: inline-flex; align-items: center; gap: var(--olly-sp-1);
  font-size: var(--olly-fs-xs);
  border: 1px solid var(--olly-line-3);
  border-radius: var(--olly-r-pill);
  padding: 3px 10px;
  color: var(--olly-muted);
  background: var(--olly-surface);
  cursor: pointer;
}
.olly-chip.is-active { background: var(--olly-primary); color: var(--olly-on-primary); border-color: var(--olly-primary); }

/* -- Form controls --------------------------------------------------------------*/
.olly-input, .olly-select {
  font: var(--olly-fw-regular) var(--olly-fs-sm) var(--olly-font-sans);
  color: var(--olly-ink);
  background: var(--olly-surface);
  border: 1px solid var(--olly-line-3);
  border-radius: var(--olly-r-sm);
  padding: 6px 10px;
}
.olly-input:focus, .olly-select:focus { outline: 2px solid var(--olly-line-3); outline-offset: 1px; }

/* -- Help-bot FAB (sticky bottom-left) --------------------------------------------*/
.olly-fab {
  position: fixed; left: var(--olly-sp-5); bottom: var(--olly-sp-5);
  width: 52px; height: 52px;
  border-radius: 50%;
  background: var(--olly-primary); color: var(--olly-on-primary);
  border: none; cursor: pointer;
  box-shadow: var(--olly-shadow-2);
  display: flex; align-items: center; justify-content: center;
  z-index: 70;
  transition: transform 0.15s ease;
}
.olly-fab:hover { transform: scale(1.06); }
.olly-fab .material-icons-outlined { font-size: 26px; }
.olly-fab__badge {
  position: absolute; top: -2px; right: -2px;
  width: 12px; height: 12px; border-radius: 50%;
  background: var(--olly-good); border: 2px solid var(--olly-surface);
}

/* -- Chat panel + bubbles -----------------------------------------------------------*/
.olly-chat-panel {
  position: fixed; left: var(--olly-sp-5); bottom: 84px;
  width: min(400px, calc(100vw - 40px));
  height: min(560px, calc(100vh - 140px));
  background: var(--olly-surface);
  border: 1px solid var(--olly-line-2);
  border-radius: var(--olly-r-md);
  box-shadow: var(--olly-shadow-3);
  display: none; flex-direction: column;
  overflow: hidden;
  z-index: 69;
}
.olly-chat-panel.is-open { display: flex; }
.olly-chat-panel__head {
  padding: var(--olly-sp-3) var(--olly-sp-4);
  border-bottom: 1px solid var(--olly-line-2);
  display: flex; align-items: center; justify-content: space-between;
  font-weight: var(--olly-fw-bold); font-size: var(--olly-fs-md); color: var(--olly-ink);
}
.olly-chat-panel__log {
  flex: 1; overflow-y: auto;
  padding: var(--olly-sp-3);
  display: flex; flex-direction: column; gap: var(--olly-sp-2);
  background: var(--olly-bg);
}
.olly-chat-panel__input {
  display: flex; gap: var(--olly-sp-2);
  padding: var(--olly-sp-3);
  border-top: 1px solid var(--olly-line-2);
}
.olly-chat-panel__input .olly-input { flex: 1; }

/* -- Chat history (hamburger) panel — swaps into the log+input's flex slot,
   never widens the floating panel itself (see olly-chat.js comment) ------*/
.olly-chat-panel__threads { flex: 1; overflow-y: auto; flex-direction: column; background: var(--olly-surface); }
.olly-chat-panel__threads-head { padding: var(--olly-sp-3); border-bottom: 1px solid var(--olly-line-2); }
.olly-chat-panel__threads-head .olly-btn { width: 100%; }
.olly-chat-panel__threads-list { flex: 1; overflow-y: auto; }
.olly-thread-item {
  padding: var(--olly-sp-3);
  border-bottom: 1px solid var(--olly-line);
  cursor: pointer;
}
.olly-thread-item:hover { background: var(--olly-bg); }
.olly-thread-item.is-active { background: var(--olly-tint-info); }
.olly-thread-item__title {
  font-size: var(--olly-fs-sm); color: var(--olly-ink); font-weight: var(--olly-fw-medium);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.olly-thread-item__meta { font-size: var(--olly-fs-2xs); color: var(--olly-muted-2); margin-top: 2px; }

.olly-chat-bubble {
  position: relative;            /* anchors the per-message copy button */
  max-width: 84%;
  padding: var(--olly-sp-2) var(--olly-sp-3);
  border-radius: var(--olly-r-md);
  font-size: var(--olly-fs-sm);
  line-height: 1.45;
  white-space: pre-wrap;
  word-wrap: break-word;
}
.olly-chat-bubble--user {
  align-self: flex-end;
  background: var(--olly-primary); color: var(--olly-on-primary);
  border-bottom-right-radius: var(--olly-sp-1);
}
.olly-chat-bubble--olly {
  align-self: flex-start;
  background: var(--olly-surface); color: var(--olly-ink);
  border: 1px solid var(--olly-line-2);
  border-bottom-left-radius: var(--olly-sp-1);
}
.olly-chat-bubble--system {
  align-self: center;
  background: var(--olly-tint-info); color: var(--olly-muted);
  font-size: var(--olly-fs-xs);
}
.olly-chat-typing { align-self: flex-start; color: var(--olly-faint); font-size: var(--olly-fs-xs); }

/* Per-message copy button (req-56366498e8f9) — hover-reveal on desktop, always
   faintly visible on touch. Mirrors the nchat-react-add affordance pattern. */
.olly-msg-copy {
  position: absolute; top: 3px; right: 4px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; background: none; padding: 2px; margin: 0; cursor: pointer;
  color: inherit; opacity: 0; border-radius: var(--olly-r-sm, 6px);
  transition: opacity .12s ease, background .12s ease;
}
.olly-chat-bubble:hover .olly-msg-copy,
.olly-msg-copy:focus-visible { opacity: .5; }
.olly-msg-copy:hover { opacity: 1; background: rgba(127, 127, 127, .18); }
.olly-msg-copy .material-icons-outlined { font-size: 15px; line-height: 1; }
.olly-msg-copy.is-copied { opacity: 1; color: var(--olly-good, #16a34a); }
@media (hover: none) { .olly-msg-copy { opacity: .4; } }  /* touch: no hover to reveal */

/* -- Canvas shell ----------------------------------------------------------------------*/
.olly-canvas-shell {
  background: var(--olly-surface);
  border: 1px solid var(--olly-line-2);
  border-radius: var(--olly-r-md);
  overflow: hidden;
  min-height: 320px;
  position: relative;
}
.olly-canvas-shell__toolbar {
  display: flex; align-items: center; gap: var(--olly-sp-2);
  padding: var(--olly-sp-2) var(--olly-sp-3);
  border-bottom: 1px solid var(--olly-line);
  background: var(--olly-surface);
  flex-wrap: wrap;
}
.olly-canvas-shell__frame { width: 100%; border: 0; display: block; background: var(--olly-bg); }
.olly-canvas-shell__badge {
  font-size: var(--olly-fs-2xs);
  color: var(--olly-muted-2);
  margin-left: auto;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* -- Grid used by widget views ------------------------------------------------------------*/
.olly-grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: var(--olly-sp-3);
}
.olly-grid > * { grid-column: span 12; }
@media (min-width: 720px) {
  .olly-grid > [data-colspan="3"] { grid-column: span 3; }
  .olly-grid > [data-colspan="4"] { grid-column: span 4; }
  .olly-grid > [data-colspan="6"] { grid-column: span 6; }
  .olly-grid > [data-colspan="12"] { grid-column: span 12; }
}

/* -- Layout primitives (dashboard rows/grids, previously ad-hoc inline styles) -----------*/
.olly-kpi-row {
  display: flex;
  gap: var(--olly-sp-3);
  flex-wrap: wrap;
  margin-bottom: var(--olly-sp-4);
}
.olly-auto-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--olly-sp-3);
  margin-bottom: var(--olly-sp-4);
}
.olly-filter-bar {
  display: flex;
  gap: var(--olly-sp-2);
  flex-wrap: wrap;
  align-items: center;
  margin-bottom: var(--olly-sp-3);
}
.olly-form-stack { display: grid; gap: var(--olly-sp-3); }
.olly-field-label { font-size: var(--olly-fs-xs); color: var(--olly-muted); }
.olly-chip-row { display: flex; gap: var(--olly-sp-2); flex-wrap: wrap; }

/* ===================================================================== */
/*  Unified Overview (redesign) — the one dashboard surface              */
/* ===================================================================== */

.olly-ov-controls {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: var(--olly-sp-3); flex-wrap: wrap;
  padding: var(--olly-sp-3) var(--olly-sp-4);
  background: color-mix(in srgb, var(--olly-bg) 88%, transparent);
  backdrop-filter: saturate(1.2) blur(6px);
  border-bottom: 1px solid var(--olly-line-2);
}
.olly-ov-controls__right { display: flex; align-items: center; gap: var(--olly-sp-2); margin-left: auto; }
.olly-ov-seg { display: flex; gap: var(--olly-sp-1); flex-wrap: wrap; }
.olly-ov-body { display: flex; flex-direction: column; gap: var(--olly-sp-4); padding: var(--olly-sp-4); }
.olly-ov-skel { color: var(--olly-faint); font-size: var(--olly-fs-sm); padding: var(--olly-sp-6); text-align: center; }

/* breadcrumb */
.olly-crumbs { display: flex; align-items: center; gap: var(--olly-sp-1); flex-wrap: wrap; }
.olly-crumb {
  font: var(--olly-fw-medium) var(--olly-fs-sm) var(--olly-font-sans);
  color: var(--olly-info); background: none; border: none; padding: 2px 4px; cursor: pointer; border-radius: 6px;
}
.olly-crumb:hover:not(:disabled) { background: var(--olly-tint-info); }
.olly-crumb.is-active { color: var(--olly-ink); font-weight: var(--olly-fw-semibold); cursor: default; }
.olly-crumb:disabled { cursor: default; }
.olly-crumb__sep { color: var(--olly-faint); font-size: var(--olly-fs-sm); }

/* freshness pill */
.olly-freshness {
  font-size: var(--olly-fs-xs); color: var(--olly-muted);
  background: var(--olly-tint-good); border: 1px solid transparent;
  padding: 4px 10px; border-radius: var(--olly-r-pill); white-space: nowrap;
}
.olly-freshness.is-stale { background: #fde8e8; color: var(--olly-bad); border-color: var(--olly-bad); font-weight: var(--olly-fw-semibold); }

/* zones */
.olly-ov-zone { }
.olly-ov-zone__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--olly-sp-2); margin-bottom: var(--olly-sp-3); }
.olly-ov-zone__head .olly-section-header { margin: 0; }
.olly-ov-zone__sub { font-size: var(--olly-fs-xs); color: var(--olly-muted-2); font-variant-numeric: tabular-nums; }
.olly-ov-foot { font-size: var(--olly-fs-2xs); color: var(--olly-muted-2); margin-top: var(--olly-sp-2); line-height: 1.5; }
.olly-ov-empty { font-size: var(--olly-fs-sm); color: var(--olly-faint); padding: var(--olly-sp-2) 0; }
.olly-ov-grid2 { display: grid; grid-template-columns: 1fr; gap: var(--olly-sp-4); }
@media (min-width: 860px) { .olly-ov-grid2 { grid-template-columns: 1fr 1fr; } }

/* live pulse */
.olly-ov-bluf { font-size: var(--olly-fs-lg); color: var(--olly-ink); margin-bottom: var(--olly-sp-2); }
.olly-ov-bluf strong { font-weight: var(--olly-fw-bold); }
.olly-ov-copilot {
  display: flex; align-items: flex-start; gap: var(--olly-sp-2);
  font-size: var(--olly-fs-sm); color: var(--olly-muted);
  background: var(--olly-tint-info); border-radius: var(--olly-r-sm);
  padding: var(--olly-sp-2) var(--olly-sp-3); margin-bottom: var(--olly-sp-3);
}
.olly-ov-copilot__dot { width: 8px; height: 8px; border-radius: 50%; background: var(--olly-info); margin-top: 5px; flex: none; }
.olly-ov-copilot em { color: var(--olly-ink); font-style: normal; font-weight: var(--olly-fw-medium); }
.olly-ov-pulsegrid { display: grid; grid-template-columns: 1fr; gap: var(--olly-sp-3); }
@media (min-width: 720px) { .olly-ov-pulsegrid { grid-template-columns: repeat(3, 1fr); } }
.olly-ov-pulsecol__title { font-size: var(--olly-fs-xs); font-weight: var(--olly-fw-semibold); color: var(--olly-muted); margin-bottom: var(--olly-sp-2); }

/* pace gauge */
.olly-gauge { margin-top: var(--olly-sp-3); }
.olly-gauge__head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: var(--olly-sp-2); }
.olly-gauge__title { font-size: var(--olly-fs-sm); color: var(--olly-muted); }
.olly-gauge__val { font-size: var(--olly-fs-md); font-weight: var(--olly-fw-bold); font-variant-numeric: tabular-nums; }
.olly-gauge__val--good { color: var(--olly-good); }
.olly-gauge__val--warn { color: var(--olly-warn); }
.olly-gauge__val--bad  { color: var(--olly-bad); }
.olly-gauge__track { position: relative; height: 12px; border-radius: 6px; background: var(--olly-line-2); overflow: visible; }
.olly-gauge__fill  { height: 100%; border-radius: 6px; transition: width 0.4s ease; }
.olly-gauge__fill--good { background: var(--olly-good); }
.olly-gauge__fill--warn { background: var(--olly-warn); }
.olly-gauge__fill--bad  { background: var(--olly-bad); }
.olly-gauge__tick { position: absolute; top: -3px; width: 2px; height: 18px; background: var(--olly-ink); opacity: 0.55; }

/* delta tones on KPI cards */
.olly-kpi__delta.is-good { color: var(--olly-good); }
.olly-kpi__delta.is-bad  { color: var(--olly-bad); }

/* charts */
.olly-chart { width: 100%; height: 240px; }
.olly-ov-movers { margin-top: var(--olly-sp-2); }
.olly-ov-missing { margin-top: var(--olly-sp-3); font-size: var(--olly-fs-sm); color: var(--olly-muted); }
.olly-ov-missing summary { cursor: pointer; }

/* overflow menu (reports / scheduling / legacy) */
.olly-ov-controls__right { position: relative; }
.olly-ov-menu {
  position: absolute; right: 0; top: calc(100% + 6px);
  background: var(--olly-surface); border: 1px solid var(--olly-line-2);
  border-radius: var(--olly-r-md); box-shadow: var(--olly-shadow-2);
  z-index: 40; min-width: 210px; overflow: hidden;
}
.olly-ov-menu__item {
  display: block; width: 100%; text-align: left; padding: 10px 14px;
  background: none; border: none; cursor: pointer;
  font: var(--olly-fw-medium) var(--olly-fs-sm) var(--olly-font-sans); color: var(--olly-ink);
}
.olly-ov-menu__item:hover { background: var(--olly-bg); }

/* No-data flag — red asterisk marking a zero-filled store/day with no data from
   the register upload OR the MTM backup (roster-completion, 2026-07-11). */
.olly-nodata-flag { color: var(--olly-bad); font-weight: var(--olly-fw-bold); }
