:root {
  --bg: #0b0e14;
  --panel: #12161f;
  --panel-2: #171c27;
  --border: #262c3a;
  --text: #e7eaf1;
  --muted: #8891a3;
  --accent: #5b8def;
  --accent-dim: #5b8def33;
  --ok: #34d399;
  --err: #f2685c;
  --radius: 10px;
  --mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  --sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  min-height: 100vh;
  /* Hard safety net — the page itself must never scroll horizontally.
     Wide content (tables, charts, card rows) scrolls inside its own
     overflow-x:auto container instead; this just guards against any one
     of those containers' children forcing the whole page wider (the
     classic flex min-width:auto gotcha — see .stat-tile). */
  overflow-x: hidden;
  background: var(--bg);
  background-image:
    radial-gradient(circle at 15% 0%, #5b8def14, transparent 45%),
    radial-gradient(circle at 85% 100%, #34d39912, transparent 40%);
  color: var(--text);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
}

body {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 28px;
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.06em;
  color: var(--muted);
  text-transform: uppercase;
}

.brand .dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--muted);
  box-shadow: 0 0 0 3px var(--accent-dim);
}
.brand .dot.ok { background: var(--ok); box-shadow: 0 0 0 3px #34d39933; }
.brand .dot.warn { background: #f2b84c; box-shadow: 0 0 0 3px #f2b84c33; }

.card {
  width: 100%;
  max-width: 380px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 28px;
  box-shadow: 0 20px 60px -20px #00000080;
}

.card h1 {
  font-size: 19px;
  font-weight: 600;
  margin: 0 0 4px;
  letter-spacing: -0.01em;
}

.card .sub {
  color: var(--muted);
  font-size: 13px;
  margin: 0 0 22px;
}

.tabs {
  display: flex;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 3px;
  margin-bottom: 20px;
}

.tabs button {
  flex: 1;
  padding: 8px 0;
  border: none;
  background: transparent;
  color: var(--muted);
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 500;
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}

.tabs button.active {
  background: var(--accent);
  color: #0b0e14;
}

label {
  display: block;
  font-size: 12px;
  color: var(--muted);
  margin: 14px 0 6px;
  font-family: var(--mono);
  letter-spacing: 0.02em;
}

input,
select {
  width: 100%;
  padding: 10px 12px;
  background: #0d1017;
  border: 1px solid var(--border);
  border-radius: 7px;
  color: var(--text);
  font-family: var(--sans);
  font-size: 14px;
  outline: none;
  transition: border-color 0.15s;
}

input:focus,
select:focus {
  border-color: var(--accent);
}

/* Native <input type="date"> doesn't read as an interactive "tap to
   change" control against this dark theme — it just looks like a plain
   text label showing today's date, with nothing to signal it opens a
   picker. A permanent calendar icon (drawn as an inline SVG, not an
   emoji glyph — style.css has no @charset declaration, and an emoji in
   a CSS content string is exactly the kind of thing that garbles if the
   stylesheet is ever served/read as something other than UTF-8) fixes
   that. It's a background-image on the input itself rather than a
   separate overlay element, so there's no extra element to keep aligned
   with — and no risk of it sitting on top of and blocking the input's
   own click target. #8891a3 below is var(--muted)'s literal value — CSS
   custom properties aren't substituted inside a data: URI. */
input[type="date"] {
  padding-right: 34px;
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238891a3' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2'/%3E%3Cline x1='16' y1='2' x2='16' y2='6'/%3E%3Cline x1='8' y1='2' x2='8' y2='6'/%3E%3Cline x1='3' y1='10' x2='21' y2='10'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 16px 16px;
}

/* Chromium's own picker icon would otherwise sit right on top of the
   icon above — hide it rather than recolor it. Its click target stays
   active even at opacity: 0, and Chromium treats the whole field (not
   just the icon) as clickable to open the picker, so this doesn't cost
   any way of opening it. */
input[type="date"]::-webkit-calendar-picker-indicator {
  opacity: 0;
  cursor: pointer;
}

.password-field {
  position: relative;
}

.password-field input {
  padding-right: 56px;
}

.toggle-password {
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  padding: 4px 8px;
  background: none;
  border: none;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  cursor: pointer;
}

.toggle-password:hover { color: var(--text); }

.checkbox-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 16px 0 0;
  font-size: 13px;
  font-family: var(--sans);
  color: var(--muted);
  text-transform: none;
  letter-spacing: normal;
  cursor: pointer;
}

.checkbox-row input[type="checkbox"] {
  width: 15px;
  height: 15px;
  accent-color: var(--accent);
  cursor: pointer;
}

.primary-btn {
  width: 100%;
  margin-top: 20px;
  padding: 11px 0;
  background: var(--accent);
  color: #0b0e14;
  border: none;
  border-radius: 7px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: opacity 0.15s;
}

.primary-btn:hover { opacity: 0.9; }
.primary-btn:disabled { opacity: 0.5; cursor: not-allowed; }

.msg {
  margin-top: 14px;
  font-size: 13px;
  padding: 10px 12px;
  border-radius: 7px;
  display: none;
  line-height: 1.4;
}

.msg.show { display: block; }
.msg.err { background: #f2685c1a; color: var(--err); border: 1px solid #f2685c33; }
.msg.ok { background: #34d3991a; color: var(--ok); border: 1px solid #34d39933; }

.config-warn {
  max-width: 380px;
  width: 100%;
  margin-bottom: 16px;
  padding: 10px 14px;
  background: #f2b84c14;
  border: 1px solid #f2b84c40;
  border-radius: 8px;
  color: #f2b84c;
  font-size: 12px;
  font-family: var(--mono);
  line-height: 1.5;
}

.footer-note {
  margin-top: 18px;
  font-size: 11px;
  color: var(--muted);
  font-family: var(--mono);
  text-align: center;
}

.link-btn {
  display: block;
  width: 100%;
  margin-top: 14px;
  padding: 0;
  background: none;
  border: none;
  color: var(--accent);
  font-family: var(--sans);
  font-size: 13px;
  text-align: center;
  cursor: pointer;
}

.link-btn:hover { text-decoration: underline; }

.back-link {
  display: inline-block;
  margin-top: 18px;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 12px;
  text-decoration: none;
}

.back-link:hover { color: var(--text); }

.btn-link {
  display: block;
  text-align: center;
  text-decoration: none;
  box-sizing: border-box;
}

/* App picker */
.picker-card {
  width: 100%;
  max-width: 760px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 28px;
}

.picker-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 22px;
}

.picker-header h1 {
  font-size: 19px;
  font-weight: 600;
  margin: 0 0 4px;
  letter-spacing: -0.01em;
}

.picker-header .sub {
  color: var(--muted);
  font-size: 13px;
  margin: 0;
}

.picker-header .signout-btn {
  width: auto;
  margin-top: 0;
  padding: 8px 16px;
}

.tile-section + .tile-section {
  margin-top: 24px;
}

.tile-section-title {
  margin: 0 0 10px;
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  font-family: var(--mono);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.app-grid {
  display: flex;
  /* Started as exactly 2 tiles (nowrap, split the row evenly). The tile
     list now grows per external tool added on landing.html, so a fixed
     single row stops making sense — let tiles wrap onto more rows
     instead of getting squeezed thinner forever. */
  flex-wrap: wrap;
  gap: 14px;
}

.app-tile {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 1 1 180px;
  min-width: 0;
  padding: 22px 18px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  text-decoration: none;
  text-align: center;
  transition: border-color 0.15s, transform 0.15s;
}

.app-tile:hover {
  border-color: var(--accent);
  transform: translateY(-1px);
}

.app-tile-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  /* Keep label + arrow on one line — a future longer label truncates
     with an ellipsis instead of spilling past the tile's edge. Needs its
     own min-width: 0 too: as a flex item, white-space: nowrap makes its
     content the min-content width, and flex items default to
     min-width: auto (never shrink below that) — the same gotcha
     .stat-tile hit, just one level deeper here. */
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* A gated tile a store doesn't have (e.g. system-restricted, or a
   store not in a per-store link map) still renders in place — faded and
   inert — instead of disappearing, so the grid reads as "not available
   yet" rather than "doesn't exist" and stays the same shape across
   stores. */
.app-tile--disabled {
  cursor: not-allowed;
  opacity: 0.45;
}

.app-tile--disabled:hover {
  border-color: var(--border);
  transform: none;
}

.app-tile-disabled-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}

.app-tile-note {
  font-size: 11px;
  font-family: var(--mono);
  color: var(--muted);
}

/* Embedded report pages */
.report-page {
  width: 100%;
  max-width: 1100px;
}

.report-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 18px;
}

.report-header h1 {
  font-size: 19px;
  font-weight: 600;
  margin: 0 0 4px;
  letter-spacing: -0.01em;
}

.report-embed {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 22px;
  box-shadow: 0 20px 60px -20px #00000080;
}

.report-embed + .report-embed {
  margin-top: 20px;
}

.report-embed-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px 16px;
  margin-bottom: 14px;
}

.report-embed h2 {
  font-size: 14px;
  font-weight: 600;
  margin: 0;
  color: var(--text);
}

.export-btn {
  padding: 6px 12px;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 7px;
  font-size: 12px;
  font-family: var(--mono);
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s;
}

.export-btn:hover:not(:disabled) {
  border-color: var(--accent);
  color: var(--accent);
}

.export-btn--secondary {
  opacity: 0.7;
  font-size: 11px;
}

.export-btn--secondary:hover:not(:disabled) {
  opacity: 1;
}

.export-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* Compact segmented control for the Daily Trend widget's Chart/Calendar
   toggle — same visual language as .tabs (pill container, accent-filled
   active state) but sized to sit inline with the export buttons in
   .report-embed-actions rather than spanning full width. "Chart" here
   means the line chart + table pair, not just the chart. */
.view-toggle-group {
  display: flex;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 7px;
  padding: 2px;
}

.view-toggle-btn {
  padding: 5px 10px;
  border: none;
  background: transparent;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 500;
  border-radius: 5px;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}

.view-toggle-btn.active {
  background: var(--accent);
  color: #0b0e14;
}

.report-page .tabs {
  max-width: 260px;
}

.scope-filter {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-bottom: 18px;
}

.scope-filter label {
  margin: 0;
}

.scope-filter input,
.scope-filter select {
  width: auto;
  min-width: 160px;
}

.filters-row {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin-bottom: 18px;
}

.filters-row > div {
  display: flex;
  flex-direction: column;
}

.filters-row label {
  margin: 0 0 6px;
}

.filters-row input,
.filters-row select {
  width: auto;
  min-width: 180px;
}

.table-scroll {
  overflow-x: auto;
  overflow-y: auto;
  max-height: 420px;
  border: 1px solid var(--border);
  border-radius: 8px;
}

.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}

.data-table th,
.data-table td {
  padding: 9px 12px;
  text-align: left;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

.data-table th {
  position: sticky;
  top: 0;
  background: var(--panel-2);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 500;
}


.data-table th.num,
.data-table td.num {
  text-align: right;
  font-family: var(--mono);
}

/* table-layout: fixed (not the .data-table default of auto) so every
   column's width comes only from the widths declared below, never from
   its own content. Without this, an empty/just-refreshed table looks
   properly narrow, but the moment real values land in it — especially
   Suggested Order's "⚠️ Manual - Insufficient Data" warning text, by
   far the widest thing that can appear in any cell — auto layout
   re-measures every column against its new (wider) content and the
   whole table balloons back out. Fixed layout means content that
   doesn't fit its column wraps (headers, and warning cells via
   .cell-warn's own white-space: normal) instead of resizing the column
   to fit it. All 8 columns' widths together (90+170+60+110+120+100+
   120+130 = 900px) comfortably fit most desktop widths without any
   horizontal scroll at all — the .table-scroll wrapper is still there
   as a safety net for anything narrower. */
.order-table {
  table-layout: fixed;
}

/* Every header in this table wraps rather than forcing its column
   wide — most just wrap using whatever width the column's own data
   (an input, a short number) already needs; Theoretical Usage's label
   is by far the longest relative to what its column actually needs. */
.order-table th {
  white-space: normal;
  line-height: 1.35;
}

.order-table th:nth-child(4),
.order-table td:nth-child(4) {
  width: 110px;
}

.order-table th:nth-child(5),
.order-table td:nth-child(5) {
  width: 120px;
}

.order-table th:nth-child(6),
.order-table td:nth-child(6) {
  width: 100px;
}

.order-table th:nth-child(7),
.order-table td:nth-child(7) {
  width: 120px;
}

.order-table th:nth-child(8),
.order-table td:nth-child(8) {
  width: 130px;
}

/* Order Details table only — Item Code/Description/UOM stay pinned to
   the left edge while the rest of the (wide) row scrolls underneath.
   Fixed widths + box-sizing: border-box are required here so the left
   offsets below (0 / 90 / 260) land exactly on the real column
   boundaries — a sticky cell's offset can't be expressed relative to
   its neighbor's actual rendered width otherwise. */
.order-table th:nth-child(1),
.order-table td:nth-child(1),
.order-table th:nth-child(2),
.order-table td:nth-child(2),
.order-table th:nth-child(3),
.order-table td:nth-child(3) {
  position: sticky;
  box-sizing: border-box;
  background: var(--panel);
}

.order-table th:nth-child(1),
.order-table td:nth-child(1) {
  left: 0;
  width: 90px;
  min-width: 90px;
}

.order-table th:nth-child(2),
.order-table td:nth-child(2) {
  left: 90px;
  width: 170px;
  min-width: 170px;
  max-width: 170px;
  overflow: hidden;
  text-overflow: ellipsis;
}

.order-table th:nth-child(3),
.order-table td:nth-child(3) {
  left: 260px;
  width: 60px;
  min-width: 60px;
  /* Divider line so the freeze boundary reads clearly once content is
     scrolling underneath it, not just implied by the pinned position. */
  box-shadow: 2px 0 4px -2px #00000080;
}

/* Header cells need both axes at once (sticky-top for vertical scroll,
   already set by .data-table th, plus sticky-left here) — a "frozen
   corner." Header background stays panel-2 (matches .data-table th),
   only re-declared here so it isn't overridden by the shared .panel
   background rule above. Higher z-index than the frozen body cells so
   the corner sits above everything, including the frozen columns'
   own box-shadow divider, while scrolling in both directions. */
.order-table th:nth-child(1),
.order-table th:nth-child(2),
.order-table th:nth-child(3) {
  background: var(--panel-2);
  z-index: 3;
}

.order-table td:nth-child(1),
.order-table td:nth-child(2),
.order-table td:nth-child(3) {
  z-index: 2;
}

/* Zebra striping, all .data-table instances (Order Details, Sense
   Check, History, etc.) — background goes on td, not tr, so it also
   covers Order Details' frozen Item Code/Description/UOM columns
   above, which already paint their own opaque background to stay
   solid while the rest of the row scrolls underneath; a tr-level
   background wouldn't show through those cells the way it does for a
   plain (non-frozen) table. Even rows get the full --panel-2 (not a
   faint blend toward --panel — that read as barely-there against how
   close those two tones already are) — the same jump already used for
   the sticky header vs. body, so it's a pairing already proven visible
   here. The three type selectors here (tbody/tr/td) are what let this
   beat the frozen columns' own `.order-table td:nth-child(...)`
   background rule above at equal class-count. */
.data-table tbody tr:nth-child(even) > td {
  background: var(--panel-2);
}

/* Hover needs to outrank the stripe above, not just match it — striped
   rows now sit at full --panel-2, so hover steps up to --border (one
   tier further, still an existing theme color rather than a new one)
   to stay visibly distinct on both odd and even rows. Set on td, not
   tr, so it also overrides a frozen column's own background, not just
   a plain cell's — this single rule replaces what used to need a
   separate `.order-table`-specific hover override for the frozen
   columns, now that hover is td-level everywhere. */
.data-table tbody tr:hover > td {
  background: var(--border);
}

.table-empty {
  text-align: center;
  color: var(--muted);
  padding: 24px 12px !important;
  white-space: normal;
}

.meta-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 20px;
  margin-bottom: 18px;
  font-size: 12px;
  font-family: var(--mono);
  color: var(--muted);
}

.meta-row strong {
  color: var(--text);
  font-weight: 500;
}

.tile-row-caption {
  font-size: 11px;
  font-family: var(--mono);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  margin-bottom: 10px;
}

.stat-tile-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 10px;
  margin-bottom: 20px;
}

.stack-total {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  padding-right: 24px;
  margin: 0;
  background: none;
  border: none;
  text-align: left;
  font: inherit;
  color: inherit;
  cursor: pointer;
}

.stack-total:hover .stat-tile-label {
  color: var(--text);
}

.stack-chevron {
  position: absolute;
  top: -2px;
  right: 0;
  color: var(--muted);
  font-size: 18px;
  line-height: 1;
  transition: transform 0.15s, color 0.15s;
}

.stack-total:hover .stack-chevron {
  color: var(--text);
}

.stack-total[aria-expanded="true"] .stack-chevron {
  transform: rotate(180deg);
}

.stack-subrows {
  display: none;
  flex-direction: column;
  gap: 6px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
}

.stack-subrows.is-open {
  display: flex;
}

.stack-subrow {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px;
  padding: 6px 8px;
  background: var(--panel);
  border-radius: 6px;
}

.stack-subrow-label {
  flex-shrink: 0;
  padding-top: 2px;
  font-size: 10px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  font-family: var(--mono);
  white-space: nowrap;
}

.stack-subrow-value-col {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  min-width: 0;
}

.stack-subrow-value {
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
  font-family: var(--mono);
  white-space: nowrap;
}

.stack-subrow-delta {
  font-size: 10px;
  font-family: var(--mono);
  white-space: nowrap;
}

.stack-subrow-delta.up { color: var(--ok); }
.stack-subrow-delta.down { color: var(--err); }
.stack-subrow-delta.flat { color: var(--muted); }

.stat-tile {
  position: relative;
  flex: 1 1 110px;
  /* Flex items default to min-width: auto, so a card holding an
     unbreakable long number (e.g. "140,546,834") won't shrink below
     that number's natural width — on a narrow screen that forces the
     whole row (and the page) wider than the viewport. */
  min-width: 0;
  background: linear-gradient(160deg, var(--panel-2) 0%, var(--panel) 100%);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 14px;
  box-shadow: 0 14px 40px -20px #000000a0;
  overflow: hidden;
}

.stat-tile::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: var(--accent);
}

.stat-tile-label {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--muted);
  margin-bottom: 5px;
  line-height: 1.3;
}

.stat-tile-value {
  font-size: 20px;
  font-weight: 600;
  color: var(--text);
  font-family: var(--mono);
  letter-spacing: -0.01em;
  line-height: 1.15;
  overflow-wrap: break-word;
}

.report-embed-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* Fixed height shared by both line charts so their own loading/empty
   states don't resize the card around them. */
#dailyTrendChart,
#monthlyTrendChart {
  min-height: 320px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* The chart's axis/tick text is sized in SVG viewBox units, so it
     shrinks proportionally with the container's rendered width — on a
     narrow phone that makes it illegible. Instead of letting the chart
     shrink to fit, give it a floor width and let it scroll horizontally,
     same pattern already used for wide tables. */
  overflow-x: auto;
  /* Native scrollbar hidden in favor of .chart-scroll-track below —
     showing both reads as a duplicated affordance. */
  scrollbar-width: none;
  -ms-overflow-style: none;
}

/* #dailyTrendChart's own `display: flex` above is an ID-selector rule,
   which beats the browser's built-in `[hidden] { display: none }` UA
   rule at equal-or-higher specificity regardless of source order — the
   same failure mode already documented on .stack-subrows/.is-open
   elsewhere in this file. Only Daily ever toggles this container's
   `hidden` (the Chart/Calendar switch); Monthly's is never hidden, but
   the override is harmless there either way. */
#dailyTrendChart[hidden] {
  display: none;
}

#dailyTrendChart::-webkit-scrollbar,
#monthlyTrendChart::-webkit-scrollbar {
  display: none;
}

/* Daily Trend's calendar heatmap (see .calendar-heatmap-card below) is
   sized to fill the available width rather than floored/centered like
   the line chart above. Horizontal scroll here is a narrow-phone safety
   net, not the normal case: .calendar-grid's columns are responsive
   (minmax), so they only hit their floor and trigger this on a
   genuinely tight viewport. */
#dailyTrendCalendar {
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

#dailyTrendCalendar::-webkit-scrollbar {
  display: none;
}

#dailyTrendTableWrap,
#monthlyTrendTableWrap {
  max-height: 320px;
}

.chart-card {
  position: relative;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 14px 14px 10px;
  min-width: 480px;
  flex-shrink: 0;
}

/* When the Chart/Calendar toggle is switched to Calendar, it's the only
   thing showing in the card (the line chart and table are hidden), so
   unlike a plain .chart-card it should fill the report card's full width
   on desktop rather than sit at a fixed floor width — unsets
   .chart-card's min-width/flex-shrink. min-width: 100% + width:
   max-content (rather than a plain width: 100%) so the card grows past
   the viewport when it has to: on a narrow phone, .calendar-grid's 46px
   column floor (see below) can force the grid wider than
   #dailyTrendCalendar's own viewport, and a plain 100% caps this card's
   background at the viewport width regardless — the extra columns you
   scroll to then render past the card's right edge, outside its
   highlighted background, on the bare page background instead.
   min-width: 100% still makes it fill the full width on desktop when
   max-content is smaller than that. (width: max(100%, max-content) was
   tried first and looked identical to a plain 100% in every inspector
   check — max-content isn't a valid argument inside max()/min()/clamp(),
   so that whole declaration was invalid and silently dropped, falling
   back to auto; min-width/width as separate longhands is the actual
   fix, confirmed in a headless Chrome test.) */
.calendar-heatmap-card {
  min-width: 100%;
  width: max-content;
  flex-shrink: 1;
}

/* Scroll position indicator for #dailyTrendChart / #monthlyTrendChart /
   #dailyTrendCalendar — a thin track+thumb below the card, like a mobile
   carousel dot bar,
   rather than an overlay on the card itself. Lives as a plain sibling of
   the scroll container (not absolutely positioned over it) specifically
   to avoid depending on the card's own bounds: the scroll container is
   taller than .chart-card (it vertically centers it via flex), so
   anything positioned top:0/bottom:0 against the container overshoots
   the card's actual rounded edges. */
.chart-scroll-track {
  display: none;
  height: 4px;
  margin: 8px 2px 0;
  border-radius: 2px;
  background: var(--border);
  overflow: hidden;
}

.chart-scroll-track.is-visible {
  display: block;
}

.chart-scroll-thumb {
  height: 100%;
  min-width: 24px;
  border-radius: 2px;
  /* Deliberately not --accent — that's the "This Year" line color in the
     chart above it, and reusing it here read as a third data series. */
  background: var(--muted);
}

.chart-card h3 {
  margin: 0 0 8px;
  font-size: 12px;
  font-weight: 500;
  color: var(--muted);
  font-family: var(--mono);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.chart-card svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

.chart-card svg rect:focus {
  outline: 1px solid var(--accent);
}

.chart-empty {
  padding: 30px 0;
  text-align: center;
  color: var(--muted);
  font-size: 12px;
}

/* Calendar heatmap — Daily Trend's alternate view (toggled in via
   .view-toggle-group, see .calendar-heatmap-card above), one month grid
   per calendar month in the selected range. Cell fill intensity encodes
   magnitude (sequential:
   one hue, light->dark, per the dataviz palette rules) rather than a
   good/bad color, since most metrics here have no inherent
   up-is-good/bad direction at the raw-value level (that distinction
   already lives in the vs-LY delta badges elsewhere on this page). */
.calendar-heatmap {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 22px;
}

.calendar-month {
  flex-shrink: 0;
}

.calendar-month-label {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 500;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  margin-bottom: 8px;
}

/* minmax columns let cells grow to fill the card's full width on
   desktop (the point of .calendar-heatmap-card above) while the 46px
   floor keeps them legible on a narrow phone — #dailyTrendCalendar's
   own overflow-x:auto is the fallback for whatever's still too tight
   below that floor. */
.calendar-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(46px, 1fr));
  gap: 6px;
}

.calendar-weekday {
  text-align: center;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--muted);
  padding-bottom: 4px;
}

.calendar-cell {
  /* Grid items default to min-width: auto, which lets a cell grow past
     its column's 46px floor to fit an unbreakable value like "571.3K"
     instead of respecting the track width — the same flex/grid gotcha
     CLAUDE.md documents elsewhere on this page. min-width: 0 forces the
     cell back to the column's actual width so overflow-wrap on
     .calendar-cell-value below can do its job. */
  min-width: 0;
  min-height: 64px;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: var(--panel-2);
  /* Fluid, tied to this cell's own rendered width (container query units,
     see container-type below) rather than a viewport breakpoint — a cell
     between the 46px mobile floor and a roomy desktop width sizes
     continuously instead of jumping between two fixed paddings, so a
     mid-size box never ends up carrying desktop padding it doesn't have
     room for. Caps out at exactly the old fixed 6px/8px once a cell is
     wide enough, so desktop is unaffected. */
  padding: clamp(4px, 9cqw, 6px) clamp(4px, 14cqw, 8px);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  /* Makes cqw below resolve against THIS element's own width, not the
     viewport — so the value/day font size tracks the box it's actually
     in, at every width, not just above/below one breakpoint. */
  container-type: inline-size;
}

.calendar-cell.has-value {
  cursor: pointer;
}

.calendar-cell.is-blank {
  border-color: transparent;
  background: transparent;
}

.calendar-cell-day {
  font-family: var(--mono);
  /* See .calendar-cell-value below for why this is fluid via cqw instead
     of a breakpoint-based override. */
  font-size: clamp(9px, 20cqw, 11px);
  color: var(--muted);
}

.calendar-cell-value {
  /* Same min-width: auto gotcha one level deeper — this is itself a
     flex item of .calendar-cell, so it needs its own min-width: 0 to
     actually shrink/wrap within the now-constrained cell rather than
     pushing past it. */
  min-width: 0;
  font-family: var(--mono);
  /* Scales with the cell's own width (cqw = % of .calendar-cell's inline
     size) instead of a single viewport breakpoint swap. A fixed mobile
     override (e.g. 9px under 640px) either overflowed a cell right at
     the 46px floor or left space unused in a wider one — this way the
     text is always sized for the box it's actually rendered in, capping
     at the old fixed 12px once a cell is roomy enough that desktop looks
     unchanged. */
  font-size: clamp(9px, 22cqw, 12px);
  font-weight: 600;
  color: var(--text);
  align-self: flex-end;
  text-align: right;
  overflow-wrap: break-word;
}

/* Reuses .chart-tooltip's look but is positioned relative to
   .calendar-heatmap (not an SVG's own viewBox), so it's a plain
   top/left-positioned child instead of the line chart's percentage-of-
   viewBox placement. */
.calendar-tooltip {
  transform: translate(-50%, calc(-100% - 8px));
}

.chart-tooltip {
  position: absolute;
  pointer-events: none;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px 9px;
  font-size: 11px;
  font-family: var(--mono);
  color: var(--text);
  box-shadow: 0 10px 30px -10px #000000a0;
  white-space: nowrap;
  opacity: 0;
  transform: translate(-50%, -100%);
  transition: opacity 0.1s;
  z-index: 5;
}

.chart-tooltip.show { opacity: 1; }

.chart-tooltip .v {
  font-weight: 600;
  color: var(--text);
}

.chart-tooltip .d {
  color: var(--muted);
  margin-top: 2px;
}

.chart-tooltip-rows {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.chart-tooltip-row {
  display: flex;
  align-items: center;
  gap: 6px;
}

.chart-tooltip-val {
  font-weight: 600;
  color: var(--text);
}

.chart-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
  margin: -2px 0 10px;
  font-size: 11px;
  font-family: var(--mono);
  color: var(--muted);
}

.chart-legend-item {
  display: flex;
  align-items: center;
  gap: 6px;
}

/* Line-key swatch — a short stroke of the series color/style, not a
   filled box, so it reads as "this is a line" rather than a bar/area. */
.chart-legend-key,
.chart-tooltip-key {
  display: inline-block;
  width: 14px;
  border-top: 2px solid;
}

.chart-legend-key.dashed,
.chart-tooltip-key.dashed {
  border-top-style: dashed;
}

.group-row td {
  background: var(--panel-2);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 500;
}

.stat-tile-delta {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-top: 8px;
  padding: 3px 8px;
  border-radius: 999px;
  font-size: 10px;
  font-weight: 500;
  font-family: var(--mono);
}

.stat-tile-delta.up { background: #34d3991a; color: var(--ok); }
.stat-tile-delta.down { background: #f2685c1a; color: var(--err); }
.stat-tile-delta.flat { background: var(--panel-2); color: var(--muted); }

.chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 14px;
}

.chip {
  padding: 6px 12px;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--muted);
  border-radius: 999px;
  font-size: 12px;
  font-family: var(--mono);
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s, background 0.15s;
}

.chip:hover {
  border-color: var(--accent);
  color: var(--text);
}

.chip.active {
  background: var(--accent-dim);
  border-color: var(--accent);
  color: var(--text);
}

.trend-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 16px;
}

.checkbox-row--inline {
  margin: 0;
  white-space: nowrap;
}

.trend-controls-left {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px;
}

.trend-controls .chip-row {
  margin-bottom: 0;
}

.trend-controls select,
.trend-controls input {
  width: auto;
  min-width: 150px;
}

.trend-controls input[type="checkbox"] {
  min-width: 0;
  width: 15px;
}

.trend-controls select#trendMetricSelect {
  min-width: 220px;
}

.trend-range {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

.trend-range .range-sep {
  color: var(--muted);
  font-family: var(--mono);
  font-size: 12px;
}

/* Searchable metric select (wraps a plain <select>, see
   createSearchableSelect in metrics-tracking.html) */
.searchable-select {
  position: relative;
  width: 220px;
  max-width: 100%;
  min-width: 0;
}

.searchable-select > select {
  display: none;
}

.searchable-select-trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  padding: 10px 12px;
  background: #0d1017;
  border: 1px solid var(--border);
  border-radius: 7px;
  color: var(--text);
  font-family: var(--sans);
  font-size: 14px;
  cursor: pointer;
  transition: border-color 0.15s;
}

.searchable-select-trigger:hover,
.searchable-select.is-open .searchable-select-trigger {
  border-color: var(--accent);
}

.searchable-select-trigger-value {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.searchable-select-trigger-arrow {
  flex-shrink: 0;
  color: var(--muted);
  font-size: 10px;
}

.searchable-select-panel {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  z-index: 20;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 20px 60px -20px #00000080;
  overflow: hidden;
}

.searchable-select-search {
  width: 100%;
  padding: 10px 12px;
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--border);
  border-radius: 0;
  color: var(--text);
  font-family: var(--sans);
  font-size: 14px;
  outline: none;
}

.searchable-select-list {
  max-height: 260px;
  overflow-y: auto;
  padding: 6px 0;
}

.searchable-select-group-label {
  padding: 8px 12px 4px;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.searchable-select-option {
  display: block;
  width: 100%;
  padding: 8px 12px;
  background: none;
  border: none;
  color: var(--text);
  font-family: var(--sans);
  font-size: 13px;
  text-align: left;
  cursor: pointer;
}

.searchable-select-option:hover,
.searchable-select-option.is-selected {
  background: var(--panel);
  color: var(--accent);
}

.searchable-select-empty {
  padding: 14px 12px;
  color: var(--muted);
  font-size: 13px;
  text-align: center;
}

/* Dashboard */
.dash-card {
  width: 100%;
  max-width: 460px;
  background: var(--panel);
  border: 1px solid var(--border);
  padding: 28px;
  border-radius: var(--radius);
}

.dash-card h1 {
  font-size: 19px;
  margin: 0 0 18px;
}

.field-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
}

.field-row:last-of-type { border-bottom: none; }

.field-row .k {
  color: var(--muted);
  font-family: var(--mono);
}

.field-row .v {
  color: var(--text);
  text-align: right;
  word-break: break-all;
  margin-left: 16px;
}

.signout-btn {
  width: 100%;
  margin-top: 22px;
  padding: 10px 0;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 7px;
  font-size: 13px;
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s;
}

.signout-btn:hover {
  border-color: var(--err);
  color: var(--err);
}

/* Stock Ordering */
.action-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 18px;
}

.btn {
  padding: 10px 18px;
  background: var(--accent);
  color: #0b0e14;
  border: none;
  border-radius: 7px;
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: opacity 0.15s;
}

.btn:hover:not(:disabled) { opacity: 0.9; }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }

.btn--secondary {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text);
}

.btn--secondary:hover:not(:disabled) {
  border-color: var(--accent);
  color: var(--accent);
}

.schedule-days {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin: 0 0 16px;
}

.schedule-day {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  min-width: 64px;
  padding: 10px 12px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}

.schedule-day:hover {
  border-color: var(--accent);
}

.schedule-day:has(input:checked) {
  background: var(--accent-dim);
  border-color: var(--accent);
}

.schedule-day input[type="checkbox"] {
  width: 22px;
  height: 22px;
  margin-top: 2px;
  accent-color: var(--accent);
  cursor: pointer;
}

.schedule-day input[type="checkbox"]:disabled {
  cursor: not-allowed;
}

.schedule-days.is-locked .schedule-day {
  opacity: 0.55;
  cursor: not-allowed;
}

.schedule-days.is-locked .schedule-day:hover {
  border-color: var(--border);
}

.schedule-day-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
}

.schedule-layout {
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
}

.schedule-main {
  flex: 3 1 380px;
  min-width: 0;
}

/* Vertical divider between the two columns — border-left on the second
   column rather than a separate element. This is a left/top border
   pair with the mobile media query below: side-by-side on desktop, so
   the divider runs vertically; stacked on mobile, where it switches to
   a horizontal rule instead (a border-left would otherwise just read
   as stray indentation once there's nothing beside it to divide from). */
.schedule-calendar-panel {
  flex: 2 1 220px;
  max-width: 300px;
  min-width: 0;
  padding-left: 20px;
  border-left: 1px solid var(--border);
}

.mini-calendar {
  display: grid;
  grid-template-columns: 44px repeat(7, minmax(0, 1fr));
  gap: 3px;
  align-items: center;
}

.mini-cal-head {
  text-align: center;
  font-family: var(--mono);
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--muted);
  padding-bottom: 3px;
}

.mini-cal-label {
  font-family: var(--mono);
  font-size: 9px;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.mini-cal-day {
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 5px;
  font-family: var(--mono);
  font-size: 10px;
  color: var(--text);
}

/* Legend entries reuse the exact .mini-cal-day classes so they can never
   drift out of sync with the real cells the way a hand-maintained
   parallel .mini-cal-swatch set of rules did (twice). Only a fixed size
   is needed here, since outside the grid there's no column width to
   derive one from. */
.mini-cal-day--legend {
  width: 20px;
  flex: none;
}

.mini-cal-day.is-delivery {
  background: var(--accent-dim);
  font-weight: 600;
}

/* Third attempt at this one — two rounds of flat-color tuning both got
   reported as "still looks like a blank cell." A texture (diagonal
   hatch), not another shade, is a categorically different signal that
   doesn't depend on subtle color perception holding up across different
   screens — genuinely harder to confuse with a plain unfilled cell than
   any flat background could be. Kept dark/muted (not a bright pattern)
   so it still reads as "closed," not competing with the vivid
   "still orderable" fill. */
.mini-cal-day.is-delivery.is-past-deadline {
  background: repeating-linear-gradient(135deg, #232b40, #232b40 4px, #171b28 4px, #171b28 8px);
  color: var(--muted);
  font-weight: 500;
  text-decoration: line-through;
}

/* Corner dot, same mechanism as .is-deadline but green and opposite
   corner — the two can coexist on one cell (leadDays = 0) without
   overlapping. */
.mini-cal-day.is-next-delivery {
  position: relative;
}

.mini-cal-day.is-next-delivery::after {
  content: "";
  position: absolute;
  bottom: 2px;
  left: 2px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--ok);
}

/* A range, not a single point — shown as a bar under the cell rather
   than another background fill, so it doesn't compete with the delivery
   fill on the coverage period's last day (always the next delivery
   date, by definition: coverage runs from the day after a delivery
   through the day the following one arrives). Border, not an absolute
   overlay, so it composes with whatever else the cell already has. */
.mini-cal-day.is-coverage {
  border-bottom: 2px solid var(--ok);
}

.mini-cal-day.is-deadline {
  position: relative;
}

.mini-cal-day.is-deadline::after {
  content: "";
  position: absolute;
  top: 2px;
  right: 2px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: #f2b84c;
}

.deadline-banner {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 18px;
  padding: 12px 16px;
  background: #f2b84c14;
  border: 1px solid #f2b84c40;
  border-radius: 8px;
  font-size: 13px;
  color: var(--text);
}

.deadline-banner-icon {
  font-size: 16px;
  flex-shrink: 0;
}

.deadline-banner.is-urgent {
  background: #f2685c1a;
  border-color: #f2685c40;
}

.mini-cal-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: 10px;
  font-size: 12px;
  color: var(--muted);
}

.mini-cal-legend-item {
  display: flex;
  align-items: center;
  gap: 6px;
}

.lock-badge {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ok);
  background: #34d3991a;
  border: 1px solid #34d39933;
  border-radius: 6px;
  padding: 4px 8px;
  white-space: nowrap;
}

.th-subnote {
  display: block;
  font-size: 9px;
  font-weight: 400;
  text-transform: none;
  letter-spacing: normal;
  opacity: 0.8;
  margin-top: 2px;
}

/* Framed as a distinct panel, not just another row under the table — this
   is the culminating action of the whole page, and it was getting lost
   directly under a dense wide table with no visual break. */
.run-by-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 12px;
  margin-top: 28px;
  margin-bottom: 18px;
  padding: 18px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 8px;
}

#computeBtn {
  padding: 13px 28px;
  font-size: 15px;
}

.run-by-row > div {
  display: flex;
  flex-direction: column;
}

.run-by-row label {
  margin: 0 0 6px;
}

.run-by-row input {
  width: auto;
  min-width: 200px;
}

.section-note {
  font-size: 12px;
  color: var(--muted);
  margin: -6px 0 16px;
}

.msg.info {
  background: var(--panel-2);
  color: var(--muted);
  border: 1px solid var(--border);
}

/* The global input style (a dark, border-muted box) reads fine on its
   own but blends into a dense table full of plain read-only cells — the
   accent border and lighter fill make clear at a glance which cells are
   actually editable versus just displaying a computed number. */
.data-table input[type="number"] {
  width: 90px;
  padding: 6px 8px;
  font-size: 13px;
  background: var(--panel-2);
  border: 1.5px solid var(--accent);
}

.data-table input[type="number"]:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-dim);
}

/* .data-table td.cell-warn (not plain .cell-warn) is required here —
   the base `.data-table th, .data-table td { white-space: nowrap; }`
   rule (a class + a type selector) otherwise has higher specificity
   than a bare .cell-warn class alone and silently wins regardless of
   source order, so the white-space: normal below was never actually
   taking effect. Covers both warning strings ("Manual - Insufficient
   Data" and "Manual - Negative Ending Inventory") since they share this
   one class. Smaller font + tighter line-height keep the wrapped
   warning compact within Suggested Order's fixed 130px column (see
   .order-table's table-layout: fixed above) instead of stretching the
   row unnecessarily tall. */
.data-table td.cell-warn {
  color: #f2b84c;
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1.3;
  white-space: normal;
}

.cell-error {
  color: var(--err);
  font-family: var(--mono);
}

/* Not .tabs — that class is capped at max-width: 260px on report pages
   for the 2-item Daily/Monthly toggle elsewhere; 5 categories need to
   wrap on narrow screens instead of being squeezed into that width. */
.category-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 4px;
  margin-bottom: 18px;
}

.category-tabs button {
  padding: 8px 16px;
  border: none;
  background: transparent;
  color: var(--muted);
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 500;
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}

.category-tabs button.active {
  background: var(--accent);
  color: #0b0e14;
}

/* Three visual zones: Overview (its own dashboard) | the 5 category
   workflows, grouped | History (read-only reporting). Dividers and
   position do the work, not a new color — same lesson learned building
   the calendar legend. */
.category-tabs button.category-tabs-overview {
  padding: 10px 22px;
  font-size: 14px;
  font-weight: 600;
  margin-right: 24px;
  border-right: 1px solid var(--border);
  padding-right: 24px;
}

.category-tabs button.category-tabs-history {
  margin-left: auto;
  border-left: 1px solid var(--border);
  padding-left: 14px;
}

.overview-setup-banner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 12px 16px;
  background: #f2b84c14;
  border: 1px solid #f2b84c40;
  border-radius: 8px;
  font-size: 13px;
  margin-bottom: 18px;
}

.overview-day {
  display: flex;
  gap: 16px;
  padding: 12px 0;
  border-bottom: 1px solid var(--border);
}

.overview-day:last-child {
  border-bottom: none;
}

.overview-day-date {
  flex-shrink: 0;
  width: 84px;
  display: flex;
  flex-direction: column;
}

.overview-day-label {
  font-family: var(--mono);
  font-size: 11px;
  text-transform: uppercase;
  color: var(--muted);
  letter-spacing: 0.04em;
}

.overview-day-num {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
}

.overview-today-tag {
  display: inline-block;
  margin-top: 3px;
  font-family: var(--mono);
  font-size: 10px;
  color: var(--accent);
  border: 1px solid var(--accent);
  border-radius: 4px;
  padding: 1px 5px;
  width: fit-content;
}

.overview-day-entries {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
  flex: 1;
}

.overview-entry {
  font-size: 13px;
}

/* Signals "you missed this one" without hiding it — an entry that
   silently disappears once the clock crosses the cutoff would look like
   nothing was ever due, when a whole cycle may have just been skipped. */
.overview-entry.is-passed {
  color: var(--err);
}

.overview-entry.is-passed .overview-entry-link {
  color: var(--err);
}

/* Confirms the deadline was actually handled, not just that its date
   passed without incident — checked against real submitted orders, not
   inferred from the clock. */
.overview-entry.is-done {
  color: var(--ok);
}

.overview-entry-empty {
  font-size: 13px;
  color: var(--muted);
}

.overview-entry strong {
  font-weight: 600;
}

.overview-entry-icon {
  margin-right: 4px;
}

.overview-entry-link {
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  color: var(--accent);
  font-weight: 600;
  font-size: inherit;
  font-family: inherit;
  text-decoration: underline;
  cursor: pointer;
}

.overview-entry-link:hover {
  opacity: 0.85;
}

.overview-schedule-row {
  padding: 14px 0;
  border-bottom: 1px solid var(--border);
}

.overview-schedule-row:last-child {
  border-bottom: none;
}

.overview-schedule-summary {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 14px;
}

.overview-schedule-summary strong {
  min-width: 60px;
}

.overview-schedule-status {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--muted);
  flex: 1;
  min-width: 0;
}

.overview-schedule-editor {
  margin-top: 14px;
}

.help-icon-btn {
  align-self: center;
  flex-shrink: 0;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--panel-2);
  border: 1px solid var(--border);
  color: var(--text);
  font-family: var(--mono);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s;
}

.help-icon-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.modal-overlay {
  position: fixed;
  inset: 0;
  background: #00000099;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  z-index: 100;
}

/* .modal-overlay's own display:flex (an author-stylesheet rule) beats
   the browser's built-in [hidden]{display:none} UA rule at equal
   specificity regardless of source order, so setting .hidden = true on
   it would otherwise silently do nothing — same failure mode already
   hit twice elsewhere in this file (.stack-subrows/.is-open,
   #dailyTrendChart[hidden]). */
.modal-overlay[hidden] {
  display: none;
}

.modal-card {
  width: 100%;
  max-width: 520px;
  max-height: 85vh;
  overflow-y: auto;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 24px;
  box-shadow: 0 20px 60px -20px #00000080;
}

.modal-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 14px;
}

.modal-header h2 {
  font-size: 17px;
  font-weight: 600;
  margin: 0;
  letter-spacing: -0.01em;
}

.modal-title-accent {
  color: var(--accent);
}

.modal-close {
  flex-shrink: 0;
  background: none;
  border: none;
  color: var(--muted);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 0;
}

.modal-close:hover {
  color: var(--text);
}

.modal-steps {
  margin: 0 0 20px;
  padding-left: 20px;
  font-size: 14px;
  line-height: 1.6;
  color: var(--text);
}

.modal-steps li + li {
  margin-top: 8px;
}

.modal-subheading {
  font-size: 16px;
  font-weight: 700;
  margin: 0 0 8px;
  color: var(--accent);
}

.modal-note {
  font-size: 13px;
  line-height: 1.6;
  color: var(--muted);
  margin: 0;
}

.modal-note strong {
  color: var(--text);
}

.modal-divider {
  border: none;
  border-top: 1px solid var(--border);
  margin: 20px 0;
}

.modal-example-text {
  font-size: 13px;
  line-height: 1.7;
  color: var(--muted);
  margin: 0 0 20px;
}

.modal-example-text strong {
  color: var(--text);
}

.modal-example-calc {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 20px;
}

.modal-example-calc-item {
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 12px;
}

.modal-example-calc-title {
  margin: 0 0 6px;
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 500;
  color: var(--text);
}

.modal-example-calc-line {
  margin: 2px 0;
  font-family: var(--mono);
  font-size: 13px;
  color: var(--muted);
}

.modal-example-calc-line strong {
  color: var(--text);
}

.modal-example-calc-result {
  margin-top: 6px;
  color: var(--text);
}

.modal-example-calc-result + .modal-example-calc-line {
  margin-top: 10px;
}

/* Mobile: tighter frame, and 16px form fields — iOS Safari auto-zooms
   the page on focus for any input/select under 16px, which is exactly
   the base 14px this app uses everywhere, so this isn't cosmetic. */
@media (max-width: 640px) {
  body {
    padding: 12px;
  }

  input,
  select {
    font-size: 16px;
  }

  .report-embed {
    padding: 16px;
  }

  .export-btn,
  .chip {
    padding: 9px 14px;
  }

  .view-toggle-btn {
    padding: 8px 11px;
  }

  .stack-total {
    padding-top: 2px;
    padding-bottom: 2px;
  }

  .data-table th,
  .data-table td {
    padding: 8px 10px;
  }

  /* Fewer, wider cards read better than a cramped 3-per-row on a phone
     — matches the flex-wrap already in place, just a bigger target. */
  .stat-tile {
    flex-basis: 140px;
  }

  .stat-tile-value {
    font-size: 18px;
  }

  /* .app-grid wraps tiles into rows on desktop — fine there, but this
     list keeps growing (external tool tiles included) and a 3-per-row
     wrap still reads cramped on a phone, so stack to one column instead. */
  .app-grid {
    flex-direction: column;
  }

  /* .app-tile's flex-basis (180px) sizes tile WIDTH when wrapping in a
     row — but flex-basis always sizes the flex container's main axis,
     and flex-direction just flipped to column above, so without this
     override every tile would stretch to a 180px-tall box instead of
     sizing to its own content. */
  .app-tile {
    flex-basis: auto;
  }

  /* Order Details' frozen Item Code/Description/UOM columns (see the
     .order-table rules above) make sense on desktop, where there's
     enough width to spare for both the pinned columns and the scrolling
     ones. On a phone-width screen those three pinned columns alone can
     eat most of the viewport, leaving barely anything for the rest of
     the row to scroll into view beside them — so drop back to a plain
     table that scrolls as one piece, same as every other wide table on
     this page. This selector set deliberately matches the sticky rules
     above exactly (equal specificity) and relies on this media block
     coming later in the file to win. */
  .order-table th:nth-child(1),
  .order-table td:nth-child(1),
  .order-table th:nth-child(2),
  .order-table td:nth-child(2),
  .order-table th:nth-child(3),
  .order-table td:nth-child(3) {
    position: static;
    left: auto;
    z-index: auto;
    box-shadow: none;
  }

  /* Delivery Schedule's two columns (checkboxes/lead time/cutoff on the
     left, mini calendar on the right — see .schedule-layout above)
     stack on a phone, same as .schedule-layout's own flex-wrap would
     eventually do on its own, but forced explicitly here so it kicks in
     at the same breakpoint as everything else on this page rather than
     whatever width the flex-basis values happen to wrap at. The
     side-by-side divider becomes a horizontal rule instead — a
     border-left reads as stray indentation once there's nothing beside
     the calendar panel to divide from. */
  .schedule-layout {
    flex-direction: column;
  }

  .schedule-calendar-panel {
    max-width: none;
    padding-left: 0;
    padding-top: 20px;
    border-left: none;
    border-top: 1px solid var(--border);
  }

  /* Mon-Sun stays one row on a phone instead of wrapping 5+2 — flex:1
     with min-width:0 divides the available width evenly across all 7
     boxes (global box-sizing: border-box up top keeps each box's own
     padding/border inside that share rather than adding to it), with
     everything inside shrunk down to fit a ~40-45px box. */
  .schedule-days {
    flex-wrap: nowrap;
    gap: 4px;
  }

  .schedule-day {
    flex: 1 1 0;
    min-width: 0;
    padding: 6px 2px;
  }

  .schedule-day-label {
    font-size: 10.5px;
  }

  .schedule-day input[type="checkbox"] {
    width: 18px;
    height: 18px;
    margin-top: 0;
  }

  /* .category-tabs-history's margin-left: auto (see base rules above)
     is meant to pin History to the far right of a single row; once the
     row wraps on a phone, that same auto margin instead shoves it to
     the far right of whatever row it lands on, leaving a large dead gap
     next to Dry/BIB. Fixed, small margins here let it just flow after
     the category it wraps next to, like every other button. Same idea
     for Overview's oversized divider spacing (margin-right/padding-
     right: 24px on desktop) — tightened so it doesn't eat a big chunk
     of a narrow row. */
  .category-tabs button.category-tabs-overview {
    padding: 9px 14px;
    margin-right: 8px;
  }

  .category-tabs button.category-tabs-history {
    margin-left: 8px;
    padding-left: 12px;
  }
}
