/* Unified styles for Delivery Alert */

/* Design tokens live in public/css/tokens.css (loaded by partials/_head_common.php). */

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  background: var(--bg);
  color: var(--text);
  min-height: 100vh;
}

/* Brand typography (brand book): Montserrat for titles, Inter for text.
   IBM Plex Sans Arabic prepends itself for Arabic glyphs via unicode-range. */
h1, h2, h3, h4, h5, h6,
.aggregator-title,
.monitor-toolbar-title,
.dashboard-section-title,
.dashboard-group-title,
.settings-group-title {
  font-family: 'Montserrat', 'Inter', sans-serif;
}

html[dir="rtl"] body {
  font-family: 'IBM Plex Sans Arabic', 'Inter', -apple-system, sans-serif;
}

html[dir="rtl"] h1, html[dir="rtl"] h2, html[dir="rtl"] h3,
html[dir="rtl"] h4, html[dir="rtl"] h5, html[dir="rtl"] h6 {
  font-family: 'IBM Plex Sans Arabic', 'Montserrat', sans-serif;
}

/* Display numerals join the title face (KPI values across report pages) */
.monitor-kpi-value,
.page-rating-daily .kpi-value,
.page-schedule-discrepancies .stat-value,
.page-lost-revenue .stat-value {
  font-family: 'Montserrat', 'Inter', sans-serif;
}

/* Header — charcoal app bar in the new design language (portfolio-style),
   shared by every layouts/main page; standalone views draw the same bar. */
.app-header {
  background: var(--appbar);
  color: var(--on-accent);
  padding: 10px 22px;
  position: relative;
  max-height: 80px;
}

.header-content {
  max-width: 1230px;
  margin: 0 auto;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  min-height: 0;
}

.header-logo {
  color: var(--on-accent);
  text-decoration: none;
  font-family: 'Montserrat', Inter, -apple-system, sans-serif;
  font-size: 15px;
  font-weight: 800;
  letter-spacing: 0.2px;
  flex-shrink: 0;
  max-width: min(280px, 50vw);
  display: flex;
  align-items: center;
}

.header-logo:hover {
  color: color-mix(in srgb, var(--on-accent) 90%, transparent);
}

.header-logo-img {
  display: block;
  height: 60px;
  width: auto;
  max-width: 100%;
  object-fit: contain;
}

.header-logo-text {
  color: inherit;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* A whitelabel install's own logo (branding/logo.svg) in place of the product name. */
.header-logo-img {
  height: 28px;
  width: auto;
  vertical-align: middle;
}

/* Side-drawer trigger (the drawer itself lives in partials/nav_drawer.php,
   included at the end of body on every page). This copy exists so the header
   button paints instantly on layouts/main pages — keep it in sync with the
   .nvd-burger rules inside the partial (standalone pages rely on those). */
.nvd-burger {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  width: 36px;
  height: 36px;
  flex-shrink: 0;
  padding: 8px 7px;
  background: color-mix(in srgb, var(--on-accent) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--on-accent) 20%, transparent);
  border-radius: 8px;
  cursor: pointer;
  transition: background 0.12s;
}

.nvd-burger:hover {
  background: color-mix(in srgb, var(--on-accent) 22%, transparent);
}

.nvd-burger span {
  display: block;
  height: 2px;
  background: var(--on-accent);
  border-radius: 1px;
}

.header-right {
  display: flex;
  align-items: center;
  gap: 12px;
}

.header-quick-links {
  display: flex;
  align-items: center;
  gap: 4px;
}

.header-quick-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 8px;
  color: color-mix(in srgb, var(--on-accent) 85%, transparent);
  text-decoration: none;
  transition: background 0.15s ease, color 0.15s ease;
}

.header-quick-link:hover {
  background: color-mix(in srgb, var(--on-accent) 14%, transparent);
  color: var(--on-accent);
}

.header-quick-link svg {
  width: 20px;
  height: 20px;
}

@media (max-width: 640px) {
  .header-quick-links { display: none; }
}

.header-user-block {
  display: flex;
  align-items: center;
  gap: 12px;
}

.header-user-name {
  font-size: 14px;
  font-weight: 500;
  color: color-mix(in srgb, var(--on-accent) 95%, transparent);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 180px;
}

.header-logout,
.header-login {
  font-size: 13px;
  font-weight: 600;
  color: var(--on-accent);
  text-decoration: none;
  padding: 6px 12px;
  background: color-mix(in srgb, var(--on-accent) 20%, transparent);
  border-radius: 6px;
  white-space: nowrap;
}

.header-logout:hover,
.header-login:hover {
  background: color-mix(in srgb, var(--on-accent) 30%, transparent);
}

/* "← Dashboard" — right side of the bar, portfolio-style bordered button */
.header-dash {
  color: var(--on-accent);
  opacity: 0.9;
  text-decoration: none;
  font-size: 12.5px;
  font-weight: 600;
  padding: 5px 11px;
  border: 1px solid color-mix(in srgb, var(--on-accent) 30%, transparent);
  border-radius: 8px;
  white-space: nowrap;
  transition: background 0.12s, border-color 0.12s, opacity 0.12s;
}

.header-dash:hover {
  opacity: 1;
  background: color-mix(in srgb, var(--on-accent) 13%, transparent);
  border-color: color-mix(in srgb, var(--on-accent) 50%, transparent);
}

/* The slide-out menu itself is partials/nav_drawer.php (.nvd-panel) — shared
   with the standalone pages. The .menu-links rules below remain as the base
   look; the drawer's scoped .nvd-panel rules restyle them in the new design. */

.menu-links {
  list-style: none;
  padding: 24px 0 16px;
}

.menu-links li a {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 24px;
  color: var(--text);
  text-decoration: none;
  font-size: 15px;
  transition: background 0.2s;
}

.menu-icon {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  color: var(--brand);
  opacity: 0.9;
}

.menu-icon svg {
  width: 100%;
  height: 100%;
  display: block;
}

.menu-links li a:hover {
  background: #f1f9e4;
  color: var(--brand);
}

.menu-links li a:hover .menu-icon {
  color: var(--brand);
  opacity: 1;
}

.menu-footer {
  padding: 20px 24px;
  border-top: 1px solid var(--border);
}

.menu-country-form,
.menu-timezone-form {
  margin-bottom: 12px;
}

.form-label {
  display: block;
  font-size: 12px;
  color: var(--muted);
  margin-bottom: 4px;
}

.menu-select {
  padding: 6px 10px;
  font-size: 13px;
  border-radius: 6px;
  border: 1px solid var(--border);
  width: 100%;
}

.menu-timezone-form .form-group {
  display: inline-block;
  margin-inline-end: 8px;
  vertical-align: middle;
  min-width: 120px;
}

.menu-tz-btn {
  padding: 6px 12px;
  font-size: 13px;
  vertical-align: middle;
}

.menu-user-info {
  display: flex;
  flex-direction: column;
  margin-bottom: 12px;
  font-size: 14px;
}

.menu-user-info .user-name {
  font-weight: 600;
}

.menu-user-info .user-email {
  font-size: 13px;
  color: var(--muted);
}

.menu-logout {
  display: inline-block;
  padding: 10px 20px;
  background: color-mix(in srgb, var(--brand) 10%, transparent);
  color: var(--brand);
  border-radius: 8px;
  text-decoration: none;
  font-weight: 600;
  font-size: 14px;
  margin-top: 8px;
}

.menu-logout:hover {
  background: color-mix(in srgb, var(--brand) 20%, transparent);
}

/* Main content */
.app-main {
  max-width: 1400px;
  margin: 0 auto;
  padding: 24px;
}

/* Container */
.container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 20px;
}

/* Cards */
.info-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 280px));
  gap: 10px;
  margin-top: 10px;
}

.dashboard-group-title {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 24px 0 4px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--border);
}

.dashboard-group-title:first-of-type {
  margin-top: 18px;
}

.info-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 16px;
  box-shadow: var(--shadow-card);
  transition: transform 0.2s ease;
  cursor: pointer;
  text-decoration: none;
  display: flex;
  flex-direction: column;
  color: inherit;
  min-height: 120px;
}

.info-card:hover {
  transform: translateY(-5px);
}

.info-card-icon {
  width: 32px;
  height: 32px;
  margin-bottom: 8px;
  color: var(--brand);
}

.info-card-icon svg {
  width: 100%;
  height: 100%;
  display: block;
}

.info-card h3 {
  color: var(--text);
  font-size: 15px;
  margin-bottom: 4px;
}

.info-card p {
  color: var(--muted);
  font-size: 12px;
}

/* Dashboard sections */
.dashboard-section {
  margin-top: 16px;
}

.dashboard-section:first-of-type {
  margin-top: 12px;
}

.dashboard-section-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 10px;
  padding-inline-start: 2px;
}

/* Install / notifications banner at the end of the client dashboard
   (dashboard/_pwa_banner.php), shown by js/pwa.js only when something is left to do. */
.pwa-banner {
  position: relative;
  margin-top: 28px;
  padding: 18px 20px;
  padding-inline-end: 52px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
}
.pwa-banner[hidden],
.pwa-banner [hidden],
.pwa-banner-actions .btn[hidden] { display: none; }
.pwa-banner-title { margin: 0 0 6px; font-size: 16px; font-weight: 700; color: var(--text); }
.pwa-banner-text { margin: 0 0 14px; font-size: 14px; line-height: 1.5; color: var(--muted); }
.pwa-banner-actions { display: flex; flex-wrap: wrap; gap: 8px; }
/* .btn-sm alone is ~28-30px tall — under the 36px tap target the rest of this
   block already keeps (.menu-pwa-link, .pwa-banner-close); these three are the
   banner's main call to action on a phone. The [hidden] rule above carries a
   third, more specific selector so it still wins here regardless of source order. */
.pwa-banner-actions .btn { min-height: 36px; display: inline-flex; align-items: center; }
.pwa-banner-hint { margin: 12px 0 0; font-size: 13.5px; line-height: 1.5; color: var(--text); }
.pwa-banner-status { margin: 10px 0 0; font-size: 13px; color: var(--muted); }
.pwa-banner-status:empty { display: none; }
.pwa-banner-close {
  position: absolute;
  top: 8px;
  inset-inline-end: 8px;
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: 0;
  border-radius: var(--radius-sm);
  color: var(--muted);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
}
.pwa-banner-close:hover { background: var(--surface-2); color: var(--text); }

/* "Push on your devices" card on the settings page (user_settings/_push_card.php):
   this device's toggle (driven by js/pwa.js, starts hidden) and the device list.
   Buttons keep the 36px tap target; rows wrap on a phone. */
.pwa-card [hidden],
.pwa-card .btn[hidden] { display: none; }
.pwa-card .btn { min-height: 36px; display: inline-flex; align-items: center; gap: 6px; }
.pwa-card-this { margin-bottom: 14px; }
.pwa-card-push { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.pwa-card-state { font-weight: 600; color: var(--muted); }
.pwa-card-state--on { color: var(--success); }
.pwa-card-denied { width: 100%; color: var(--text); }
.pwa-card-hint { margin: 8px 0 0; font-size: 13px; line-height: 1.5; color: var(--muted); }
.pwa-card-status { margin: 8px 0 0; font-size: 13px; color: var(--muted); }
.pwa-card-status:empty { display: none; }
.pwa-card-empty { margin: 0; color: var(--muted); }
.pwa-card-devices { list-style: none; margin: 0; padding: 0; }
.pwa-card-device {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 12px;
  padding: 8px 0;
  border-top: 1px solid var(--border);
}
.pwa-card-device:first-child { border-top: 0; }
.pwa-card-device-name { font-weight: 600; color: var(--text); }
.pwa-card-device-dates { flex: 1 1 auto; font-size: 13px; color: var(--muted); }
.pwa-card-device-this { font-size: 13px; font-weight: 600; color: var(--success); }

/* ── Dashboard in brand-book colours ────────────────────────────────────
   First content page of the global redesign: colours only — layout stays.
   White canvas (Artem, 22.07 — the greenish #eef1e8 didn't land); hairline
   borders carry the card separation, charcoal text #403e3e, muted #8d8b88,
   usable lime-green #7db521 icons, lime-washed hover. Scoped to
   .page-dashboard so old pages migrate one by one. */
/* (dashboard tokens now live in :root) */

/* ── Monitor in brand-book colours ──────────────────────────────────────
   Colours only. Status semantics stay (green/amber/red pastels, glossy
   dots, red OFF emphasis); the chrome moves to the brand palette: warm
   neutrals, charcoal instead of teal, active pills = bright lime + near-
   black (the .seg pattern), interactive accents via --brand = usable
   lime-green for hovers/focus/checkboxes. */
/* (monitor tokens now live in :root) */

/* Calm white cards; the loud brand lime is the RESPONSE — a full-card lime
   flood on hover with near-black content (22 lime cards at rest turned the
   accent into wallpaper and killed scanning; as a reaction the colour keeps
   its "active" meaning from the drawer/portfolio). background/border/box-shadow
   already come from the global .info-card (tokens.css); only the extended
   transition and the hover states below are page-specific — the base h3/icon
   colours matched the global tokens exactly and were dropped as duplicates. */
.page-dashboard .info-card {
  transition: transform 0.2s ease, background 0.15s ease, border-color 0.15s ease, box-shadow 0.2s ease;
}

.page-dashboard .info-card:hover {
  background: var(--cta);
  border-color: var(--cta-hover);
  box-shadow: 0 6px 16px color-mix(in srgb, var(--text) 14%, transparent);
}

.page-dashboard .info-card:hover h3 {
  color: var(--cta-text);
}

.page-dashboard .info-card:hover p {
  color: color-mix(in srgb, var(--cta-text) 68%, transparent);
}

.page-dashboard .info-card:hover .info-card-icon {
  color: var(--cta-text);
}

/* Menu group dividers */
.menu-group-label {
  display: block;
  font-size: 11px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 16px 24px 4px;
  margin-top: 4px;
  border-top: 1px solid var(--border);
}

.menu-group-label:first-child {
  border-top: none;
  margin-top: 0;
  padding-top: 8px;
}

/* Buttons — neutral base; colour comes from a modifier. Page scopes
   (.page-menu .btn-secondary …) are more specific and keep winning. */
.btn {
  display: inline-block;
  padding: 10px 20px;
  background: var(--surface-3);
  color: var(--text);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.btn:hover { background: var(--border-strong); }
.btn:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.btn:disabled,
.btn[aria-disabled="true"] { opacity: 0.5; cursor: not-allowed; }

.btn-primary {
  background: var(--cta);
  color: var(--cta-text);
  border: none;
  padding: 12px 24px;
  border-radius: 10px;
  font-weight: 600;
  cursor: pointer;
}
.btn-primary:hover { background: var(--cta-hover); }

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

.btn-danger {
  background: var(--danger-bg);
  color: var(--danger);
  border: 1px solid var(--danger-border);
}
.btn-danger:hover { background: var(--danger); color: var(--text-inverse); }

/* Size modifier last so it beats the colour modifiers' padding. */
.btn-sm { padding: 6px 12px; font-size: 13px; border-radius: var(--radius-sm); }

/* Cards and flash messages */
.card {
  background: var(--surface);
  border-radius: var(--radius-lg);
  padding: 24px;
  box-shadow: var(--shadow-card);
  margin-bottom: 24px;
}
.card--form { max-width: 720px; }

/* Empty state — shared "nothing to show" placeholder (9 per-page copies fold into this
   in Task 2). */
.empty-state {
  text-align: center;
  padding: 60px 20px;
  color: var(--muted);
  background: var(--surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
}
/* The card look is for block placeholders. Pages outside wave C that already used the
   class name had no rule behind it before this component and keep their own look until
   their wave adopts it:
   - a table cell (admin audit/engagement: <td colspan class="empty-state">) stays a plain
     cell — the base `th, td` values; each table's own, more specific cell rules still win;
   - coverage booking draws a flat bordered box (its .cb-page rule sets no shadow);
   - admin restaurant rating shows a bare heading and line. */
td.empty-state { padding: 12px; text-align: start; color: inherit; background: none; border-radius: 0; box-shadow: none; }
.cb-page .empty-state { box-shadow: none; }
.page-admin-restaurant-rating .empty-state { padding: 0; text-align: start; color: inherit; background: none; border-radius: 0; box-shadow: none; }

/* Phones: the old page-level .card copies (user-settings, account/password, …) shrank
   padding at this breakpoint (30px -> 20px, then 16px at <=480px); the shared .card has
   no mobile step, so pages that relied on the page-scoped copy grew (user-settings +116px
   at 375px). .empty-state also grew vs. the old per-page placeholders (status-by-id +40px
   at 375px). Page scopes with their own .card/.empty-state padding are more specific and
   still win over this. */
@media (max-width: 768px) {
  .card { padding: 12px; }
  .empty-state { padding: 36px 16px; }
}

.message {
  padding: 12px 16px;
  border-radius: var(--radius-sm);
  margin-bottom: 20px;
  border: 1px solid transparent;
}
.message-success { background: var(--success-bg); color: var(--success-ink); border-color: var(--success-border); }
.message-error { background: var(--danger-bg); color: var(--danger); border-color: var(--danger-border); }
.message-warn { background: var(--warn-bg); color: var(--warn-ink); border-color: var(--warn); }

/* Badges */
.badge {
  display: inline-block;
  padding: 4px 10px;
  border-radius: 20px;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.3;
  white-space: nowrap;
  background: var(--surface-3);
  color: var(--muted);
}
.badge-gray { background: var(--surface-3); color: var(--muted); }
.badge-green { background: var(--success-bg); color: var(--success-ink); }
.badge-yellow { background: var(--warn-bg); color: var(--warn-ink); }
.badge-orange { background: var(--warn-bg); color: var(--warn-ink); }
.badge-red { background: var(--danger-bg); color: var(--danger); }

/* Forms */
.form-group {
  margin-bottom: 20px;
}

.form-group label {
  display: block;
  color: var(--text);
  font-size: 14px;
  font-weight: 500;
  margin-bottom: 8px;
}

.form-group input,
.form-group select {
  width: 100%;
  padding: 12px 16px;
  border: 2px solid var(--border-strong);
  border-radius: 10px;
  font-size: 15px;
  outline: none;
  background: var(--surface);
  color: var(--text);
}

.form-group input:focus,
.form-group select:focus {
  border-color: var(--brand);
}

.form-group input[type="checkbox"],
.form-group input[type="radio"] {
  width: auto;
  padding: 0;
}

/* Tables */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }

table { width: 100%; border-collapse: collapse; }
th, td { padding: 12px; text-align: start; border-bottom: 1px solid var(--border); }
th { background: var(--surface-2); font-weight: 600; }

.data-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.data-table th {
  padding: 12px 16px;
  border-bottom: 2px solid var(--border-soft);
  background: var(--surface-2);
  font-weight: 600;
  text-align: start;
}
.data-table td { padding: 12px 16px; border-bottom: 1px solid var(--border-soft); }
.data-table td.strong { font-weight: 600; }
.data-table td.actions { white-space: nowrap; }
.data-table td.empty { padding: 40px; text-align: center; color: var(--muted); }
.muted { color: var(--muted); }
.inline-form { display: inline-block; margin-inline-start: 6px; }

/* Page header */
.page-header {
  margin-bottom: 24px;
}

.page-header h2 {
  font-size: 24px;
  color: var(--text);
}

.page-header p {
  color: var(--muted);
  margin-top: 4px;
}

.page-header--actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 16px;
}

/* Filter toolbar (admin lists) */
.toolbar {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  align-items: flex-end;
  margin-bottom: 24px;
}
.toolbar .form-group { margin-bottom: 0; min-width: 140px; }
.toolbar .form-group--wide { min-width: 220px; }
@media (max-width: 480px) {
  .toolbar .form-group,
  .toolbar .form-group--wide { min-width: 0; flex: 1 1 100%; }
}

.form-actions { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 24px; }

/* Shared modal layer (spec §1). Opening stays with each page's JS: inline display,
   the hidden attribute, or an open/on/is-open class — the layer only paints. */
.kc-modal-backdrop {
  position: fixed; inset: 0; z-index: 1000;
  display: none; align-items: center; justify-content: center;
  background: var(--overlay);
  padding: 16px;
}
.kc-modal-backdrop.open,
.kc-modal-backdrop.on,
.kc-modal-backdrop.is-open { display: flex; }
.kc-modal-backdrop[hidden] { display: none; }
.kc-modal-panel {
  background: var(--surface);
  color: var(--text);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-modal);
  max-width: 100%;
}
.kc-modal-close {
  border: none; background: transparent; color: var(--muted);
  cursor: pointer; font-size: 22px; line-height: 1;
}
.kc-modal-close:hover { color: var(--text); }
/* Menu's backdrop is deliberately charcoal-tinted (brand flavour, .page-menu), not the
   plain overlay every other modal uses — kept as an additive modifier so it still shares
   the rest of the layer (position/z-index/open-state/hidden-state) instead of forking it. */
.kc-modal-backdrop--tinted { background: color-mix(in srgb, var(--appbar) 60%, transparent); }
@media (max-width: 768px) {
  .kc-modal-panel { max-width: calc(100vw - 32px); max-height: 90dvh; overflow: auto; }
}

/* Tom Select (CDN 2.4.3) recoloured on tokens. app.css is linked in <head> before
   the CDN's tom-select.min.css on all 5 admin pages that use it (the <link> sits
   in each view's pageStyles/content section, which layouts/main renders after
   app.css's own <link>), so on equal specificity the later-loaded stock rule
   would win the cascade. 4 of the 5 views also ship their own <style> block with
   .ts-wrapper/.ts-control rules, rendered later still (right after the CDN
   <link>, same section) — admin_restaurants/index.php + form.php,
   admin_parsing_queue/index.php, admin_restaurant_analytics/index.php
   (admin_coverage/form.php has none). Checked all four: they only set
   border/border-color (the same --border-strong token used below) plus pure
   layout — height, padding, border-radius, flex-wrap, min-width, font-size —
   never background or text colour, so they don't fight this block regardless of
   load order. Some overrides below target a selector the stock sheet already
   prefixes with .ts-wrapper (the multi-item chip), where a bare .ts-wrapper
   prefix would only tie — not win. Prefixing every rule with the always-present
   `body` ancestor adds one specificity point without having to match whichever
   state class the stock rule happened to use. */
body .ts-wrapper .ts-control {
  background: var(--surface);
  border-color: var(--border-strong);
  color: var(--text);
}
body .ts-wrapper .ts-control input { color: var(--text); }
body .ts-wrapper .ts-control input::placeholder { color: var(--muted); }
body .ts-wrapper .ts-control:hover,
body .ts-wrapper.focus .ts-control { border-color: var(--brand); }
body .ts-wrapper.disabled .ts-control { background: var(--surface-2); }
/* Stock state rules that outrank the (0,2,1) base above and repaint in literals:
   `.ts-wrapper.single.input-active .ts-control { background:#fff }` (0,4,0) turned a
   single select white in dark mode while typing (the multi-chip pair is below).
   Background/text only: a border-color here would out-rank the .focus border above.
   The rest of the 2.4.3 sheet was checked: .focus / .dropdown-active / .full /
   .disabled .ts-control set no colour or lose to these rules; the remaining literal
   colours belong to plugins no page loads (remove_button, dropdown_header, …). */
body .ts-wrapper.single.input-active .ts-control { background: var(--surface); color: var(--text); }
body .ts-wrapper .ts-dropdown {
  background: var(--surface);
  border-color: var(--border-strong);
  box-shadow: var(--shadow-dropdown);
  color: var(--text);
}
body .ts-wrapper .ts-dropdown .optgroup-header { background: var(--surface); color: var(--muted); }
body .ts-wrapper .ts-dropdown .active { background-color: var(--surface-2); color: var(--text); }
body .ts-wrapper .ts-dropdown .create { color: var(--muted); }
/* Tom Select puts both classes on a keyboard-highlighted "Add …" row at once;
   without this, .create (declared after .active, same specificity) would win
   and mute the text on a row meant to read as highlighted — stock itself keeps
   .ts-dropdown .active.create the same colour as plain .active for this reason. */
body .ts-wrapper .ts-dropdown .active.create { color: var(--text); }
body .ts-wrapper.multi .ts-control > div { background: var(--surface-3); color: var(--text); }
/* Selected chip = the CTA pair (14.2:1 in both themes); --brand under white was 2.47:1. */
body .ts-wrapper.multi .ts-control > div.active { background: var(--cta); color: var(--cta-text); }
/* Stock `.ts-wrapper.multi.disabled .ts-control > div(.active)` (0,4,1)/(0,5,1) paints
   white chips with #7d7d7d text — out-ranks both chip rules above. */
body .ts-wrapper.multi.disabled .ts-control > div,
body .ts-wrapper.multi.disabled .ts-control > div.active { background: var(--surface); color: var(--muted); }

/* Pagination — one look for $pager->links() everywhere */
.pager-wrap { margin-top: 24px; }
.pager-wrap .pagination {
  display: flex; flex-wrap: wrap; gap: 6px; list-style: none; margin: 0; padding: 0; align-items: center;
}
.pager-wrap .pagination li a {
  display: inline-flex; align-items: center; justify-content: center; min-width: 36px; height: 36px;
  padding: 0 12px; border-radius: var(--radius-sm); font-size: 14px; font-weight: 500; color: var(--brand);
  text-decoration: none; background: var(--surface-2); border: 1px solid var(--border); transition: all 0.15s ease;
}
.pager-wrap .pagination li a:hover,
.pager-wrap .pagination li.active a { background: var(--cta); color: var(--cta-text); border-color: var(--cta-hover); }
.pager-wrap .pagination li.active a { cursor: default; font-weight: 600; }
.pager-wrap .pagination li.disabled a { opacity: 0.5; cursor: not-allowed; pointer-events: none; }

/* Filter multi-select — shared component (partials/_multi_select.php + js/multi-select.js).
   One look for every filter dropdown; pages must not redefine these rules. */
.multi-select { position: relative; }
.multi-select-toggle {
  width: 100%; padding: 10px; border: 2px solid var(--border-strong); border-radius: 8px;
  background: var(--surface); text-align: start; cursor: pointer; font-size: 14px; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; transition: border-color 0.15s;
}
.multi-select-toggle:hover { border-color: var(--brand); }
.multi-select-toggle::after { content: "▾"; float: right; float: inline-end; color: var(--muted); }
.multi-select.open .multi-select-toggle { border-color: var(--brand); }
.multi-select.open .multi-select-toggle::after { content: "▴"; }
/* Fixed width, not the toggle's: in a two-column phone grid a toggle is half the screen
   and names wrapped into three lines. Never narrower than the toggle, never wider than
   the screen; js/multi-select.js adds .ms-open-end when the panel would cross the far
   screen edge, and it then opens from the toggle's other side. */
.multi-select-panel {
  position: absolute; inset-inline-start: 0; top: calc(100% + 6px);
  width: 280px; min-width: 100%; max-width: calc(100vw - 24px); box-sizing: border-box;
  background: var(--surface);
  border: 1px solid var(--border-strong); border-radius: 8px; box-shadow: var(--shadow-dropdown);
  max-height: 260px; overflow-y: auto; padding: 8px 10px; display: none; z-index: 50;
}
.multi-select.ms-open-end .multi-select-panel { inset-inline-start: auto; inset-inline-end: 0; }
.multi-select.open .multi-select-panel { display: block; }
/* Sticky so the search box stays reachable while the option list scrolls. */
.multi-select-search {
  position: sticky; top: -8px; background: var(--surface); padding: 4px 0 6px;
  margin: -4px 0 4px; border-bottom: 1px solid var(--border); z-index: 1;
}
.multi-select-search input {
  width: 100%; padding: 7px 9px; border: 1.5px solid var(--border-strong); border-radius: 6px;
  font-size: 13px; color: var(--text);
}
.multi-select-search input:focus { outline: none; border-color: var(--brand); }
.multi-select-option {
  display: flex; align-items: center; gap: 8px; padding: 6px 4px;
  font-size: 14px; color: var(--text); cursor: pointer; border-radius: 4px;
}
/* display:flex above would otherwise beat the UA rule for [hidden], leaving the options
   the search filtered out still on screen. */
/* Must beat the per-page `.page-X .multi-select-option { display: flex }` rules (same
   specificity, declared later) — otherwise the search box's hidden options stay visible. */
.multi-select-option[hidden] { display: none !important; }
.multi-select-option:hover { background: var(--surface-2); }
.multi-select-option input { width: auto; min-width: 16px; flex-shrink: 0; accent-color: var(--brand); }
.multi-select-option.select-all {
  font-weight: 600; color: var(--brand); border-bottom: 1px solid var(--border);
  margin-bottom: 6px; padding-bottom: 8px;
}
.multi-select-empty { font-size: 13px; color: var(--muted); padding: 6px 4px; margin: 0; }

/* Facet counters + selected-value chips (js/filter-facets.js).
   ⚠️ Kept in sync with partials/_multi_select_css.php (standalone pages). */
.multi-select-option .ms-count {
  margin-inline-start: auto; padding-inline-start: 10px; font-size: 11px;
  color: var(--muted); font-variant-numeric: tabular-nums; font-weight: 600;
}
.multi-select-option.ms-zero { color: color-mix(in srgb, var(--muted) 60%, var(--surface)); }
.multi-select-option.ms-zero .ms-count { color: color-mix(in srgb, var(--muted) 40%, var(--surface)); }
.flt-chips { display: flex; flex-wrap: wrap; gap: 6px; flex-basis: 100%; align-items: center; }
.filter-form .flt-chips { margin-top: 14px; }
.flt-chip {
  display: inline-flex; align-items: center; gap: 6px; background: var(--success-bg);
  border: 1px solid var(--success-border); color: var(--success-ink); border-radius: 999px;
  padding: 3px 6px 3px 11px; font-size: 12px; font-weight: 600; line-height: 1.4;
}
.flt-chip button {
  border: 0; background: color-mix(in srgb, var(--success-ink) 12%, transparent); color: var(--success-ink); width: 16px; height: 16px;
  border-radius: 50%; cursor: pointer; font-size: 12px; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center; padding: 0; flex-shrink: 0;
}
.flt-chip button:hover { background: color-mix(in srgb, var(--success-ink) 16%, transparent); }

/* Monitor's toolbar has no Apply button (filters auto-submit), so export sits at the end
   of the toggle row, sized like the chips next to it. */
.monitor-toolbar-form .btn-export {
  margin-inline-start: auto; display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 14px; border: 1.5px solid var(--text); border-radius: 999px;
  background: var(--surface); color: var(--text); font-size: 13px; font-weight: 600;
  line-height: 1; cursor: pointer; transition: background 0.15s, color 0.15s;
}
.monitor-toolbar-form .btn-export:hover { background: var(--text); color: var(--surface); }
.monitor-toolbar-form .btn-export svg { flex-shrink: 0; }

/* Report export button — shared component. Export acts on the whole report rather than on
   the filter form, so it sits apart at the end of the actions row (logical margin keeps it
   at the far edge in RTL too). */
.filter-actions .btn-export {
  margin-inline-start: auto; display: inline-flex; align-items: center; gap: 8px;
  padding: 11px 20px; border: 1.5px solid var(--text); border-radius: 8px;
  background: var(--surface); color: var(--text); font-size: 14px; font-weight: 600;
  line-height: 1; cursor: pointer; transition: background 0.15s, color 0.15s;
}
.filter-actions .btn-export:hover { background: var(--cta); color: var(--cta-text); }
.filter-actions .btn-export[aria-busy="true"] { opacity: 0.55; pointer-events: none; }
.filter-actions .btn-export svg { flex-shrink: 0; }
/* Wrapped onto its own line the auto margin would strand it — keep it beside the others. */
@media (max-width: 640px) {
  .filter-actions .btn-export,
  .monitor-toolbar-form .btn-export { margin-inline-start: 0; }
}

/* (legacy standalone login skin removed — Auth views carry their own styles) */


/* Monitor page - exact design from monitor.php */
.page-monitor .container {
  max-width: 1600px;
  padding: 30px 40px;
}

/* Toolbar */
.page-monitor .monitor-toolbar { background: var(--surface); border-radius: 12px; padding: 14px 16px; box-shadow: var(--shadow-card); margin-bottom: 0; position: sticky; top: 0; z-index: 30; border: 1px solid var(--border); }
.page-monitor .monitor-toolbar-form { margin: 0; }
.page-monitor .monitor-toolbar-header { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.page-monitor .monitor-toolbar-collapse { background: var(--surface-2); border: 1px solid var(--border); border-radius: 6px; padding: 5px 10px; cursor: pointer; display: inline-flex; align-items: center; gap: 6px; font-size: 11px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: 0.4px; transition: all .15s; }
.page-monitor .monitor-toolbar-collapse:hover { border-color: var(--brand); color: var(--brand); }
.page-monitor .monitor-toolbar-collapse .chevron { transition: transform .15s; }
.page-monitor .monitor-toolbar.collapsed .monitor-toolbar-collapse .chevron { transform: rotate(-90deg); }
.page-monitor .monitor-toolbar.collapsed { padding: 8px 14px; margin-bottom: 0; }
.page-monitor .monitor-toolbar.collapsed .monitor-toolbar-form { display: none; }
.page-monitor .monitor-toolbar.collapsed .monitor-toolbar-header { margin-bottom: 0; }
.page-monitor .monitor-toolbar-summary { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; font-size: 12px; }
.page-monitor .monitor-toolbar:not(.collapsed) .monitor-toolbar-summary { display: none; }
.page-monitor .monitor-toolbar-summary .summary-chip { background: color-mix(in srgb, var(--brand) 12%, var(--surface)); color: color-mix(in srgb, var(--brand) 55%, var(--cta-text)); border: 1px solid color-mix(in srgb, var(--brand) 30%, var(--surface)); padding: 2px 8px; border-radius: 10px; font-size: 11px; font-weight: 600; white-space: nowrap; }
.page-monitor .monitor-toolbar-summary .summary-chip.summary-default { background: var(--surface-2); color: var(--muted); border-color: var(--border); font-weight: 500; }
.page-monitor .monitor-toolbar-summary .summary-sep { color: var(--muted); font-size: 10px; }
.page-monitor .monitor-kpi-grid { position: sticky; top: var(--monitor-toolbar-h, 70px); z-index: 25; background: var(--bg); padding: 12px 4px 4px; margin: 0 -4px 12px; }
.page-monitor .toolbar-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.page-monitor .toolbar-row-filters { padding-bottom: 10px; margin-bottom: 10px; border-bottom: 1px solid var(--border-soft); }
.page-monitor .toolbar-toggles-label { font-size: 11px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: 0.5px; margin-inline-end: 2px; }
.page-monitor .toolbar-select { min-width: 140px; flex: 1; max-width: 200px; }
.page-monitor .toolbar-select-label { display: block; font-size: 10px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: 0.6px; margin-bottom: 4px; }
.page-monitor .toolbar-divider { width: 1px; height: 28px; background: var(--border); flex-shrink: 0; }
.page-monitor .toolbar-search { min-width: 160px; flex: 1; max-width: 220px; }
/* Keep all filters (Brand/Country/City/Area/Aggregator/Search) on a single row:
   never wrap, and let each control shrink equally to share the width. */
@media (min-width: 860px) {
    .page-monitor .toolbar-row-filters { flex-wrap: nowrap; }
    .page-monitor .toolbar-row-filters .toolbar-select,
    .page-monitor .toolbar-row-filters .toolbar-search { min-width: 0; max-width: none; flex: 1 1 0; }
}
.page-monitor .toolbar-row-filters .multi-select-toggle { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.page-monitor .toolbar-search-input-wrap { position: relative; }
.page-monitor .toolbar-search-icon { position: absolute; inset-inline-start: 10px; top: 50%; transform: translateY(-50%); color: var(--muted); pointer-events: none; }
.page-monitor .toolbar-search input { width: 100%; padding-block: 8px; padding-inline: 32px 10px; border: 1.5px solid var(--border-strong); border-radius: 8px; font-size: 13px; color: var(--text); background: var(--surface); transition: border-color 0.15s; }
.page-monitor .toolbar-search input:focus { outline: none; border-color: var(--brand); }
.page-monitor .toolbar-search input::placeholder { color: var(--muted); }
.page-monitor .toolbar-chip { display: inline-flex; align-items: center; gap: 6px; padding: 7px 12px; border: 1.5px solid var(--border); border-radius: 20px; cursor: pointer; font-size: 12px; font-weight: 600; color: var(--muted); white-space: nowrap; transition: all 0.15s; background: var(--surface); }
.page-monitor .toolbar-chip:hover { border-color: var(--brand); color: var(--brand); }
.page-monitor .toolbar-chip.active, .page-monitor .toolbar-chip:has(input:checked) { background: var(--cta); color: var(--cta-text); border-color: color-mix(in srgb, var(--brand) 40%, var(--cta) 60%); }
.page-monitor .toolbar-chip input { display: none; }

/* Denser toolbar on purpose (kept out of FILTER_SCOPES — see ViewStyleContractTest);
   only the rules that differ from the shared component survive here, on tokens. Rules
   identical to the global block (position/hover/open-state/option hover+input) were
   deleted — the unscoped component already covers them. The toggle sets only its
   border WIDTH: a full border shorthand here (0,2,0, later) would beat the global
   .multi-select-toggle:hover colour (also 0,2,0) and kill the hover feedback. */
.page-monitor .multi-select-toggle { width: 100%; background: var(--surface); border-width: 1.5px; border-radius: 8px; padding: 8px 10px; text-align: start; cursor: pointer; font-size: 13px; color: var(--text); transition: border-color 0.15s; }
.page-monitor .multi-select-toggle::after { content: "▾"; float: right; float: inline-end; color: var(--muted); }
/* Width and the .ms-open-end flip come from the shared component; the monitor's own
   script (monitor/index.php alignPanel) sets the flip class, it does not load
   js/multi-select.js. */
.page-monitor .multi-select-panel { top: calc(100% + 4px); border-width: 1.5px; padding: 8px; }
/* No color here — same value as the shared .multi-select-option default; redeclaring it
   would beat .multi-select-option.ms-zero at equal specificity (source order) and
   zero-count options would stop graying out (this was the live bug on /monitor). */
.page-monitor .multi-select-option { display: flex; align-items: center; gap: 8px; padding: 5px 4px; font-size: 13px; cursor: pointer; border-radius: 4px; }
.page-monitor .multi-select-option.select-all { font-weight: 600; color: var(--brand); border-bottom: 1px solid var(--border); margin-bottom: 4px; padding-bottom: 6px; }

/* KPI cards */
.page-monitor .monitor-kpi-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 12px; margin-bottom: 16px; }
.page-monitor .monitor-kpi { background: var(--surface); border-radius: 12px; padding: 16px 14px; box-shadow: var(--shadow-card); text-align: center; border: 1px solid var(--border); transition: box-shadow 0.15s, transform 0.15s; position: relative; }
.page-monitor .monitor-kpi-link { color: inherit; text-decoration: none; }
.page-monitor .monitor-kpi:hover { box-shadow: 0 4px 12px color-mix(in srgb, var(--text) 10%, transparent); transform: translateY(-1px); }
.page-monitor .monitor-kpi.clickable { cursor: pointer; }
.page-monitor .monitor-kpi-icon { display: none; }
.page-monitor .monitor-kpi-value { font-size: 28px; font-weight: 800; line-height: 1; letter-spacing: -0.5px; }
/* Colour modifiers for .monitor-kpi-value — also applied standalone (e.g. to the
   inline <b> in the coverage KPI sub-line), so each rule only sets `color`. */
.page-monitor .monitor-kpi-value--text { color: var(--text); }
.page-monitor .monitor-kpi-value--success { color: var(--success); }
.page-monitor .monitor-kpi-value--warn { color: var(--warn); }
.page-monitor .monitor-kpi-value--caution { color: var(--caution); }
.page-monitor .monitor-kpi-label { font-size: 11px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: 0.5px; margin-top: 6px; }
.page-monitor .monitor-kpi-sub { font-size: 11px; color: var(--muted); margin-top: 4px; }

/* Compact mode */
.page-monitor.compact-mode .cards-grid { grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 6px; }
.page-monitor.compact-mode .card { padding: 8px 10px; border-radius: 8px; }
.page-monitor.compact-mode .card h3 { font-size: 11px; line-height: 1.3; margin-bottom: 2px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; padding-inline-end: 14px; white-space: normal; }
.page-monitor.compact-mode .card p { display: none; }
.page-monitor.compact-mode .card-status-dot { width: 8px; height: 8px; top: 8px; inset-inline-end: 8px; }
.page-monitor.compact-mode .agg-list { margin-top: 4px; display: flex; flex-wrap: wrap; gap: 3px; }
.page-monitor.compact-mode .agg-item { padding: 0; margin: 0; border: none; }
.page-monitor.compact-mode .agg-row { gap: 0; }
.page-monitor.compact-mode .agg-badge { height: 18px; padding: 0 5px; font-size: 9px; border-radius: 4px; box-shadow: none; border: none; }
.page-monitor.compact-mode .agg-sub { display: none; }
.page-monitor.compact-mode .status-on,
.page-monitor.compact-mode .status-off,
.page-monitor.compact-mode .status-closed-sched { display: none; }
.page-monitor.compact-mode .card-footer { display: none; }

/* Table view */
.page-monitor .monitor-table-wrap { background: var(--surface); border-radius: 12px; box-shadow: var(--shadow-card); border: 1px solid var(--border); overflow-x: clip; overflow-y: visible; margin-bottom: 20px; }
.page-monitor .monitor-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.page-monitor .monitor-table th { padding: 10px 12px; text-align: start; background: var(--bg); color: var(--muted); font-weight: 700; font-size: 11px; text-transform: uppercase; letter-spacing: 0.3px; border-bottom: 2px solid var(--border); white-space: nowrap; position: sticky; top: var(--monitor-stack-h, 200px); z-index: 4; box-shadow: 0 2px 4px -2px color-mix(in srgb, var(--text) 8%, transparent); }
.page-monitor .monitor-table th.mt-sortable { cursor: pointer; user-select: none; }
.page-monitor .monitor-table th.mt-sortable:hover { color: var(--brand); }
.page-monitor .monitor-table th.mt-agg-col { text-align: center; }
.page-monitor .monitor-table td { padding: 8px 12px; border-bottom: 1px solid var(--border-soft); }
.page-monitor .monitor-table tr:hover td { background: var(--bg); }
.page-monitor .mt-name { font-weight: 600; color: var(--text); white-space: nowrap; }
.page-monitor .mt-area { color: var(--muted); white-space: nowrap; }
.page-monitor .mt-status { text-align: center; }
.page-monitor .mt-badge { display: inline-block; padding: 3px 8px; border-radius: 5px; font-size: 11px; font-weight: 700; }
.page-monitor .mt-on { background: var(--success-bg); color: var(--success-ink); }
.page-monitor .mt-off { background: var(--danger-bg); color: var(--danger); }
.page-monitor .mt-na { background: var(--border-soft); color: var(--muted); }
/* Closed by schedule — neutral slate, deliberately quiet so it scans past the eye
   when looking for real problems. */
.page-monitor .mt-closed-sched { background: var(--surface-2); color: var(--muted); font-weight: 600; }
/* Only-closed + table view: scream the OFF cells so they don't blend with greens.
   Scheduled-closed cells stay calm (no pulse, no row tint) — they're not outages. */
.page-monitor.mt-emphasize-off .mt-badge.mt-off { background: var(--danger); color: var(--text-inverse); box-shadow: 0 0 0 2px var(--danger-border), 0 2px 6px color-mix(in srgb, var(--danger) 40%, transparent); padding: 4px 10px; font-weight: 800; letter-spacing: 0.3px; animation: mt-off-pulse 2s ease-in-out infinite; }
.page-monitor.mt-emphasize-off .mt-badge.mt-closed-sched { background: var(--surface-2); color: var(--muted); box-shadow: none; padding: 3px 8px; font-weight: 600; letter-spacing: normal; animation: none; }
.page-monitor.mt-emphasize-off .mt-row[data-has-offline="1"] td { background: color-mix(in srgb, var(--danger) 4%, var(--surface)); }
.page-monitor.mt-emphasize-off .mt-row[data-has-offline="1"]:hover td { background: color-mix(in srgb, var(--danger) 8%, var(--surface)); }
@keyframes mt-off-pulse {
  0%, 100% { box-shadow: 0 0 0 2px var(--danger-border), 0 2px 6px color-mix(in srgb, var(--danger) 40%, transparent); }
  50%      { box-shadow: 0 0 0 3px color-mix(in srgb, var(--danger) 60%, var(--danger-border)), 0 0 12px color-mix(in srgb, var(--danger) 60%, transparent); }
}
/* Sound alerts widget */
/* Sit LEFT (inline-end offset 72px) of the global .support-fab (inline-end 20px, 40px wide) so the icons don't overlap. */
.page-monitor .monitor-alerts-fab { position: fixed; inset-inline-end: 72px; bottom: 20px; z-index: 100; }
/* .monitor-alerts-fab is its own stacking context (fixed + z-index) — a z-index set only on
   the open .monitor-alerts-panel inside it can never rise above a document-level sibling
   like .samira-launcher (z-index 1200): stacking contexts nest, they don't merge. Bumping
   the FAB itself while the panel is open is what actually lifts it above the launcher's
   "Ask Samira" label at widths >1100px where that label isn't visually clipped away. */
.page-monitor .monitor-alerts-fab:has(.monitor-alerts-panel:not([hidden])) { z-index: 1250; }
.page-monitor .monitor-alerts-btn { position: relative; width: 40px; height: 40px; border-radius: 50%; border: none; background: var(--surface); color: var(--muted); box-shadow: 0 2px 10px color-mix(in srgb, var(--text) 18%, transparent); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; transition: transform .12s, box-shadow .12s; }
.page-monitor .monitor-alerts-btn:hover { transform: translateY(-1px); box-shadow: 0 4px 14px color-mix(in srgb, var(--text) 22%, transparent); color: var(--brand); }
.page-monitor .monitor-alerts-dot { position: absolute; top: 6px; inset-inline-end: 6px; width: 9px; height: 9px; border-radius: 50%; background: var(--danger); border: 2px solid var(--surface); animation: monitor-alerts-dot 1.5s ease-in-out infinite; }
@keyframes monitor-alerts-dot { 0%,100%{transform:scale(1);opacity:1} 50%{transform:scale(1.25);opacity:0.85} }
.page-monitor .monitor-alerts-panel { position: absolute; inset-inline-end: 0; bottom: 50px; min-width: 230px; background: var(--surface); border-radius: 10px; box-shadow: 0 8px 26px color-mix(in srgb, var(--text) 18%, transparent); padding: 12px 14px; border: 1px solid var(--border); }
.page-monitor .monitor-alerts-panel-head { display: flex; align-items: center; justify-content: space-between; font-weight: 700; font-size: 12px; text-transform: uppercase; letter-spacing: 0.4px; color: var(--muted); margin-bottom: 10px; }
.page-monitor .monitor-alerts-close { background: none; border: none; font-size: 18px; line-height: 1; color: var(--muted); cursor: pointer; padding: 0 4px; }
.page-monitor .monitor-alerts-close:hover { color: var(--brand); }
.page-monitor .monitor-alerts-row { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text); padding: 4px 0; cursor: pointer; }
.page-monitor .monitor-alerts-row input[type="checkbox"] { margin: 0; }
.page-monitor .monitor-alerts-row-volume { gap: 6px; cursor: default; }
.page-monitor .monitor-alerts-volume-label { font-size: 12px; color: var(--muted); }
.page-monitor .monitor-alerts-volume-val { font-size: 11px; color: var(--muted); width: 20px; text-align: end; }
.page-monitor .monitor-alerts-row-volume input[type="range"] { flex: 1; }
.page-monitor .monitor-alerts-test { margin-top: 8px; width: 100%; padding: 6px 10px; border: 1px solid var(--border); background: var(--surface-2); border-radius: 6px; font-size: 12px; font-weight: 600; color: var(--muted); cursor: pointer; }
.page-monitor .monitor-alerts-test:hover { border-color: var(--brand); color: var(--brand); }
.page-monitor .mt-health, .page-monitor .mt-health-th { text-align: center; width: 40px; }
.page-monitor .mt-dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; }
.page-monitor .mt-dot-green { background: var(--success); }
.page-monitor .mt-dot-yellow { background: var(--warn); }
.page-monitor .mt-dot-red { background: var(--danger); }
.page-monitor .mt-dot-scheduled { background: var(--muted); }

/* Coverage panel */
.page-monitor .coverage-panel { background: var(--surface); border-radius: 12px; padding: 20px; box-shadow: var(--shadow-card); margin-bottom: 16px; border: 1px solid var(--border); border-inline-start: 4px solid var(--warn); }
.page-monitor .coverage-panel-head { margin-bottom: 14px; }
.page-monitor .coverage-panel-head h3 { font-size: 16px; font-weight: 700; color: var(--text); margin: 0 0 4px 0; }
.page-monitor .coverage-panel-sub { font-size: 13px; color: var(--muted); }
.page-monitor .coverage-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.page-monitor .coverage-table th { text-align: start; padding: 8px 10px; background: var(--bg); color: var(--muted); font-weight: 700; font-size: 11px; text-transform: uppercase; letter-spacing: 0.3px; border-bottom: 2px solid var(--border); }
.page-monitor .coverage-table td { padding: 10px 10px; border-bottom: 1px solid var(--border-soft); }
.page-monitor .ct-name { font-weight: 600; color: var(--text); }
.page-monitor .ct-area { color: var(--muted); }
.page-monitor .ct-count { font-weight: 700; color: var(--warn-ink); }
.page-monitor .ct-missing { display: flex; gap: 4px; flex-wrap: wrap; }
.page-monitor .ct-missing-badge { display: inline-block; padding: 3px 8px; border-radius: 5px; font-size: 11px; font-weight: 700; background: var(--warn-bg); color: var(--warn-ink); }

.page-monitor .aggregator-section { margin-bottom: 26px; }
.page-monitor .aggregator-title { font-size: 18px; font-weight: 700; color: var(--text); margin-bottom: 12px; }

.page-monitor .cards-grid {
  display: grid;
  gap: 10px;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  justify-content: start;
  align-items: stretch;
}

.page-monitor .card {
  position: relative;
  border-radius: 10px;
  padding: 12px;
  box-shadow: 0 1px 8px color-mix(in srgb, var(--text) 7%, transparent);
  overflow: hidden;
  width: 100%;
  display: flex;
  flex-direction: column;
  /* Global .card's margin-bottom: 24px would otherwise leak in here (this
     rule never declared it) and grow every row of .cards-grid by 24px. */
  margin-bottom: 0;
}
/* .card declares its own `display`, which would otherwise beat the UA [hidden]
   rule at equal specificity — restated so the search filter's card.hidden=true
   (see report-export.js sibling script in index.php) actually hides it. */
.page-monitor .card[hidden] { display: none; }

.page-monitor .card-green  { background: var(--success-bg); border: 1px solid var(--success-border); }
.page-monitor .card-red    { background: var(--danger-bg); border: 1px solid var(--danger-border); }
.page-monitor .card-yellow { background: var(--warn-bg); border: 1px solid color-mix(in srgb, var(--warn) 40%, var(--surface)); }
/* Scheduled-closed = the restaurant is correctly closed per its own hours.
   Quiet slate-gray so it scans past the eye when looking for problems.
   Text colour shifted to slate too so the card reads as "calm/inactive". */
.page-monitor .card-scheduled { background: var(--surface-2); border: 1px solid var(--border); }
.page-monitor .card-scheduled h3 { color: var(--muted); }
.page-monitor .card-scheduled p { color: var(--muted); }

.page-monitor .card-status-dot {
  position: absolute;
  top: 10px;
  inset-inline-end: 10px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  box-shadow: 0 1px 4px color-mix(in srgb, var(--cta-text) 18%, transparent), inset 0 1px 2px color-mix(in srgb, var(--on-accent) 55%, transparent);
  border: 1px solid color-mix(in srgb, var(--cta-text) 10%, transparent);
}

/* Glossy "sphere" bevel: a theme-invariant white highlight (--on-accent) fading
   into the status colour, darkened toward --cta-text (also theme-invariant) at
   the rim — keeps the 3D look identical in light and dark mode. */
.page-monitor .dot-green { background: radial-gradient(circle at 30% 30%, color-mix(in srgb, var(--on-accent) 90%, transparent), var(--success) 55%, color-mix(in srgb, var(--success) 75%, var(--cta-text)) 100%); }
.page-monitor .dot-yellow { background: radial-gradient(circle at 30% 30%, color-mix(in srgb, var(--on-accent) 90%, transparent), var(--warn) 55%, color-mix(in srgb, var(--warn) 75%, var(--cta-text)) 100%); }
.page-monitor .dot-red { background: radial-gradient(circle at 30% 30%, color-mix(in srgb, var(--on-accent) 90%, transparent), var(--danger) 55%, color-mix(in srgb, var(--danger) 75%, var(--cta-text)) 100%); }
.page-monitor .dot-scheduled { background: radial-gradient(circle at 30% 30%, color-mix(in srgb, var(--on-accent) 85%, transparent), var(--muted) 55%, color-mix(in srgb, var(--muted) 75%, var(--cta-text)) 100%); }

.page-monitor .card h3 { font-size: 15px; margin-bottom: 2px; color: var(--text); padding-inline-end: 20px; }
.page-monitor .card p { font-size: 12px; color: var(--muted); margin-bottom: 2px; }

.page-monitor .agg-list { margin-top: 6px; flex: 1; }
.page-monitor .agg-item {
  padding-top: 5px;
  margin-top: 5px;
  border-top: 1px solid color-mix(in srgb, var(--text) 6%, transparent);
}
.page-monitor .agg-item:first-child { border-top: none; padding-top: 0; margin-top: 0; }

.page-monitor .agg-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.page-monitor .agg-label { display: flex; align-items: center; gap: 8px; min-width: 0; }
.page-monitor .agg-badge {
  height: 22px;
  padding: 0 8px;
  border-radius: 6px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.2px;
  white-space: nowrap;
  line-height: 1;
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--on-accent) 35%, transparent), 0 1px 3px color-mix(in srgb, var(--text) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--text) 8%, transparent);
}
/* Colour modifiers. .agg-badge--default has no inline style to beat (the view
   only emits background/color when the DB actually has them), so it's a plain
   rule. --uniform/--off/--compact-on are JS-toggled *on top of* a badge that
   usually DOES carry the aggregator's own inline DB colour — per Global
   Constraints, that inline colour is dynamic-from-data and stays put, so these
   need !important to actually win (same precedent as .compact-mode .agg-brand-id
   below). Compact mode "forces its own colour scheme" (see index.php), so
   --compact-on is kept after --uniform/--off in source order to win when both
   toggles are on at once. */
.page-monitor .agg-badge--default { background: var(--surface-3); color: var(--text); }
.page-monitor .agg-badge--uniform { background: var(--surface-3) !important; color: var(--text) !important; }
.page-monitor .agg-badge--off { background: var(--danger-bg) !important; color: var(--danger) !important; }
.page-monitor .agg-badge--compact-on { background: var(--surface-2) !important; color: var(--muted) !important; }

.page-monitor .agg-text { font-size: 12px; font-weight: 600; color: var(--text); }
.page-monitor .agg-sub { font-size: 11px; color: var(--muted); margin-top: 1px; }
.page-monitor .agg-sub .offline-datetime { color: var(--danger); font-weight: 700; }
.page-monitor .status-on { color: var(--success-ink); font-weight: 700; font-size: 12px; }
.page-monitor .status-off { color: var(--danger); font-weight: 700; font-size: 12px; }
/* Closed by schedule — neutral slate so it's clearly NOT a screaming alert. */
.page-monitor .status-closed-sched { color: var(--muted); font-weight: 600; font-size: 12px; }
/* Soften the "Offline since" timestamp for scheduled-closed aggs (default is red). */
.page-monitor .agg-item.closed-by-sched .offline-datetime { color: var(--muted); font-weight: 600; }

.page-monitor .card-footer {
  margin-top: auto;
  padding-top: 6px;
  border-top: 1px dashed color-mix(in srgb, var(--text) 15%, transparent);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-size: 11px;
  color: var(--text);
}
.page-monitor .card-footer .label { font-weight: 700; color: var(--text); opacity: 0.95; }
.page-monitor .card-footer .value { color: var(--text); font-weight: 600; }

.page-monitor .empty-state-celebrate {
  background: linear-gradient(135deg, var(--success-bg) 0%, color-mix(in srgb, var(--success-bg) 60%, var(--surface)) 100%);
  border: 1px solid var(--success-border);
  color: color-mix(in srgb, var(--success) 70%, var(--text));
  padding: 48px 20px;
}
.page-monitor .empty-state-celebrate h3 { color: var(--success); font-weight: 700; margin: 4px 0 6px; font-size: 20px; }
.page-monitor .empty-state-celebrate p { color: color-mix(in srgb, var(--success) 60%, var(--text)); font-size: 14px; margin: 0; }
.page-monitor .empty-state-emoji { font-size: 44px; line-height: 1; margin-bottom: 4px; animation: ms-celebrate-bounce 1.2s ease-out 1; }
@keyframes ms-celebrate-bounce {
  0%   { transform: scale(0.4); opacity: 0; }
  50%  { transform: scale(1.15); opacity: 1; }
  70%  { transform: scale(0.95); }
  100% { transform: scale(1); }
}

.page-monitor .error-message {
  background: var(--danger-bg);
  color: var(--danger);
  border: 1px solid var(--danger-border);
  padding: 12px 16px;
  border-radius: 8px;
  margin-bottom: 20px;
  font-size: 14px;
}

@media (max-width: 1600px) {
  .page-monitor .cards-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (max-width: 1200px) {
  .page-monitor .cards-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 1024px) {
  .page-monitor .container { padding-inline-start: 18px; padding-inline-end: 18px; }
  .page-monitor .cards-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .page-monitor .card { max-width: 100%; }
  /* Compact mode's 6-col rule outspecifies the plain .cards-grid overrides —
     restate it per breakpoint or phones get 47px cards. */
  .page-monitor.compact-mode .cards-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 1200px) {
  .page-monitor .monitor-kpi-grid { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 768px) {
  .page-monitor .monitor-kpi-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 720px) {
  .page-monitor .cards-grid { grid-template-columns: 1fr; }
  .page-monitor.compact-mode .cards-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* Phones: the sticky toolbar+KPI stack can exceed the whole viewport when the
   toolbar is expanded, leaving no window onto the cards — unpin both. Table
   view swaps clip for a real horizontal scroller (sticky th can't follow a
   scroll container, so it unpins too). */
@media (max-width: 768px) {
  .page-monitor .monitor-toolbar,
  .page-monitor .monitor-kpi-grid { position: static; }
  .page-monitor .monitor-table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .page-monitor .monitor-table th { position: static; }
  .page-monitor .container { padding: 20px 14px; }
  .page-monitor .coverage-panel { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .page-monitor .coverage-table { min-width: 480px; }
}
/* Phones, expanded panel: 2-column filter grid instead of a shrinking flex row.
   Higher specificity than the plain .toolbar-select/.toolbar-search rules above,
   so it wins at every width down to 0 — no separate ≤480 "full width" rule needed. */
@media (max-width: 768px) {
  .page-monitor .toolbar-row-filters {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px 8px;
  }
  .page-monitor .toolbar-row-filters .toolbar-select,
  .page-monitor .toolbar-row-filters .toolbar-search {
    min-width: 0;
    max-width: none;
    flex: none;
  }
  .page-monitor .toolbar-select-label {
    font-size: 11px;
  }
  .page-monitor .toolbar-row-filters .multi-select-toggle,
  .page-monitor .toolbar-row-filters .toolbar-search input {
    height: 38px;
    box-sizing: border-box;
  }
  .page-monitor .toolbar-row-toggles .toolbar-chip {
    padding: 5px 10px;
    font-size: 12px;
  }
  .page-monitor .monitor-toolbar-form .btn-export {
    width: 100%;
    margin-inline-start: 0;
    justify-content: center;
  }
}

/* Status by ID page */
.status-export-dialog { width: min(720px, calc(100vw - 32px)); max-height: min(760px, calc(100vh - 40px)); margin: auto; padding: 0; border: 0; border-radius: 16px; background: var(--surface); box-shadow: var(--shadow-modal); color: var(--text); }
.status-export-dialog::backdrop { background: var(--overlay); backdrop-filter: blur(2px); }
.status-export-dialog form { display: flex; flex-direction: column; max-height: min(760px, calc(100vh - 40px)); }
.status-export-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; padding: 22px 24px 14px; border-bottom: 1px solid var(--border); }
.status-export-head h3 { margin: 0 0 5px; font-size: 20px; }
.status-export-head p { margin: 0; color: var(--muted); font-size: 13px; line-height: 1.45; }
.status-export-close { border: 0; background: transparent; color: var(--muted); cursor: pointer; font-size: 26px; line-height: 1; padding: 0 3px; }
.status-export-tools { display: flex; gap: 8px; padding: 14px 24px; background: var(--surface-2); border-bottom: 1px solid var(--border); }
.status-export-tools input { flex: 1; min-width: 160px; padding: 9px 11px; border: 1px solid var(--border-strong); border-radius: 8px; }
.status-export-tools button { border: 1px solid var(--border-strong); background: var(--surface); border-radius: 8px; padding: 8px 10px; color: var(--text); cursor: pointer; font-size: 12px; font-weight: 600; }
.status-export-list { overflow-y: auto; padding: 8px 16px; min-height: 180px; }
.status-export-option { display: flex; align-items: center; gap: 11px; padding: 9px 8px; border-radius: 9px; cursor: pointer; }
.status-export-option:hover { background: var(--surface-2); }
.status-export-option input { width: 17px; height: 17px; flex: 0 0 auto; accent-color: var(--brand); }
.status-export-option span { display: flex; flex-direction: column; min-width: 0; }
.status-export-option strong { font-size: 13px; color: var(--text); }
.status-export-option small { color: var(--muted); font-size: 11px; margin-top: 2px; }
.status-export-empty { display: none; padding: 28px 12px; text-align: center; color: var(--muted); font-size: 13px; }
.status-export-error { min-height: 18px; padding: 0 24px; color: var(--danger); font-size: 12px; font-weight: 600; }
.status-export-foot { display: flex; align-items: center; gap: 10px; padding: 14px 24px 20px; border-top: 1px solid var(--border); }
.status-export-foot > span { margin-inline-end: auto; color: var(--muted); font-size: 12px; }
/* --brand is a bright green in both themes, so its label wants the always-dark
   --cta-text (2.5:1 with --text-inverse in light) rather than the theme-flipping
   --text-inverse, which goes white there. */
.status-export-foot .btn-export { display: inline-flex; align-items: center; justify-content: center; padding: 11px 18px; border: 1.5px solid var(--brand); border-radius: 8px; background: var(--brand); color: var(--cta-text); font-size: 14px; font-weight: 600; line-height: 1; cursor: pointer; }
.status-export-foot .btn-export:hover { background: var(--brand-dark); border-color: var(--brand-dark); }
@media (max-width: 640px) {
  .status-export-tools { flex-wrap: wrap; }
  .status-export-tools input { flex-basis: 100%; }
  .status-export-foot { flex-wrap: wrap; }
  .status-export-foot > span { flex-basis: 100%; }
}
.page-status-by-id .container {
  max-width: 1200px;
  margin: 40px auto;
  padding: 0 20px;
}

.page-status-by-id .filter-form {
  background: var(--surface);
  border-radius: var(--radius);
  padding: 25px;
  box-shadow: var(--shadow-card);
  margin-bottom: 30px;
}

.page-status-by-id .filter-form h3 {
  margin-bottom: 20px;
  color: var(--text);
}

.page-status-by-id .filter-grid,
.page-status-by-id .filter-grid-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 20px;
  margin-bottom: 20px;
}

/* No page-level `.filter-group > label`/`> select`/`> input` here on purpose: this page
   always carries filter-form--compact (app.css ~5975), whose higher-specificity
   `.filter-group > label` / `.filter-group input`/`select` rules already own the
   field-caption and control look (floating-label design) — a page copy at lower
   specificity was dead weight, shadowed regardless of source order (same situation
   offline-summary already had removed, see its filter-grid comment below). */

.page-status-by-id .filter-actions {
  display: flex;
  gap: 10px;
  align-items: center;
}

.page-status-by-id .summary-card {
  background: var(--surface);
  border-radius: 12px;
  padding: 20px;
  box-shadow: var(--shadow-card);
  margin-bottom: 20px;
}

.page-status-by-id .summary-card p {
  color: var(--text);
  margin-bottom: 6px;
}

.page-status-by-id .summary-card span {
  color: var(--brand);
  font-weight: 600;
}

.page-status-by-id .report-table-container {
  background: var(--surface);
  border-radius: 12px;
  box-shadow: var(--shadow-card);
  overflow: hidden;
}

/* .report-table / .status-off / .transitions-cell (app.css elsewhere): dead — the view's
   table uses .hm-table (the heatmap grid), not .report-table; grepped across app/Views and
   public/js, neither class is referenced anywhere for this page. Leftovers of a pre-heatmap
   table layout — removed rather than tokenized. */

.page-status-by-id .error-message {
  background: var(--danger-bg);
  color: var(--danger);
  border: 1px solid var(--danger-border);
  padding: 12px 16px;
  border-radius: 8px;
  margin-bottom: 20px;
  font-size: 14px;
}

.page-status-by-id .warning-message {
  background: var(--warn-bg);
  color: var(--warn-ink);
  border: 1px solid var(--warn);
  padding: 12px 16px;
  border-radius: 8px;
  margin-bottom: 20px;
  font-size: 14px;
}

/* Offline summary page */
.page-offline-summary .container { max-width: 1600px; margin: 16px auto; padding: 0 20px; }
.page-offline-summary .filter-form {
  background: var(--surface); border-radius: var(--radius); padding: 12px 20px; box-shadow: var(--shadow-card); margin-bottom: 12px;
}
.page-offline-summary .filter-form h3 { color: var(--text); font-size: 14px; font-weight: 700; margin: 0; }
/* Collapsible filter header */
.page-offline-summary .ofs-filter-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.page-offline-summary .filter-form.collapsed .ofs-filter-header { margin-bottom: 0; }
.page-offline-summary .ofs-collapse { background: var(--surface-2); border: 1px solid var(--border); border-radius: 6px; padding: 5px 10px; cursor: pointer; display: inline-flex; align-items: center; gap: 6px; font-size: 11px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: 0.4px; transition: all .15s; }
.page-offline-summary .ofs-collapse:hover { border-color: var(--brand); color: var(--brand); }
.page-offline-summary .ofs-collapse .chevron { transition: transform .15s; }
.page-offline-summary .filter-form.collapsed .ofs-collapse .chevron { transform: rotate(-90deg); }
.page-offline-summary .filter-form.collapsed .ofs-filter-body { display: none; }

/* Pills summary block */
.page-offline-summary .ofs-pills-block { background: var(--surface); border-radius: 12px; box-shadow: var(--shadow-card); border: 1px solid var(--border); padding: 12px 16px; margin-bottom: 12px; }
.page-offline-summary .ofs-pills-head { display: flex; align-items: center; gap: 14px; margin-bottom: 14px; flex-wrap: wrap; }
.page-offline-summary .ofs-pills-title { margin: 0; font-size: 14px; font-weight: 700; color: var(--text); letter-spacing: -0.005em; }
.page-offline-summary .ofs-pills-summary { margin-inline-start: auto; font-size: 12px; color: var(--muted); font-weight: 500; }
.page-offline-summary .ofs-pills-summary b { color: var(--text); font-weight: 700; }

/* Value-driven bento grid — 6 cols, 56px rows, dense flow.
   Each card sets its own --col-span / --row-span based on share of total downtime. */
.page-offline-summary .ofs-pills { display: grid; grid-template-columns: repeat(6, 1fr); grid-auto-rows: 56px; gap: 6px; grid-auto-flow: row dense; font-variant-numeric: tabular-nums; }
/* Phones: 6 tracks of ~45px turn every pill into 3-char ellipsis soup — go to
   2 uniform columns (share-of-downtime spans read as size on desktop; on a
   phone the sort order carries that signal). */
@media (max-width: 480px) {
  .page-offline-summary .ofs-pills { grid-template-columns: repeat(2, 1fr); }
  .page-offline-summary .ofs-pill { grid-column: auto !important; }
}
.page-offline-summary .ofs-pills:not(.expanded) .ofs-pill.is-extra { display: none; }

/* Bento card — Dusty rose palette, centered layout, balanced typography */
.page-offline-summary .ofs-pill {
    container-type: size;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 9px;
    padding: 7px 10px;
    cursor: pointer;
    transition: transform .12s ease, box-shadow .12s ease, border-color .12s ease;
    position: relative;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    justify-content: center;     /* center vertically */
    align-items: center;          /* center horizontally */
    text-align: center;
    gap: 3px;
    grid-column: span var(--col-span, 1);
    grid-row: span var(--row-span, 1);
}
.page-offline-summary .ofs-pill:hover { transform: translateY(-1px); box-shadow: 0 6px 14px color-mix(in srgb, var(--text) 9%, transparent); border-color: var(--cat-1); }

/* TIERS — Dusty rose, as a --danger heat scale (color-mix(in srgb, var(--danger) N%, var(--surface)))
   so it tracks the theme instead of a fixed hex. Steps light→dark: tier-medium 8%, tier-large
   12%, tier-hero 18%→26% (its own two-stop gradient). tier-small is the one genuinely dynamic
   step — per-card relative intensity (--ofs-i, 0..1). Its formula (2%–7%) is capped strictly
   BELOW tier-medium's flat 8% at every --ofs-i in [0,1] (a flat distribution can put --ofs-i at
   1 for a small-tier row), so a small card can never tie or outweigh medium/large — the original
   hard-coded version was safe by construction (its palette ceiling stayed lighter than medium's),
   this preserves that invariant algebraically instead of by accident. */
.page-offline-summary .ofs-pill.tier-hero {
    background: linear-gradient(135deg, color-mix(in srgb, var(--danger) 18%, var(--surface)) 0%, color-mix(in srgb, var(--danger) 26%, var(--surface)) 100%);
    border-color: color-mix(in srgb, var(--danger) 40%, var(--surface));
    padding: 9px 12px;
}
.page-offline-summary .ofs-pill.tier-large { background: color-mix(in srgb, var(--danger) 12%, var(--surface)); border-color: color-mix(in srgb, var(--danger) 30%, var(--surface)); }
.page-offline-summary .ofs-pill.tier-medium { background: color-mix(in srgb, var(--danger) 8%, var(--surface)); border-color: color-mix(in srgb, var(--danger) 20%, var(--surface)); }
.page-offline-summary .ofs-pill.tier-small { background: linear-gradient(135deg, var(--surface) 0%, color-mix(in srgb, var(--danger) calc(var(--ofs-i, 0) * 5% + 2%), var(--surface)) 100%); }

/* Typography — adaptive, NAME size ≥ MINUTES so the place is the lede, value is the support */
.page-offline-summary .ofs-pill-name { font-weight: 700; line-height: 1.15; letter-spacing: -0.005em; font-size: clamp(13px, min(5cqi, 22cqb), 26px); color: var(--text); max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.page-offline-summary .ofs-pill-name small { display: block; font-weight: 500; line-height: 1.2; margin-top: 2px; font-size: clamp(10px, min(3cqi, 12cqb), 13px); color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.page-offline-summary .ofs-pill-stats { display: flex; align-items: baseline; justify-content: center; gap: 6px; max-width: 100%; white-space: nowrap; overflow: hidden; }
.page-offline-summary .ofs-pill-minutes { font-weight: 800; letter-spacing: -0.02em; line-height: 1; font-variant-numeric: tabular-nums; color: color-mix(in srgb, var(--danger) 70%, var(--text)); font-size: clamp(13px, min(4.5cqi, 22cqb), 28px); }
.page-offline-summary .ofs-pill-sep { color: var(--border-strong); font-weight: 400; line-height: 1; font-size: clamp(10px, min(3cqi, 12cqb), 14px); }
.page-offline-summary .ofs-pill-count { font-weight: 600; line-height: 1; color: var(--muted); font-size: clamp(9px, min(2.6cqi, 11cqb), 13px); }
.page-offline-summary .ofs-pill-rank { position: absolute; top: 4px; inset-inline-end: 6px; font-weight: 800; color: color-mix(in srgb, var(--text) 22%, transparent); letter-spacing: .5px; font-size: clamp(8px, min(2.2cqi, 9cqb), 11px); }

/* Hero — text colours (same --danger/70%-mixed-with-text tint as .ofs-pill-minutes above;
   the two original hex shades, #6b1f1f and #8b3a3a, consolidate to one formula). */
.page-offline-summary .ofs-pill.tier-hero .ofs-pill-name,
.page-offline-summary .ofs-pill.tier-hero .ofs-pill-minutes { color: color-mix(in srgb, var(--danger) 70%, var(--text)); }
.page-offline-summary .ofs-pill.tier-hero .ofs-pill-name small { color: color-mix(in srgb, var(--danger) 70%, var(--text)); }
.page-offline-summary .ofs-pill.tier-hero .ofs-pill-count { color: color-mix(in srgb, var(--danger) 70%, var(--text)); }
.page-offline-summary .ofs-pill.tier-hero .ofs-pill-rank { color: color-mix(in srgb, color-mix(in srgb, var(--danger) 70%, var(--text)) 35%, transparent); }

/* Small: drop only subtitle to fit 56px height; keep stats (minutes · count) */
.page-offline-summary .ofs-pill.tier-small .ofs-pill-name small { display: none; }
.page-offline-summary .ofs-pill.tier-small { gap: 2px; justify-content: center; padding: 6px 6px; }
.page-offline-summary .ofs-pill.tier-small .ofs-pill-name { font-size: clamp(11px, min(11cqi, 26cqb), 14px); }
.page-offline-summary .ofs-pill.tier-small .ofs-pill-stats { gap: 4px; }
.page-offline-summary .ofs-pill.tier-small .ofs-pill-minutes { font-size: clamp(10px, min(9cqi, 22cqb), 13px); }
.page-offline-summary .ofs-pill.tier-small .ofs-pill-count { font-size: clamp(9px, min(7cqi, 18cqb), 11px); }
.page-offline-summary .ofs-pill.tier-small .ofs-pill-sep { font-size: clamp(8px, min(6cqi, 16cqb), 11px); }

/* Expand button */
.page-offline-summary .ofs-expand-btn { margin-top: 8px; background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 6px 12px; cursor: pointer; font-size: 11.5px; font-weight: 600; color: var(--muted); width: 100%; transition: all .15s; display: flex; align-items: center; justify-content: center; gap: 6px; }
.page-offline-summary .ofs-expand-btn[hidden] { display: none; }
/* Plain --cat-1 as text is ~4.3:1 on this near-white hover tint — under AA. Blend
   toward --text for the label only; the border/tint stay pure --cat-1 (category identity). */
.page-offline-summary .ofs-expand-btn:hover { border-color: var(--cat-1); color: color-mix(in srgb, var(--cat-1) 55%, var(--text)); background: color-mix(in srgb, var(--cat-1) 4%, var(--surface)); }
.page-offline-summary .filter-grid,
.page-offline-summary .filter-grid-row {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 10px; margin-bottom: 10px;
}
.page-offline-summary .filter-grid-row:last-of-type { margin-bottom: 8px; }
/* No page-level `.filter-group label`/`input` here on purpose: this page always carries
   filter-form--compact (app.css ~5975), whose higher-specificity `.filter-group > label`
   / `.filter-group input` rules already own the field-caption and control look — a page
   copy (even a fixed '>' one) was dead weight, shadowed by the 3-class compact selector
   beating this scope's 2-class one regardless of source order (fix round 1). */

/* Duration dual-range slider (mirrors /offline-report) */
.page-offline-summary .duration-filter-group { min-width: 240px; }
.page-offline-summary .duration-range-text { font-weight: 700; color: var(--brand); margin-inline-start: 6px; }
.page-offline-summary .duration-slider { position: relative; height: 36px; margin: 6px 0 4px; }
.page-offline-summary .duration-slider-track { position: absolute; left: 8px; right: 8px; top: 50%; transform: translateY(-50%); height: 6px; background: var(--border); border-radius: 3px; }
.page-offline-summary .duration-slider-range { position: absolute; top: 50%; transform: translateY(-50%); height: 6px; background: var(--brand); border-radius: 3px; left: 8px; right: 8px; pointer-events: none; }
.page-offline-summary .duration-slider input[type="range"] { position: absolute; left: 0; right: 0; top: 0; bottom: 0; width: 100%; margin: 0; padding: 0; background: transparent; pointer-events: none; -webkit-appearance: none; appearance: none; }
.page-offline-summary .duration-slider input[type="range"]::-webkit-slider-runnable-track { background: transparent; height: 6px; }
.page-offline-summary .duration-slider input[type="range"]::-moz-range-track { background: transparent; height: 6px; }
.page-offline-summary .duration-slider input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; pointer-events: auto; width: 18px; height: 18px; border-radius: 50%; background: var(--surface); border: 2px solid var(--brand); box-shadow: 0 1px 4px color-mix(in srgb, var(--text) 18%, transparent); cursor: grab; margin-top: -6px; }
.page-offline-summary .duration-slider input[type="range"]::-webkit-slider-thumb:active { cursor: grabbing; transform: scale(1.08); }
.page-offline-summary .duration-slider input[type="range"]::-moz-range-thumb { pointer-events: auto; width: 18px; height: 18px; border-radius: 50%; background: var(--surface); border: 2px solid var(--brand); box-shadow: 0 1px 4px color-mix(in srgb, var(--text) 18%, transparent); cursor: grab; }
.page-offline-summary .duration-still-toggle { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--muted); cursor: pointer; margin-top: 6px; user-select: none; }
.page-offline-summary .duration-still-toggle input { width: auto !important; padding: 0 !important; border: none !important; }
/* Multi-select styling comes from the shared component block near the top of this file
   (page copy removed here — Task 2: it duplicated the global look and, being declared
   later, beat .multi-select-option.ms-zero, un-muting zero-count options). */
/* No page-level .filter-actions button sizing here either (fix round 1): same
   filter-form--compact rule (.filter-actions .btn-primary/-secondary { height:38px;
   padding:0 18px; }, app.css ~6043) outranks this 3-class page selector too. */
.page-offline-summary .filter-actions { display: flex; gap: 8px; margin-top: 4px; }
.page-offline-summary .empty-state.date-range-error { background: var(--danger-bg); border: 1px solid var(--danger-border); }
.page-offline-summary .summary-table-container {
  background: var(--surface); border-radius: 12px; padding: 14px 18px; box-shadow: var(--shadow-card);
  overflow-x: auto; margin-bottom: 16px;
}
/* border-collapse: separate so sticky th keeps its visible border */
.page-offline-summary .summary-table { width: 100%; border-collapse: separate; border-spacing: 0; min-width: 900px; }
.page-offline-summary .summary-table th,
.page-offline-summary .summary-table td { padding: 12px 15px; text-align: start; font-size: 14px; }
.page-offline-summary .summary-table td { border-bottom: 1px solid var(--border-soft); }
.page-offline-summary .summary-table th {
    background: var(--surface-2); font-weight: 600; color: var(--text);
    position: sticky; top: 0; z-index: 3;
    box-shadow: inset 0 -1px 0 var(--border), 0 1px 0 var(--border);
}
.page-offline-summary .totals-table { width: 100%; border-collapse: collapse; margin-top: 20px; }
.page-offline-summary .totals-table th,
.page-offline-summary .totals-table td { padding: 10px 12px; border-bottom: 1px solid var(--border-soft); text-align: start; font-size: 14px; }
.page-offline-summary .totals-table th { background: var(--surface-2); font-weight: 600; color: var(--text); }
.page-offline-summary details summary { cursor: pointer; list-style: none; font-weight: 600; color: var(--brand); }
.page-offline-summary details summary::before { content: "+"; display: inline-block; margin-inline-end: 6px; font-weight: 700; }
.page-offline-summary details[open] summary::before { content: "−"; }
.page-offline-summary .detail-list { margin-top: 10px; font-size: 13px; color: var(--text); }
.page-offline-summary .detail-item { margin-bottom: 6px; }
.page-offline-summary .detail-time { font-weight: 700; color: var(--text); }

/* Restaurant ranking page */
.page-restaurant-ranking .container { max-width: 1400px; margin: 40px auto; padding: 0 20px; }
.page-restaurant-ranking .filter-form {
  background: var(--surface); border-radius: var(--radius-lg); padding: 24px; box-shadow: var(--shadow-card); margin-bottom: 30px;
}
.page-restaurant-ranking .filter-form h3 { font-size: 18px; color: var(--text); margin-bottom: 16px; }
.page-restaurant-ranking .view-toggle {
  display: flex; gap: 0; background: var(--border-soft); border-radius: 8px; padding: 4px; margin-bottom: 24px; width: fit-content;
}
.page-restaurant-ranking .view-toggle a,
.page-restaurant-ranking .view-toggle button {
  padding: 10px 20px; border-radius: 6px; text-decoration: none; font-size: 14px; font-weight: 600; color: var(--muted);
  background: transparent; border: 0; cursor: pointer; font-family: inherit;
}
.page-restaurant-ranking .view-toggle a:hover,
.page-restaurant-ranking .view-toggle button:hover { color: var(--brand); background: color-mix(in srgb, var(--brand) 12%, var(--surface)); }
.page-restaurant-ranking .view-toggle a.active,
.page-restaurant-ranking .view-toggle button.active { background: var(--surface); color: var(--brand); box-shadow: 0 1px 3px color-mix(in srgb, var(--text) 8%, transparent); }
.page-restaurant-ranking .filter-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; align-items: end;
}
/* Direct child only — see status-by-id above for why (breaks multi-select-option rows
   without '>'). Multi-select styling itself comes from the shared component block near
   the top of this file; the page copy that used to live here duplicated it and, being
   declared later, beat .multi-select-option.ms-zero, un-muting zero-count options. */
.page-restaurant-ranking .filter-group > label { font-size: 13px; font-weight: 600; color: var(--muted); margin-bottom: 6px; display: block; }
.page-restaurant-ranking .filter-group > input:not([type="checkbox"]):not([type="radio"]) { width: 100%; padding: 10px; border: 2px solid var(--border-strong); border-radius: 8px; font-size: 14px; }
.page-restaurant-ranking .filter-actions { margin-top: 20px; display: flex; gap: 12px; flex-wrap: wrap; }
.page-restaurant-ranking .date-range-error { color: var(--danger); margin-bottom: 16px; }
.page-restaurant-ranking .empty-state h3 { margin-bottom: 8px; color: var(--text); }
.page-restaurant-ranking .section-title {
  font-size: 22px; color: var(--text); margin-bottom: 16px; padding-bottom: 8px; border-bottom: 2px solid var(--brand);
}
.page-restaurant-ranking .section-need { margin-bottom: 40px; }
.page-restaurant-ranking .section-need .section-title { border-bottom-color: var(--danger); }
.page-restaurant-ranking .section-reliable .section-title { border-bottom-color: var(--success); }
.page-restaurant-ranking .area-hint { margin-bottom: 16px; font-size: 14px; }
.page-restaurant-ranking .ranking-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 20px;
}
.page-restaurant-ranking .ranking-card {
  background: var(--surface); border-radius: 12px; padding: 20px; box-shadow: var(--shadow-card);
  display: flex; align-items: center; gap: 20px; cursor: pointer; text-decoration: none; color: inherit;
}
.page-restaurant-ranking .ranking-card:hover { box-shadow: 0 2px 4px color-mix(in srgb, var(--text) 6%, transparent), 0 8px 20px color-mix(in srgb, var(--text) 9%, transparent); }
.page-restaurant-ranking .ranking-card .card-info { flex: 1; min-width: 0; }
.page-restaurant-ranking .ranking-card .card-info .brand { font-weight: 600; color: var(--text); font-size: 17px; }
.page-restaurant-ranking .ranking-card .card-info .meta { font-size: 13px; color: var(--muted); margin-top: 6px; }
.page-restaurant-ranking .ranking-card .card-info .area-name { font-weight: 700; color: var(--brand); }
.page-restaurant-ranking .circle-wrap { flex-shrink: 0; }
.page-restaurant-ranking .circle-container {
  width: 64px; height: 64px; border-radius: 50%; position: relative; display: flex; align-items: center; justify-content: center;
}
.page-restaurant-ranking .circle-container .circle-bg { position: absolute; inset: 0; border-radius: 50%; }
.page-restaurant-ranking .circle-container .circle-inner {
  position: relative; z-index: 1; width: 52px; height: 52px; border-radius: 50%; background: var(--surface);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0; line-height: 1.15; padding: 2px;
}
.page-restaurant-ranking .circle-pct-on { font-size: 14px; font-weight: 700; color: var(--text); }
.page-restaurant-ranking .circle-pct-off { font-size: 10px; font-weight: 600; color: var(--danger); opacity: 0.9; }
/* Lost Revenue page */
.page-lost-revenue .container { max-width: 1600px; margin: 40px auto; padding: 0 20px; }
.page-lost-revenue .view-toggle { display: flex; gap: 8px; margin-top: 14px; }
.page-lost-revenue .view-toggle a {
  text-decoration: none; padding: 6px 12px; border-radius: 999px; font-size: 13px; font-weight: 600;
  border: 1px solid var(--border); color: var(--brand); background: var(--surface-2);
}
.page-lost-revenue .view-toggle a.active { background: var(--cta); color: var(--cta-text); border-color: var(--cta-hover); }
.page-lost-revenue .filter-form { background: var(--surface); border-radius: var(--radius-lg); padding: 30px; box-shadow: var(--shadow-card); margin-bottom: 30px; }
.page-lost-revenue .filter-form h3 { color: var(--text); font-size: 20px; margin-bottom: 20px; }
.page-lost-revenue .filter-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 15px; margin-bottom: 15px; }
/* Direct child only — see status-by-id above. Multi-select styling comes from the shared
   component block near the top of this file; the page copy that used to live here
   duplicated it and, being declared later, beat .multi-select-option.ms-zero. */
.page-lost-revenue .filter-group > label { font-size: 13px; font-weight: 600; color: var(--muted); margin-bottom: 6px; }
.page-lost-revenue .filter-group > input:not([type="checkbox"]):not([type="radio"]), .page-lost-revenue .filter-group > select { padding: 10px; border: 2px solid var(--border-strong); border-radius: 8px; font-size: 14px; width: 100%; }
.page-lost-revenue .empty-state.date-range-error { background: var(--danger-bg); border: 1px solid var(--danger-border); color: var(--danger); }
.page-lost-revenue .empty-state.date-range-error h3 { color: var(--danger); }
.page-lost-revenue .filter-group .required { color: var(--danger); }
.page-lost-revenue .brand-section { margin-bottom: 28px; }
.page-lost-revenue .brand-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; padding: 0 4px; flex-wrap: wrap; gap: 8px; }
@media (max-width: 480px) {
  .page-lost-revenue .container { margin: 16px auto; padding: 0 12px; }
  .page-lost-revenue .filter-form { padding: 16px; }
}
.page-lost-revenue .brand-title { font-size: 20px; font-weight: 700; color: var(--text); }
.page-lost-revenue .brand-meta { font-size: 13px; color: var(--muted); }
/* --brand-dark alone is 3.0:1 on this lime tint; half-way to --text keeps the hue at 4.9:1. */
.page-lost-revenue .brand-metric { font-size: 13px; color: color-mix(in srgb, var(--brand-dark) 55%, var(--text)); font-weight: 600; background: color-mix(in srgb, var(--brand) 18%, var(--surface)); padding: 6px 10px; border-radius: 999px; }
.page-lost-revenue .brand-summary { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 16px; }
.page-lost-revenue .brand-summary-item { background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 8px 10px; min-width: 180px; }
.page-lost-revenue .brand-summary-title { font-size: 11px; font-weight: 700; color: var(--muted); margin-bottom: 6px; }
.page-lost-revenue .brand-summary-row { display: flex; flex-wrap: wrap; gap: 6px; font-size: 12px; color: var(--muted); }
.page-lost-revenue .brand-summary-row span { background: var(--surface-2); border-radius: 999px; padding: 3px 8px; }
.page-lost-revenue .cards-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; }
.page-lost-revenue .card { background: var(--surface); border-radius: 16px; padding: 18px; box-shadow: 0 2px 4px color-mix(in srgb, var(--text) 6%, transparent), 0 8px 20px color-mix(in srgb, var(--text) 8%, transparent); border: 1px solid var(--border); display: flex; flex-direction: column; gap: 12px; margin-bottom: 0; }
.page-lost-revenue .card-top { display: flex; justify-content: space-between; gap: 12px; align-items: flex-start; }
.page-lost-revenue .card-title { font-size: 18px; font-weight: 700; color: var(--text); }
.page-lost-revenue .card-sub { font-size: 13px; color: var(--muted); margin-top: 4px; }
.page-lost-revenue .card-badge { background: var(--surface-2); color: var(--brand); font-weight: 700; font-size: 12px; padding: 6px 10px; border-radius: 999px; white-space: nowrap; }
.page-lost-revenue .stat-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.page-lost-revenue .stat-item { background: var(--surface-2); border-radius: 10px; padding: 10px; }
.page-lost-revenue .stat-label { font-size: 12px; color: var(--muted); margin-bottom: 4px; }
.page-lost-revenue .stat-value { font-size: 18px; font-weight: 700; color: var(--text); }
.page-lost-revenue .stat-sub { font-size: 12px; color: var(--muted); }
.page-lost-revenue .loss-row { display: flex; justify-content: space-between; align-items: center; background: var(--surface-2); border-radius: 10px; padding: 10px 12px; font-size: 14px; color: var(--text); }
.page-lost-revenue .loss-value { font-weight: 700; color: var(--brand); }
.page-lost-revenue .detail-list { margin-top: 10px; display: flex; flex-direction: column; gap: 6px; }
.page-lost-revenue .detail-item { font-size: 13px; color: var(--muted); }
.page-lost-revenue .detail-time { font-weight: 700; color: var(--text); }
.page-lost-revenue .detail-agg { margin-top: 8px; font-weight: 600; color: var(--brand); }
/* Colour dropped on purpose — the global .muted (var(--muted)) already applies here at
   lower specificity; this page only needed a smaller font-size, not its own colour. */
.page-lost-revenue .muted { font-size: 13px; }

/* Aggregator comparison page */
.page-aggregator-comparison .container { max-width: 1200px; margin: 0 auto; padding: 24px; }
.page-aggregator-comparison .filter-form { background: var(--surface); border-radius: var(--radius); padding: 20px; margin-bottom: 24px; box-shadow: var(--shadow-card); }
.page-aggregator-comparison .filter-form h3 { font-size: 16px; margin-bottom: 16px; }
.page-aggregator-comparison .filter-grid,
.page-aggregator-comparison .filter-grid-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; margin-bottom: 16px; }
/* Direct child only — see status-by-id above. Multi-select styling comes from the shared
   component block near the top of this file; the page copy that used to live here
   duplicated it and, being declared later, beat .multi-select-option.ms-zero. */
.page-aggregator-comparison .filter-group > label { display: block; font-size: 13px; font-weight: 600; color: var(--muted); margin-bottom: 6px; }
.page-aggregator-comparison .filter-group > input:not([type="checkbox"]):not([type="radio"]) { width: 100%; padding: 10px; border: 2px solid var(--border-strong); border-radius: 8px; font-size: 14px; }
.page-aggregator-comparison .filter-actions { display: flex; gap: 10px; margin-top: 8px; }
.page-aggregator-comparison .date-range-error { background: var(--danger-bg); border: 1px solid var(--danger-border); border-radius: 12px; padding: 24px; text-align: center; margin-bottom: 24px; }
.page-aggregator-comparison .date-range-error h3 { color: var(--danger); margin-bottom: 8px; }
.page-aggregator-comparison .agg-table-container { background: var(--surface); border-radius: 12px; padding: 24px; box-shadow: var(--shadow-card); overflow-x: auto; }
.page-aggregator-comparison .agg-table { width: 100%; border-collapse: collapse; min-width: 400px; }
.page-aggregator-comparison .agg-table th,
.page-aggregator-comparison .agg-table td { padding: 12px 16px; border-bottom: 1px solid var(--border-soft); text-align: start; font-size: 14px; }
.page-aggregator-comparison .agg-table th { background: var(--surface-2); font-weight: 600; color: var(--text); }
.page-aggregator-comparison .agg-table tr:hover { background: var(--surface-2); }
.page-aggregator-comparison .agg-name { font-weight: 600; color: var(--brand); }
.page-aggregator-comparison .agg-link { font-size: 13px; color: var(--brand); text-decoration: none; }
.page-aggregator-comparison .agg-link:hover { text-decoration: underline; }

/* Downtime patterns page */
.page-downtime-patterns .container { max-width: 1600px; margin: 0 auto; padding: 24px; }
.page-downtime-patterns .filter-form { background: var(--surface); border-radius: var(--radius-lg); padding: 24px; box-shadow: var(--shadow-card); margin-bottom: 24px; }
.page-downtime-patterns .filter-form h3 { font-size: 18px; margin-bottom: 16px; color: var(--text); }
.page-downtime-patterns .filter-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; margin-bottom: 16px; }
/* Direct child only: this styles the field's caption, not the option rows inside the
   multi-select panel (which are labels too, and own their layout). */
.page-downtime-patterns .filter-group > label { display: block; font-size: 13px; font-weight: 600; color: var(--muted); margin-bottom: 6px; }
/* Direct child only: the multi-select's own inputs are styled by the shared component. */
.page-downtime-patterns .filter-group > input:not([type="checkbox"]):not([type="radio"]) { width: 100%; padding: 10px; border: 2px solid var(--border-strong); border-radius: 8px; font-size: 14px; }
/* Multi-select styling comes from the shared component block near the top of this file. */
.page-downtime-patterns .filter-actions { margin-top: 16px; display: flex; gap: 12px; flex-wrap: wrap; align-items: center; }
.page-downtime-patterns .date-range-error { color: var(--danger); margin-bottom: 16px; }
.page-downtime-patterns .page-header-caveat { color: var(--muted); font-size: 13px; }
.page-downtime-patterns .view-toggle-wrap { display: flex; align-items: center; gap: 12px; margin-bottom: 20px; flex-wrap: wrap; }
.page-downtime-patterns .view-toggle-label { font-size: 14px; font-weight: 600; color: var(--muted); }
.page-downtime-patterns .view-toggle { display: inline-flex; gap: 0; padding: 0; background: var(--surface); border: 2px solid var(--border); border-radius: 10px; overflow: hidden; }
.page-downtime-patterns .view-toggle button { background: var(--surface); border: none; padding: 10px 20px; font-size: 14px; font-weight: 600; color: var(--muted); cursor: pointer; transition: background 0.15s, color 0.15s; border-inline-end: 2px solid var(--border); }
.page-downtime-patterns .view-toggle button:last-child { border-inline-end: none; }
.page-downtime-patterns .view-toggle button:hover:not(.active) { background: var(--surface-2); color: var(--text); }
.page-downtime-patterns .view-toggle button.active { background: var(--cta); color: var(--cta-text); box-shadow: inset 0 1px 3px color-mix(in srgb, var(--text) 15%, transparent); }
.page-downtime-patterns .trivial-toggle { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--muted); cursor: pointer; user-select: none; padding-inline-start: 6px; }
.page-downtime-patterns .trivial-toggle input { cursor: pointer; }
.page-downtime-patterns .grace-note { display: inline-flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--muted); background: var(--surface-2); border: 1px solid var(--border); border-radius: 8px; padding: 8px 14px; margin: 0 0 18px; }
.page-downtime-patterns .grace-note svg { color: var(--brand); flex-shrink: 0; }
.page-downtime-patterns .grace-note strong { color: var(--text); font-weight: 600; }
.page-downtime-patterns[data-mode="pct"] .legend-min { display: none; }
.page-downtime-patterns[data-mode="avg"] .legend-pct { display: none; }
.page-downtime-patterns[data-mode="pct"] .problem-list-min { display: none; }
.page-downtime-patterns[data-mode="avg"] .problem-list-pct { display: none; }
.page-downtime-patterns .store-card { background: var(--surface); border-radius: 15px; padding: 24px; box-shadow: var(--shadow-card); margin-bottom: 24px; }
.page-downtime-patterns.dp-hide-clean .store-card[data-clean="1"] { display: none; }
.page-downtime-patterns .store-card h3 { font-size: 18px; color: var(--text); margin-bottom: 6px; }
.page-downtime-patterns .store-card .meta { font-size: 13px; color: var(--muted); margin-bottom: 16px; }
.page-downtime-patterns .heatmap-wrap { overflow-x: auto; margin-bottom: 16px; }
.page-downtime-patterns .heatmap-table { border-collapse: collapse; font-size: 12px; width: max-content; table-layout: fixed; }
.page-downtime-patterns .heatmap-table th { padding: 6px 5px; text-align: center; font-weight: 600; color: var(--muted); border: 1px solid var(--border); background: var(--surface-2); font-size: 11px; }
.page-downtime-patterns .heatmap-table td { padding: 0; border: 1px solid var(--border); width: 28px; height: 26px; min-width: 28px; min-height: 26px; cursor: default; border-radius: 2px; text-align: center; font-size: 10px; line-height: 24px; color: var(--text); font-weight: 600; }
.page-downtime-patterns .heatmap-table td.dp-cell { cursor: pointer; transition: outline 0.1s; }
.page-downtime-patterns .heatmap-table td.dp-cell:hover { outline: 2px solid var(--brand); outline-offset: -1px; position: relative; z-index: 1; }
.page-downtime-patterns .heatmap-table td.cell-closed { background: repeating-linear-gradient(-45deg, var(--border), var(--border) 2px, var(--surface-2) 2px, var(--surface-2) 5px) !important; }
/* Heat scale (4 steps, matches the legend order): JS toggles these classes instead of
   painting td.style.background directly — see downtime_patterns/index.php paint(). */
.page-downtime-patterns .heat-0 { background: color-mix(in srgb, var(--success) 15%, var(--surface)); }
.page-downtime-patterns .heat-1 { background: color-mix(in srgb, var(--warn) 25%, var(--surface)); }
.page-downtime-patterns .heat-2 { background: color-mix(in srgb, var(--caution) 35%, var(--surface)); }
.page-downtime-patterns .heat-3 { background: color-mix(in srgb, var(--danger) 45%, var(--surface)); }
.page-downtime-patterns .heatmap-legend { display: flex; align-items: center; gap: 12px; font-size: 12px; color: var(--muted); margin-bottom: 12px; }
.page-downtime-patterns .heatmap-legend span { display: inline-block; width: 22px; height: 22px; border-radius: 2px; }
.page-downtime-patterns .heatmap-legend span.legend-closed { background: repeating-linear-gradient(-45deg, var(--border), var(--border) 2px, var(--surface-2) 2px, var(--surface-2) 5px) !important; border: 1px solid var(--border); }
.page-downtime-patterns .problem-list { margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--border-soft); }
.page-downtime-patterns .problem-list h4 { font-size: 14px; color: var(--text); margin-bottom: 8px; }
.page-downtime-patterns .problem-list ul { list-style: none; }
.page-downtime-patterns .problem-list p.muted { font-size: 13px; }

/* Restaurants page */
.page-restaurants .container { max-width: 1600px; margin: 40px auto; padding: 0 20px; }
.page-restaurants .page-header { background: var(--surface); border-radius: var(--radius-lg); padding: 30px; box-shadow: var(--shadow-card); margin-bottom: 30px; }
.page-restaurants .page-header h2 { color: var(--text); font-size: 28px; margin-bottom: 10px; }
.page-restaurants .page-header p { color: var(--muted); font-size: 16px; }
.page-restaurants .restaurants-list { display: flex; flex-direction: column; gap: 24px; }
.page-restaurants .restaurant-card { background: var(--surface); border-radius: var(--radius-lg); padding: 24px; box-shadow: var(--shadow-card); }
.page-restaurants .restaurant-title { font-size: 20px; color: var(--text); margin-bottom: 16px; }
.page-restaurants .restaurant-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.page-restaurants .restaurant-table td { padding: 8px 12px; border-bottom: 1px solid var(--border-soft); color: var(--text); }
.page-restaurants .restaurant-table .field-name { font-weight: 600; color: var(--text); width: 25%; }
.page-restaurants .restaurant-table .field-value { width: 25%; }
.page-restaurants .restaurant-table .field-link { color: var(--brand); text-decoration: none; word-break: break-all; }
.page-restaurants .restaurant-table .field-link:hover { text-decoration: underline; }
.page-restaurants .restaurant-table .ext-icon { font-size: 12px; opacity: 0.8; }
.page-restaurants .restaurant-table .schedule-cell { vertical-align: top; padding-top: 12px; }
.page-restaurants .schedule-days-block { display: flex; flex-wrap: wrap; gap: 8px 16px; }
.page-restaurants .schedule-day { display: inline-flex; align-items: center; gap: 6px; background: var(--surface-2); padding: 4px 10px; border-radius: 6px; font-size: 13px; }
/* Same ink as .page-lost-revenue .brand-metric: --brand-dark is 3.2:1 on --surface-2, this is 5.2:1. */
.page-restaurants .schedule-day-name { font-weight: 600; color: color-mix(in srgb, var(--brand-dark) 55%, var(--text)); min-width: 28px; }
.page-restaurants .schedule-time { color: var(--text); }
.page-restaurants .schedule-closed { color: var(--muted); font-style: italic; }
.page-restaurants .schedule-empty { color: var(--muted); }
.page-restaurants .schedule-override-block { margin-top: 8px; padding-top: 6px; border-top: 1px dashed var(--border); }
.page-restaurants .schedule-override-name { display: block; font-size: 12px; font-weight: 600; color: var(--muted); margin-bottom: 4px; }

/* Offline report page */
.page-offline-report .container { max-width: 1600px; margin: 40px auto; padding: 0 20px; }
.page-offline-report .filter-form { background: var(--surface); border-radius: var(--radius-lg); padding: 30px; box-shadow: var(--shadow-card); margin-bottom: 30px; }
.page-offline-report .filter-form h3 { color: var(--text); font-size: 20px; margin-bottom: 20px; }
.page-offline-report .filter-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin-bottom: 15px; }
.page-offline-report .filter-grid-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin-bottom: 15px; }
/* No page-level `.filter-group > label`/`> input`/`> select` here on purpose: same
   shadowing as status-by-id (app.css ~1290) — filter-form--compact's higher-specificity
   `.filter-group > label` / `.filter-group input`/`select` rules (app.css ~5975) already
   own the field-caption and control look and win regardless of source order. */
/* Multi-select dropdown for aggregator filter — mirrors downtime-patterns pattern */
/* Multi-select styling comes from the shared component block near the top of this file. */
.page-offline-report .overnight-hint { font-size: 11px; color: var(--muted); display: block; margin-top: 4px; }

/* Duration dual-range slider */
.page-offline-report .duration-filter-group { min-width: 240px; }
.page-offline-report .duration-range-text { font-weight: 700; color: var(--brand); margin-inline-start: 6px; }
.page-offline-report .duration-slider { position: relative; height: 36px; margin: 6px 0 4px; }
.page-offline-report .duration-slider-track { position: absolute; left: 8px; right: 8px; top: 50%; transform: translateY(-50%); height: 6px; background: var(--border); border-radius: 3px; }
.page-offline-report .duration-slider-range { position: absolute; top: 50%; transform: translateY(-50%); height: 6px; background: var(--brand); border-radius: 3px; left: 8px; right: 8px; pointer-events: none; }
.page-offline-report .duration-slider input[type="range"] { position: absolute; left: 0; right: 0; top: 0; bottom: 0; width: 100%; margin: 0; padding: 0; background: transparent; pointer-events: none; -webkit-appearance: none; appearance: none; }
.page-offline-report .duration-slider input[type="range"]::-webkit-slider-runnable-track { background: transparent; height: 6px; }
.page-offline-report .duration-slider input[type="range"]::-moz-range-track { background: transparent; height: 6px; }
.page-offline-report .duration-slider input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; pointer-events: auto; width: 18px; height: 18px; border-radius: 50%; background: var(--surface); border: 2px solid var(--brand); box-shadow: 0 1px 4px color-mix(in srgb, var(--text) 18%, transparent); cursor: grab; margin-top: -6px; }
.page-offline-report .duration-slider input[type="range"]::-webkit-slider-thumb:active { cursor: grabbing; transform: scale(1.08); }
.page-offline-report .duration-slider input[type="range"]::-moz-range-thumb { pointer-events: auto; width: 18px; height: 18px; border-radius: 50%; background: var(--surface); border: 2px solid var(--brand); box-shadow: 0 1px 4px color-mix(in srgb, var(--text) 18%, transparent); cursor: grab; }
.page-offline-report .duration-still-toggle { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--muted); cursor: pointer; margin-top: 6px; user-select: none; }
.page-offline-report .duration-still-toggle input { width: auto !important; padding: 0 !important; border: none !important; }
.page-offline-report .filter-actions { display: flex; gap: 10px; flex-wrap: wrap; }
.page-offline-report .stats { display: flex; gap: 20px; margin-bottom: 20px; flex-wrap: wrap; }
.page-offline-report .stat-item { background: var(--surface-2); padding: 15px 20px; border-radius: 8px; flex: 1; min-width: 100px; }
.page-offline-report .stat-item strong { display: block; font-size: 24px; color: var(--brand); margin-bottom: 5px; }
.page-offline-report .stat-item span { font-size: 13px; color: var(--muted); }
.page-offline-report .report-table-container { background: var(--surface); border-radius: 15px; padding: 30px; box-shadow: var(--shadow-card); overflow-x: auto; margin-bottom: 20px; }
@media (max-width: 600px) {
  .page-offline-report .filter-form,
  .page-offline-report .report-table-container { padding: 16px; }
}
.page-offline-report .report-table { width: 100%; border-collapse: collapse; min-width: 900px; }
.page-offline-report .report-table th, .page-offline-report .report-table td { padding: 12px 15px; border-bottom: 1px solid var(--border-soft); text-align: start; font-size: 14px; }
.page-offline-report .report-table th { background: var(--surface-2); font-weight: 600; color: var(--text); }
.page-offline-report .report-table tbody tr:hover { background: var(--surface-2); }
.page-offline-report .still-offline { color: var(--danger); font-weight: 600; }
.page-offline-report .next-day { color: var(--warn-ink); }
.page-offline-report .pagination { display: flex; justify-content: center; align-items: center; gap: 10px; margin-top: 20px; padding: 20px; flex-wrap: wrap; }
.page-offline-report .pagination a, .page-offline-report .pagination span, .page-offline-report .pagination button { padding: 8px 12px; border-radius: 6px; text-decoration: none; color: var(--brand); font-weight: 500; background: none; border: none; font-size: 14px; cursor: pointer; }
.page-offline-report .pagination a:hover, .page-offline-report .pagination button:hover { background: var(--surface-2); }
.page-offline-report .pagination .current { background: var(--cta); color: var(--cta-text); }
.page-offline-report .pagination .disabled { color: var(--muted); cursor: not-allowed; }
.page-offline-report .empty-state.date-range-error { background: var(--danger-bg); border: 1px solid var(--danger-border); }

/* Schedule hours helper (restaurant form) */
.schedule-hours { font-size: 13px; color: var(--muted); }
.schedule-hours.warn { color: var(--caution); font-weight: 600; }
.schedule-hours.error { color: var(--danger); font-weight: 600; }

/* Per-aggregator working-hours overrides (restaurant forms, admin + client) */
.agg-override-card { border: 1px solid var(--border); border-radius: 8px; padding: 12px 16px; margin-bottom: 12px; background: #faf9f7; }
.agg-override-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.agg-override-head .agg-badge { display: inline-block; padding: 3px 10px; border-radius: 6px; font-size: 12px; font-weight: 700; letter-spacing: 0.2px; }
.agg-override-remove { color: #c0392b; font-size: 12px; text-decoration: none; }
.agg-override-remove:hover { text-decoration: underline; }

/* Multi-shift schedule editor (partials/schedule_editor.php + js/schedule-editor.js) */
.sed-days { max-width: 560px; }
.sed-row { display: flex; align-items: flex-start; gap: 14px; padding: 8px 0; border-bottom: 1px solid var(--border-soft); }
.sed-day-head { display: flex; flex-direction: column; gap: 4px; min-width: 86px; padding-top: 6px; }
.sed-day-name { font-weight: 500; font-size: 14px; }
.sed-closed { display: flex; align-items: center; gap: 5px; font-size: 12px; color: var(--muted); cursor: pointer; white-space: nowrap; }
.sed-closed input.sed-closed-cb { width: 14px; height: 14px; margin: 0; }
.sed-day-body { flex: 1; }
.sed-shift { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.sed-shift input.sed-time { width: 120px; max-width: 120px; }
.sed-dash { color: var(--muted); }
.sed-hours { min-width: 70px; }
.sed-shift-remove { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; background: var(--surface); border: 1px solid var(--border); color: var(--danger); font-size: 15px; line-height: 1; cursor: pointer; padding: 0; border-radius: 6px; transition: background 0.15s, border-color 0.15s; }
.sed-shift-remove:hover { background: var(--danger-bg); border-color: var(--danger-border); }
.sed-add-shift { display: inline-block; background: var(--surface-2); border: 1px solid var(--border); color: var(--text); font-size: 12px; font-weight: 600; cursor: pointer; padding: 5px 12px; border-radius: 6px; margin-top: 2px; transition: background 0.15s; }
.sed-add-shift:hover { background: var(--border); }
.sed-add-shift:disabled { opacity: 0.45; cursor: default; }
.sed-add-shift:disabled:hover { background: var(--surface-2); }
.sed-is-closed .sed-day-body { display: none; }
.sed-day-error { color: var(--danger); font-size: 12px; }
.sed-day-error:empty { display: none; }
.sed-has-error { background: var(--danger-bg); }
.sed-days-compact .sed-day-name { font-size: 13px; }
.sed-days-compact .sed-shift input.sed-time { width: 108px; max-width: 108px; }

/* Phones: .page-restaurants kept full desktop chrome (40px top margin, 30px
   card padding) — reclaim the width; wrap/shrink the schedule editors. */
@media (max-width: 480px) {
  .page-restaurants .container { margin: 16px auto; padding: 0 12px; }
  .page-restaurants .page-header,
  .page-restaurants .restaurant-card { padding: 16px; }
  .page-restaurants .page-header h2 { font-size: 22px; }
  .sed-row { flex-wrap: wrap; }
  .sed-day-head { min-width: 100%; flex-direction: row; align-items: center; justify-content: space-between; padding-top: 0; }
  .sed-day-body { min-width: 0; }
  .sed-shift { flex-wrap: wrap; }
  .sed-shift input.sed-time { width: 96px; max-width: 96px; }
  .sed-hours { min-width: auto; }
}

/* ── User Settings (user_settings/index.php, Task 12, 2026-09-cabinets-ui-
   unification wave C) ────────────────────────────────────────────────────
   Header/card/base .message/.form-group look come from the shared .card /
   .page-header--card / .message components (Task 1). This page never had a
   .page-header element in its markup — the old copy was dead CSS, dropped
   rather than ported. .card-title stays page-scoped: no global equivalent. */
.page-user-settings .container { max-width: 900px; margin: 40px auto; padding: 0 20px; }
.page-user-settings .card-title { font-size: 20px; font-weight: 700; color: var(--text); margin-bottom: 20px; padding-bottom: 12px; border-bottom: 2px solid var(--border-soft); }
.page-user-settings .brand-scope-notice { background: var(--success-bg); color: var(--success-ink); border: 1px solid var(--success-border); padding: 10px 14px; border-radius: 8px; font-size: 13px; margin-bottom: 16px; display: flex; align-items: center; gap: 8px; }
.page-user-settings .brand-scope-notice .icon { font-size: 16px; flex-shrink: 0; }

/* Block A: Settings */
.page-user-settings .settings-group { margin-bottom: 24px; }
.page-user-settings .settings-group-title { font-size: 16px; font-weight: 600; color: var(--text); margin-bottom: 12px; }
.page-user-settings .settings-row { display: flex; align-items: center; justify-content: space-between; padding: 10px 0; border-bottom: 1px solid var(--surface-2); gap: 16px; }
.page-user-settings .settings-row:last-child { border-bottom: none; }
.page-user-settings .settings-row label { font-size: 14px; color: var(--text); flex: 1; }
.page-user-settings .settings-row select { padding: 8px 12px; border: 2px solid var(--border-strong); border-radius: 8px; font-size: 14px; width: 260px; flex-shrink: 0; background: var(--surface); color: var(--text); }
.page-user-settings .settings-row select:focus { border-color: var(--brand); outline: none; }
.page-user-settings .checkbox-row { display: flex; align-items: center; padding: 10px 0; border-bottom: 1px solid var(--surface-2); gap: 10px; }
.page-user-settings .checkbox-row:last-child { border-bottom: none; }
.page-user-settings .checkbox-row input[type="checkbox"] { width: 18px; height: 18px; accent-color: var(--brand); cursor: pointer; }
.page-user-settings .checkbox-row label { font-size: 14px; color: var(--text); cursor: pointer; }
.page-user-settings .checkbox-row-with-desc { align-items: flex-start; padding: 12px 0; }
.page-user-settings .checkbox-row-with-desc input[type="checkbox"] { margin-top: 2px; flex-shrink: 0; }
.page-user-settings .checkbox-row-text { flex: 1; }
.page-user-settings .checkbox-row-text label { display: block; font-size: 14px; color: var(--text); cursor: pointer; font-weight: 500; }
.page-user-settings .checkbox-desc { font-size: 13px; color: var(--muted); margin-top: 4px; line-height: 1.45; }
.page-user-settings .checkbox-dependency-hint { font-size: 12px; color: var(--danger); margin-top: 6px; font-style: italic; }
.page-user-settings .checkbox-row-disabled input[type="checkbox"] { cursor: not-allowed; }
.page-user-settings .checkbox-row-disabled .checkbox-row-text label,
.page-user-settings .checkbox-row-disabled .checkbox-desc { opacity: 0.55; cursor: not-allowed; }
.page-user-settings .mute-agg-label { display: flex; align-items: center; gap: 8px; }
/* Glossy edge on a badge that usually carries the aggregator's own inline DB
   colour (background/color) — same formula as .page-monitor .agg-badge. */
.page-user-settings .agg-badge { height: 22px; padding: 0 8px; border-radius: 6px; display: inline-flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 800; letter-spacing: 0.2px; white-space: nowrap; line-height: 1; box-shadow: inset 0 1px 0 color-mix(in srgb, var(--on-accent) 35%, transparent), 0 1px 3px color-mix(in srgb, var(--text) 10%, transparent); border: 1px solid color-mix(in srgb, var(--text) 8%, transparent); }
.page-user-settings .settings-group-hint { font-size: 13px; color: var(--muted); margin-bottom: 8px; }
.page-user-settings .form-actions { display: flex; gap: 12px; margin-top: 20px; align-items: center; }

/* Block B: Emails */
.page-user-settings .email-section { margin-bottom: 28px; }
.page-user-settings .email-section:last-child { margin-bottom: 0; }
.page-user-settings .email-section-title { font-size: 15px; font-weight: 600; color: var(--text); margin-bottom: 10px; }
.page-user-settings .email-subsection { margin-bottom: 12px; }
.page-user-settings .email-subsection-title { font-size: 13px; font-weight: 600; color: var(--muted); margin-bottom: 8px; text-transform: uppercase; letter-spacing: 0.5px; }
.page-user-settings .email-list { list-style: none; padding: 0; margin: 0 0 8px 0; }
.page-user-settings .email-item { display: flex; align-items: center; gap: 8px; padding: 6px 0; }
.page-user-settings .email-item .email-text { font-size: 14px; color: var(--text); }
.page-user-settings .btn-delete-email { background: none; border: none; color: var(--danger); font-size: 16px; cursor: pointer; padding: 2px 6px; border-radius: 4px; line-height: 1; }
.page-user-settings .btn-delete-email:hover { background: var(--danger-bg); }
.page-user-settings .email-add-form { display: flex; align-items: center; gap: 8px; margin-top: 4px; }
/* .email-add-form sets its own display — [hidden] needs the extra specificity
   to still win over it (plain author rules would otherwise beat the UA [hidden]
   rule regardless of specificity, since both are normal-importance). */
.page-user-settings .email-add-form[hidden] { display: none; }
.page-user-settings .email-add-form input[type="email"] { padding: 6px 10px; border: 2px solid var(--border-strong); border-radius: 6px; font-size: 13px; width: 260px; }
.page-user-settings .email-add-form input[type="email"]:focus { border-color: var(--brand); outline: none; }
.page-user-settings .btn-show-add { background: none; border: none; color: var(--brand); font-size: 13px; font-weight: 600; cursor: pointer; padding: 4px 0; }
.page-user-settings .btn-show-add:hover { text-decoration: underline; }
.page-user-settings .muted-text { font-size: 13px; color: var(--muted); font-style: italic; padding: 4px 0; }
.page-user-settings .summary-hint { font-weight: 400; }
.page-user-settings .email-error { font-size: 12px; color: var(--danger); margin-top: 4px; display: none; }

/* Restaurant blocks */
.page-user-settings .restaurant-block { border: 1px solid var(--border-soft); border-radius: 10px; padding: 14px; margin-bottom: 10px; }
.page-user-settings .restaurant-block-title { font-size: 14px; font-weight: 600; color: var(--text); margin-bottom: 8px; }
.page-user-settings .restaurant-block-meta { font-size: 12px; color: var(--muted); font-weight: 400; margin-inline-start: 6px; }

/* Collapsible per-restaurant section */
.page-user-settings .per-rest-details { margin-top: 16px; }
.page-user-settings .per-rest-details summary { cursor: pointer; font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.5px; list-style: none; display: flex; align-items: center; gap: 6px; user-select: none; padding: 4px 0; }
.page-user-settings .per-rest-details summary::-webkit-details-marker { display: none; }
.page-user-settings .per-rest-details summary::before { content: '\25B6'; font-size: 10px; transition: transform 0.2s; }
.page-user-settings .per-rest-details[open] summary::before { transform: rotate(90deg); }
.page-user-settings .per-rest-details .per-rest-content { padding-top: 10px; }

@media (max-width: 768px) {
    .page-user-settings .container { margin: 20px auto; padding: 0 12px; }
    .page-user-settings .settings-row { flex-direction: column; align-items: flex-start; gap: 6px; }
    .page-user-settings .settings-row select { width: 100%; }
    .page-user-settings .email-add-form { flex-direction: column; align-items: stretch; }
    .page-user-settings .email-add-form input[type="email"] { width: 100%; }
    .page-user-settings .btn-add-email { text-align: center; }
    .page-user-settings .restaurant-block { padding: 10px; }
    .page-user-settings .email-section-title { font-size: 14px; }
    .page-user-settings .card-title { font-size: 18px; }
}

@media (max-width: 480px) {
    .page-user-settings .container { padding: 0 8px; margin: 12px auto; }
    .page-user-settings .card-title { font-size: 16px; margin-bottom: 14px; padding-bottom: 10px; }
    .page-user-settings .settings-group-title { font-size: 14px; }
    .page-user-settings .save-button { width: 100%; text-align: center; padding: 12px; }
}

/* Block C: WhatsApp Alerts */
.page-user-settings .wa-slot-row { display: flex; align-items: center; justify-content: space-between; padding: 10px 0; border-bottom: 1px solid var(--surface-2); gap: 12px; }
.page-user-settings .wa-slot-row:last-child { border-bottom: none; }
.page-user-settings .wa-slot-label { font-size: 14px; font-weight: 500; color: var(--text); min-width: 140px; }
.page-user-settings .wa-slot-status { font-size: 14px; color: var(--muted); flex: 1; }
.page-user-settings .wa-slot-status.linked { color: var(--success-ink); font-weight: 600; }
.page-user-settings .wa-slot-actions { flex-shrink: 0; }
.page-user-settings .btn-wa { padding: 6px 14px; border-radius: 6px; font-size: 13px; font-weight: 600; cursor: pointer; border: none; }
.page-user-settings .btn-wa-link { background: var(--cta); color: var(--cta-text); }
.page-user-settings .btn-wa-link:hover { opacity: 0.9; }
.page-user-settings .btn-wa-unlink { background: none; color: var(--danger); border: 1px solid var(--danger-border); }
.page-user-settings .btn-wa-unlink:hover { background: var(--danger-bg); }
.page-user-settings .btn-wa-cancel { background: none; color: var(--muted); border: 1px solid var(--border-strong); }
.page-user-settings .btn-wa-cancel:hover { background: var(--bg); }
.page-user-settings .btn-wa-override { background: none; border: none; color: var(--brand); font-size: 13px; font-weight: 600; cursor: pointer; padding: 4px 0; }
.page-user-settings .btn-wa-override:hover { text-decoration: underline; }
.page-user-settings .wa-linking-panel { background: var(--bg); border: 1px solid var(--border); border-radius: 10px; padding: 16px; margin: 8px 0; }
.page-user-settings .wa-linking-panel ol { margin: 10px 0; padding-inline-start: 20px; font-size: 14px; color: var(--text); line-height: 1.8; }
.page-user-settings .wa-code-box { display: inline-flex; align-items: center; gap: 8px; background: var(--surface); border: 2px solid var(--brand); border-radius: 8px; padding: 8px 14px; margin: 6px 0; }
.page-user-settings .wa-code { font-family: monospace; font-size: 18px; font-weight: 700; color: var(--brand); letter-spacing: 1px; }
.page-user-settings .btn-wa-copy { background: none; border: none; cursor: pointer; font-size: 16px; padding: 2px; color: var(--muted); }
.page-user-settings .btn-wa-copy:hover { color: var(--brand); }
.page-user-settings .wa-countdown { font-size: 13px; color: var(--muted); margin-top: 8px; }
.page-user-settings .wa-countdown .time { font-weight: 600; color: var(--text); }
.page-user-settings .wa-error { font-size: 12px; color: var(--danger); margin-top: 4px; }
.page-user-settings .wa-info { font-size: 13px; color: var(--muted); font-style: italic; margin-top: 12px; }
.page-user-settings .wa-open-link-wrap { margin: 8px 0; }
.page-user-settings .wa-cancel-wrap { margin-top: 10px; }

/* Chat Alerts card — one card, channel switch (WhatsApp default, Telegram optional) */
.page-user-settings .alerts-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; padding-bottom: 16px; margin-bottom: 18px; border-bottom: 2px solid var(--border-soft); }
.page-user-settings .alerts-head .card-title { margin: 0; padding: 0; border: none; }
.page-user-settings .chan-switch { display: inline-flex; background: var(--surface-2); border-radius: 10px; padding: 3px; gap: 2px; }
.page-user-settings .chan-btn { display: inline-flex; align-items: center; gap: 7px; border: none; background: transparent; color: var(--muted); font-size: 14px; font-weight: 600; padding: 7px 15px; border-radius: 8px; cursor: pointer; transition: background 0.15s, color 0.15s, box-shadow 0.15s; }
.page-user-settings .chan-btn:hover { color: var(--text); }
.page-user-settings .chan-btn.active { background: var(--surface); color: var(--text); box-shadow: 0 1px 3px color-mix(in srgb, var(--text) 12%, transparent); }
.page-user-settings .chan-btn .chan-ico { width: 17px; height: 17px; flex-shrink: 0; color: currentColor; opacity: 0.55; transition: opacity 0.15s, color 0.15s; }
.page-user-settings .chan-btn.active .chan-ico { opacity: 1; }
/* WhatsApp/Telegram brand colours have no matching token — mapped onto the
   nearest existing role, same precedent as the WhatsApp Outreach section
   below (brand for the WhatsApp green, info for the Telegram blue). */
.page-user-settings .chan-btn.active[data-chan="wa"] .chan-ico { color: var(--brand); }
.page-user-settings .chan-btn.active[data-chan="tg"] .chan-ico { color: var(--info); }
.page-user-settings .chan-pane--hidden { display: none; }
@media (max-width: 768px) {
    .page-user-settings .wa-slot-row { flex-direction: column; align-items: flex-start; gap: 6px; }
    .page-user-settings .wa-slot-label { min-width: auto; }
    .page-user-settings .alerts-head { align-items: stretch; }
    .page-user-settings .chan-switch { width: 100%; }
    .page-user-settings .chan-btn { flex: 1; justify-content: center; }
}

/* ── Account / change password (account/password.php, Task 12) ──────────
   Header/card/.message/.form-group look come from the shared components
   (Task 1); .btn-save stays as a width/padding modifier on top of the
   shared .btn.btn-primary (full-width submit, larger touch target). */
.page-account-password .container { max-width: 560px; margin: 40px auto; padding: 0 20px; }
.page-account-password .message-info { background: var(--success-bg); color: var(--success-ink); border: 1px solid var(--success-border); }
.page-account-password .btn-save { width: 100%; padding: 14px; font-size: 16px; }
.page-account-password .btn-save:hover { transform: translateY(-1px); box-shadow: 0 8px 20px color-mix(in srgb, var(--text) 15%, transparent); }
@media (max-width: 480px) {
  .page-account-password .container { margin: 16px auto; padding: 0 12px; }
}

/* ── My Restaurants — list + Needs attention + form (Task 11, 2026-09-cabinets-
   ui-unification wave C) ─────────────────────────────────────────────────
   .page-user-restaurants: shared by index.php, attention.php and form.php
   (all three carry it on the page wrapper). .page-rest-attention: content
   specific to the Needs attention tab only (attention.php also carries
   .page-user-restaurants for the shared tabs/header/readonly-note). */
.page-user-restaurants .rest-tabs { display: flex; gap: 22px; border-bottom: 1px solid var(--border); margin: -4px 0 18px; }
.page-user-restaurants .rest-tab { display: inline-flex; align-items: center; gap: 8px; padding: 10px 2px 12px; margin-bottom: -1px; border-bottom: 2px solid transparent; font-size: 14px; font-weight: 600; color: var(--muted); text-decoration: none; }
.page-user-restaurants .rest-tab:hover { color: var(--text); }
.page-user-restaurants .rest-tab.on { color: var(--text); border-bottom-color: var(--brand); }
.page-user-restaurants .rest-tab-count { font-size: 12px; font-weight: 600; color: var(--muted); font-variant-numeric: tabular-nums; }
.page-user-restaurants .rest-tab-alert { background: var(--danger); color: var(--text-inverse); border-radius: 999px; font-size: 11.5px; font-weight: 700; padding: 2px 8px; font-variant-numeric: tabular-nums; }
@media (max-width: 600px) {
    .page-user-restaurants .rest-tabs { gap: 0; }
    .page-user-restaurants .rest-tab { flex: 1; justify-content: center; }
}

/* Header (_list_header.php): title/count use the shared .page-header.page-header--card
   shell (Task 1) + .page-header--actions for the button on the right — the page's own
   .rest-list-header box was dropped, folding two near-duplicate copies (index.php,
   attention.php) into the one global pattern every other client page already uses. */
.page-user-restaurants .rest-readonly-note { display: inline-block; padding: 7px 14px; border-radius: 8px; font-size: 13px; font-weight: 600; color: var(--muted); background: var(--surface-3); border: 1px solid var(--border); white-space: nowrap; }
.page-user-restaurants .rest-limit-badge { cursor: not-allowed; opacity: 0.4; background: var(--muted); color: var(--text-inverse); }

/* Needs-attention strip on the list tab */
.page-user-restaurants .rest-attn-strip { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border: 1px solid var(--danger-border); background: var(--danger-bg); border-radius: 10px; margin-bottom: 16px; }
.page-user-restaurants .rest-attn-strip p { flex: 1; margin: 0; font-size: 13.5px; line-height: 1.45; color: var(--text); }
.page-user-restaurants .rest-attn-strip b { color: var(--danger); }
.page-user-restaurants .rest-attn-ico { flex: 0 0 26px; height: 26px; border-radius: 50%; background: var(--danger); color: var(--text-inverse); font-weight: 800; display: grid; place-items: center; font-size: 14px; }
.page-user-restaurants .rest-attn-review { background: var(--surface); border: 1px solid var(--border-strong); color: var(--text); border-radius: 8px; padding: 6px 12px; font-size: 13px; font-weight: 600; text-decoration: none; white-space: nowrap; }
.page-user-restaurants .rest-attn-review:hover { background: var(--surface-3); border-color: var(--muted); }
@media (max-width: 600px) { .page-user-restaurants .rest-attn-strip { flex-wrap: wrap; } .page-user-restaurants .rest-attn-review { width: 100%; text-align: center; } }
.page-user-restaurants .rest-card .rest-info .rest-issue { display: block; margin-top: 6px; color: var(--danger); font-size: 12.5px; }
.page-user-restaurants .rest-card .rest-info .rest-issue a { color: var(--danger); font-weight: 600; }
.page-user-restaurants a.agg-status-dot { text-decoration: none; }

/* Restaurant cards */
.page-user-restaurants .rest-card { background: var(--surface); border-radius: 12px; padding: 16px 20px; box-shadow: var(--shadow-card); margin-bottom: 12px; display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.page-user-restaurants .rest-card .rest-info { flex: 1; min-width: 200px; }
.page-user-restaurants .rest-card .rest-info h3 { margin: 0 0 4px; font-size: 16px; }
.page-user-restaurants .rest-card .rest-info .rest-id { color: var(--muted); font-size: 12px; font-weight: 500; margin-inline-start: 6px; }
.page-user-restaurants .rest-card .rest-info .rest-sales { color: var(--muted); font-size: 13px; display: block; margin-top: 2px; }
.page-user-restaurants .rest-card .rest-info .rest-location { color: var(--muted); font-size: 13px; }

/* Filter bar */
.page-user-restaurants .rest-filter-wrap { margin-bottom: 16px; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.page-user-restaurants .rest-filter-input { flex: 1 1 260px; max-width: 420px; padding: 10px 14px; border: 1px solid var(--border-strong); border-radius: 8px; font-size: 14px; box-sizing: border-box; }
.page-user-restaurants .rest-filter-input:focus { outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 15%, transparent); }
.page-user-restaurants .rest-status-filter { display: inline-flex; gap: 4px; padding: 3px; background: var(--surface-3); border-radius: 999px; flex-wrap: wrap; }
.page-user-restaurants .rest-status-pill { border: none; background: transparent; padding: 5px 14px; border-radius: 999px; font-size: 13px; font-weight: 600; color: var(--muted); cursor: pointer; line-height: 1.3; }
.page-user-restaurants .rest-status-pill:hover { color: var(--text); }
.page-user-restaurants .rest-status-pill.on { background: var(--surface); color: var(--brand); box-shadow: 0 1px 4px color-mix(in srgb, var(--text) 10%, transparent); }
.page-user-restaurants .rest-status-pill .pill-count { font-weight: 500; color: var(--muted); margin-inline-start: 4px; font-size: 12px; }
.page-user-restaurants .rest-hide-paused { display: inline-flex; align-items: center; gap: 7px; font-size: 13px; font-weight: 600; color: var(--muted); cursor: pointer; user-select: none; padding: 5px 12px; border: 1px solid var(--border); border-radius: 999px; background: var(--surface); line-height: 1.3; }
.page-user-restaurants .rest-hide-paused:hover { color: var(--text); border-color: var(--border-strong); }
.page-user-restaurants .rest-hide-paused.on { color: var(--brand); border-color: var(--brand); background: color-mix(in srgb, var(--brand) 15%, var(--surface)); }
.page-user-restaurants .rest-hide-paused input { accent-color: var(--brand); margin: 0; cursor: pointer; }
.page-user-restaurants .rest-hide-paused .hp-count { font-weight: 500; color: var(--muted); font-size: 12px; }
.page-user-restaurants .rest-empty-filter { background: var(--surface); border-radius: 12px; padding: 24px 20px; box-shadow: var(--shadow-card); text-align: center; color: var(--muted); display: none; }
.page-user-restaurants .rest-empty-lead { font-size: 16px; margin-bottom: 16px; }

.page-user-restaurants .rest-card .rest-aggs { flex: 0 0 auto; display: flex; flex-wrap: wrap; gap: 4px; }
.page-user-restaurants .rest-card .rest-aggs .agg-badge { padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 600; display: inline-block; }
.page-user-restaurants .rest-no-aggs { color: var(--muted); font-size: 12px; }
.page-user-restaurants .rest-card .rest-status { flex: 0 0 auto; min-width: 60px; text-align: center; }
.page-user-restaurants .rest-card .rest-actions { flex: 0 0 auto; display: flex; gap: 8px; }
.page-user-restaurants .rest-inline-form { margin: 0; }
.page-user-restaurants .rest-action-hint { color: var(--muted); }

/* Action buttons + row status badges (shared with the aggregator default-colour fallback) */
.page-user-restaurants .agg-badge--default { background: var(--surface-3); color: var(--text); }
.page-user-restaurants .rest-btn { display: inline-block; padding: 6px 16px; border-radius: 8px; font-size: 13px; font-weight: 600; cursor: pointer; text-decoration: none; border: none; line-height: 1.4; }
.page-user-restaurants .rest-btn-edit { background: color-mix(in srgb, var(--brand) 15%, var(--surface)); color: var(--brand); border: 1px solid var(--brand); }
.page-user-restaurants .rest-btn-edit:hover { background: var(--cta); color: var(--cta-text); }
.page-user-restaurants .rest-btn-delete { background: var(--danger-bg); color: var(--danger); border: 1px solid var(--danger-border); }
.page-user-restaurants .rest-btn-delete:hover { background: var(--danger); color: var(--text-inverse); }
.page-user-restaurants .rest-btn-pause { background: var(--warn-bg); color: var(--warn-ink); border: 1px solid var(--warn); }
.page-user-restaurants .rest-btn-pause:hover { background: var(--warn); color: var(--text-inverse); }
.page-user-restaurants .rest-btn-resume { background: var(--success-bg); color: var(--success-ink); border: 1px solid var(--success-border); }
.page-user-restaurants .rest-btn-resume:hover { background: var(--success); color: var(--text-inverse); }
.page-user-restaurants .rest-actions-menu { position: relative; display: inline-block; }
.page-user-restaurants .rest-actions-trigger { background: var(--surface); border: 1px solid var(--border-strong); padding: 6px 12px; border-radius: 8px; font-size: 13px; font-weight: 600; cursor: pointer; color: var(--text); line-height: 1.4; }
.page-user-restaurants .rest-actions-trigger:hover { background: var(--surface-3); border-color: var(--muted); }
.page-user-restaurants .rest-actions-dropdown { display: none; position: absolute; inset-inline-end: 0; top: calc(100% + 4px); background: var(--surface); border: 1px solid var(--border); border-radius: 10px; box-shadow: var(--shadow-dropdown); min-width: 200px; z-index: 50; padding: 6px; }
.page-user-restaurants .rest-actions-menu.open .rest-actions-dropdown { display: block; }
.page-user-restaurants .rest-actions-item { display: flex; align-items: center; gap: 10px; padding: 8px 12px; border: none; background: none; width: 100%; font-size: 13px; color: var(--text); text-align: start; cursor: pointer; border-radius: 6px; }
.page-user-restaurants .rest-actions-item:hover { background: var(--surface-2); }
.page-user-restaurants .rest-actions-item.is-destructive { color: var(--danger); }
.page-user-restaurants .rest-actions-item.is-destructive:hover { background: var(--danger-bg); }
.page-user-restaurants .rest-actions-item-icon { width: 18px; text-align: center; font-size: 13px; }
.page-user-restaurants .rest-actions-divider { height: 1px; background: var(--border); margin: 4px 0; }
.page-user-restaurants .rest-empty { background: var(--surface); border-radius: 12px; padding: 48px 20px; box-shadow: var(--shadow-card); text-align: center; color: var(--muted); }
.page-user-restaurants .rest-status-badge { display: inline-block; padding: 3px 9px; border-radius: 999px; font-size: 11px; font-weight: 600; }
.page-user-restaurants .rest-status-badge--active { background: var(--success-bg); color: var(--success-ink); }
.page-user-restaurants .rest-status-badge--paused { background: var(--warn-bg); color: var(--warn-ink); }

/* Remove confirmation modal — the panel also carries .kc-modal-panel (markup), which paints
   background/radius/shadow; this rule keeps only its size and padding. */
.page-user-restaurants .rm-modal-backdrop { display: none; position: fixed; inset: 0; background: var(--overlay); z-index: 1000; align-items: center; justify-content: center; padding: 16px; }
.page-user-restaurants .rm-modal-backdrop.open { display: flex; }
.page-user-restaurants .rm-modal-panel { max-width: 460px; width: 100%; padding: 24px; }
.page-user-restaurants .rm-modal-title { margin: 0 0 10px; font-size: 18px; color: var(--text); }
.page-user-restaurants .rm-modal-body { margin: 0 0 8px; color: var(--text); font-size: 14px; line-height: 1.55; }
.page-user-restaurants .rm-modal-rest-name { margin: 12px 0; padding: 10px 14px; background: var(--surface-2); border-radius: 8px; border-inline-start: 3px solid var(--danger); font-weight: 600; color: var(--text); font-size: 14px; }
.page-user-restaurants .rm-modal-note { margin: 0; font-size: 12px; color: var(--muted); }
.page-user-restaurants .rm-modal-actions { margin-top: 20px; display: flex; gap: 10px; justify-content: flex-end; }
.page-user-restaurants .rm-modal-btn { border: none; padding: 9px 18px; border-radius: 8px; font-size: 13px; font-weight: 600; cursor: pointer; }
.page-user-restaurants .rm-modal-btn-cancel { background: var(--surface-3); color: var(--text); }
.page-user-restaurants .rm-modal-btn-cancel:hover { background: var(--border); }
.page-user-restaurants .rm-modal-btn-confirm { background: var(--danger); color: var(--text-inverse); }
.page-user-restaurants .rm-modal-btn-confirm:hover { filter: brightness(0.85); }

/* form.php — carries .page-admin-crud (wave A shared CRUD shell) + .page-user-restaurants;
   only the form-specific rules below live here, .page-admin-crud's own rules are untouched. */
.page-user-restaurants .rest-form-card { background: var(--surface); border-radius: var(--radius); padding: 28px 28px 24px; box-shadow: 0 1px 4px color-mix(in srgb, var(--text) 6%, transparent); margin-bottom: 16px; }
.page-user-restaurants .rest-form-card h3 { margin: 0 0 20px; font-size: 12px; font-weight: 700; letter-spacing: 0.8px; text-transform: uppercase; color: var(--muted); }
.page-user-restaurants .rest-form-row { display: flex; gap: 20px; flex-wrap: wrap; margin-bottom: 16px; }
.page-user-restaurants .rest-form-row:last-child { margin-bottom: 0; }
.page-user-restaurants .rest-form-row .form-group { flex: 0 0 auto; }
/* An id the saved link carries, shown read-only under the link (AggLinkFields::FROM_URL). */
.page-user-restaurants .rest-form-row .rest-link-id { max-width: 400px; }
.page-user-restaurants .rest-address-row { margin-top: 16px; }
.page-user-restaurants .form-control[readonly] { background: var(--surface-3); color: var(--muted); }

.page-user-restaurants .fw-50  { width: 50%; min-width: 240px; }
.page-user-restaurants .fw-200 { width: 200px; }
.page-user-restaurants .fw-220 { width: 220px; }
.page-user-restaurants .fw-260 { width: 260px; }
.page-user-restaurants .fw-400 { width: 400px; max-width: 100%; }
.page-user-restaurants .fw-560 { width: 560px; max-width: 100%; }

.page-user-restaurants .map-wrap { position: relative; margin-top: 12px; }
.page-user-restaurants #restaurant-map { height: 400px; border: 1px solid var(--border); border-radius: 6px; z-index: 1; }
.page-user-restaurants .map-search-box { position: absolute; top: 12px; inset-inline-start: 80px; z-index: 1000; width: 340px; background: var(--surface); border-radius: 8px; padding: 6px; box-shadow: 0 2px 12px color-mix(in srgb, var(--text) 18%, transparent); }
.page-user-restaurants .map-search-box input.form-control { border: none; box-shadow: none; padding: 8px 10px; font-size: 13px; background: transparent; }
.page-user-restaurants .map-search-box input.form-control:focus { border: none; box-shadow: none; }
.page-user-restaurants .address-results { position: absolute; top: 100%; inset-inline: 0; background: var(--surface); border-radius: 0 0 8px 8px; max-height: 200px; overflow-y: auto; z-index: 1001; display: none; box-shadow: 0 6px 16px color-mix(in srgb, var(--text) 12%, transparent); border-top: 1px solid var(--border-soft); }
.page-user-restaurants .address-results div { padding: 9px 12px; cursor: pointer; font-size: 13px; border-bottom: 1px solid var(--border-soft); }
.page-user-restaurants .address-results div:hover { background: color-mix(in srgb, var(--brand) 12%, var(--surface)); }
/* Phones: the 340px search box anchored at inset-inline-start:80 lands past the
   viewport — stretch it across the map instead (zoom controls sit lower anyway). */
@media (max-width: 480px) {
    .page-user-restaurants .map-search-box { inset-inline: 12px; width: auto; }
}
/* Phones: aggregator field inputs carry inline max-widths (per-field config)
   and .rest-form-row .form-group is flex 0 0 auto — together they hold the
   desktop width and drag the whole form into horizontal scroll. Override
   every fixed width; !important is needed against the inline styles. */
@media (max-width: 600px) {
    .page-user-restaurants .rest-form-row .form-group { flex: 1 1 100%; max-width: 100% !important; min-width: 0; }
    .page-user-restaurants .rest-form-card .form-control { width: 100% !important; max-width: 100% !important; box-sizing: border-box; }
    .page-user-restaurants .fw-400, .page-user-restaurants .fw-560 { width: 100%; }
}

.page-user-restaurants .gps-row { display: flex; gap: 16px; margin-top: 12px; flex-wrap: wrap; }
.page-user-restaurants .gps-row .form-group { flex: 1 1 150px; min-width: 0; max-width: 200px; }
.page-user-restaurants .gps-row .form-control { font-family: 'SF Mono', 'Consolas', 'Monaco', monospace; font-size: 13px; letter-spacing: 0.3px; }

.page-user-restaurants .agg-block { margin-bottom: 12px; border: 1px solid var(--border); border-radius: 8px; padding: 12px 16px; transition: border-color 0.15s; }
.page-user-restaurants .agg-block:has(.agg-checkbox:checked) { border-color: var(--brand); border-width: 1.5px; }
.page-user-restaurants .agg-header { display: flex; align-items: center; gap: 10px; cursor: pointer; }
.page-user-restaurants .agg-header input[type="checkbox"] { width: 17px; height: 17px; accent-color: var(--brand); }
.page-user-restaurants .agg-badge { display: inline-block; padding: 3px 10px; border-radius: 6px; font-size: 12px; font-weight: 700; letter-spacing: 0.2px; }
.page-user-restaurants .agg-fields { padding-block: 14px 4px; padding-inline: 27px 0; }
.page-user-restaurants .agg-fields.hidden { display: none; }
.page-user-restaurants .agg-fields .form-group { max-width: 400px; }
.page-user-restaurants .agg-fields .agg-url-section .form-control { max-width: 560px; width: 100%; }
.page-user-restaurants .rest-or-divider { color: var(--muted); font-size: 13px; font-weight: 500; margin: 8px 0; text-transform: uppercase; letter-spacing: 0.5px; }
.page-user-restaurants .rest-noon-feedback { margin-top: 4px; }
.page-user-restaurants .rest-noon-feedback-ok { color: var(--success-ink); font-weight: 500; }

.page-user-restaurants .input-mode-toggle { display: flex; gap: 16px; margin-bottom: 12px; }
.page-user-restaurants .input-mode-toggle label { display: flex; align-items: center; gap: 5px; cursor: pointer; font-size: 13px; font-weight: 500; color: var(--text); }
.page-user-restaurants .input-mode-toggle input[type="radio"] { margin: 0; accent-color: var(--brand); }

.page-user-restaurants .advanced-toggle { cursor: pointer; color: var(--muted); font-size: 13px; margin-top: 8px; display: inline-flex; align-items: center; gap: 4px; }
.page-user-restaurants .advanced-toggle:hover { color: var(--brand); }
.page-user-restaurants .advanced-fields { display: none; }
.page-user-restaurants .advanced-fields.show { display: block; }
.page-user-restaurants .careem-resolve-result { font-size: 13px; margin-top: 6px; }
/* Status line of the Careem share-link resolver (user-restaurant-form.js setResolveResult). */
.page-user-restaurants .careem-resolve-msg--error { color: var(--danger); }
.page-user-restaurants .careem-resolve-msg--pending { color: var(--muted); }
.page-user-restaurants .careem-resolve-msg--ok { color: var(--success-ink); font-weight: 500; }
.page-user-restaurants .careem-advanced-toggle { margin-top: 12px; }
.page-user-restaurants .careem-share-link-group { margin-top: 8px; max-width: 560px; }
.page-user-restaurants .careem-share-link-row { display: flex; gap: 8px; }
.page-user-restaurants .careem-resolve-btn { white-space: nowrap; }

.page-user-restaurants .schedule-table { border-collapse: collapse; font-size: 14px; }
.page-user-restaurants .schedule-table th { text-align: start; padding: 8px 12px; border-bottom: 2px solid var(--border-soft); font-weight: 600; font-size: 12px; text-transform: uppercase; letter-spacing: 0.5px; color: var(--muted); }
.page-user-restaurants .schedule-table td { padding-block: 6px; padding-inline: 12px 6px; }
.page-user-restaurants .schedule-table tr { border-bottom: 1px solid var(--border-soft); }
.page-user-restaurants .schedule-table .day-label { font-weight: 500; width: 60px; }
.page-user-restaurants .schedule-table .form-control { padding: 8px 10px; max-width: 130px; }

.page-user-restaurants .form-actions { padding: 20px 0 8px; display: flex; gap: 12px; align-items: center; margin-top: 0; }

.page-user-restaurants .sales-trigger { display: inline-flex; align-items: center; gap: 4px; color: var(--brand); font-size: 13px; cursor: pointer; font-weight: 500; padding: 10px 0 0; }
.page-user-restaurants .sales-trigger:hover { text-decoration: underline; }
.page-user-restaurants .rest-sales-name-field { margin-top: 4px; }

.page-user-restaurants .form-control::placeholder { color: var(--muted); }

.page-user-restaurants .field-error { color: var(--danger); font-size: 12px; display: block; margin-top: 4px; }
.page-user-restaurants .hint-text { color: var(--muted); font-size: 12px; margin-top: 3px; }

.page-user-restaurants .form-control.has-error { border-color: var(--danger) !important; background: var(--danger-bg); }
.page-user-restaurants .field-error-js { color: var(--danger); font-size: 12px; display: block; margin-top: 4px; }
@keyframes rest-form-shake { 0%,100% { transform: translateX(0); } 20%,60% { transform: translateX(-4px); } 40%,80% { transform: translateX(4px); } }
.page-user-restaurants .shake { animation: rest-form-shake 0.35s ease; }

/* attention.php — Needs attention tab only */
/* The two original <style> blocks never coexisted: index.php rendered this as a
   badge (padding/background/border/radius), attention.php as plain muted text —
   reset the box the shared .page-user-restaurants rule now adds, back to the
   attention tab's original look. */
.page-rest-attention .rest-readonly-note { display: inline; padding: 0; background: none; border: none; border-radius: 0; font-weight: inherit; white-space: normal; }
.page-rest-attention .filter-form { background: var(--surface); border-radius: var(--radius); padding: 22px 24px; box-shadow: var(--shadow-card); margin-bottom: 18px; }
.page-rest-attention .filter-form h3 { margin: 0 0 16px; font-size: 16px; color: var(--text); }
.page-rest-attention .filter-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 16px 14px; }
.page-rest-attention .filter-group > label { display: block; margin-bottom: 8px; color: var(--text); font-weight: 500; font-size: 14px; }
.page-rest-attention .attn-id-search input { width: 100%; box-sizing: border-box; padding: 10px; border: 2px solid var(--border-strong); border-radius: 8px; background: var(--surface); font-size: 14px; color: var(--text); font-variant-numeric: tabular-nums; }
.page-rest-attention .attn-id-search input:hover, .page-rest-attention .attn-id-search input:focus { border-color: var(--brand); outline: none; }
@media (min-width: 700px) { .page-rest-attention .attn-id-search { grid-column: span 2; } }
.page-rest-attention .filter-actions { display: flex; gap: 10px; align-items: center; margin-top: 18px; flex-wrap: wrap; }
.page-rest-attention .attn-download { margin-inline-start: auto; font-size: 13px; font-weight: 600; color: var(--text); }

.page-rest-attention .attn-summary { background: var(--surface); border-radius: var(--radius); box-shadow: var(--shadow-card); padding: 18px 20px; display: flex; gap: 20px; flex-wrap: wrap; margin-bottom: 18px; }
.page-rest-attention .attn-summary .lead { flex: 1 1 380px; }
.page-rest-attention .attn-summary h2 { margin: 0 0 6px; font-size: 19px; text-wrap: balance; }
.page-rest-attention .attn-summary p { margin: 0; color: var(--muted); line-height: 1.5; max-width: 64ch; }
.page-rest-attention .attn-summary .checked { margin-top: 10px; font-size: 12px; color: var(--muted); }
.page-rest-attention .attn-tiles { display: flex; gap: 10px; flex-wrap: wrap; }
.page-rest-attention .attn-tile { min-width: 150px; border-radius: 10px; padding: 12px 14px; border: 1px solid var(--border-soft); display: flex; flex-direction: column; gap: 3px; text-decoration: none; color: inherit; }
.page-rest-attention .attn-tile .k { font-size: 12px; font-weight: 600; color: var(--muted); }
.page-rest-attention .attn-tile .v { font-size: 24px; font-weight: 800; font-variant-numeric: tabular-nums; }
.page-rest-attention .attn-tile .s { font-size: 12px; color: var(--muted); }
.page-rest-attention .attn-tile.wrong { border-color: var(--danger-border); background: var(--danger-bg); } .page-rest-attention .attn-tile.wrong .v { color: var(--danger); }
.page-rest-attention .attn-tile.untracked { border-color: var(--warn); background: var(--warn-bg); } .page-rest-attention .attn-tile.untracked .v { color: var(--warn-ink); }

.page-rest-attention .attn-section { margin: 30px 0 26px; }
.page-rest-attention .attn-sec-head { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.page-rest-attention .attn-sec-head h2 { margin: 0; display: flex; align-items: center; gap: 10px; font-size: 24px; font-weight: 800; letter-spacing: -.2px; color: var(--text); }
.page-rest-attention .attn-sec-head h2::before { content: ""; width: 12px; height: 12px; border-radius: 50%; flex: none; }
.page-rest-attention .attn-section.wrong .attn-sec-head h2::before { background: var(--danger); }
.page-rest-attention .attn-section.untracked .attn-sec-head h2::before { background: var(--warn); }
.page-rest-attention .attn-sec-count { font-size: 13px; font-weight: 700; padding: 3px 10px; border-radius: 999px; font-variant-numeric: tabular-nums; }
.page-rest-attention .attn-section.wrong .attn-sec-count { background: var(--danger-bg); color: var(--danger); border: 1px solid var(--danger-border); }
.page-rest-attention .attn-section.untracked .attn-sec-count { background: var(--warn-bg); color: var(--warn-ink); border: 1px solid var(--warn); }
.page-rest-attention .attn-sec-sub { margin: 8px 0 4px; font-size: 15px; font-weight: 600; color: var(--text); }
.page-rest-attention .attn-sec-why { margin: 0 0 14px; color: var(--muted); font-size: 13px; line-height: 1.5; max-width: 80ch; }

.page-rest-attention .attn-card { background: var(--surface); border-radius: var(--radius); box-shadow: var(--shadow-card); margin-bottom: 12px; overflow: hidden; border-inline-start: 3px solid transparent; }
.page-rest-attention .attn-card.wrong { border-inline-start-color: var(--danger); }
.page-rest-attention .attn-card.untracked { border-inline-start-color: var(--warn); }
.page-rest-attention .attn-card-head { padding: 14px 18px 10px; display: flex; gap: 10px; align-items: flex-start; flex-wrap: wrap; }
.page-rest-attention .attn-card-head .agg-badge { padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 600; margin-top: 2px; }
.page-rest-attention .attn-card-title { flex: 1; min-width: 220px; }
.page-rest-attention .attn-card-title h4 { margin: 0 0 4px; font-size: 14.5px; }
.page-rest-attention .attn-card-title p { margin: 0; color: var(--muted); font-size: 13px; line-height: 1.5; max-width: 78ch; }
.page-rest-attention .attn-evidence { font-size: 12px; font-weight: 600; background: var(--surface-3); border-radius: 6px; padding: 3px 8px; white-space: nowrap; }
.page-rest-attention .attn-rows { border-top: 1px solid var(--border-soft); }
/* Every row of a card, the column header included, has the same tracks: the action column
   is a fixed width, so the columns line up whether a row has a button or not. */
.page-rest-attention .attn-row { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr) minmax(0, .6fr) 96px; gap: 12px; align-items: center; padding: 10px 18px; border-bottom: 1px solid var(--border-soft); }
.page-rest-attention .attn-row:last-child { border-bottom: 0; }
.page-rest-attention .attn-row.head { font-size: 11px; font-weight: 700; letter-spacing: .5px; text-transform: uppercase; color: var(--muted); padding-top: 8px; padding-bottom: 6px; }
.page-rest-attention .attn-row .loc span { color: var(--muted); }
.page-rest-attention .attn-row .idv { font-variant-numeric: tabular-nums; color: var(--text); font-weight: 600; font-size: 13px; overflow-wrap: anywhere; }
.page-rest-attention .attn-row .since { color: var(--muted); font-size: 12.5px; }
.page-rest-attention .attn-row .act { display: flex; justify-content: flex-end; }
.page-rest-attention .attn-row.target { background: var(--warn-bg); }
.page-rest-attention .attn-row.saved .since { display: none; }
.page-rest-attention .attn-row.saved .act { grid-column: 3 / -1; }
.page-rest-attention .attn-row[hidden] { display: none; }
.page-rest-attention .attn-btn { background: var(--surface); border: 1px solid var(--border-strong); color: var(--text); border-radius: 8px; padding: 6px 11px; font-size: 12.5px; font-weight: 600; cursor: pointer; }
.page-rest-attention .attn-btn:hover { background: var(--surface-3); border-color: var(--muted); }
.page-rest-attention .attn-btn.primary { background: var(--brand); border-color: var(--brand); color: var(--text-inverse); }
.page-rest-attention .attn-btn.primary:hover { background: var(--brand-dark); }
.page-rest-attention .attn-btn:disabled { opacity: .55; cursor: default; }
.page-rest-attention .attn-editor { grid-column: 1 / -1; display: flex; gap: 10px; align-items: flex-end; flex-wrap: wrap; background: var(--surface-2); border: 1px dashed var(--border); border-radius: 8px; padding: 10px; }
.page-rest-attention .attn-editor[hidden] { display: none; }
.page-rest-attention .attn-editor label { display: flex; flex-direction: column; gap: 4px; font-size: 12px; font-weight: 600; color: var(--text); flex: 1 1 220px; }
.page-rest-attention .attn-editor input { padding: 8px 10px; border: 1px solid var(--border-strong); border-radius: 7px; font-size: 13px; }
.page-rest-attention .attn-editor .hint { font-weight: 400; color: var(--muted); font-size: 11.5px; }
.page-rest-attention .attn-editor .err { flex-basis: 100%; color: var(--danger); font-size: 12.5px; margin: 0; }
.page-rest-attention .attn-row > .err.warn { grid-column: 1 / -1; color: var(--warn-ink); font-size: 12.5px; margin: 0; }
.page-rest-attention .attn-state { font-size: 12.5px; font-weight: 600; border-radius: 6px; padding: 4px 9px; }
.page-rest-attention .attn-state.checking { background: var(--warn-bg); color: var(--warn-ink); }
.page-rest-attention .attn-state.tracking { background: var(--success-bg); color: var(--success-ink); }
.page-rest-attention .attn-card-foot { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; padding: 10px 18px 12px; background: var(--surface-2); border-top: 1px solid var(--border-soft); }
.page-rest-attention .attn-more { width: 100%; border: 1px dashed var(--border); background: var(--surface); border-radius: 10px; padding: 10px; font-weight: 600; color: var(--muted); cursor: pointer; margin-bottom: 12px; }
.page-rest-attention .attn-card[hidden] { display: none; }
.page-rest-attention .attn-empty { background: var(--surface); border-radius: 12px; box-shadow: var(--shadow-card); padding: 28px 24px; text-align: center; color: var(--muted); }
.page-rest-attention .attn-empty h2 { color: var(--text); font-size: 18px; margin: 0 0 6px; }
.page-rest-attention details.attn-fold { background: var(--surface); border-radius: 12px; box-shadow: var(--shadow-card); padding: 4px 18px; margin-bottom: 12px; }
.page-rest-attention details.attn-fold summary { cursor: pointer; padding: 10px 0; font-weight: 700; font-size: 14px; }
.page-rest-attention details.attn-fold summary span { font-weight: 500; color: var(--muted); margin-inline-start: 6px; }
.page-rest-attention .attn-fold-row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; padding: 10px 0; border-top: 1px solid var(--border-soft); font-size: 13px; }
.page-rest-attention .attn-fold-row .loc { flex: 1; min-width: 200px; }
.page-rest-attention .attn-fold-row .agg-badge { padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 600; }
@media (max-width: 700px) {
    .page-rest-attention .attn-row, .page-rest-attention .attn-row.head { grid-template-columns: 1fr auto; row-gap: 4px; }
    .page-rest-attention .attn-row.head { display: none; }
    .page-rest-attention .attn-row .since { text-align: end; }
    .page-rest-attention .attn-row .act, .page-rest-attention .attn-row.saved .act { grid-column: 1 / -1; }
    .page-rest-attention .attn-row .act .attn-btn { flex: 1; }
    .page-rest-attention .attn-sec-head h2 { font-size: 21px; }
    .page-rest-attention .filter-actions > * { flex: 1; text-align: center; }
    .page-rest-attention .attn-download { margin-inline-start: 0; }
}

/* Admin CRUD — общие стили для aggregators, users, parsing queue */
.page-admin-crud .container { max-width: 1200px; margin: 40px auto; padding: 0 20px; }
.page-admin-crud .page-header h2 { color: var(--text); font-size: 28px; margin-bottom: 8px; }
.page-admin-crud .page-header p { color: var(--muted); font-size: 16px; }
.page-admin-crud .form-group { margin-bottom: 20px; }
.page-admin-crud .toolbar .form-group { margin-bottom: 0; }
.page-admin-crud .form-group label { display: block; margin-bottom: 8px; font-weight: 600; color: var(--text); }
.page-admin-crud .form-control { padding: 12px 16px; border: 2px solid var(--border-strong); border-radius: 8px; font-size: 14px; background: var(--surface); color: var(--text); }
.page-admin-crud .form-control:focus { border-color: var(--brand); outline: none; }

/* Только countries */
.page-admin-countries .field-error { color: var(--danger); font-size: 13px; margin-top: 4px; }
.page-admin-countries .code-input { width: 120px; text-transform: uppercase; }
.page-admin-countries .radio-option { display: inline-flex; align-items: center; margin-inline-end: 16px; }
.page-admin-countries .radio-option-text { margin-inline-start: 6px; }
.page-admin-countries .aggregators-group { margin-top: 24px; padding-top: 20px; border-top: 1px solid var(--border); }
.page-admin-countries .aggregators-hint { font-size: 13px; margin-bottom: 12px; }
.page-admin-countries .agg-list-wrap { background: var(--bg); border-radius: 8px; padding: 8px; max-height: 420px; overflow-y: auto; }
.page-admin-countries .agg-empty { font-size: 13px; margin: 4px 8px; }
.page-admin-countries .agg-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.page-admin-countries .agg-item { display: flex; align-items: center; gap: 10px; padding: 6px 10px; border-radius: 6px; cursor: pointer; background: var(--surface); border: 1px solid var(--border); }
.page-admin-countries .agg-checkbox { width: 16px; height: 16px; padding: 0; margin: 0; border: 0; flex-shrink: 0; }
.page-admin-countries .agg-badge { display: inline-block; padding: 2px 10px; border-radius: 12px; font-size: 12px; font-weight: 600; line-height: 1.6; border: 1px solid var(--border); }
.page-admin-countries .agg-disabled { font-size: 11px; color: var(--muted); }

/* Только brands */
.page-admin-brands .field-error { color: var(--danger); font-size: 13px; margin-top: 4px; }
.page-admin-brands .radio-option { display: inline-flex; align-items: center; margin-inline-end: 16px; }
.page-admin-brands .radio-option-text { margin-inline-start: 6px; }
.page-admin-brands .form-section { margin-bottom: 24px; padding-top: 16px; border-top: 1px solid var(--border); }
.page-admin-brands .form-section-label { font-weight: 600; margin-bottom: 8px; display: block; }
.page-admin-brands .checkbox-row { display: flex; gap: 24px; flex-wrap: wrap; }
.page-admin-brands .checkbox-row label { display: flex; align-items: center; gap: 6px; cursor: pointer; }
.page-admin-brands .budget-input { max-width: 220px; }
.page-admin-brands .budget-hint { display: block; margin-top: 6px; }

/* Только geo cities */
.page-admin-geo-cities .field-error { color: var(--danger); font-size: 13px; margin-top: 4px; }
.page-admin-geo-cities .form-row { display: flex; gap: 16px; }
.page-admin-geo-cities .form-row .form-group { flex: 1; }
@media (max-width: 480px) {
  .page-admin-geo-cities .form-row { flex-wrap: wrap; }
  .page-admin-geo-cities .form-row .form-group { flex: 1 1 100%; }
}

/* Только geo zones */
.page-admin-geo-zones .header-actions { display: flex; gap: 10px; }
.page-admin-geo-zones .form-row { display: flex; gap: 16px; }
.page-admin-geo-zones .form-row .form-group { flex: 1; }
.page-admin-geo-zones .geohash-preview { display: inline-block; padding: 6px 10px; background: var(--surface-2); border-radius: 6px; font-size: 14px; }
.page-admin-geo-zones .zone-slug { font-size: 12px; }
.page-admin-geo-zones .latlon-cell { white-space: nowrap; }
.page-admin-geo-zones .data-table th:last-child,
.page-admin-geo-zones .data-table td.actions { text-align: end; }
@media (max-width: 480px) {
  .page-admin-geo-zones .form-row { flex-wrap: wrap; }
  .page-admin-geo-zones .form-row .form-group { flex: 1 1 100%; }
}

/* Только languages */
.page-admin-languages .lang-dir { text-transform: uppercase; }
.page-admin-languages .default-check { color: var(--success); font-weight: 600; }
.page-admin-languages .drafts-note { color: var(--warn); font-size: 12px; }
.page-admin-languages .field-error { color: var(--danger); font-size: 13px; margin-top: 4px; }
.page-admin-languages .field-hint { color: var(--muted); font-size: 12px; margin-top: 4px; }
.page-admin-languages .code-display { display: inline-block; padding: 8px 12px; background: var(--surface-2); border-radius: var(--radius-sm); font-size: 14px; }
.page-admin-languages .code-input { width: 160px; }
.page-admin-languages .status-select { max-width: 320px; }
.page-admin-languages .sort-input { width: 120px; }
.page-admin-languages .radio-option { display: inline-flex; align-items: center; margin-inline-end: 16px; }
.page-admin-languages .radio-option-text { margin-inline-start: 6px; }
.page-admin-languages .danger-zone { margin-top: 24px; border: 1px solid var(--danger-border); }
.page-admin-languages .danger-zone h3 { color: var(--danger); margin-top: 0; }
.page-admin-languages .danger-zone p { color: var(--muted); font-size: 14px; }
.page-admin-languages .confirm-cascade-label { display: flex; align-items: center; gap: 8px; cursor: pointer; margin-bottom: 16px; }

/* Только translations */
.page-admin-translations .db-note { font-size: 12px; }
.page-admin-translations .message-warning { background: var(--warn-bg); color: var(--warn-ink); }
.page-admin-translations .drafts-form { margin-bottom: 10px; }
.page-admin-translations .col-en { width: 34%; }
.page-admin-translations .col-value { width: 40%; }
.page-admin-translations .key-cell { font-family: monospace; white-space: nowrap; }
.page-admin-translations .state-cell { white-space: nowrap; }
.page-admin-translations .data-table input.form-control { width: 100%; }
.page-admin-translations .badge-info { background: var(--info-bg); color: var(--info); }

/* Только coverage */
.page-admin-coverage .owner-row { display: flex; gap: 16px; flex-wrap: wrap; }
.page-admin-coverage .owner-col { flex: 1; min-width: 220px; }
.page-admin-coverage .owner-sublabel { font-size: 13px; }
.page-admin-coverage .field-hint-warn { color: var(--warn); font-size: 12px; margin-top: 4px; }
.page-admin-coverage .active-checkbox-label { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; font-weight: 600; }
.page-admin-coverage .agg-chip { display: inline-block; padding: 2px 8px; border-radius: 12px; font-size: 12px; font-weight: 600; margin: 1px; }
.page-admin-coverage .orphaned-note { color: var(--danger); }

/* Только aggregators */
.page-admin-aggregators .color-swatch { width: 44px; height: 44px; padding: 4px; border: 2px solid var(--border-strong); border-radius: 8px; cursor: pointer; }
.page-admin-aggregators .badge-info { background: var(--info-bg); color: var(--info); }
.page-admin-aggregators .field-error { color: var(--danger); font-size: 13px; }
.page-admin-aggregators .checkbox-inline { display: flex; align-items: center; gap: 8px; cursor: pointer; }
.page-admin-aggregators .checkbox-inline input[type="checkbox"] { width: 16px; height: 16px; margin: 0; }
.page-admin-aggregators .field-hint { font-size: 13px; margin-top: 6px; }
.page-admin-aggregators .field-hint--indent { margin-inline-start: 24px; }
.page-admin-aggregators .flag-history { margin-top: 12px; margin-inline-start: 24px; padding: 10px 12px; background: var(--surface-2); border-radius: 6px; }
.page-admin-aggregators .flag-history-label { font-size: 12px; font-weight: 600; margin-bottom: 6px; }
.page-admin-aggregators .flag-history .data-table { font-size: 12px; }
.page-admin-aggregators .flag-history .data-table td { padding: 3px 8px; }
.page-admin-aggregators .input-narrow { width: 120px; max-width: 100%; }
.page-admin-aggregators .color-input-row { display: flex; gap: 12px; align-items: center; }
.page-admin-aggregators .color-swatches { display: inline-flex; align-items: center; gap: 6px; }
.page-admin-aggregators .color-swatch-dot { display: inline-block; width: 18px; height: 18px; border-radius: 4px; border: 1px solid var(--border-strong); }
.page-admin-aggregators .color-swatch-dot--default { background: var(--surface-3); }
.page-admin-aggregators .mute-audit { display: block; margin-top: 4px; font-size: 11px; color: var(--muted); }
.page-admin-aggregators .linked-restaurants-group { margin-top: 28px; padding-top: 24px; border-top: 1px solid var(--border); }
.page-admin-aggregators .linked-restaurants-label { display: block; margin-bottom: 12px; font-weight: 600; }
.page-admin-aggregators .linked-restaurants-hint { font-size: 13px; margin-bottom: 12px; }
.page-admin-aggregators .linked-restaurants-box { max-height: 640px; overflow-y: auto; background: var(--surface-2); border-radius: 8px; padding: 12px 16px; }
.page-admin-aggregators .restaurant-country { margin-bottom: 10px; }
.page-admin-aggregators .restaurant-country-name { font-weight: 600; color: var(--text); margin-bottom: 6px; }
.page-admin-aggregators .restaurant-city { margin-bottom: 8px; }
.page-admin-aggregators .restaurant-city-name { font-size: 13px; margin-bottom: 4px; }
.page-admin-aggregators .restaurant-list { display: flex; flex-direction: column; gap: 2px; align-items: flex-start; }
.page-admin-aggregators .restaurant-item { display: flex; align-items: center; cursor: pointer; font-size: 14px; white-space: nowrap; line-height: 1.3; width: 100%; }
.page-admin-aggregators .restaurant-item-check { display: flex; align-items: center; width: 24px; flex-shrink: 0; }
.page-admin-aggregators .restaurant-item-label { white-space: nowrap; }
.page-admin-aggregators .restaurant-empty { font-size: 13px; }

/* Только users */
.page-admin-users .field-error { color: var(--danger); font-size: 13px; }
.page-admin-users .toolbar-checkbox { display: flex; align-items: center; gap: 8px; cursor: pointer; padding-top: 8px; }
.page-admin-users .toolbar-checkbox input[type="checkbox"] { width: 16px; height: 16px; }
.page-admin-users .sort-link { color: inherit; text-decoration: none; cursor: pointer; white-space: nowrap; }
.page-admin-users .sort-sep { font-weight: 400; }
.page-admin-users .user-name { font-weight: 600; }
.page-admin-users .user-email { font-size: 13px; }
.page-admin-users .brand-tag { display: inline-block; margin-top: 4px; padding: 2px 8px; border-radius: 20px; font-size: 11px; font-weight: 600; background: var(--surface-2); color: var(--muted); }
.page-admin-users .badge-purple { background: var(--info-bg); color: var(--info); }
.page-admin-users .text-expired { color: var(--danger); font-weight: 600; }
.page-admin-users .btn-impersonate { background: var(--success-bg); color: var(--success-ink); }
.page-admin-users .radio-option { display: inline-flex; align-items: center; margin-inline-end: 16px; cursor: pointer; }
.page-admin-users .radio-option-text { margin-inline-start: 6px; }
.page-admin-users .attachment-block { margin-top: 14px; }
.page-admin-users #restaurant_ids { width: 100%; max-width: 100%; }
.page-admin-users .sublabel { display: block; margin-bottom: 6px; font-weight: 500; }
.page-admin-users .field-hint { color: var(--muted); font-size: 12px; margin-top: 4px; }
.page-admin-users .form-section { margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--border); }
.page-admin-users .form-section-label { font-weight: 600; margin-bottom: 8px; display: block; }
.page-admin-users .checkbox-row { display: flex; gap: 24px; flex-wrap: wrap; }
.page-admin-users .checkbox-row label { display: flex; align-items: center; gap: 6px; cursor: pointer; }
.page-admin-users .checkbox-inline { display: flex; align-items: center; gap: 6px; cursor: pointer; }
.page-admin-users .pager-wrap--split { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 12px; }
.page-admin-users .per-page-control { display: flex; align-items: center; gap: 8px; }
.page-admin-users .per-page-label { font-weight: 600; font-size: 14px; }
.page-admin-users .per-page-select { padding: 6px 10px; border: 1px solid var(--border); border-radius: 6px; font-size: 14px; }

/* Только restaurants — общие утилиты шарятся между index/form/show через одну .page-admin-restaurants-обёртку */
.page-admin-restaurants .field-error { color: var(--danger); font-size: 13px; margin-top: 4px; }
.page-admin-restaurants .message-warning { background: var(--warn-bg); color: var(--warn-ink); }
.page-admin-restaurants .text-xs { font-size: 12px; }
.page-admin-restaurants .text-sm { font-size: 13px; }
.page-admin-restaurants .nowrap { white-space: nowrap; }
.page-admin-restaurants .brand-name-link { color: var(--text); text-decoration: none; }
.page-admin-restaurants .agg-badge-wrap { margin: 1px 2px; }
.page-admin-restaurants .btn-restore { background: var(--success-bg); color: var(--success-ink); }
.page-admin-restaurants .data-table td.actions a.btn { margin-inline-end: 4px; }
.page-admin-restaurants .pager-wrap--split { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 16px; }
.page-admin-restaurants .per-page-control { display: flex; align-items: center; gap: 8px; font-size: 13px; }
.page-admin-restaurants .per-page-label { margin: 0; font-weight: 500; color: var(--muted); }
.page-admin-restaurants .per-page-select { padding: 4px 8px; border: 1px solid var(--border-strong); border-radius: 6px; cursor: pointer; }
.page-admin-restaurants .data-table th, .page-admin-restaurants .data-table td { padding: 10px 10px; }

/* Только parsing queue */
.page-admin-parsing-queue .badge { text-transform: uppercase; }
.page-admin-parsing-queue .badge-info { background: var(--info-bg); color: var(--info); }
.page-admin-parsing-queue .restaurant-name { font-weight: 600; }
.page-admin-parsing-queue .field-error { color: var(--danger); font-size: 13px; }
.page-admin-parsing-queue .checkbox-inline { display: flex; align-items: center; gap: 8px; cursor: pointer; }
.page-admin-parsing-queue .queue-table td,
.page-admin-parsing-queue .queue-table th { padding: 6px 8px; }
.page-admin-parsing-queue .queue-table th { border-bottom: 2px solid var(--border-soft); background: var(--surface-2); font-weight: 600; text-align: start; }
.page-admin-parsing-queue .pager-wrap { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 12px; }
.page-admin-parsing-queue .pager-simple { display: flex; align-items: center; gap: 8px; }
.page-admin-parsing-queue .pager-page-label { font-weight: 600; font-size: 14px; padding: 0 8px; }
.page-admin-parsing-queue .btn-disabled { opacity: 0.5; pointer-events: none; }
.page-admin-parsing-queue .per-page-control { display: flex; align-items: center; gap: 8px; }
.page-admin-parsing-queue .per-page-label { font-weight: 600; font-size: 14px; }
.page-admin-parsing-queue .per-page-select { padding: 6px 10px; border: 1px solid var(--border); border-radius: 6px; font-size: 14px; }
.page-admin-restaurants .data-table td.actions, .page-admin-parsing-queue .data-table td.actions { white-space: normal; }

/* Alert Events — компактные карточки, цветные кнопки */
.page-admin-alert-events { font-size: 13px; }
.page-admin-alert-events .page-header h2 { font-size: 22px; }
.page-admin-alert-events .page-header p { font-size: 14px; }
.page-admin-alert-events .filter-form .form-control { font-size: 13px; padding: 8px 12px; }
.page-admin-alert-events .filter-form label { font-size: 12px; }
.page-admin-alert-events .field-error { color: var(--danger); font-size: 13px; }
.page-admin-alert-events .empty-message { padding: 40px; text-align: center; color: var(--muted); }
.page-admin-alert-events .pager-wrap { display: flex; align-items: center; gap: 8px; }
.page-admin-alert-events .pager-page-label { font-weight: 600; font-size: 14px; padding: 0 8px; }
.page-admin-alert-events .btn-disabled { opacity: 0.5; pointer-events: none; }
.page-admin-alert-events .alert-event-card {
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 8px;
  padding: 10px 14px; margin-bottom: 8px; box-shadow: var(--shadow-card);
}
.page-admin-alert-events .event-card-row { display: flex; flex-wrap: wrap; gap: 8px 16px; align-items: center; margin-bottom: 6px; }
.page-admin-alert-events .event-card-row:last-of-type { margin-bottom: 0; }
.page-admin-alert-events .event-card-row.event-card-main { display: flex; justify-content: space-between; align-items: center; gap: 16px; margin-bottom: 0; }
.page-admin-alert-events .event-card-actions { display: flex; flex-shrink: 0; align-items: center; gap: 4px; }
@media (max-width: 480px) {
  .page-admin-alert-events .event-card-row.event-card-main { flex-wrap: wrap; }
  .page-admin-alert-events .event-card-actions { width: 100%; justify-content: flex-end; }
}
.page-admin-alert-events .event-card-content { flex: 1; min-width: 0; }
.page-admin-alert-events .event-card-field { display: inline-flex; align-items: center; gap: 6px; }
.page-admin-alert-events .rest-status-badge {
  display: inline-block; padding: 2px 8px; border-radius: 6px; font-size: 11px; font-weight: 600;
}
.page-admin-alert-events .rest-status-on { background: var(--success-bg); color: var(--success-ink); }
.page-admin-alert-events .rest-status-off { background: var(--danger-bg); color: var(--danger); }
.page-admin-alert-events .agg-badge {
  display: inline-block; padding: 2px 8px; border-radius: 6px; font-size: 12px; font-weight: 600;
}
.page-admin-alert-events .status-badge {
  display: inline-block; padding: 2px 8px; border-radius: 6px; font-size: 11px; font-weight: 600; text-transform: uppercase;
}
.page-admin-alert-events .status-badge-success { background: var(--success-bg); color: var(--success-ink); }
.page-admin-alert-events .status-badge-failed { background: var(--danger-bg); color: var(--danger); }
.page-admin-alert-events .status-badge-processing { background: var(--info-bg); color: var(--info); }
.page-admin-alert-events .status-badge-pending { background: var(--text); color: var(--bg); }
.page-admin-alert-events .dates-group { display: flex; flex-wrap: wrap; gap: 6px 14px; font-size: 11px; color: var(--muted); }

/* Login Log — admin (index/brand/user); dense read-only table, compact card kept
   as a normal-specificity rule (no !important needed: two ancestor classes already
   out-specificity the plain .card default). */
.page-admin-login-log .card { padding: 14px 16px; margin-bottom: 14px; }
.page-admin-login-log .toolbar { gap: 10px; margin-bottom: 14px; }
.page-admin-login-log .toolbar .form-group label { font-size: 11px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: .3px; margin-bottom: 3px; }
.page-admin-login-log .toolbar .form-control { padding: 5px 8px; font-size: 12.5px; height: 30px; line-height: 1.2; }
.page-admin-login-log .toolbar .btn { padding: 6px 14px; font-size: 12.5px; height: 30px; line-height: 1.2; }
.page-admin-login-log .data-table { font-size: 13px; }
.page-admin-login-log .data-table th,
.page-admin-login-log .data-table td { padding: 8px 10px; }
.page-admin-login-log .data-table th { font-size: 11px; }
.page-admin-login-log .section-title { font-size: 18px; margin: 24px 0 12px; color: var(--text); }
.page-admin-login-log .section-title:first-child { margin-top: 0; }
.page-admin-login-log .page-title-tight { margin: 8px 0 4px; }
.page-admin-login-log .back-link { color: var(--muted); text-decoration: none; font-size: 14px; }
.page-admin-login-log .header-meta { font-size: 14px; color: var(--muted); font-weight: 400; }
.page-admin-login-log .header-aside { text-align: end; }
.page-admin-login-log .sep-dot { color: var(--muted); padding: 0 6px; }
.page-admin-login-log .last-active-meta { margin-top: 8px; }
.page-admin-login-log .last-active-meta strong { color: var(--text); }
.page-admin-login-log .meta-note { font-size: 11px; font-weight: 400; color: var(--muted); }
.page-admin-login-log .row-link { color: inherit; text-decoration: none; }
.page-admin-login-log .user-name { font-weight: 600; }
.page-admin-login-log .user-email { font-size: 13px; }
.page-admin-login-log .mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px; }
.page-admin-login-log .text-xs { font-size: 12px; }
.page-admin-login-log .text-sm { font-size: 13px; }
.page-admin-login-log .nowrap { white-space: nowrap; }
.page-admin-login-log .brand-chip { display: inline-block; padding: 4px 10px; border-radius: 20px; font-size: 12px; font-weight: 600; background: var(--success-bg); color: var(--success-ink); text-decoration: none; }
.page-admin-login-log .flag-emoji { font-size: 16px; margin-inline-end: 6px; vertical-align: middle; }
.page-admin-login-log .flag-text { vertical-align: middle; }
.page-admin-login-log .cell-danger-note { color: var(--danger); font-size: 12px; }
.page-admin-login-log .pager-wrap--split { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 12px; }
.page-admin-login-log .per-page-control { display: flex; align-items: center; gap: 8px; }
.page-admin-login-log .per-page-label { font-weight: 600; font-size: 14px; }
.page-admin-login-log .per-page-select { padding: 6px 10px; border: 1px solid var(--border); border-radius: 6px; font-size: 14px; }
.page-admin-login-log .toolbar .form-group { min-width: 0; }

.page-downtime-patterns .problem-list li { font-size: 13px; color: var(--muted); padding: 4px 0; }
.page-downtime-patterns .problem-list li strong { color: var(--danger); }

@media (max-width: 768px) {
  .page-restaurant-ranking .filter-grid { grid-template-columns: 1fr; }
  .page-restaurant-ranking .filter-actions { flex-direction: column; align-items: stretch; }
  .page-restaurant-ranking .ranking-grid { grid-template-columns: 1fr; gap: 16px; }
}

@media (max-width: 768px) {
  .page-offline-summary .filter-grid,
  .page-offline-summary .filter-grid-row { grid-template-columns: 1fr; }
  .page-offline-summary .filter-actions { flex-direction: column; align-items: stretch; }
  .page-offline-summary .summary-table { min-width: 600px; }
  .page-offline-summary .summary-table th,
  .page-offline-summary .summary-table td { padding: 8px 10px; font-size: 12px; }
}

/* Filter row templates live here (not inline in the view) so the 768px
   override below can actually win — inline styles beat any stylesheet rule. */
.page-status-by-id .filter-grid--rest { grid-template-columns: 1fr 280px; }
.page-status-by-id .filter-grid--times { grid-template-columns: repeat(4, 1fr); margin-top: 12px; }

@media (max-width: 768px) {
  .page-status-by-id .report-table-container { overflow-x: auto; -webkit-overflow-scrolling: touch; padding: 12px; }
  .page-status-by-id .filter-grid,
  .page-status-by-id .filter-grid--rest,
  .page-status-by-id .filter-grid-row { grid-template-columns: 1fr; gap: 15px; }
  .page-status-by-id .filter-grid--times { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
  .page-status-by-id .filter-grid--times input { min-width: 0; width: 100%; }
  .page-status-by-id .filter-actions { flex-direction: column; align-items: stretch; }
}

/* Responsive */
@media (max-width: 768px) {
  .app-main {
    padding: 16px 12px;
  }
  .info-grid {
    grid-template-columns: repeat(2, 1fr);
  }
  .info-card h3 { font-size: 14px; }
  .info-card p { font-size: 11px; }
}

@media (max-width: 480px) {
  .info-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px;
  }
  .info-card {
    padding: 12px;
  }
  .info-card-icon { width: 28px; height: 28px; margin-bottom: 6px; }
  .info-card h3 { font-size: 13px; }
  .info-card p { font-size: 11px; line-height: 1.3; }
}

/* Realtime control panel page */

.page-realtime-control-panel .container {
  max-width: 1720px;
  margin: 0 auto;
  padding: 24px;
}

.page-realtime-control-panel .panel-meta {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.page-realtime-control-panel .time-switch {
  display: inline-flex;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 2px;
}

.page-realtime-control-panel .time-switch-btn {
  border: none;
  background: transparent;
  color: var(--muted);
  font-size: 12px;
  font-weight: 700;
  padding: 6px 10px;
  border-radius: 999px;
  cursor: pointer;
}

.page-realtime-control-panel .time-switch-btn.is-active {
  background: var(--cta);
  color: var(--cta-text);
}

.page-realtime-control-panel .meta-chip {
  background: var(--success-bg);
  border: 1px solid var(--success-border);
  border-radius: 999px;
  padding: 7px 12px;
  font-size: 13px;
  color: var(--success-ink);
  white-space: nowrap;
}

.page-realtime-control-panel .countdown-standalone {
  margin-inline-start: auto;
  width: 82px;
  min-width: 82px;
  display: flex;
  justify-content: center;
}

.page-realtime-control-panel .countdown-value {
  display: inline-block;
  min-width: 1.5em;
  text-align: center;
  font-family: 'Montserrat', 'Inter', sans-serif;
  font-size: 40px;
  line-height: 1;
  vertical-align: middle;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

.page-realtime-control-panel .panel-grid {
  display: grid;
  grid-template-columns: minmax(250px, 1fr) minmax(250px, 1fr) minmax(0, 4fr);
  gap: 16px;
  align-items: start;
}

.page-realtime-control-panel .panel-main {
  min-width: 0;
}

.page-realtime-control-panel .panel-kitchain,
.page-realtime-control-panel .panel-queue {
  position: sticky;
  top: 16px;
  background: var(--surface);
  border-radius: 14px;
  box-shadow: var(--shadow-card);
  border: 1px solid var(--border-soft);
  padding: 8px;
}

.page-realtime-control-panel .queue-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  margin-bottom: 6px;
}

.page-realtime-control-panel .queue-header h3 {
  margin: 0;
  font-size: 14px;
  color: var(--brand-dark);
}

.page-realtime-control-panel .queue-meta {
  font-size: 10px;
  font-weight: 700;
  color: var(--muted);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 2px 6px;
}

.page-realtime-control-panel .panel-queue .agg-badge {
  height: 18px;
  padding: 0 7px;
  border-radius: 6px;
  font-size: 10px;
  border-width: 1px;
  box-shadow: var(--shadow-card);
  display: inline-flex;
  align-items: center;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.page-realtime-control-panel .queue-summary {
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.page-realtime-control-panel .queue-summary-head,
.page-realtime-control-panel .queue-summary-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 44px 44px 44px;
  align-items: center;
  gap: 4px;
  padding: 3px 6px;
  border-radius: 6px;
  min-height: 22px;
}

.page-realtime-control-panel .queue-summary-head {
  text-transform: uppercase;
  font-size: 9px;
  letter-spacing: 0.4px;
  font-weight: 700;
  color: var(--muted);
  min-height: 18px;
  padding-top: 2px;
  padding-bottom: 2px;
}

.page-realtime-control-panel .queue-summary-head .qs-num {
  color: var(--muted);
  font-weight: 700;
}

.page-realtime-control-panel .queue-summary-row {
  background: var(--bg);
}

.page-realtime-control-panel .queue-summary-row:hover {
  background: var(--surface-2);
}

.page-realtime-control-panel .qs-col {
  min-width: 0;
}

.page-realtime-control-panel .qs-num {
  text-align: end;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  font-size: 12px;
  color: var(--muted);
  line-height: 1.1;
}

.page-realtime-control-panel .qs-link {
  color: inherit;
  text-decoration: none;
  cursor: pointer;
}

.page-realtime-control-panel .qs-link:hover {
  text-decoration: underline;
}

.page-realtime-control-panel .queue-summary-row.has-queue .qs-queue {
  color: var(--text);
  font-weight: 800;
}

.page-realtime-control-panel .queue-summary-row.has-done .qs-done {
  color: var(--success);
  font-weight: 800;
}

.page-realtime-control-panel .queue-summary-row.has-errors .qs-errors {
  color: var(--danger);
  font-weight: 800;
}

/* Zero = nothing happened. Fade it so the row reads as its non-zero counters.
   Mutually exclusive with the has-* rules above, which only apply when > 0. */
.page-realtime-control-panel .qs-num.qs-zero {
  color: var(--border-strong);
  font-weight: 600;
}

.page-realtime-control-panel .kitchain-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  margin-bottom: 6px;
}

.page-realtime-control-panel .kitchain-header h3 {
  margin: 0;
  font-size: 14px;
  color: var(--brand-dark);
}

.page-realtime-control-panel .kitchain-meta {
  font-size: 10px;
  font-weight: 700;
  color: var(--muted);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 2px 6px;
}

.page-realtime-control-panel .kitchain-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.page-realtime-control-panel .kitchain-card {
  display: block;
  border-radius: 10px;
  border: 1px solid transparent;
  box-shadow: var(--shadow-card);
  padding: 5px 6px;
  min-height: 0;
  color: inherit;
  text-decoration: none;
  cursor: pointer;
  transition: box-shadow 120ms ease;
}

.page-realtime-control-panel .kitchain-card:hover {
  box-shadow: 0 2px 4px color-mix(in srgb, var(--text) 10%, transparent),
    0 8px 20px color-mix(in srgb, var(--text) 10%, transparent);
}

.page-realtime-control-panel .kitchain-row-top {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 4px;
  margin-bottom: 2px;
}

.page-realtime-control-panel .panel-kitchain .agg-badge {
  height: 16px;
  padding: 0 6px;
  border-radius: 6px;
  font-size: 9px;
  border-width: 1px;
  box-shadow: var(--shadow-card);
  flex-shrink: 0;
}

.page-realtime-control-panel .kitchain-status {
  min-width: 0;
  text-align: end;
  font-size: 9px;
  font-weight: 900;
  letter-spacing: 0.2px;
  color: var(--text);
  white-space: nowrap;
}

.page-realtime-control-panel .kitchain-name-area {
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.page-realtime-control-panel .kitchain-restaurant {
  font-size: 9px;
  font-weight: 800;
  color: var(--text);
  line-height: 1;
}

.page-realtime-control-panel .kitchain-area {
  font-size: 9px;
  color: var(--muted);
  line-height: 1;
}

.page-realtime-control-panel .kitchain-separator {
  color: var(--muted);
  font-size: 8px;
  font-weight: 700;
}

.page-realtime-control-panel .kitchain-row-bottom {
  display: flex;
  align-items: center;
  justify-content: flex-start;
}

.page-realtime-control-panel .kitchain-metric {
  font-size: 8px;
  font-weight: 700;
  color: var(--text);
  line-height: 1;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.page-realtime-control-panel .kitchain-proxy {
  font-weight: 800;
  letter-spacing: 0.3px;
  color: var(--text);
}

.page-realtime-control-panel .kitchain-sep {
  color: var(--muted);
  font-weight: 600;
}

.page-realtime-control-panel .kitchain-time {
  color: var(--text);
}

.page-realtime-control-panel .kitchain-on {
  background: var(--success-bg);
  border-color: var(--success-border);
}

.page-realtime-control-panel .kitchain-off {
  background: var(--danger-bg);
  border-color: var(--danger-border);
}

.page-realtime-control-panel .kitchain-empty-state {
  text-align: center;
  padding: 20px 12px;
  border-radius: 10px;
  border: 1px dashed var(--border);
  background: var(--surface-2);
}

.page-realtime-control-panel .kitchain-empty-state h4 {
  margin: 0 0 6px;
  color: var(--text);
  font-size: 14px;
}

.page-realtime-control-panel .kitchain-empty-state p {
  margin: 0;
  color: var(--muted);
  font-size: 12px;
}

/* ── Traffic panel ───────────────────────────────────── */
.page-realtime-control-panel .panel-traffic {
  background: var(--surface);
  border-radius: 14px;
  box-shadow: var(--shadow-card);
  padding: 14px 20px;
  margin-bottom: 16px;
}

.page-realtime-control-panel .traffic-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
}

.page-realtime-control-panel .traffic-header h3 {
  margin: 0;
  font-size: 14px;
  color: var(--brand-dark);
}

.page-realtime-control-panel .traffic-agg-badge {
  display: inline-block;
  min-width: 80px;
  text-align: center;
  padding: 2px 8px;
  border-radius: 7px;
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}

.page-realtime-control-panel .traffic-bar-track-clear {
  height: 8px;
  border-radius: 4px;
  overflow: hidden;
}

.page-realtime-control-panel .traffic-bar-soax {
  height: 100%;
  border-radius: 4px;
  transition: width 0.4s ease;
}

/* Table */
.page-realtime-control-panel .traffic-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

.page-realtime-control-panel .traffic-table th {
  text-align: end;
  padding: 6px 8px;
  font-weight: 700;
  color: var(--muted);
  border-bottom: 2px solid var(--border-soft);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.3px;
}

.page-realtime-control-panel .traffic-table td {
  text-align: end;
  padding: 6px 8px;
  vertical-align: middle;
}

.page-realtime-control-panel .traffic-table td:nth-child(4),
.page-realtime-control-panel .traffic-table th:nth-child(4) {
  background: var(--danger-bg);
}

.page-realtime-control-panel .traffic-table tbody td {
  border-bottom: 1px solid var(--border-soft);
}

.page-realtime-control-panel .traffic-table .ta-left {
  text-align: start;
}

.page-realtime-control-panel .traffic-col-bars {
  width: 40%;
  min-width: 200px;
}

.page-realtime-control-panel .traffic-table tfoot td {
  border-top: 2px solid var(--border-soft);
  border-bottom: none;
  padding-top: 8px;
}

.page-realtime-control-panel .traffic-delta-up {
  color: var(--danger);
  font-weight: 600;
}

.page-realtime-control-panel .traffic-delta-down {
  color: var(--success);
  font-weight: 600;
}

.page-realtime-control-panel .traffic-delta-neutral {
  color: var(--muted);
}

.page-realtime-control-panel .traffic-empty {
  text-align: center;
  padding: 16px;
  color: var(--muted);
  font-size: 13px;
}

/* ── VPN Status panel ────────────────────────────────── */
.page-realtime-control-panel .panel-vpn-status {
  background: var(--surface);
  border-radius: 14px;
  box-shadow: var(--shadow-card);
  padding: 14px 20px;
  margin-bottom: 16px;
}

.page-realtime-control-panel .vpn-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}

.page-realtime-control-panel .vpn-header h3 {
  margin: 0;
  font-size: 14px;
  color: var(--brand-dark);
}

.page-realtime-control-panel .vpn-badge {
  padding: 2px 10px;
  border-radius: 8px;
  font-size: 11px;
  font-weight: 600;
}

.page-realtime-control-panel .vpn-badge.ok { background: var(--success-bg); color: var(--success-ink); }
.page-realtime-control-panel .vpn-badge.warn { background: var(--warn-bg); color: var(--warn-ink); }
.page-realtime-control-panel .vpn-badge.err { background: var(--danger-bg); color: var(--danger); }

.page-realtime-control-panel .vpn-country-grid {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.page-realtime-control-panel .vpn-country {
  display: flex;
  align-items: flex-start;
  gap: 8px;
}

.page-realtime-control-panel .vpn-country-label {
  font-size: 12px;
  font-weight: 700;
  color: var(--text);
  min-width: 48px;
  padding-top: 10px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

.page-realtime-control-panel .vpn-country-label .fi {
  width: 18px;
  height: 13.5px;
  border-radius: 2px;
  box-shadow: var(--shadow-card);
  flex-shrink: 0;
}

.page-realtime-control-panel .vpn-groups {
  display: flex;
  flex-wrap: wrap;
  gap: 2px 12px;
}

.page-realtime-control-panel .vpn-group {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1px;
}

.page-realtime-control-panel .vpn-group-label {
  font-size: 9px;
  font-weight: 600;
  color: var(--muted);
  letter-spacing: 0.02em;
  line-height: 1;
  text-transform: lowercase;
  white-space: nowrap;
}

.page-realtime-control-panel .vpn-dots {
  display: flex;
  gap: 4px;
  align-items: center;
}

.page-realtime-control-panel .vpn-dot {
  display: inline-block;   /* FIX: bare <span> in a <td> is inline by default → width/height ignored → invisible Status cell */
  vertical-align: middle;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  cursor: default;
  flex-shrink: 0;
  position: relative;
}

.page-realtime-control-panel .vpn-dot.alive {
  background: var(--success);
}

.page-realtime-control-panel .vpn-dot.down {
  background: var(--danger);
  animation: vpn-pulse 1.5s infinite;
  cursor: pointer;
}

.page-realtime-control-panel .vpn-dot.restarting {
  background: var(--warn);
  animation: vpn-pulse 1s infinite;
}

@keyframes vpn-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.4; }
}

.page-realtime-control-panel .country-groups {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.page-realtime-control-panel .country-group {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: var(--shadow-card);
  overflow: hidden;
}

.page-realtime-control-panel .country-head {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 13px 16px;
  user-select: none;
}

.page-realtime-control-panel .country-head::-webkit-details-marker {
  display: none;
}

.page-realtime-control-panel .country-head .fi {
  font-size: 18px;
  line-height: 1;
  border-radius: 3px;
  box-shadow: var(--shadow-card);
}

.page-realtime-control-panel .country-name {
  font-size: 17px;
  font-weight: 800;
  color: var(--brand-dark);
}

.page-realtime-control-panel .country-meta {
  font-size: 12px;
  color: var(--muted);
  font-weight: 700;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 4px 10px;
}

.page-realtime-control-panel .country-head .chev {
  margin-inline-start: auto;
  opacity: 0.6;
  font-size: 12px;
  color: var(--text);
  transition: transform 150ms ease;
}

.page-realtime-control-panel .country-group[open] > .country-head .chev {
  transform: rotate(180deg);
}

.page-realtime-control-panel .country-group[open] > .country-head {
  border-bottom: 1px solid var(--border-soft);
}

.page-realtime-control-panel .country-group > .city-cards {
  padding: 12px;
  background: var(--surface-2);
}

.page-realtime-control-panel .city-cards {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.page-realtime-control-panel .city-card {
  background: var(--surface);
  border-radius: 14px;
  box-shadow: var(--shadow-card);
  padding: 12px;
  transition: box-shadow 200ms ease;
}

.page-realtime-control-panel .city-card.is-loading {
  box-shadow: 0 2px 14px color-mix(in srgb, var(--brand) 35%, transparent);
}

.page-realtime-control-panel .city-card-head {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.page-realtime-control-panel .city-title {
  font-size: 17px;
  font-weight: 800;
  color: var(--brand-dark);
}

.page-realtime-control-panel .city-count {
  font-size: 12px;
  color: var(--muted);
  font-weight: 700;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 4px 10px;
  margin-inline-end: auto;
}

.page-realtime-control-panel .city-actions {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.page-realtime-control-panel .city-action-btn {
  appearance: none;
  border: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--text);
  font-size: 12px;
  font-weight: 700;
  padding: 6px 12px;
  border-radius: 8px;
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}

.page-realtime-control-panel .city-action-btn:hover {
  background: var(--success-bg);
  border-color: var(--success-border);
}

.page-realtime-control-panel .city-action-btn.is-active {
  background: var(--cta);
  border-color: var(--brand);
  color: var(--cta-text);
}

.page-realtime-control-panel .city-action-btn.is-active .city-action-count {
  color: var(--cta-text);
}

.page-realtime-control-panel .city-action-count {
  color: var(--muted);
  font-weight: 700;
  margin-inline-start: 2px;
}

.page-realtime-control-panel .city-hide-btn {
  background: var(--danger-bg);
  border-color: var(--danger-border);
  color: var(--danger);
}

.page-realtime-control-panel .city-hide-btn:hover {
  background: color-mix(in srgb, var(--danger-bg) 80%, var(--danger) 20%);
  border-color: var(--danger-border);
}

.page-realtime-control-panel .city-matrix-slot {
  margin-top: 10px;
}

.page-realtime-control-panel .city-matrix-slot:empty {
  margin-top: 0;
}

.page-realtime-control-panel .city-empty {
  padding: 18px;
  text-align: center;
  color: var(--muted);
  background: var(--surface-2);
  border: 1px dashed var(--border);
  border-radius: 10px;
  font-size: 13px;
}

.page-realtime-control-panel .matrix-wrap {
  overflow-x: auto;
}

.page-realtime-control-panel .matrix-table {
  width: max-content;
  min-width: 100%;
  border-collapse: separate;
  border-spacing: 0;
}

.page-realtime-control-panel .matrix-table th,
.page-realtime-control-panel .matrix-table td {
  border-inline-end: 1px solid var(--border-soft);
  border-bottom: 1px solid var(--border-soft);
  padding: 7px 8px;
  vertical-align: middle;
}

.page-realtime-control-panel .matrix-table th {
  position: sticky;
  top: 0;
  background: var(--surface-2);
  z-index: 2;
  text-align: center;
  font-size: 12px;
}

.page-realtime-control-panel .matrix-table th:first-child,
.page-realtime-control-panel .matrix-table td:first-child {
  border-inline-start: 1px solid var(--border-soft);
}

.page-realtime-control-panel .matrix-table tr:first-child th {
  border-top: 1px solid var(--border-soft);
}

.page-realtime-control-panel .agg-badge {
  height: 24px;
  padding: 0 8px;
  border-radius: 8px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.2px;
  white-space: nowrap;
  line-height: 1;
  box-shadow: var(--shadow-card);
  border: 1px solid var(--border);
}

.page-realtime-control-panel .sticky-col,
.page-realtime-control-panel .sticky-col-second {
  position: sticky;
  inset-inline-start: 0;
  z-index: 3;
  background: var(--surface-2);
}

.page-realtime-control-panel .sticky-col-second {
  inset-inline-start: 140px;
}

.page-realtime-control-panel .restaurant-name {
  min-width: 140px;
  max-width: 140px;
  background: var(--surface);
  z-index: 1;
  font-weight: 700;
  font-size: 14px;
  color: var(--text);
}

.page-realtime-control-panel .area-name {
  min-width: 80px;
  max-width: 80px;
  background: var(--surface);
  z-index: 1;
  color: var(--muted);
  font-weight: 600;
  font-size: 13px;
}

.page-realtime-control-panel .cell-content {
  min-width: 70px;
  display: flex;
  flex-direction: column;
  gap: 3px;
  align-items: center;
}

.page-realtime-control-panel .cell-state {
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.2px;
}

.page-realtime-control-panel .state-open { color: var(--success); }
.page-realtime-control-panel .state-closed { color: var(--danger); }
.page-realtime-control-panel .state-nodata { color: var(--muted); }

.page-realtime-control-panel .cell-time-link {
  color: inherit;
  text-decoration: none;
}
.page-realtime-control-panel .cell-time-link:hover {
  text-decoration: underline;
}
.page-realtime-control-panel .cell-time {
  font-size: 11px;
  color: var(--muted);
}

.page-realtime-control-panel .cell-placeholder {
  font-size: 14px;
  color: var(--muted);
  font-weight: 700;
}

.page-realtime-control-panel .cell-green { background: var(--success-bg); }
.page-realtime-control-panel .cell-yellow { background: var(--warn-bg); }
.page-realtime-control-panel .cell-red { background: var(--danger-bg); }
.page-realtime-control-panel .cell-gray { background: var(--border-soft); }

.page-realtime-control-panel .blinking {
  animation: rcp-blink 1.4s ease-in-out infinite;
}

@keyframes rcp-blink {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.4; }
}

.page-realtime-control-panel .empty-state {
  text-align: center;
  padding: 56px 20px;
  background: var(--surface);
  border-radius: 14px;
  box-shadow: var(--shadow-card);
  color: var(--muted);
}

@media (max-width: 1000px) {
  .page-realtime-control-panel .panel-grid {
    grid-template-columns: 1fr;
  }

  .page-realtime-control-panel .panel-kitchain,
  .page-realtime-control-panel .panel-queue {
    position: static;
  }

  .page-realtime-control-panel .sticky-col,
  .page-realtime-control-panel .sticky-col-second {
    position: static;
  }
}

.page-realtime-control-panel .agg-pill--default {
  background: var(--surface-3);
  color: var(--text);
}

/* Aggregator has a DB background colour but no paired text colour — fall back
   to the theme-invariant on-accent text instead of emitting a bare "color:;". */
.page-realtime-control-panel .agg-badge--on-accent {
  color: var(--on-accent);
}

.page-realtime-control-panel .traffic-bar-soax--default {
  background: var(--border-strong);
}

.page-realtime-control-panel .traffic-direct-alert,
.page-realtime-control-panel .traffic-total-alert {
  color: var(--danger);
  font-weight: 700;
}

.page-realtime-control-panel .vpn-empty {
  text-align: center;
  padding: 12px;
  color: var(--muted);
  font-size: 13px;
}

.page-realtime-control-panel .restaurant-name a {
  color: inherit;
  text-decoration: none;
}

/* ── Consumer Heartbeat ── */
.page-admin-consumers .container {
  max-width: 1720px;
  margin: 0 auto;
  padding: 24px;
}

.page-admin-consumers .panel-meta {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  align-items: center;
}
.page-admin-consumers .meta-chip {
  background: var(--success-bg);
  border: 1px solid var(--success-border);
  border-radius: 999px;
  padding: 6px 16px;
  font-size: 13px;
  color: var(--success-ink);
  font-weight: 600;
}
.page-admin-consumers .countdown-standalone {
  width: 82px;
  min-width: 82px;
  text-align: center;
  background: var(--success-bg);
  border: 1px solid var(--success-border);
  border-radius: 999px;
  padding: 6px 16px;
  font-size: 13px;
  color: var(--success-ink);
  font-weight: 600;
}
.page-admin-consumers .countdown-value {
  display: inline-block;
  min-width: 1.5em;
  text-align: center;
  font-variant-numeric: tabular-nums;
  font-weight: 800;
  color: var(--success-ink);
}

.page-admin-consumers .chb-card {
  background: var(--surface);
  border-radius: 14px;
  box-shadow: var(--shadow-card);
  padding: 0;
  overflow: hidden;
}

.chb-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}
.chb-table th,
.chb-table td {
  padding: 10px 14px;
  text-align: start;
  border-bottom: 1px solid var(--border-soft);
  white-space: nowrap;
}
.chb-table th {
  background: var(--surface-2);
  font-weight: 700;
  font-size: 11px;
  text-transform: uppercase;
  color: var(--muted);
  letter-spacing: 0.4px;
}
.chb-table tbody tr:hover { background: var(--bg); }

.chb-consumer-id { font-weight: 700; font-family: monospace; color: var(--brand-dark); }
.chb-time { font-family: monospace; font-size: 12px; color: var(--muted); }
.chb-num { text-align: end; font-family: monospace; }
.chb-failed { color: var(--danger); font-weight: 700; }

.chb-age { font-weight: 700; font-family: monospace; }
.chb-age-warning { color: var(--warn); }
.chb-age-danger { color: var(--danger); }

.chb-row-warning { background: var(--warn-bg) !important; }
.chb-row-warning:hover { background: color-mix(in srgb, var(--warn-bg) 80%, var(--warn) 20%) !important; }
.chb-row-danger { background: var(--danger-bg) !important; }
.chb-row-danger:hover { background: color-mix(in srgb, var(--danger-bg) 80%, var(--danger) 20%) !important; }
.chb-row-restarting { border-inline-start: 3px solid var(--brand); }

.chb-restart-badge {
  display: inline-block;
  background: var(--cta);
  color: var(--cta-text);
  font-size: 11px;
  font-weight: 700;
  padding: 3px 10px;
  border-radius: 10px;
}
.chb-restart-meta {
  display: block;
  font-size: 11px;
  color: var(--muted);
  margin-top: 2px;
}
.chb-restart-none { color: var(--muted); }

.chb-actions .btn-sm {
  font-size: 12px;
  padding: 5px 14px;
  border-radius: 8px;
}

.chb-empty {
  text-align: center;
  padding: 56px 20px;
  background: var(--surface);
  border-radius: 14px;
  box-shadow: var(--shadow-card);
  color: var(--muted);
  font-size: 15px;
}

@media (max-width: 1024px) {
  .chb-table { font-size: 12px; }
  .chb-table th,
  .chb-table td { padding: 8px 10px; }
}

/* ═══════════════════════════════════════════════
   ApexCharts chrome (toolbar / export menu) on tokens
   ═══════════════════════════════════════════════ */
/* ApexCharts injects its own stylesheet into <head> at runtime, AFTER app.css, so
   equal-specificity selectors would lose that cascade — these are raised on purpose.
   Values equal Apex's own light-theme defaults, so the light theme is unaffected. */
body .apexcharts-toolbar { background: transparent; }
.apexcharts-canvas .apexcharts-menu {
  background: var(--surface);
  border-color: var(--border);
  color: var(--text);
}
.apexcharts-canvas .apexcharts-menu-item:hover {
  background: var(--surface-2);
}

/* ═══════════════════════════════════════════════
   Daily Rating page
   ═══════════════════════════════════════════════ */

/* Base layout (pattern from downtime-patterns) */
.page-rating-daily .container { max-width: 1600px; margin: 0 auto; padding: 24px; }
/* Filter form */
.page-rating-daily .filter-form { background: var(--surface); border-radius: var(--radius-lg); padding: 24px; box-shadow: var(--shadow-card); margin-bottom: 24px; }
.page-rating-daily .filter-form h3 { font-size: 18px; margin-bottom: 16px; color: var(--text); }
.page-rating-daily .filter-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; margin-bottom: 16px; }
/* Direct child only — see status-by-id above. Multi-select styling comes from the shared
   component block near the top of this file; the page copy that used to live here
   duplicated it and, being declared later, beat .multi-select-option.ms-zero. */
.page-rating-daily .filter-group > label { display: block; font-size: 13px; font-weight: 600; color: var(--muted); margin-bottom: 6px; }
.page-rating-daily .filter-group > input:not([type="checkbox"]):not([type="radio"]) { width: 100%; padding: 10px; border: 2px solid var(--border-strong); border-radius: 8px; font-size: 14px; }
.page-rating-daily .filter-actions { margin-top: 16px; display: flex; gap: 12px; flex-wrap: wrap; }
.page-rating-daily .date-range-error { color: var(--danger); margin-bottom: 16px; }

/* Empty state */
.page-rating-daily .empty-state h3 { margin-bottom: 8px; color: var(--text); }

/* Zone distribution bar */
.page-rating-daily .zone-card { background: var(--surface); border-radius: var(--radius-lg); padding: 20px 24px; box-shadow: var(--shadow-card); margin-bottom: 24px; }
.page-rating-daily .zone-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.page-rating-daily .zone-header h3 { font-size: 16px; font-weight: 600; color: var(--text); margin: 0; }
.page-rating-daily .zone-header .zone-total { font-size: 13px; color: var(--muted); }
.page-rating-daily .zone-bar { display: flex; height: 44px; border-radius: 10px; overflow: hidden; cursor: pointer; }
.page-rating-daily .zone-segment { display: flex; align-items: center; justify-content: center; min-width: 40px; transition: filter 0.2s, transform 0.15s; position: relative; }
.page-rating-daily .zone-segment:hover { filter: brightness(1.1); transform: scaleY(1.08); z-index: 1; }
/* --text-inverse (not --on-accent, which stays white in both themes) because these
   fills (.zone--good/warn/caution/bad) get LIGHTER in dark theme. Shadow uses --appbar
   (theme-invariant dark surface), not --text, which would go pale in dark theme too. */
.page-rating-daily .zone-segment-label { font-size: 13px; font-weight: 700; color: var(--text-inverse); text-shadow: 0 1px 2px color-mix(in srgb, var(--appbar) 20%, transparent); white-space: nowrap; padding: 0 8px; }
.page-rating-daily .zone-segment-label small { font-weight: 500; opacity: 0.85; }
.page-rating-daily .zone-legend { display: flex; gap: 20px; margin-top: 10px; }
.page-rating-daily .zone-legend-item { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); cursor: pointer; }
.page-rating-daily .zone-legend-item:hover { color: var(--text); }
.page-rating-daily .zone-legend-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }
.page-rating-daily .zone-list { max-height: 0; overflow: hidden; transition: max-height 0.35s ease; }
.page-rating-daily .zone-list.open { max-height: 600px; }
.page-rating-daily .zone-list-inner { padding: 12px 0 4px; display: flex; flex-wrap: wrap; gap: 8px; }
.page-rating-daily .zone--good { background: var(--success); }
.page-rating-daily .zone--warn { background: var(--warn); }
.page-rating-daily .zone--caution { background: var(--caution); }
.page-rating-daily .zone--bad { background: var(--danger); }
.page-rating-daily .zone-chip { display: inline-flex; align-items: center; gap: 6px; background: var(--bg); border-radius: 8px; padding: 6px 12px; font-size: 13px; color: var(--text); border: 1px solid var(--border); }
.page-rating-daily .zone-chip .rating-badge { font-size: 11px; padding: 2px 6px; }
.page-rating-daily .zone-chip .trend-val { font-size: 11px; }
.page-rating-daily .text-sm { font-size: 13px; }

/* Granularity toggle */
.page-rating-daily .granularity-bar { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; position: sticky; top: 0; z-index: 20; background: var(--surface); padding: 12px 16px; border-bottom: 2px solid var(--brand); border-radius: 0 0 10px 10px; box-shadow: 0 4px 12px color-mix(in srgb, var(--text) 10%, transparent); }
.page-rating-daily .granularity-label { font-size: 14px; font-weight: 700; color: var(--brand); }
.page-rating-daily .granularity-toggle { display: flex; background: var(--bg); border-radius: 8px; padding: 3px; gap: 2px; box-shadow: inset 0 1px 3px color-mix(in srgb, var(--text) 8%, transparent); }
.page-rating-daily .granularity-btn { border: none; background: transparent; padding: 7px 16px; font-size: 13px; font-weight: 500; color: var(--muted); border-radius: 6px; cursor: pointer; transition: all 0.2s; }
.page-rating-daily .granularity-btn:hover { color: var(--text); }
.page-rating-daily .granularity-btn.active { background: var(--cta); color: var(--cta-text); font-weight: 600; box-shadow: 0 1px 4px color-mix(in srgb, var(--cta) 35%, transparent); }

/* KPI cards */
/* One row whatever the count (4 or 5 KPI cards) — auto-fit splits evenly.
   minmax(0, 1fr) + min-width: 0 обязательны: у голого 1fr минимальный размер
   колонки равен ширине её контента, поэтому длинные значения распирали сетку
   и карточки вылезали за пределы страницы. Тень оставлена из master (новее). */
.page-rating-daily .kpi-grid { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 16px; margin-bottom: 24px; align-items: stretch; }
/* With the New reviews card there are six: one row of six squeezed every card
   and cut its words, so they go three by two. The breakpoints below still win. */
.page-rating-daily .kpi-grid--six { grid-auto-flow: row; grid-template-columns: repeat(3, minmax(0, 1fr)); }
.page-rating-daily .kpi-card { min-width: 0; background: var(--surface); border-radius: var(--radius-lg); padding: 24px; box-shadow: var(--shadow-card); display: flex; flex-direction: column; min-height: 140px; }
.page-rating-daily .kpi-label { font-size: 13px; color: var(--muted); font-weight: 500; margin-bottom: 6px; text-transform: uppercase; letter-spacing: 0.3px; }
.page-rating-daily .kpi-value { font-size: 36px; font-weight: 700; color: var(--text); line-height: 1.1; }
.page-rating-daily .kpi-unit { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: .4px; }
.page-rating-daily .kpi-sub { font-size: 13px; color: var(--muted); margin-top: 4px; overflow-wrap: anywhere; }
.page-rating-daily .kpi-trend { font-size: 13px; font-weight: 600; margin-top: 4px; }
.page-rating-daily .kpi-trend-up { color: var(--success-ink); }
.page-rating-daily .kpi-trend-down { color: var(--danger); }
.page-rating-daily .kpi-sparkline { height: 40px; margin-top: auto; padding-top: 8px; }
.page-rating-daily .kpi-best .kpi-value { color: var(--success); }
.page-rating-daily .kpi-worst .kpi-value { color: var(--danger); }
.page-rating-daily .kpi-attention .kpi-value { color: var(--danger); }
.page-rating-daily .kpi-ok .kpi-value { color: var(--success); }
.page-rating-daily .kpi-link { color: var(--brand); text-decoration: none; font-weight: 600; }
.page-rating-daily .kpi-link:hover { text-decoration: underline; }

/* Heatmap scroll */
.page-rating-daily .heatmap-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; margin: 0 -8px; padding: 0 8px; }

/* Chart cards */
.page-rating-daily .chart-card { background: var(--surface); border-radius: var(--radius-lg); padding: 24px 24px 16px; box-shadow: var(--shadow-card); margin-bottom: 24px; }
.page-rating-daily .chart-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px; flex-wrap: wrap; gap: 8px; }
.page-rating-daily .chart-header h3 { font-size: 16px; font-weight: 600; color: var(--text); margin: 0; }
.page-rating-daily .chart-sub { font-size: 12px; color: var(--muted); }

/* Chart toggle pills */
.page-rating-daily .chart-toggle { display: flex; background: var(--bg); border-radius: 8px; padding: 3px; gap: 2px; }
.page-rating-daily .chart-toggle-btn { border: none; background: transparent; padding: 6px 14px; font-size: 13px; font-weight: 500; color: var(--muted); border-radius: 6px; cursor: pointer; transition: all 0.2s; }
.page-rating-daily .chart-toggle-btn.active { background: var(--surface); color: var(--brand); box-shadow: 0 1px 4px color-mix(in srgb, var(--text) 10%, transparent); font-weight: 600; }
.page-rating-daily .detailed-heatmap-toggle { margin-inline-start: auto; }

/* Export button. Text uses --text, not --appbar: --appbar is a dark SURFACE token in
   both themes, invisible against --surface-2 (also dark in dark theme). Hover keeps
   --appbar/--on-accent — that pairing stays theme-invariant (dark fill + white label). */
.page-rating-daily .rt-export-btn { display: inline-flex; align-items: center; gap: 4px; padding: 6px 12px; font-size: 12px; font-weight: 600; color: var(--text); background: var(--surface-2); border: 1px solid var(--border-strong); border-radius: 6px; cursor: pointer; text-decoration: none; transition: all 0.15s; margin-inline-start: auto; line-height: 1; letter-spacing: 0.1px; white-space: nowrap; }
.page-rating-daily .rt-export-btn:hover { background: var(--appbar); color: var(--on-accent); border-color: var(--appbar); }
.page-rating-daily .rt-export-btn:disabled { opacity: 0.4; cursor: not-allowed; pointer-events: none; }
.page-rating-daily .zone-header .rt-export-btn,
.page-rating-daily .attention-header .rt-export-btn { margin-inline-start: auto; }

/* Expand / Show all button — very visible, full-width under truncated block */
.page-rating-daily .rt-expand-wrap { margin-top: 14px; text-align: center; }
.page-rating-daily .rt-expand-btn {
    display: inline-block;
    padding: 10px 22px;
    font-size: 13px;
    font-weight: 700;
    color: var(--cta-text);
    background: var(--cta);
    border: none;
    border-radius: 8px;
    cursor: pointer;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    transition: all 0.15s;
    box-shadow: 0 2px 8px color-mix(in srgb, var(--cta) 35%, transparent);
}
.page-rating-daily .rt-expand-btn:hover { background: var(--cta-hover); box-shadow: 0 4px 12px color-mix(in srgb, var(--cta) 35%, transparent); transform: translateY(-1px); }
.page-rating-daily .rt-expand-btn:active { transform: translateY(0); }

/* Comparison table */
.page-rating-daily .comparison-wrap { overflow-x: auto; }
.page-rating-daily .comparison-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.page-rating-daily .comparison-table th { background: var(--surface-2); padding: 10px 14px; text-align: start; font-weight: 600; font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.3px; border-bottom: 2px solid var(--border); white-space: nowrap; }
.page-rating-daily .comparison-table th.sortable { cursor: pointer; }
.page-rating-daily .comparison-table th.sortable:hover { color: var(--brand); }
.page-rating-daily .comparison-table th.sort-asc::after { content: ' \25B2'; font-size: 10px; }
.page-rating-daily .comparison-table th.sort-desc::after { content: ' \25BC'; font-size: 10px; }
.page-rating-daily .comparison-table td { padding: 10px 14px; border-bottom: 1px solid var(--border-soft); vertical-align: middle; }
.page-rating-daily .comparison-table tbody tr:hover { background: var(--bg); }

/* Rating badges — deliberate 4-step status scale (distinct from the categorical
   palette), shared with the leaderboard/attention/no-rating tables below. */
.page-rating-daily .rating-badge { display: inline-block; padding: 3px 10px; border-radius: 12px; font-weight: 700; font-size: 13px; }
.page-rating-daily .badge-green { background: var(--success-bg); color: var(--success-ink); }
.page-rating-daily .badge-yellow { background: var(--warn-bg); color: var(--warn-ink); }
.page-rating-daily .badge-orange { background: var(--caution-bg); color: var(--caution); }
.page-rating-daily .badge-red { background: var(--danger-bg); color: var(--danger); }

/* Trend values */
.page-rating-daily .trend-val { font-weight: 600; font-size: 13px; }
.page-rating-daily .trend-up { color: var(--success-ink); }
.page-rating-daily .trend-down { color: var(--danger); }
.page-rating-daily .trend-na { color: color-mix(in srgb, var(--muted) 50%, var(--surface)); }

/* Table sparklines */
.page-rating-daily .table-sparkline { width: 100px; height: 30px; }

/* Rank column */
.page-rating-daily .rank-cell { font-weight: 700; color: var(--muted); font-size: 13px; width: 36px; text-align: center; }

/* Attention section */
.page-rating-daily .attention-card { background: var(--surface); border-radius: var(--radius-lg); padding: 24px; box-shadow: var(--shadow-card); margin-bottom: 24px; border-inline-start: 4px solid var(--warn); }
.page-rating-daily .attention-card.attention-ok { border-inline-start-color: var(--success); }
.page-rating-daily .attention-header { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.page-rating-daily .attention-header h3 { font-size: 16px; font-weight: 600; color: var(--text); margin: 0; }
.page-rating-daily .attention-ok .attention-header { margin-bottom: 8px; }
.page-rating-daily .attention-ok p { color: var(--muted); font-size: 14px; margin: 0; }
.page-rating-daily .ok-icon { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; background: var(--success-bg); color: var(--success-ink); border-radius: 50%; font-weight: 700; font-size: 16px; }
.page-rating-daily .attention-badge { background: var(--warn-bg); color: var(--warn-ink); font-size: 12px; font-weight: 700; padding: 3px 10px; border-radius: 12px; }
.page-rating-daily .attention-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.page-rating-daily .attention-table th { background: var(--warn-bg); padding: 8px 14px; text-align: start; font-weight: 600; font-size: 12px; color: var(--warn-ink); text-transform: uppercase; letter-spacing: 0.3px; border-bottom: 2px solid color-mix(in srgb, var(--warn) 35%, var(--surface)); white-space: nowrap; }
.page-rating-daily .attention-table td { padding: 10px 14px; border-bottom: 1px solid var(--warn-bg); vertical-align: middle; }
.page-rating-daily .attention-table tbody tr:hover { background: var(--warn-bg); }
.page-rating-daily .attn-name { font-weight: 600; }
.page-rating-daily .attn-date { font-size: 11px; color: var(--muted); margin-inline-start: 4px; }

/* Aggregator tag — background/text usually come from the aggregator's own DB
   colour (dynamic, inline); --default is only for rows where that's unset. */
.page-rating-daily .agg-tag { display: inline-block; padding: 2px 10px; border-radius: 10px; font-size: 12px; font-weight: 600; white-space: nowrap; }
.page-rating-daily .agg-tag--default { background: var(--surface-3); color: var(--text); }

/* No-rating section (informational, not a critical alert — neutral slate) */
.page-rating-daily .no-rating-card { background: var(--surface); border-radius: var(--radius-lg); padding: 24px; box-shadow: var(--shadow-card); margin-bottom: 24px; border-inline-start: 4px solid var(--muted); }
.page-rating-daily .no-rating-card.no-rating-ok { border-inline-start-color: var(--success); }
.page-rating-daily .no-rating-header { margin-bottom: 8px; }
.page-rating-daily .no-rating-badge { background: var(--surface-3); color: var(--muted); font-size: 12px; font-weight: 700; padding: 3px 10px; border-radius: 12px; }
.page-rating-daily .no-rating-note { color: var(--muted); font-size: 13px; margin: 0 0 14px; }
.page-rating-daily .no-rating-status-sub { font-size: 11px; color: var(--muted); margin-inline-start: 6px; }
.page-rating-daily .badge-gray { background: var(--surface-2); color: var(--muted); }
.page-rating-daily .badge-gray.no-rating-chronic { background: var(--danger-bg); color: var(--danger); }
.page-rating-daily .kpi-no-rating .kpi-value { color: var(--muted); }
.page-rating-daily .no-rating-table th { background: var(--surface-2); color: var(--muted); border-bottom: 2px solid var(--border-strong); }
.page-rating-daily .no-rating-table tbody tr:hover { background: var(--bg); }

/* New reviews: location × platform rows, one column per period. The location
   column stays put while a long day range scrolls sideways. */
.page-rating-daily .newrev-lead { color: var(--muted); font-size: 13px; margin: -8px 0 8px; }
.page-rating-daily .newrev-sum { font-size: 14px; font-weight: 600; color: var(--text); margin: 0 0 8px; }
.page-rating-daily .newrev-notes { margin: 0 0 14px; padding-inline-start: 18px; color: var(--muted); font-size: 13px; line-height: 1.5; }
.page-rating-daily .newrev-hint { color: var(--muted); font-size: 12px; margin: 10px 0 0; }
.page-rating-daily .newrev-table th.newrev-num,
.page-rating-daily .newrev-table td.newrev-num { text-align: center; white-space: nowrap; padding-inline: 8px; }
.page-rating-daily .newrev-table td.newrev-num { font-variant-numeric: tabular-nums; }
.page-rating-daily .newrev-table .newrev-loc { position: sticky; inset-inline-start: 0; z-index: 1; background: var(--surface); font-weight: 600; min-width: 140px; max-width: 220px; overflow-wrap: anywhere; }
.page-rating-daily .newrev-table th.newrev-loc { background: var(--surface-2); }
.page-rating-daily .newrev-table tr.newrev-first td { border-top: 2px solid var(--border-strong); }
.page-rating-daily .newrev-table tbody tr:first-child td { border-top: none; }
.page-rating-daily .newrev-table .newrev-zero { color: var(--muted); }
.page-rating-daily .newrev-table .newrev-dash,
.page-rating-daily .newrev-table .newrev-gap { color: color-mix(in srgb, var(--muted) 60%, var(--surface)); cursor: help; }
.page-rating-daily .newrev-table .newrev-total { font-weight: 700; border-inline-end: 1px solid var(--border-soft); }

/* Aggregator bars */
.page-rating-daily .agg-bars { display: flex; flex-direction: column; gap: 14px; padding: 4px 0; }
.page-rating-daily .agg-bar-row { display: flex; align-items: center; gap: 14px; }
.page-rating-daily .agg-bar-label { width: 100px; font-size: 14px; font-weight: 600; color: var(--text); text-align: end; flex-shrink: 0; }
.page-rating-daily .agg-bar-asof { display: block; font-size: 10px; font-weight: 500; color: color-mix(in srgb, var(--muted) 60%, var(--surface)); margin-top: 2px; text-transform: none; letter-spacing: 0; }
.page-rating-daily .agg-bar-track { flex: 1; height: 28px; background: var(--surface-2); border-radius: 6px; overflow: hidden; }
.page-rating-daily .agg-bar-fill { height: 100%; border-radius: 6px; transition: width 0.6s ease; min-width: 20px; }
.page-rating-daily .agg-bar-fill--default { background: var(--brand); }
.page-rating-daily .agg-bar-value { width: 140px; flex-shrink: 0; display: flex; flex-direction: column; }
.page-rating-daily .agg-bar-rating { font-size: 18px; font-weight: 700; color: var(--text); line-height: 1.2; }
.page-rating-daily .agg-bar-reviews { font-size: 12px; color: var(--muted); }

/* Responsive: rating daily */
@media (max-width: 1024px) {
  .page-rating-daily .kpi-grid { grid-auto-flow: row; grid-template-columns: repeat(2, 1fr); }
  .page-rating-daily .chart-header { flex-direction: column; align-items: flex-start; }
  .page-rating-daily .filter-grid { grid-template-columns: repeat(2, 1fr); }
  .page-rating-daily .zone-legend { flex-wrap: wrap; gap: 10px; }
  .page-rating-daily .agg-bar-label { width: 80px; font-size: 12px; }
  .page-rating-daily .agg-bar-value { width: 110px; }
  .page-rating-daily .agg-bar-rating { font-size: 15px; }
  .page-rating-daily .chart-toggle { flex-wrap: wrap; }
}

@media (max-width: 768px) {
  .page-rating-daily .container { padding: 16px; }
  .page-rating-daily .filter-grid { grid-template-columns: 1fr; }
  .page-rating-daily .filter-actions { flex-direction: column; align-items: stretch; }
  /* The sticky bar wraps into two rows at this width and eats the screen —
     let it scroll away with the page instead of pinning to the top. */
  .page-rating-daily .granularity-bar { flex-wrap: wrap; gap: 8px; position: static; box-shadow: none; border-radius: var(--radius); }
  .page-rating-daily .zone-header { flex-direction: column; align-items: flex-start; gap: 4px; }
  .page-rating-daily .zone-segment-label { font-size: 11px; }
  .page-rating-daily .zone-segment-label small { display: none; }
  .page-rating-daily .attention-table { font-size: 12px; }
  .page-rating-daily .attention-table th,
  .page-rating-daily .attention-table td { padding: 8px 8px; }
  .page-rating-daily .attention-header { flex-wrap: wrap; }
  .page-rating-daily .comparison-table { font-size: 12px; }
  .page-rating-daily .comparison-table th,
  .page-rating-daily .comparison-table td { padding: 8px 8px; }
}

@media (max-width: 600px) {
  .page-rating-daily .kpi-grid { grid-auto-flow: row; grid-template-columns: 1fr; }
  .page-rating-daily .kpi-card { min-height: auto; }
  .page-rating-daily .kpi-value { font-size: 28px; }
  .page-rating-daily .container { padding: 12px; }
  .page-rating-daily .filter-form,
  .page-rating-daily .chart-card,
  .page-rating-daily .zone-card,
  .page-rating-daily .attention-card { padding: 16px; border-radius: 10px; }
  .page-rating-daily .zone-bar { height: 36px; }
  .page-rating-daily .zone-chip { font-size: 12px; padding: 4px 8px; }
  .page-rating-daily .agg-bar-row { flex-wrap: wrap; gap: 6px; }
  .page-rating-daily .agg-bar-label { width: 100%; text-align: start; }
  .page-rating-daily .agg-bar-value { width: 100%; flex-direction: row; gap: 8px; align-items: baseline; }
  .page-rating-daily .newrev-table .newrev-loc { min-width: 96px; max-width: 128px; }
  .page-rating-daily .granularity-btn { padding: 6px 10px; font-size: 12px; }
  .page-rating-daily .rest-detail-selectors { flex-direction: column; }
  .page-rating-daily .rest-detail-selectors select { width: 100%; }
}

/* Restaurant Detail selectors */
.page-rating-daily .rest-detail-selectors {
    display: flex;
    gap: 12px;
    margin-bottom: 16px;
}
.page-rating-daily .rest-detail-selectors select {
    padding: 8px 12px;
    border: 1px solid var(--border-strong);
    border-radius: 8px;
    font-size: 13px;
    color: var(--text);
    background: var(--surface);
    min-width: 200px;
    cursor: pointer;
}
.page-rating-daily .rest-detail-selectors select:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* Detailed Rating Heatmap table */
.page-rating-daily .detailed-heatmap-wrap { border-radius: 8px; scrollbar-width: thin; max-height: 520px; overflow-x: auto; overflow-y: auto; }
.page-rating-daily .detailed-heatmap-wrap.is-expanded { max-height: none; }
.page-rating-daily .dh-message { padding: 12px; color: var(--muted); }
.page-rating-daily .dh-table { border-collapse: collapse; font-size: 12px; }
.page-rating-daily .dh-table thead { position: sticky; top: 0; z-index: 2; }
.page-rating-daily .dh-table th.dh-date { background: var(--surface-2); padding: 6px 4px; font-size: 10px; font-weight: 600; color: var(--muted); text-align: center; white-space: nowrap; border-bottom: 2px solid var(--border); }
.page-rating-daily .dh-table th.dh-label-col { background: var(--surface-2); position: sticky; inset-inline-start: 0; z-index: 3; min-width: 120px; border-bottom: 2px solid var(--border); }
.page-rating-daily .dh-group-row td { background: var(--surface-2); font-size: 12px; font-weight: 700; color: var(--text); padding: 6px 10px; position: sticky; inset-inline-start: 0; border-top: 2px solid var(--border-strong); white-space: nowrap; }
.page-rating-daily .dh-agg-name { padding-block: 4px; padding-inline: 20px 10px; font-size: 11px; font-weight: 500; color: var(--muted); white-space: nowrap; background: var(--surface); position: sticky; inset-inline-start: 0; z-index: 1; border-inline-end: 1px solid var(--border-soft); }
.page-rating-daily .dh-cell { padding: 4px 2px; text-align: center; font-size: 11px; font-weight: 600; min-width: 42px; white-space: nowrap; border-inline-end: 1px solid color-mix(in srgb, var(--surface) 30%, transparent); }

/* Heat levels (detailed heatmap DOM cells) — a brand-tinted gradient, distinct
   from the badge/attention 4-step status scale above. Both themes recolour
   automatically since color-mix reads --brand/--surface live. */
/* Plain --muted on --surface-3 is 4.23:1 in light (4.94 dark) — just under AA. A light
   15% nudge toward --text clears both (4.70:1 light / 5.62:1 dark) while keeping the
   "no data" cell reading as muted, not as regular body text. */
.page-rating-daily .hm-l0 { background: var(--surface-3); color: color-mix(in srgb, var(--text) 15%, var(--muted)); }
/* l1's --text already clears 4.5:1 on this pale tint in both themes. l2/l3 used
   --text-inverse (white in light mode) at only ~1.7:1/2.5:1 there — switched to
   --cta-text, with --hm-l2-fill nudging dark mode's brand share to clear 4.5:1 too. */
.page-rating-daily .hm-l1 { background: color-mix(in srgb, var(--brand) 25%, var(--surface)); color: var(--text); }
.page-rating-daily .hm-l2 { background: var(--hm-l2-fill); color: var(--cta-text); }
.page-rating-daily .hm-l3 { background: var(--brand); color: var(--cta-text); }

/* ═══════════════════════════════════════════════════════
   Schedule Discrepancies page
   ═══════════════════════════════════════════════════════ */
.page-schedule-discrepancies .container { max-width: 1600px; margin: 0 auto; padding: 24px; }
/* Filters */
.page-schedule-discrepancies .filter-form { background: var(--surface); border-radius: var(--radius-lg); padding: 24px; box-shadow: var(--shadow-card); margin-bottom: 24px; }
.page-schedule-discrepancies .filter-form h3 { font-size: 18px; margin-bottom: 16px; color: var(--text); }
.page-schedule-discrepancies .filter-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; margin-bottom: 16px; }
.page-schedule-discrepancies .filter-grid-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; margin-bottom: 16px; }
/* Direct child only. Without `>` this also hits every <label class="multi-select-option">
   inside the dropdown panels — they are labels in a .filter-group too — and (0,2,1) beats
   the component's own (0,2,0) rule, so option rows lose their flex row and get the field
   label's block/13px/600 instead: no gap after the checkbox, no room for the count badge. */
.page-schedule-discrepancies .filter-group > label { display: block; font-size: 13px; font-weight: 600; color: var(--muted); margin-bottom: 6px; }
.page-schedule-discrepancies .filter-group > input:not([type="checkbox"]):not([type="radio"]) { width: 100%; padding: 10px; border: 2px solid var(--border-strong); border-radius: 8px; font-size: 14px; }
/* No page-level copies of .multi-select/-toggle/-panel/-option here on purpose: they were
   identical to the global component rules but declared later, so
   `.multi-select-option.ms-zero { color }` lost to them and a zero-count option looked
   exactly like a populated one. Multi-select styling comes from the shared component
   block near the top of this file. */
/* Issue Type is a fixed list of eight named kinds, not a long searchable list of brands:
   show all eight at once and let the panel grow past the ~200px grid column, so a name
   like "Opens earlier than other aggregators" stays on one line. Anchored to the
   inline-end because this filter sits last in the row.
   Selector deliberately avoids the ".multi-select…" class names (targets the [data-name]
   attribute + the panel's structural position instead): this scope may not define its own
   copy of those classes — see ViewStyleContractTest::testNoScopedMultiSelectOverrides —
   and the shared partial only renders one <div> child (the panel) inside [data-name]. */
.page-schedule-discrepancies [data-name="type"] > div { inset-inline-start: auto; inset-inline-end: 0; min-width: min(360px, calc(100vw - 48px)); max-height: 400px; }
/* min() guard is load-bearing: anchored to the inline-end, a flat 360px panel hangs 25px
   off the screen edge on a 375px phone — the checkbox column is the part that's clipped. */
.page-schedule-discrepancies .filter-actions { margin-top: 16px; display: flex; gap: 12px; flex-wrap: wrap; }
/* No page-level .btn-secondary here on purpose (fix round 1): the view already carries
   `btn btn-secondary` and the shared .btn + .btn-secondary (app.css ~530) gives the same
   grey look on tokens — this copy was a literal-colour duplicate. */

/* Days of week (24.09.2026): seven real checkboxes drawn as one week strip beside the
   dates. The strip copies the field look — height, border, radius — so it reads as one
   more filter. All seven ticked = every day = no filter, and it looks plain; with some
   days unticked the ticked ones take the selected-filter tint (the chips' green) so a
   narrowed week shows at a glance. Specificity (0,4,0) on the row: the compact filter
   bar's own grid rule is (0,3,0) and sits at the end of the file. */
.page-schedule-discrepancies .filter-form .filter-grid-row.sd-when-row {
  grid-template-columns: minmax(150px, 1fr) minmax(150px, 1fr) minmax(0, 2.6fr);
  align-items: end;
}
.page-schedule-discrepancies .sd-days { position: relative; min-width: 0; }
.page-schedule-discrepancies .sd-days-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin-bottom: 6px; }
.page-schedule-discrepancies .sd-days-label { font-size: 13px; font-weight: 600; color: var(--muted); }
.page-schedule-discrepancies .sd-days-all { padding: 0; border: 0; background: none; font: inherit; font-size: 12px; font-weight: 600; color: var(--brand-dark); cursor: pointer; }
.page-schedule-discrepancies .sd-days-all:hover { text-decoration: underline; }
.page-schedule-discrepancies .sd-days-all:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 3px; }
.page-schedule-discrepancies .sd-days-all[hidden] { display: none; }
.page-schedule-discrepancies .sd-days-grid { display: flex; container-type: inline-size; border: 2px solid var(--border-strong); border-radius: 8px; background: var(--surface); overflow: hidden; }
.page-schedule-discrepancies .sd-day { position: relative; flex: 1 1 0; min-width: 0; display: flex; align-items: center; justify-content: center; gap: 6px; height: 37px; padding: 0 4px; border-inline-start: 1px solid var(--border-soft); color: var(--muted); font-size: 13px; font-weight: 600; line-height: 1.2; white-space: nowrap; cursor: pointer; user-select: none; transition: background-color .15s, color .15s; }
.page-schedule-discrepancies .sd-day:first-child { border-inline-start: 0; }
.page-schedule-discrepancies .sd-day:hover { background: var(--surface-2); }
/* The checkbox stays focusable (visually hidden, not display:none): Tab + Space work. */
.page-schedule-discrepancies .sd-day input { position: absolute; width: 1px; height: 1px; margin: 0; opacity: 0; pointer-events: none; }
.page-schedule-discrepancies .sd-day:has(input:focus-visible) { outline: 2px solid var(--brand); outline-offset: -3px; border-radius: 6px; }
.page-schedule-discrepancies .sd-day-box { position: relative; flex: none; width: 15px; height: 15px; border: 1.5px solid color-mix(in srgb, var(--muted) 45%, var(--surface)); border-radius: 4px; background: var(--surface); transition: background-color .15s, border-color .15s; }
.page-schedule-discrepancies .sd-day-name { overflow: hidden; text-overflow: ellipsis; }
.page-schedule-discrepancies .sd-day-count { font-size: 11px; font-weight: 700; color: color-mix(in srgb, var(--muted) 65%, var(--surface)); font-variant-numeric: tabular-nums; }
.page-schedule-discrepancies .sd-day.is-zero .sd-day-count { color: color-mix(in srgb, var(--muted) 40%, var(--surface)); }
.page-schedule-discrepancies .sd-day:has(input:checked) { color: var(--text); }
.page-schedule-discrepancies .sd-day:has(input:checked) .sd-day-box { background: var(--brand); border-color: var(--brand); }
/* The tick. Physical left: a check mark does not mirror in RTL. --text-inverse, not a
   fixed white: in the dark theme --brand turns light green and a white tick fades on it. */
.page-schedule-discrepancies .sd-day:has(input:checked) .sd-day-box::after { content: ""; position: absolute; left: 3.5px; top: 0.5px; width: 4px; height: 8px; border: solid var(--text-inverse); border-width: 0 2px 2px 0; transform: rotate(45deg); }
.page-schedule-discrepancies .sd-days.is-narrowed .sd-day:has(input:checked) { background: color-mix(in srgb, var(--cta) 22%, var(--surface)); }
.page-schedule-discrepancies .sd-days.is-narrowed .sd-day:has(input:checked) .sd-day-count { color: color-mix(in srgb, var(--brand-dark) 55%, var(--text)); }
.page-schedule-discrepancies .sd-days.is-narrowed .sd-day:not(:has(input:checked)) { color: color-mix(in srgb, var(--muted) 65%, var(--surface)); }
/* A narrow strip (phones): each day becomes a small tile — the box on top, the name and
   the count under it. Taller than the field on purpose: a finger needs ~44px to hit it. */
@container (max-width: 470px) {
  .page-schedule-discrepancies .sd-day { flex-direction: column; gap: 3px; height: auto; min-height: 50px; padding: 6px 1px; font-size: 12px; }
  .page-schedule-discrepancies .sd-day-box { width: 14px; height: 14px; }
  .page-schedule-discrepancies .sd-day:has(input:checked) .sd-day-box::after { left: 3px; top: 0; }
  .page-schedule-discrepancies .sd-day-name { max-width: 100%; text-overflow: clip; }
  .page-schedule-discrepancies .sd-day-count { font-size: 10px; line-height: 1; }
}
/* Inside .filter-form--compact (js/filter-compact.js) the fields are outlined boxes with the
   label sitting on the top border — the strip follows, with the "All days" link on that line.
   (Not titled like the end-of-file block: MobileCompactContractTest finds that one by name.) */
.page-schedule-discrepancies .filter-form--compact .sd-days-head { position: absolute; top: -7px; inset-inline: 9px; z-index: 2; margin: 0; pointer-events: none; }
.page-schedule-discrepancies .filter-form--compact .sd-days-label,
.page-schedule-discrepancies .filter-form--compact .sd-days-all { padding: 0 4px; background: var(--surface); font-size: 11px; line-height: 14px; }
.page-schedule-discrepancies .filter-form--compact .sd-days-label { color: var(--muted); letter-spacing: 0.2px; }
.page-schedule-discrepancies .filter-form--compact .sd-days-all { pointer-events: auto; }
.page-schedule-discrepancies .filter-form--compact .sd-days-grid { border: 1px solid var(--border-strong); border-radius: var(--radius-sm); }
.page-schedule-discrepancies .filter-form--compact .sd-day { height: 36px; border-inline-start-color: var(--border-soft); }
@container (max-width: 470px) {
  .page-schedule-discrepancies .filter-form--compact .sd-day { height: auto; }
}
@media (max-width: 900px) {
  .page-schedule-discrepancies .filter-form .filter-grid-row.sd-when-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .page-schedule-discrepancies .sd-days { grid-column: 1 / -1; }
}

/* Notice banner */
.page-schedule-discrepancies .notice-banner { background: var(--warn-bg); border: 1px solid var(--warn); border-radius: 10px; padding: 14px 20px; margin-bottom: 24px; font-size: 14px; color: var(--warn-ink); }
.page-schedule-discrepancies .notice-banner a { color: var(--brand-dark); font-weight: 600; }
/* Export refusal under the filter buttons (inside the form, so no bottom gap of its own). */
.page-schedule-discrepancies #sd-export-error { margin: 14px 0 0; }

/* Empty state — base box removed (fix round 1): duplicated the shared .empty-state
   (app.css ~591, Task 1) and, being scoped + later in the file, beat it outright,
   staying white/#777 in dark theme. */
.page-schedule-discrepancies .empty-state h3 { margin-bottom: 8px; color: var(--text); }
.page-schedule-discrepancies .empty-state.date-range-error { background: var(--danger-bg); border: 1px solid var(--danger-border); }

/* KPI cards */
.page-schedule-discrepancies .kpi-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; margin-bottom: 24px; }
.page-schedule-discrepancies .stat-card { background: var(--surface); border-radius: 15px; padding: 24px; box-shadow: var(--shadow-card); text-align: center; }
.page-schedule-discrepancies .stat-label { font-size: 14px; font-weight: 600; color: var(--muted); margin-bottom: 8px; }
.page-schedule-discrepancies .stat-value { font-size: 36px; font-weight: 700; }
/* Alert/ok colour per KPI (the "good" tier is shared; which alert colour a KPI uses
   for its ">0" tier depends on how severe that particular count is — see index.php). */
.page-schedule-discrepancies .stat-value--danger { color: var(--danger); }
.page-schedule-discrepancies .stat-value--caution { color: var(--caution); }
.page-schedule-discrepancies .stat-value--success { color: var(--success); }
.page-schedule-discrepancies .stat-value--accent { color: var(--success-ink); }

/* Severity legend */
.page-schedule-discrepancies .severity-legend { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 20px; margin-bottom: 20px; font-size: 13px; color: var(--muted); }
.page-schedule-discrepancies .severity-legend-item { display: flex; align-items: center; gap: 6px; }
.page-schedule-discrepancies .severity-dot { width: 10px; height: 10px; border-radius: 50%; display: inline-block; }
.page-schedule-discrepancies .severity-dot--severe { background: var(--danger); }
.page-schedule-discrepancies .severity-dot--moderate { background: var(--caution); }
/* Rows between the reporting threshold and the moderate band: listed, but not alarming. */
.page-schedule-discrepancies .severity-dot--minor { background: var(--muted); }
.page-schedule-discrepancies .severity-legend-end { margin-inline-start: auto; display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 8px 16px; }
.page-schedule-discrepancies .severity-legend-note { color: var(--muted); font-size: 12px; }

/* "Show Brand ID" switch: the Monitor's chip, sitting at the end of the legend row. The
   checkbox stays focusable (visually hidden, not display:none) so the chip works from the keyboard. */
.page-schedule-discrepancies .sd-view-chip { position: relative; display: inline-flex; align-items: center; gap: 6px; padding: 5px 12px; border: 1.5px solid var(--border); border-radius: 20px; cursor: pointer; font-size: 12px; font-weight: 600; color: var(--muted); white-space: nowrap; background: var(--surface); transition: all 0.15s; user-select: none; }
.page-schedule-discrepancies .sd-view-chip:hover { border-color: var(--brand); color: var(--brand); }
.page-schedule-discrepancies .sd-view-chip.active,
.page-schedule-discrepancies .sd-view-chip:has(input:checked) { background: var(--cta); color: var(--cta-text); border-color: var(--brand-dark); }
.page-schedule-discrepancies .sd-view-chip input { position: absolute; width: 1px; height: 1px; margin: 0; opacity: 0; pointer-events: none; }
.page-schedule-discrepancies .sd-view-chip:focus-within { outline: 2px solid var(--brand); outline-offset: 2px; }

/* Aggregator IDs behind "Show Brand ID" (public/js/listing-ids.js). They are in the markup at
   all times, popups included, and one class on <html> shows them, so with the switch off the
   page is unchanged. Not scoped to the page: the popup lives outside it. */
.kc-lid,
.kc-ids-line { display: none; }
.kc-ids-on .kc-lid { display: block; margin-top: 3px; font-family: 'SF Mono', SFMono-Regular, Consolas, monospace; font-size: 10.5px; font-weight: 600; line-height: 1.2; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Inside a comparison pill the ID takes a line of its own under the badge and the time. */
.kc-ids-on .kc-lid--pill { grid-column: 1 / -1; margin-top: 0; }
.kc-ids-on .kc-ids-line { display: flex; flex-wrap: wrap; gap: 6px 14px; margin: 6px 0 8px; }
.kc-ids-item { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; color: var(--text); }
.kc-ids-badge { display: inline-block; padding: 1px 6px; border-radius: 4px; font-size: 10px; font-weight: 600; line-height: 1.5; }
.kc-ids-val { font-family: 'SF Mono', SFMono-Regular, Consolas, monospace; font-weight: 600; font-variant-numeric: tabular-nums; }
.kc-ids-val--brand { font-family: inherit; font-weight: 500; color: var(--muted); }

/* Restaurant sections */
.page-schedule-discrepancies .rest-section { background: var(--surface); border-radius: 15px; box-shadow: var(--shadow-card); margin-bottom: 20px; overflow: hidden; }
.page-schedule-discrepancies .rest-header { display: flex; justify-content: space-between; align-items: center; padding: 16px 20px; background: var(--surface-2); border-bottom: 2px solid var(--border); }
.page-schedule-discrepancies .rest-header-info { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.page-schedule-discrepancies .rest-header-name { font-size: 16px; font-weight: 700; color: var(--text); margin: 0; }
.page-schedule-discrepancies .rest-header-location { font-size: 13px; color: var(--muted); }
/* The IDs line under the name, full width of the header. */
.page-schedule-discrepancies .rest-header-info .kc-ids-line { flex-basis: 100%; margin: 2px 0 0; }
.page-schedule-discrepancies .rest-header-count { font-size: 13px; font-weight: 600; color: var(--danger); background: var(--danger-bg); padding: 4px 12px; border-radius: 20px; white-space: nowrap; }

/* Discrepancy table (6 columns) */
/* The card has overflow:hidden (rounded corners) — the wrap is the scroller,
   otherwise the fixed-width Delta/Freq columns are clipped unreachable on phones. */
.page-schedule-discrepancies .disc-table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.page-schedule-discrepancies .disc-table { width: 100%; border-collapse: collapse; }
.page-schedule-discrepancies .disc-table th,
.page-schedule-discrepancies .disc-table td { padding: 10px 14px; border-bottom: 1px solid var(--border-soft); font-size: 13px; }
.page-schedule-discrepancies .disc-table th { background: transparent; font-weight: 600; color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; }
.page-schedule-discrepancies .col-day { width: 60px; text-align: center; }
.page-schedule-discrepancies .col-type { width: 120px; }
.page-schedule-discrepancies .col-agg { width: 110px; }
.page-schedule-discrepancies .col-expected { font-family: 'SF Mono', SFMono-Regular, Consolas, monospace; font-size: 13px; color: var(--muted); }
.page-schedule-discrepancies .col-actual { font-family: 'SF Mono', SFMono-Regular, Consolas, monospace; font-size: 13px; font-weight: 600; }
.page-schedule-discrepancies .col-delta { width: 90px; text-align: center; font-weight: 700; font-size: 13px; }
.page-schedule-discrepancies .col-freq { width: 50px; text-align: center; font-size: 13px; color: var(--muted); }
.page-schedule-discrepancies .time-label { font-family: 'Inter', sans-serif; font-size: 10px; font-weight: 600; text-transform: uppercase; color: var(--muted); letter-spacing: 0.03em; }
.page-schedule-discrepancies .offline-marker { font-family: 'Inter', sans-serif; font-size: 12px; font-weight: 600; color: var(--muted); font-style: italic; }
.page-schedule-discrepancies .col-cross-agg-detail { padding: 8px 14px; }
.page-schedule-discrepancies .cross-agg-desc { font-size: 12px; color: var(--muted); margin-bottom: 6px; }

/* Severity border-left */
.page-schedule-discrepancies .disc-row { border-inline-start: 4px solid transparent; }
.page-schedule-discrepancies .disc-row.severity--severe { border-inline-start-color: var(--danger); }
.page-schedule-discrepancies .disc-row.severity--moderate { border-inline-start-color: var(--caution); }
.page-schedule-discrepancies .disc-row.severity--minor { border-inline-start-color: var(--muted); }
.page-schedule-discrepancies .weekday-separator td { height: 0; border: none; padding: 0; border-top: 3px solid var(--border-strong); padding-top: 14px; }

/* Badges. Default bg/colour (var(--surface-3)/var(--text)) is what shows when the
   view's dynamic style="" is absent (no aggregator colour data) — see the aggregator
   colour lesson in index.php's sanitizeCssColor()/safeCssColor(). */
.page-schedule-discrepancies .agg-badge { display: inline-block; padding: 3px 10px; border-radius: 6px; font-size: 12px; font-weight: 600; background: var(--surface-3); color: var(--text); }
/* "All Aggregators" rest-level pseudo-badge — static, not data-driven. */
.page-schedule-discrepancies .agg-badge--all { background: var(--appbar); color: var(--on-accent); }
.page-schedule-discrepancies .type-badge { display: inline-block; padding: 3px 10px; border-radius: 6px; font-size: 11px; font-weight: 600; white-space: nowrap; }
.page-schedule-discrepancies .type-badge--late-open { background: var(--warn-bg); color: var(--warn-ink); }
.page-schedule-discrepancies .type-badge--early-close { background: var(--danger-bg); color: var(--danger); }
.page-schedule-discrepancies .type-badge--offline { background: var(--surface-3); color: var(--text); }
/* Cross-aggregator kinds keep the cool half of the palette (warm amber/red stays
   reserved for "off its own schedule"), one hue step apart so the four badges are
   still tellable apart at 11px: indigo → blue → violet → purple. Not a status
   severity — a tinted-fill/ink pair derived from the categorical tokens the same
   way app.css already does elsewhere (color-mix with --surface/--text), since
   --cat-N has no dedicated -bg/-ink pair of its own. Ink mixed at 60% (not the
   12%/75% used for the one existing precedent nearby): at 75% the two brightest
   hues (--cat-6 pink, --cat-7 cyan) read as low as 4.06:1/4.19:1 against their own
   tint in light mode — 60% clears AA (≥4.5:1) for all four hues in both themes
   (worst case 4.86:1 light / 6.69:1 dark, measured against real token hex values). */
.page-schedule-discrepancies .type-badge--cross-open-late { background: color-mix(in srgb, var(--cat-1) 12%, var(--surface)); color: color-mix(in srgb, var(--cat-1) 60%, var(--text)); }
.page-schedule-discrepancies .type-badge--cross-open-early { background: color-mix(in srgb, var(--cat-7) 12%, var(--surface)); color: color-mix(in srgb, var(--cat-7) 60%, var(--text)); }
.page-schedule-discrepancies .type-badge--cross-close-late { background: color-mix(in srgb, var(--cat-5) 12%, var(--surface)); color: color-mix(in srgb, var(--cat-5) 60%, var(--text)); }
.page-schedule-discrepancies .type-badge--cross-close-early { background: color-mix(in srgb, var(--cat-6) 12%, var(--surface)); color: color-mix(in srgb, var(--cat-6) 60%, var(--text)); }

/* Clickable rows */
.page-schedule-discrepancies .proof-row { cursor: pointer; transition: background 0.15s; }
.page-schedule-discrepancies .proof-row:hover { background: var(--surface-2); }
.page-schedule-discrepancies .detail-link { white-space: nowrap; color: var(--brand); }
.page-schedule-discrepancies .proof-row:hover .detail-link { text-decoration: underline; }

/* Cross-agg inline pills */
.page-schedule-discrepancies .cross-agg-inline { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.page-schedule-discrepancies .ca-pill { display: inline-flex; align-items: center; gap: 5px; padding: 3px 6px; border-radius: 6px; background: var(--surface-2); }
/* With IDs shown the pill turns into a two-row grid, badge and time on top, the ID under
   them, and keeps the width of its widest row (a wrapping flex row would not). */
.kc-ids-on .page-schedule-discrepancies .ca-pill { display: inline-grid; grid-template-columns: auto auto; column-gap: 5px; row-gap: 1px; }
.page-schedule-discrepancies .ca-pill--late { outline: 2px solid var(--danger); background: var(--caution-bg); }
.page-schedule-discrepancies .ca-pill-badge { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 600; background: var(--surface-3); color: var(--text); }
.page-schedule-discrepancies .ca-pill-time { font-family: 'SF Mono', SFMono-Regular, Consolas, monospace; font-size: 13px; font-weight: 600; }
.page-schedule-discrepancies .ca-pill:not(.ca-pill--late) { opacity: 0.6; }
.page-schedule-discrepancies .ca-pill:not(.ca-pill--late):hover { opacity: 1; }

/* Proof modal — #proofModal renders as a SIBLING of .page-schedule-discrepancies (after
   its closing </div> in index.php), never a descendant, so a `.page-schedule-discrepancies
   .proof-modal-*` selector would never match — these stay bare/global (covered by the
   '.proof-modal-' family in ScopedCssTokensTest::SCOPES, not by the page scope).
   Wave D Task 2: #proofModal/.proof-modal-panel also carry .kc-modal-backdrop/
   .kc-modal-panel (markup) — background/radius/shadow now come from that shared layer,
   this block keeps only proof-modal's own layout (JS still toggles the backdrop via
   inline style.display, unaffected by the shared class's default display:none). */
.proof-modal-panel { padding: 28px; max-width: 800px; width: 90vw; max-height: 85vh; overflow-y: auto; position: relative; }
.proof-modal-close { position: absolute; top: 12px; inset-inline-end: 16px; background: none; border: none; font-size: 28px; color: var(--muted); cursor: pointer; line-height: 1; }
.proof-modal-close:hover { color: var(--text); }

/* Proof popup content — built by JS in index.php (buildProofHTML / buildCrossAggProofHTML /
   buildScheduleProofHTML) into #proofContent, which sits inside #proofModal: a sibling of
   .page-schedule-discrepancies, not a descendant (see note above), so these are scoped to
   #proofContent rather than under the page class — a page-scoped selector here would never
   match. Covered by the '.sd-' family entry in ScopedCssTokensTest::SCOPES. */
#proofContent .sd-proof-title,
#proofContent .sd-accent { color: var(--success-ink); }
#proofContent .sd-proof-title { margin-bottom: 4px; }
#proofContent .sd-proof-sub { margin-bottom: 16px; color: var(--muted); font-size: 14px; }
#proofContent .sd-proof-sub--tight { margin-bottom: 4px; color: var(--muted); font-size: 14px; }
#proofContent .sd-proof-note { margin-bottom: 16px; color: var(--muted); font-size: 12px; }
#proofContent .sd-proof-heading { margin-bottom: 8px; }
#proofContent .sd-proof-empty,
#proofContent .sd-muted { color: var(--muted); }
#proofContent .sd-proof-tag { font-size: 11px; color: var(--success-ink); }

#proofContent .sd-proof-table { width: 100%; border-collapse: collapse; font-size: 13px; }
#proofContent .sd-proof-table--spaced { margin-bottom: 20px; }
#proofContent .sd-proof-table thead tr { background: var(--surface-2); }
#proofContent .sd-proof-table th,
#proofContent .sd-proof-table td { padding: 8px; text-align: center; }
/* First column (Date/Aggregator) reads start-aligned; every other column is a
   value/time/delta and stays centered — true for all three builders. */
#proofContent .sd-proof-table th:first-child,
#proofContent .sd-proof-table td:first-child { text-align: start; }
#proofContent .sd-proof-table tbody tr { border-bottom: 1px solid var(--border-soft); }
#proofContent .sd-proof-th-sched { font-size: 12px; color: var(--success-ink); }
#proofContent .sd-proof-th-note { font-size: 12px; line-height: 1.3; }
#proofContent .sd-nowrap { white-space: nowrap; }
#proofContent .sd-mono { font-family: 'SF Mono', SFMono-Regular, Consolas, monospace; }
#proofContent .sd-sched-cell { font-family: 'SF Mono', SFMono-Regular, Consolas, monospace; font-weight: 600; color: var(--success-ink); }

/* Threshold colours (≥60min bad, ≥30min late, else ok) — the same three-tier scale as
   the page's own .severity-dot-- and .disc-row.severity-- modifiers, kept in sync by using the same
   tokens. Always bold, so the tier is legible even at 13px in a dense grid. --ok uses
   --text rather than --muted: at 13px (below the large-text AA exception) --muted on
   --caution-bg (the .sd-row--late tint a same-row "ok" cell can share with a "late"
   sibling column) measures only 4.44:1, just under the 4.5:1 AA floor; --text clears
   9.27:1+ against every background this class can sit on.
   Two ancestors on purpose: the SAME $deltaColorClass/-class names come out of both
   index.php's server-rendered main table (.cross-agg-desc <strong>, td.col-delta —
   inside .page-schedule-discrepancies, plain surface / surface-2 on :hover) and the
   JS-built proof popup (inside #proofContent). A #proofContent-only rule left the
   main table's Δ/outlier colours unstyled. Contrast checked against both real
   backgrounds: danger/caution/text on surface 5.18–10.62:1 (light) / 5.82–13.16:1
   (dark), on the .proof-row:hover surface-2 tint 4.75–9.74:1 (light) / 5.82–11.86:1
   (dark) — all clear AA. */
.page-schedule-discrepancies .sd-delta--bad,
#proofContent .sd-delta--bad { font-weight: 700; color: var(--danger); }
.page-schedule-discrepancies .sd-delta--late,
#proofContent .sd-delta--late { font-weight: 700; color: var(--caution); }
.page-schedule-discrepancies .sd-delta--ok,
#proofContent .sd-delta--ok { font-weight: 700; color: var(--text); }
/* Row/column highlights. --late unifies two near-identical legacy tints (#fef9f5 in the
   day-by-day table, #fef5f5 in the cross-agg/schedule grids) that both meant "exceeds the
   ≥30min threshold" onto the one caution-bg token. */
#proofContent .sd-row--late { background: var(--caution-bg); }
#proofContent .sd-row--current { background: var(--success-bg); }
#proofContent .sd-col--selected { background: var(--caution-bg); }
#proofContent .sd-cell--empty { color: var(--border-strong); }
#proofContent .sd-cell--selected { font-weight: 600; }
/* The schedule builder's "starred" aggregator column (its own gold accent, distinct
   from the caution tint above — this is "this column is what the card is about", not
   an alert). --warn is the closest available token family to the original gold. */
#proofContent .sd-col--starred { background: var(--warn-bg); border-bottom: 2px solid var(--warn); }
#proofContent .sd-cell--starred-bg { background: var(--warn-bg); }
#proofContent .sd-star { font-size: 10px; color: var(--warn-ink); }

/* Aggregator colour chip: background/colour are data-driven and stay inline (the
   aggregator colour lesson — safeCssColor() returns '' on invalid/missing input, so an
   absent inline style falls back to this default rather than a hardcoded grey). */
#proofContent .sd-agg-chip { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 600; background: var(--surface-3); color: var(--text); }
#proofContent .sd-agg-chip--lg { font-size: 12px; }

/* Loading / error state for #proofContent itself while the fetch is in flight. */
#proofContent.sd-proof-loading { text-align: center; padding: 40px; color: var(--muted); }
#proofContent.sd-proof-error { color: var(--danger); }

/* Responsive */
@media (max-width: 1024px) {
  .page-schedule-discrepancies .kpi-grid { grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; }
  .page-schedule-discrepancies .stat-value { font-size: 28px; }
  .page-schedule-discrepancies .rest-header { flex-direction: column; align-items: flex-start; gap: 8px; }
}

@media (max-width: 768px) {
  .page-schedule-discrepancies .container { padding: 16px; }
  .page-schedule-discrepancies .filter-grid,
  .page-schedule-discrepancies .filter-grid-row,
  .page-schedule-discrepancies .filter-form:not(.filter-form--compact) .filter-grid-row.sd-when-row { grid-template-columns: 1fr; }
  /* One filter per row here, so the Issue Type panel has no narrow column to escape:
     drop the desktop widening and let it sit inside the card, labels wrapping. */
  .page-schedule-discrepancies [data-name="type"] > div { inset-inline-start: 0; inset-inline-end: 0; min-width: 0; }
  .page-schedule-discrepancies .filter-actions { flex-direction: column; align-items: stretch; }
  .page-schedule-discrepancies .kpi-grid { grid-template-columns: 1fr; }
  .page-schedule-discrepancies .stat-card { padding: 16px; }
  .page-schedule-discrepancies .stat-value { font-size: 28px; }
  .page-schedule-discrepancies .disc-table { font-size: 12px; min-width: 620px; }
  .page-schedule-discrepancies .cross-agg-inline { gap: 6px; }
  /* Bare rule only — see the "Proof modal" comment above on why the
     .page-schedule-discrepancies half of this selector was dead and dropped. */
  .proof-modal-panel { width: 95vw; padding: 20px; max-height: 90vh; }
}

/* Support FAB */
.support-fab {
  position: fixed;
  bottom: 20px;
  inset-inline-end: 20px;
  z-index: 900;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text);
  text-decoration: none;
  box-shadow: 0 2px 12px color-mix(in srgb, var(--text) 12%, transparent);
  transition: transform .2s ease, box-shadow .2s ease;
  cursor: pointer;
}
.support-fab:hover {
  transform: scale(1.08);
  box-shadow: 0 4px 16px color-mix(in srgb, var(--text) 18%, transparent);
}
.support-fab svg {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}
.support-fab-tooltip {
  position: absolute;
  inset-inline-end: calc(100% + 10px);
  top: 50%;
  transform: translateY(-50%);
  /* Always a dark bubble with light text, in both themes — same theme-invariant
     pairing as --on-accent (see tokens.css): --appbar stays a dark neutral in
     both :root and [data-theme="dark"], so the tooltip keeps working contrast
     regardless of the page's own theme. */
  background: var(--appbar);
  color: var(--on-accent);
  font-size: 13px;
  padding: 5px 10px;
  border-radius: 6px;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s;
}
.support-fab:hover .support-fab-tooltip {
  opacity: 1;
}
.support-fab-tooltip::after {
  content: '';
  position: absolute;
  inset-inline-start: 100%;
  top: 50%;
  transform: translateY(-50%);
  border: 5px solid transparent;
  border-inline-start-color: var(--appbar);
}

/* ===== Visibility (demo) ===== */
.page-visibility .filter-form { background: var(--surface); border-radius: 15px; padding: 24px; box-shadow: var(--shadow-card); margin-bottom: 24px; min-width: 0; }
.page-visibility .filter-form h3 { font-size: 18px; margin-bottom: 16px; color: var(--text); }
.page-visibility .filter-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; margin-bottom: 16px; }
.page-visibility .filter-group label { display: block; font-size: 13px; font-weight: 600; color: var(--muted); margin-bottom: 6px; }
.page-visibility .filter-group input:not([type="checkbox"]):not([type="radio"]), .page-visibility .filter-group select { width: 100%; padding: 10px; border: 2px solid var(--border-strong); border-radius: 8px; font-size: 14px; background: var(--surface); color: var(--text); }
.page-visibility .filter-actions { margin-top: 16px; display: flex; gap: 12px; flex-wrap: wrap; }
.page-visibility .filter-actions .btn-primary { background: var(--cta); color: var(--cta-text); border: none; padding: 10px 24px; border-radius: 8px; font-size: 14px; font-weight: 600; cursor: pointer; }
.page-visibility .filter-actions .btn-primary:hover { background: var(--cta-hover); }
/* --brand as plain text on --surface is ≈2.5:1 (fails AA) — a 50/50 mix with
   --text keeps the brand hue recognisable while clearing 4.5:1 in both themes. */
.page-visibility .filter-actions .btn-secondary { background: var(--surface); color: color-mix(in srgb, var(--brand) 50%, var(--text)); border: 2px solid var(--brand); padding: 8px 22px; border-radius: 8px; font-size: 14px; font-weight: 600; cursor: pointer; text-decoration: none; display: inline-block; }

.page-visibility .multi-select { position: relative; }
.page-visibility .multi-select-toggle { width: 100%; padding: 10px; border: 2px solid var(--border-strong); border-radius: 8px; font-size: 14px; background: var(--surface); color: var(--text); text-align: start; cursor: pointer; }
.page-visibility .multi-select-toggle:hover { border-color: var(--brand); }
.page-visibility .multi-select-toggle::after { content: "▾"; float: right; float: inline-end; color: var(--muted); }
.page-visibility .multi-select.open .multi-select-toggle::after { content: "▴"; }
.page-visibility .multi-select-panel { display: none; position: absolute; top: calc(100% + 4px); left: 0; right: 0; background: var(--surface); border: 2px solid var(--border-strong); border-radius: 8px; padding: 10px; max-height: 260px; overflow-y: auto; z-index: 50; box-shadow: var(--shadow-dropdown); }
.page-visibility .multi-select.open .multi-select-panel { display: block; }
.page-visibility .multi-select-option { display: flex; align-items: center; gap: 8px; padding: 6px 4px; font-size: 14px; color: var(--text); cursor: pointer; }
.page-visibility .multi-select-option:hover { background: var(--surface-2); }
.page-visibility .multi-select-option input { width: auto; min-width: 16px; flex-shrink: 0; accent-color: var(--brand); }
.page-visibility .multi-select-option.select-all { font-weight: 600; color: var(--brand); border-bottom: 1px solid var(--border); margin-bottom: 6px; padding-bottom: 8px; }

.page-visibility .granularity-bar { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; position: sticky; top: 0; z-index: 20; background: var(--surface); padding: 12px 16px; border-bottom: 2px solid var(--brand); border-radius: 0 0 10px 10px; box-shadow: 0 4px 12px color-mix(in srgb, var(--text) 10%, transparent); flex-wrap: wrap; }
.page-visibility .granularity-label { font-size: 14px; font-weight: 700; color: color-mix(in srgb, var(--brand) 50%, var(--text)); }
.page-visibility .granularity-toggle { display: flex; background: var(--bg); border-radius: 8px; padding: 3px; gap: 2px; box-shadow: inset 0 1px 3px color-mix(in srgb, var(--text) 8%, transparent); }
.page-visibility .granularity-btn { border: none; background: transparent; padding: 7px 16px; font-size: 13px; font-weight: 500; color: var(--muted); border-radius: 6px; cursor: pointer; transition: all 0.2s; }
.page-visibility .granularity-btn:hover { color: var(--text); }
.page-visibility .granularity-btn.active { background: var(--cta); color: var(--cta-text); font-weight: 600; box-shadow: 0 1px 4px color-mix(in srgb, var(--cta) 35%, transparent); }

.page-visibility .kpi-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 20px; margin-bottom: 24px; align-items: stretch; }
.page-visibility .kpi-card { background: var(--surface); border-radius: 15px; padding: 24px; box-shadow: var(--shadow-card); display: flex; flex-direction: column; min-height: 140px; min-width: 0; }
.page-visibility .kpi-label { font-size: 13px; color: var(--muted); font-weight: 500; margin-bottom: 6px; text-transform: uppercase; letter-spacing: 0.3px; }
.page-visibility .kpi-value { font-size: 36px; font-weight: 700; color: var(--text); line-height: 1.1; }
.page-visibility .kpi-sub { font-size: 13px; color: var(--muted); margin-top: 4px; }
.page-visibility .kpi-best .kpi-value { color: var(--success); }
.page-visibility .kpi-worst .kpi-value { color: var(--danger); }
.page-visibility .kpi-mini { display: flex; gap: 14px; font-size: 11px; color: var(--muted); margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border-soft); }
.page-visibility .kpi-mini b { display: block; font-size: 14px; color: var(--text); margin-top: 2px; font-weight: 700; }

.page-visibility .chart-card { background: var(--surface); border-radius: 15px; padding: 24px; box-shadow: var(--shadow-card); margin-bottom: 24px; min-width: 0; }
.page-visibility .chart-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 18px; flex-wrap: wrap; gap: 8px; }
.page-visibility .chart-title { font-size: 18px; font-weight: 600; margin: 0; color: var(--text); }
.page-visibility .chart-sub { color: var(--muted); font-size: 13px; margin-top: 4px; }
.page-visibility #trendChart { height: 380px; }

.page-visibility .tabs { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 16px; }
.page-visibility .agg-tab { background: var(--surface-2); border: 1px solid var(--border-strong); padding: 7px 14px; border-radius: 8px; cursor: pointer; font-size: 13px; color: var(--muted); font-weight: 500; }
.page-visibility .agg-tab.active { background: var(--cta); color: var(--cta-text); border-color: var(--cta-hover); font-weight: 600; }

.page-visibility .heatmap-grid { display: grid; gap: 3px; font-size: 11px; }
.page-visibility .heatmap-grid .col-h, .page-visibility .heatmap-grid .row-d { text-align: center; color: var(--muted); padding: 5px 2px; font-weight: 600; font-size: 11px; }
.page-visibility .heatmap-grid .row-d { text-align: start; padding-inline-start: 8px; }
.page-visibility .heatmap-grid .cell { text-align: center; padding: 8px 2px; color: var(--on-accent); border-radius: 4px; font-weight: 600; font-size: 11px; }

.page-visibility table.lb { width: 100%; border-collapse: collapse; font-size: 14px; }
.page-visibility table.lb th { text-align: start; padding: 12px; background: var(--bg); color: var(--muted); font-weight: 600; font-size: 12px; text-transform: uppercase; letter-spacing: 0.4px; border-bottom: 2px solid var(--border-strong); }
.page-visibility table.lb td { padding: 14px 12px; border-bottom: 1px solid var(--border-soft); }
.page-visibility table.lb tr.target { background: var(--success-bg); }
.page-visibility table.lb tr.target td:first-child::before { content: '★ '; color: var(--success-ink); font-size: 13px; }
.page-visibility table.lb tr.target td { font-weight: 600; }
/* Two green tiers, one token: mid rank/promo stays on the flat --success-bg tint;
   the stronger tier (top rank, flat-price promo) gets a deeper --success mix so the
   two are visually distinct again, both ≥4.5:1 with --success-ink in both themes. */
.page-visibility .rank-pill { display: inline-block; background: var(--success-bg); color: var(--success-ink); padding: 4px 11px; border-radius: 12px; font-weight: 600; font-size: 12px; }
.page-visibility .rank-pill.top { background: color-mix(in srgb, var(--success) 25%, var(--surface)); color: var(--success-ink); }
.page-visibility .rank-pill.bad { background: var(--danger-bg); color: var(--danger); }
.page-visibility .promo-tag { display: inline-block; padding: 3px 9px; border-radius: 5px; font-size: 11px; font-weight: 600; background: var(--surface-2); color: var(--muted); }
.page-visibility .promo-tag.bogo { background: var(--danger-bg); color: var(--danger); }
.page-visibility .promo-tag.pct { background: var(--success-bg); color: var(--success-ink); }
.page-visibility .promo-tag.flat { background: color-mix(in srgb, var(--success) 25%, var(--surface)); color: var(--success-ink); }
.page-visibility .promo-tag.free { background: var(--warn-bg); color: var(--warn-ink); }

.page-visibility .row-2 { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 24px; }
.page-visibility .h2h-row { display: grid; grid-template-columns: 170px minmax(0, 1fr) 56px; gap: 14px; align-items: center; margin-bottom: 11px; font-size: 13px; }
.page-visibility .h2h-name { color: var(--text); font-weight: 500; }
.page-visibility .h2h-bar { height: 24px; background: var(--surface-2); border-radius: 6px; position: relative; overflow: hidden; }
.page-visibility .h2h-bar-fill { height: 100%; border-radius: 6px; display: flex; align-items: center; padding-inline-start: 10px; font-size: 11px; font-weight: 600; }
/* --text-inverse on --success/--warn fails 4.5:1 in light (both fills are still
   fairly light there) — --cta-text (near-black, theme-invariant) reads on all four
   fill/theme combinations; --danger stays dark enough in light for white text, and
   its dark-theme fill is light enough for --text-inverse's dark flip either way. */
.page-visibility .h2h-bar-fill-bad { background: var(--danger); color: var(--text-inverse); }
.page-visibility .h2h-bar-fill-ok { background: var(--warn); color: var(--cta-text); }
.page-visibility .h2h-bar-fill-good { background: var(--success); color: var(--cta-text); }
.page-visibility .h2h-pct { text-align: end; font-weight: 700; font-size: 13px; }
.page-visibility .h2h-pct-bad { color: var(--danger); }
.page-visibility .h2h-pct-ok { color: color-mix(in srgb, var(--brand) 50%, var(--text)); }
.page-visibility .h2h-pct-good { color: var(--success-ink); }

@media (max-width: 1100px) {
    .page-visibility .kpi-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .page-visibility .row-2 { grid-template-columns: minmax(0, 1fr); }
}
/* Demo-visibility scroll wrappers (heatmap grid + leaderboard are wider than a
   phone) and the win-rate row compaction. */
.page-visibility .heatmap-scroll-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.page-visibility .heatmap-scroll-wrap #heatmap { min-width: 440px; }
.page-visibility .lb-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.page-visibility .lb-scroll .lb { min-width: 520px; }
@media (max-width: 480px) {
    .page-visibility .kpi-grid { grid-template-columns: minmax(0, 1fr); }
    .page-visibility .h2h-row { grid-template-columns: 110px minmax(0, 1fr) 48px; gap: 8px; }
    .page-visibility .h2h-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
}

/* ===== Promo Monitor (demo) ===== */
.page-promo-monitor .filter-form { background: var(--surface); border-radius: var(--radius-lg); padding: 24px; box-shadow: var(--shadow-card); margin-bottom: 24px; }
.page-promo-monitor .filter-form h3 { font-size: 18px; margin-bottom: 16px; color: var(--text); }
.page-promo-monitor .filter-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 16px; margin-bottom: 16px; }
/* Direct child only — see status-by-id above. */
.page-promo-monitor .filter-group > label { display: block; font-size: 13px; font-weight: 600; color: var(--muted); margin-bottom: 6px; }
.page-promo-monitor .filter-group > input:not([type="checkbox"]):not([type="radio"]), .page-promo-monitor .filter-group > select { width: 100%; padding: 10px; border: 2px solid var(--border-strong); border-radius: 8px; font-size: 14px; background: var(--surface); color: var(--text); }
.page-promo-monitor .filter-actions { margin-top: 16px; display: flex; gap: 12px; flex-wrap: wrap; }
/* Outline secondary button is deliberately different here (brand-outline, not the shared
   grey fill) — kept, literal background token'd. */
.page-promo-monitor .filter-actions .btn-secondary { background: var(--surface); color: var(--brand); border: 2px solid var(--brand); padding: 8px 22px; border-radius: 8px; font-size: 14px; font-weight: 600; cursor: pointer; text-decoration: none; display: inline-block; }

/* Multi-select styling comes from the shared component block near the top of this file
   (page copy removed here — Task 2: it duplicated the global look and, being declared
   later, beat .multi-select-option.ms-zero, un-muting zero-count options). */

.page-promo-monitor .kpi-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; margin-bottom: 24px; align-items: stretch; }
@media (max-width: 480px) {
  .page-promo-monitor .kpi-grid { grid-template-columns: 1fr; }
  .page-promo-monitor .kpi-card { padding: 16px 18px; min-height: 0; }
  .page-promo-monitor .snapshot-controls input[type="date"] { flex: 1 1 120px; }
}
.page-promo-monitor .kpi-card { background: var(--surface); border-radius: 15px; padding: 24px; box-shadow: var(--shadow-card); display: flex; flex-direction: column; min-height: 140px; }
.page-promo-monitor .kpi-label { font-size: 13px; color: var(--muted); font-weight: 500; margin-bottom: 6px; text-transform: uppercase; letter-spacing: 0.3px; }
.page-promo-monitor .kpi-value { font-size: 36px; font-weight: 700; color: var(--text); line-height: 1.1; }
/* Top-competitor KPI shows a name, not a number — too wide at the default 36px. */
.page-promo-monitor .kpi-value--sm { font-size: 18px; }
.page-promo-monitor .kpi-sub { font-size: 13px; color: var(--muted); margin-top: 4px; }
.page-promo-monitor .kpi-card.you .kpi-value { color: var(--brand); }
.page-promo-monitor .kpi-card.danger .kpi-value { color: var(--danger); }

.page-promo-monitor .chart-card { background: var(--surface); border-radius: 15px; padding: 24px; box-shadow: var(--shadow-card); margin-bottom: 24px; }
.page-promo-monitor .chart-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 18px; flex-wrap: wrap; gap: 8px; }
.page-promo-monitor .chart-title { font-size: 18px; font-weight: 600; margin: 0; color: var(--text); }
.page-promo-monitor .chart-sub { color: var(--muted); font-size: 13px; margin-top: 4px; }

.page-promo-monitor .alert-banner { padding: 14px 18px; border-radius: 10px; margin-bottom: 20px; display: flex; align-items: flex-start; gap: 12px; font-size: 14px; }
.page-promo-monitor .alert-banner.danger { background: var(--danger-bg); border-inline-start: 4px solid var(--danger); color: var(--danger); }
.page-promo-monitor .alert-banner.good { background: var(--success-bg); border-inline-start: 4px solid var(--success); color: var(--success-ink); }
.page-promo-monitor .alert-banner .icon { font-size: 20px; line-height: 1; }
.page-promo-monitor .alert-banner b { display: block; font-size: 14px; margin-bottom: 2px; }

.page-promo-monitor .spine-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.page-promo-monitor .spine-card { border: 1px solid var(--border); border-radius: 12px; padding: 16px; background: var(--bg); display: flex; flex-direction: column; min-height: 140px; }
.page-promo-monitor .spine-head { display: flex; justify-content: space-between; align-items: center; padding-bottom: 10px; margin-bottom: 10px; border-bottom: 1px solid var(--border); }
.page-promo-monitor .spine-agg { font-weight: 700; font-size: 13px; color: var(--text); text-transform: uppercase; letter-spacing: 0.3px; }
.page-promo-monitor .spine-count { background: var(--success-bg); color: var(--success-ink); padding: 3px 10px; border-radius: 10px; font-size: 11px; font-weight: 700; }
.page-promo-monitor .spine-count.paused { background: var(--danger-bg); color: var(--danger); }
.page-promo-monitor .spine-body { display: flex; flex-direction: column; gap: 8px; flex: 1; }
.page-promo-monitor .spine-promo { display: flex; gap: 10px; padding: 8px 10px; background: var(--surface); border-radius: 8px; border-inline-start: 3px solid var(--border); }
/* Promo-type palette — single source: tokens.css --cat-1..--cat-8 (Task 1). Mirrored
   by .drawer-item.<type> and .type-dot.<type> below so every consumer of a promo's
   type resolves to the same colour. */
.page-promo-monitor .spine-promo.bogo { border-inline-start-color: var(--cat-4); }
.page-promo-monitor .spine-promo.pct { border-inline-start-color: var(--cat-1); }
.page-promo-monitor .spine-promo.flat { border-inline-start-color: var(--cat-2); }
.page-promo-monitor .spine-promo.free { border-inline-start-color: var(--cat-3); }
.page-promo-monitor .spine-promo.combo { border-inline-start-color: var(--cat-5); }
.page-promo-monitor .spine-promo.loyalty { border-inline-start-color: var(--cat-6); }
.page-promo-monitor .spine-promo .type-lbl { font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.4px; color: var(--muted); min-width: 40px; line-height: 1.6; }
.page-promo-monitor .spine-promo .name-wrap { flex: 1; font-size: 12px; line-height: 1.4; color: var(--text); font-weight: 600; word-break: break-word; }
.page-promo-monitor .spine-promo .desc { font-size: 11px; color: var(--muted); margin-top: 2px; font-weight: 400; line-height: 1.35; }
.page-promo-monitor .spine-empty { font-size: 12px; color: var(--muted); font-style: italic; text-align: center; padding: 20px 0; }
/* Change-feed empty state needs more breathing room than the default .spine-empty
   padding — was a static style="padding:30px" in the view and in the drawer's
   empty-state JS; now a shared modifier. */
.page-promo-monitor .spine-empty--pad { padding: 30px; }
.page-promo-monitor .spine-paused { font-size: 11px; color: var(--danger); font-weight: 700; text-transform: uppercase; text-align: center; padding: 20px 10px; background: repeating-linear-gradient(45deg, transparent, transparent 6px, var(--danger-bg) 6px, var(--danger-bg) 12px); border-radius: 8px; letter-spacing: 0.4px; }

.page-promo-monitor .matrix-wrap { overflow-x: auto; }

/* min-width lets .matrix-wrap actually scroll on phones instead of crushing
   the 9% aggregator columns to unlabelable 26px slivers. */
.page-promo-monitor table.promo-matrix { width: 100%; min-width: 560px; border-collapse: collapse; font-size: 13px; table-layout: fixed; }
.page-promo-monitor table.promo-matrix colgroup col { width: 9%; }
.page-promo-monitor table.promo-matrix colgroup col.promo-col-head { width: 28%; }
.page-promo-monitor table.promo-matrix th { padding: 10px 4px; text-align: center; color: var(--muted); font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.3px; border-bottom: 2px solid var(--border); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.page-promo-monitor table.promo-matrix th:first-child { text-align: start; padding-inline-start: 14px; }
.page-promo-monitor table.promo-matrix td { padding: 10px 6px; border-bottom: 1px solid var(--border-soft); vertical-align: middle; }
.page-promo-monitor table.promo-matrix td.promo-col { padding: 12px 14px; }
.page-promo-monitor table.promo-matrix tr:hover td.promo-col { background: var(--bg); }
.page-promo-monitor table.promo-matrix tr.target-promo td.promo-col { background: var(--success-bg); border-inline-start: 3px solid var(--success); }
.page-promo-monitor table.promo-matrix tr.target-promo td { background: var(--success-bg); }
.page-promo-monitor table.promo-matrix tr.target-promo + tr.non-target td { border-top: 2px solid var(--border); }
.page-promo-monitor .promo-row-head { display: flex; align-items: flex-start; gap: 10px; }
/* Default: unknown promo type (defensive — see $typeDot fallback removed from the
   view). Overridden below by the six known .type-dot.<type> classes (promo-matrix)
   and by .target/.competitor (restaurant-matrix, not a promo type at all). */
.page-promo-monitor .promo-row-head .type-dot { width: 10px; height: 10px; border-radius: 50%; margin-top: 4px; flex-shrink: 0; background: var(--cat-8); }
.page-promo-monitor .promo-row-head .type-dot.bogo { background: var(--cat-4); }
.page-promo-monitor .promo-row-head .type-dot.pct { background: var(--cat-1); }
.page-promo-monitor .promo-row-head .type-dot.flat { background: var(--cat-2); }
.page-promo-monitor .promo-row-head .type-dot.free { background: var(--cat-3); }
.page-promo-monitor .promo-row-head .type-dot.combo { background: var(--cat-5); }
.page-promo-monitor .promo-row-head .type-dot.loyalty { background: var(--cat-6); }
/* Restaurant×Aggregator matrix: dot marks target vs. competitor, not a promo type. */
.page-promo-monitor .promo-row-head .type-dot.target { background: var(--success); }
.page-promo-monitor .promo-row-head .type-dot.competitor { background: var(--cat-1); }
.page-promo-monitor .promo-row-head .meta { flex: 1; min-width: 0; }
.page-promo-monitor .promo-row-head .name { font-size: 13px; font-weight: 600; color: var(--text); line-height: 1.35; word-break: break-word; }
.page-promo-monitor .promo-row-head .who { font-size: 11px; color: var(--muted); margin-top: 3px; }
.page-promo-monitor .promo-row-head .who.target { color: var(--success-ink); font-weight: 700; }
.page-promo-monitor .coverage-cell { width: 100%; height: 36px; display: flex; align-items: center; justify-content: center; border-radius: 6px; margin: 2px; }
/* .on and .on.target were two near-identical greens (#f0fadd/#33531a vs.
   #dcfce7/#15803d) pre-tokens — both read as "active promo here"; consolidated
   to the one --success pair, so .on.target no longer needs its own rule. */
.page-promo-monitor .coverage-cell.on { background: var(--success-bg); color: var(--success-ink); font-weight: 700; font-size: 12px; }
.page-promo-monitor .coverage-cell.off { color: var(--border-strong); font-size: 16px; }

.page-promo-monitor .feed-group { margin-bottom: 20px; }
.page-promo-monitor .feed-group:last-child { margin-bottom: 0; }
.page-promo-monitor .feed-group-title { font-size: 11px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: 0.6px; margin-bottom: 10px; padding-bottom: 6px; border-bottom: 1px solid var(--border); }
.page-promo-monitor .feed-item { display: grid; grid-template-columns: 32px 1fr auto; gap: 12px; padding: 12px 14px; background: var(--bg); border-radius: 10px; margin-bottom: 6px; align-items: center; font-size: 13px; }
.page-promo-monitor .feed-item.added { border-inline-start: 3px solid var(--success); }
.page-promo-monitor .feed-item.removed { border-inline-start: 3px solid var(--danger); }
.page-promo-monitor .feed-icon { width: 28px; height: 28px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 14px; font-weight: 700; }
.page-promo-monitor .feed-icon.added { background: var(--success-bg); color: var(--success-ink); }
.page-promo-monitor .feed-icon.removed { background: var(--danger-bg); color: var(--danger); }
.page-promo-monitor .feed-text b { color: var(--text); font-weight: 600; }
.page-promo-monitor .feed-text .faint { color: var(--muted); }
.page-promo-monitor .feed-time { font-size: 11px; color: var(--muted); }

@media (max-width: 1100px) {
    .page-promo-monitor .kpi-grid { grid-template-columns: repeat(2, 1fr); }
    .page-promo-monitor .spine-grid { grid-template-columns: 1fr; }
}

/* Promo Monitor: count cell (clickable, on Restaurant×Agg matrix) */
.page-promo-monitor .coverage-cell.count-cell { font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums; cursor: pointer; transition: transform 0.1s; }
.page-promo-monitor .coverage-cell.count-cell:hover { transform: scale(1.06); box-shadow: 0 2px 8px color-mix(in srgb, var(--text) 15%, transparent); }
.page-promo-monitor .coverage-cell.count-cell.off { cursor: default; }
.page-promo-monitor .coverage-cell.count-cell.off:hover { transform: none; box-shadow: none; }

/* Drawer */
.page-promo-monitor .drawer-overlay { display: none; position: fixed; inset: 0; background: var(--overlay); z-index: 100; }
.page-promo-monitor .drawer-overlay.open { display: block; }
.page-promo-monitor .drawer { position: fixed; top: 0; inset-inline-end: 0; bottom: 0; width: 480px; max-width: 100vw; background: var(--surface); z-index: 101; box-shadow: -10px 0 40px color-mix(in srgb, var(--text) 20%, transparent); transform: translateX(100%); transition: transform 0.25s; display: flex; flex-direction: column; }
.page-promo-monitor .drawer.open { transform: translateX(0); }
.page-promo-monitor .drawer-head { padding: 24px 28px 18px 28px; border-bottom: 1px solid var(--border); position: relative; }
.page-promo-monitor .drawer-close { position: absolute; top: 22px; inset-inline-end: 22px; background: transparent; border: none; font-size: 28px; cursor: pointer; color: var(--muted); line-height: 1; }
.page-promo-monitor .drawer-body { flex: 1; overflow-y: auto; padding: 20px 28px; }
.page-promo-monitor .drawer-item { padding: 14px 16px; background: var(--bg); border-radius: 10px; margin-bottom: 10px; border-inline-start: 3px solid var(--border); }
.page-promo-monitor .drawer-item.bogo { border-inline-start-color: var(--cat-4); }
.page-promo-monitor .drawer-item.pct { border-inline-start-color: var(--cat-1); }
.page-promo-monitor .drawer-item.flat { border-inline-start-color: var(--cat-2); }
.page-promo-monitor .drawer-item.free { border-inline-start-color: var(--cat-3); }
.page-promo-monitor .drawer-item.combo { border-inline-start-color: var(--cat-5); }
.page-promo-monitor .drawer-item.loyalty { border-inline-start-color: var(--cat-6); }
.page-promo-monitor .drawer-item .type-lbl { font-size: 10px; font-weight: 700; text-transform: uppercase; color: var(--muted); margin-bottom: 4px; }
.page-promo-monitor .drawer-item .name { font-size: 14px; font-weight: 600; color: var(--text); margin-bottom: 4px; word-break: break-word; }
.page-promo-monitor .drawer-item .desc { font-size: 13px; color: var(--muted); line-height: 1.5; }
.page-promo-monitor .drawer-item .cov { font-size: 11px; color: var(--muted); margin-top: 8px; padding-top: 8px; border-top: 1px dashed var(--border); }

/* Promo Monitor: snapshot bar — always a dark charcoal bar with light text/controls, in
   both themes (same theme-invariant --appbar/--on-accent pairing as .support-fab-tooltip
   above), so it keeps its own contrast regardless of the page's theme. */
.page-promo-monitor .snapshot-bar { background: var(--appbar); color: var(--on-accent); border-radius: 15px; padding: 20px 28px; margin-bottom: 24px; display: flex; align-items: center; gap: 24px; flex-wrap: wrap; box-shadow: 0 2px 4px color-mix(in srgb, var(--text) 8%, transparent), 0 8px 20px color-mix(in srgb, var(--text) 12%, transparent); }
.page-promo-monitor .snapshot-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; opacity: 0.8; margin-bottom: 4px; }
.page-promo-monitor .snapshot-date { font-size: 22px; font-weight: 700; letter-spacing: -0.3px; }
.page-promo-monitor .snapshot-info { flex: 1; min-width: 200px; }
.page-promo-monitor .snapshot-controls { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.page-promo-monitor .snapshot-nav { background: color-mix(in srgb, var(--on-accent) 15%, transparent); border: 1px solid color-mix(in srgb, var(--on-accent) 30%, transparent); color: var(--on-accent); width: 42px; height: 42px; border-radius: 10px; cursor: pointer; font-size: 20px; font-weight: 600; display: flex; align-items: center; justify-content: center; transition: background 0.15s; }
.page-promo-monitor .snapshot-nav:hover { background: color-mix(in srgb, var(--on-accent) 25%, transparent); }
.page-promo-monitor .snapshot-controls input[type="date"] { padding: 10px 12px; border: 1px solid color-mix(in srgb, var(--on-accent) 30%, transparent); background: color-mix(in srgb, var(--on-accent) 15%, transparent); color: var(--on-accent); border-radius: 10px; font-size: 14px; font-weight: 600; color-scheme: dark; }
.page-promo-monitor .snapshot-today { background: var(--cta); color: var(--cta-text); border: none; padding: 10px 18px; border-radius: 10px; font-size: 13px; font-weight: 700; cursor: pointer; }
.page-promo-monitor .snapshot-today:hover { background: var(--success-bg); }

.page-promo-monitor .historical-badge { display: inline-flex; align-items: center; gap: 6px; background: var(--warn-bg); color: var(--warn-ink); padding: 4px 12px; border-radius: 12px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; margin-inline-start: 10px; }
.page-promo-monitor .historical-badge::before { content: '📅'; }
.page-promo-monitor .live-badge { display: inline-flex; align-items: center; gap: 6px; background: var(--success-bg); color: var(--success-ink); padding: 4px 12px; border-radius: 12px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; margin-inline-start: 10px; }
.page-promo-monitor .live-badge::before { content: ''; width: 8px; height: 8px; background: var(--success); border-radius: 50%; animation: pulseDot 2s infinite; }
@keyframes pulseDot { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }

/* Snapshot date bar: prev/date/next/latest stay one row on phones (spec
   2026-09-23-mobile-menu-promo-monitor task 2). flex-wrap:nowrap + min-width:0 on the date
   input let it shrink instead of wrapping the nav buttons onto a second line — same
   technique as .ps-dt-nav / .mn-datebar. */
@media (max-width: 768px) {
    .page-promo-monitor .snapshot-bar { padding: 12px; gap: 12px; }
    .page-promo-monitor .snapshot-nav { width: 36px; height: 36px; flex-shrink: 0; }
    .page-promo-monitor .snapshot-controls { flex-wrap: nowrap; width: 100%; gap: 6px; }
    .page-promo-monitor .snapshot-controls input[type="date"] { flex: 1 1 auto; min-width: 0; }
    .page-promo-monitor .snapshot-today { flex-shrink: 0; white-space: nowrap; height: 36px; padding: 8px 12px; font-size: 11px; }
}

/* ===== Promo Snapshot v5 — Brand Guidelines =====
   --ps-* are aliases onto the real tokens (spec 2026-09-22-cabinets-ui-unification,
   wave D task 4) — no page-private colour values left; the handful with no 1:1 token
   (accent tints/border, the bright --ps-warn fill) are color-mix() off a real token. */
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@600;700;800&family=Inter:wght@400;500;600;700&display=swap');
.page-promo-snapshot {
  --ps-text: var(--text);
  --ps-muted: var(--muted);
  --ps-card: var(--surface);
  --ps-border: var(--border);
  --ps-bg: var(--bg);
  --ps-accent: var(--cat-1);
  --ps-accent-light: color-mix(in srgb, var(--ps-accent) 10%, var(--surface));
  --ps-accent-border: color-mix(in srgb, var(--ps-accent) 35%, var(--surface));
  --ps-danger: var(--danger);
  --ps-danger-light: var(--danger-bg);
  --ps-success: var(--cta);
  --ps-success-dark: var(--success-ink);
  /* No global token is this bright/saturated — mixed light enough that --ps-warn-dark
     text on top still clears 4.5:1 in the light theme (measured ~4.8:1). */
  --ps-warn: color-mix(in srgb, var(--warn) 25%, var(--surface));
  --ps-warn-dark: var(--warn-ink);
  --ps-warn-light: var(--warn-bg);
  --ps-warn-border: color-mix(in srgb, var(--warn) 45%, var(--surface));
  /* "This branch differs from the brand" row/cell highlight — a step lighter than the
     --ps-warn-light badge chip so the whole row tint doesn't compete with it. */
  --ps-diff-bg: color-mix(in srgb, var(--ps-warn-light) 55%, var(--surface));
  --ps-radius: var(--radius-lg);
  --ps-shadow: var(--shadow-card);
  --ps-font-title: 'Montserrat', sans-serif;
  --ps-font-body: 'Inter', sans-serif;
}
body:has(.page-promo-snapshot) { background: var(--bg) !important; }
/* (the app bar is now charcoal site-wide — no per-page header override needed) */
.page-promo-snapshot { font-family: var(--ps-font-body); color: var(--ps-text); }
.page-promo-snapshot .ps-wrap { max-width:1200px; margin:0 auto; padding:28px 24px; }

/* Card */
.page-promo-snapshot .ps-card { background:var(--ps-card); border-radius:var(--ps-radius); padding:24px; box-shadow:var(--ps-shadow); margin-bottom:20px; }
.page-promo-snapshot .ps-card-title { font-family:var(--ps-font-title); font-size:16px; font-weight:700; margin-bottom:2px; }
.page-promo-snapshot .ps-card-sub { font-size:12px; color:var(--ps-muted); margin-bottom:18px; }
/* Export buttons (#1/#2 card headers, #4 brand modal) + per-row history mini-form (#3).
   Text uses --text, not --appbar — see the .page-rating-daily .rt-export-btn comment
   above for why (--appbar is a dark surface token in both themes). */
.page-promo-snapshot .rt-export-btn { display:inline-flex; align-items:center; gap:4px; padding:6px 12px; font-size:12px; font-weight:600; color:var(--text); background:var(--surface-2); border:1px solid var(--border-strong); border-radius:6px; cursor:pointer; text-decoration:none; transition:all .15s; line-height:1; letter-spacing:.1px; white-space:nowrap; }
.page-promo-snapshot .rt-export-btn:hover { background:var(--appbar); color:var(--on-accent); border-color:var(--appbar); }
/* Export-button layout modifier — shared by all 3 float:inline-end copies (#1/#2/#4 headers) */
.page-promo-snapshot .ps-export-float { float:right; float:inline-end; margin-top:-4px; }
.page-promo-snapshot .ps-hist { display:inline-block; margin-top:4px; }
.page-promo-snapshot .ps-hist > summary { cursor:pointer; font-size:11px; font-weight:600; color:var(--brand-dark); list-style:none; user-select:none; }
.page-promo-snapshot .ps-hist > summary::-webkit-details-marker { display:none; }
.page-promo-snapshot .ps-hist[open] > summary { margin-bottom:6px; }
.page-promo-snapshot .ps-hist form { display:flex; flex-wrap:wrap; gap:6px; align-items:center; }
.page-promo-snapshot .ps-hist input[type=date] { font-size:11px; padding:3px 6px; border:1px solid var(--ps-border); border-radius:6px; }
.page-promo-snapshot .ps-hist .rt-export-btn { padding:4px 10px; }
/* Header */
.page-promo-snapshot .ps-hdr { display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:16px; }
.page-promo-snapshot .ps-hdr h2 { font-family:var(--ps-font-title); font-size:24px; font-weight:800; letter-spacing:-.5px; }
.page-promo-snapshot .ps-hdr p { font-size:14px; color:var(--ps-muted); margin-top:2px; }
.page-promo-snapshot .ps-dt-nav { display:flex; gap:6px; align-items:center; }
.page-promo-snapshot .ps-dt-nav form { display:flex; gap:6px; align-items:center; }
.page-promo-snapshot .ps-dt-btn { width:36px; height:36px; border-radius:10px; border:2px solid var(--ps-border); background:var(--ps-card); color:var(--ps-text); font-size:16px; font-weight:700; cursor:pointer; display:flex; align-items:center; justify-content:center; }
.page-promo-snapshot .ps-dt-btn:hover { border-color:var(--ps-accent); color:var(--ps-accent); }
.page-promo-snapshot .ps-dt-input { padding:8px 14px; border:2px solid var(--ps-border); border-radius:10px; font-family:var(--ps-font-body); font-size:13px; font-weight:600; }
.page-promo-snapshot .ps-dt-latest { padding:8px 18px; border-radius:10px; border:none; background:var(--ps-accent); color:var(--text-inverse); font-family:var(--ps-font-body); font-size:12px; font-weight:700; cursor:pointer; }

/* Filters */
.page-promo-snapshot .ps-flt-title { font-family:var(--ps-font-title); font-size:16px; font-weight:700; margin-bottom:14px; }
.page-promo-snapshot .ps-flt-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(160px,1fr)); gap:14px; margin-bottom:14px; }
.page-promo-snapshot .ps-flt-group label { display:block; font-size:11px; font-weight:600; color:var(--ps-muted); text-transform:uppercase; letter-spacing:.5px; margin-bottom:5px; }
.page-promo-snapshot .filter-group > label { display:block; font-size:11px; font-weight:600; color:var(--ps-muted); text-transform:uppercase; letter-spacing:.5px; margin-bottom:5px; }
.page-promo-snapshot .flt-chips { margin:0 0 12px; }
.page-promo-snapshot .ps-flt-actions .btn-primary { padding:9px 22px; border-radius:10px; font-size:13px; font-weight:700; }
.page-promo-snapshot .ps-flt-group select { width:100%; padding:9px 12px; border:2px solid var(--ps-border); border-radius:10px; font-family:var(--ps-font-body); font-size:13px; color:var(--ps-text); background:var(--ps-card); }
.page-promo-snapshot .ps-flt-group select:focus { border-color:var(--ps-accent); outline:none; }
.page-promo-snapshot .ps-flt-actions { display:flex; gap:8px; }

/* Alerts */
.page-promo-snapshot .ps-alert { background:var(--ps-card); border-radius:var(--radius); padding:14px 20px; box-shadow:var(--ps-shadow); margin-bottom:10px; display:flex; align-items:center; gap:14px; font-size:13px; }
.page-promo-snapshot .ps-alert-dng { border-inline-start:4px solid var(--ps-danger); }
.page-promo-snapshot .ps-alert-wrn { border-inline-start:4px solid var(--ps-warn); }
.page-promo-snapshot .ps-alert-icon { width:28px; height:28px; border-radius:50%; display:flex; align-items:center; justify-content:center; font-weight:800; font-size:13px; flex-shrink:0; font-family:var(--ps-font-title); }
.page-promo-snapshot .ps-alert-dng .ps-alert-icon { background:var(--ps-danger-light); color:var(--ps-danger); }
.page-promo-snapshot .ps-alert-wrn .ps-alert-icon { background:var(--ps-warn-light); color:var(--ps-warn-dark); }
.page-promo-snapshot .ps-alert-muted { opacity:.85; }
/* "Show all N alerts" wrap sits tighter than the shared .rt-expand-wrap default */
.page-promo-snapshot .ps-expand-tight { margin:8px 0 18px; }

/* Promo-discrepancies banner (0.) — was 4 static style="" attributes */
.page-promo-snapshot .ps-disc-banner { display:flex; align-items:center; gap:12px; margin-bottom:14px; padding:12px 18px; border-radius:14px; text-decoration:none; background:linear-gradient(90deg, var(--danger-bg), var(--surface)); border:1.5px solid var(--danger-border); box-shadow:0 2px 10px color-mix(in srgb, var(--danger) 10%, transparent); }
.page-promo-snapshot .ps-disc-banner-icon { font-size:18px; line-height:1; }
.page-promo-snapshot .ps-disc-banner-text { flex:1 1 auto; color:var(--ps-text); font-size:14px; font-weight:600; }
.page-promo-snapshot .ps-disc-banner-count { color:var(--danger); }
.page-promo-snapshot .ps-disc-banner-cta { color:var(--ps-accent); font-size:13px; font-weight:700; white-space:nowrap; }

/* Per-aggregator status badges next to the coverage ratio (collecting/uncollected/closed) */
.page-promo-snapshot .ps-agg-badge { display:inline-block; margin-inline-start:5px; font-size:9.5px; font-weight:800; border-radius:5px; padding:1px 6px; white-space:nowrap; vertical-align:middle; }
.page-promo-snapshot .ps-agg-badge--collecting { color:var(--caution); background:var(--caution-bg); }
.page-promo-snapshot .ps-agg-badge--uncollected { color:var(--ps-muted); background:var(--surface-3); }
.page-promo-snapshot .ps-agg-badge--closed { color:var(--ps-warn-dark); background:var(--ps-warn-light); }

/* Expand / Show all button — shared style across pages */
.page-promo-snapshot .rt-expand-wrap { margin-top:14px; text-align:center; }
.page-promo-snapshot .rt-expand-btn { display:inline-block; padding:10px 22px; font-size:13px; font-weight:700; color:var(--text-inverse); background:var(--ps-accent); border:none; border-radius:8px; cursor:pointer; text-transform:uppercase; letter-spacing:.4px; transition:all .15s; box-shadow:0 2px 8px color-mix(in srgb, var(--ps-accent) 25%, transparent); }
.page-promo-snapshot .rt-expand-btn:hover { background:color-mix(in srgb, var(--ps-accent) 80%, var(--text)); box-shadow:0 4px 12px color-mix(in srgb, var(--ps-accent) 35%, transparent); transform:translateY(-1px); }
.page-promo-snapshot .rt-expand-btn:active { transform:translateY(0); }

/* KPI */
.page-promo-snapshot .ps-kpi-row { display:grid; grid-template-columns:repeat(4,1fr); gap:16px; margin-bottom:20px; }
.page-promo-snapshot .ps-kpi { background:var(--ps-card); border-radius:var(--ps-radius); padding:22px 24px; box-shadow:var(--ps-shadow); }
.page-promo-snapshot .ps-kpi-good { border-bottom:3px solid var(--ps-success); }
.page-promo-snapshot .ps-kpi-lbl { font-size:11px; font-weight:600; color:var(--ps-muted); text-transform:uppercase; letter-spacing:.4px; margin-bottom:6px; }
.page-promo-snapshot .ps-kpi-val { font-family:var(--ps-font-title); font-size:34px; font-weight:800; line-height:1; letter-spacing:-1px; }
.page-promo-snapshot .ps-c-accent { color:var(--ps-accent); }
.page-promo-snapshot .ps-c-warn { color:var(--ps-warn-dark); }
.page-promo-snapshot .ps-c-muted { color:var(--ps-muted); }
.page-promo-snapshot .ps-kpi-sub { font-size:12px; color:var(--ps-muted); margin-top:4px; }
.page-promo-snapshot .ps-kpi-locked { cursor:pointer; position:relative; overflow:hidden; opacity:.7; transition:opacity .2s; }
.page-promo-snapshot .ps-kpi-locked:hover { opacity:.85; }
.page-promo-snapshot .ps-kpi-lock-svg { width:16px; height:16px; position:absolute; top:16px; inset-inline-end:16px; color:var(--ps-muted); }
.page-promo-snapshot .ps-kpi-blur { filter:blur(4px); user-select:none; pointer-events:none; }
.page-promo-snapshot .ps-kpi-locked .ps-kpi-val { font-size:18px; }
.page-promo-snapshot .ps-kpi-unlock { font-size:10px; color:var(--ps-muted); margin-top:8px; }
.page-promo-snapshot .ps-upsell-body-text { color:var(--ps-muted); font-size:13px; line-height:1.7; margin-bottom:20px; }
.page-promo-snapshot .ps-upsell-contact { font-size:12px; color:var(--ps-muted); }
.page-promo-snapshot .ps-bcp-locked-row { cursor:pointer; transition:all .2s; background:color-mix(in srgb, var(--cta) 12%, var(--surface)) !important; border:1px dashed color-mix(in srgb, var(--cta) 45%, var(--border)) !important; }
.page-promo-snapshot .ps-bcp-locked-row:hover { opacity:.75; }
.page-promo-snapshot .ps-locked-row-body { padding:10px 20px; display:flex; align-items:center; gap:8px; }
.page-promo-snapshot .ps-locked-row-svg { opacity:.4; }
.page-promo-snapshot .ps-locked-row-text { font-size:11px; color:var(--ps-muted); }

/* Agg badge */
.page-promo-snapshot .ps-agg { display:inline-flex; align-items:center; padding:3px 12px; border-radius:8px; font-size:11px; font-weight:700; letter-spacing:.2px; }
/* DB aggregator colour has no bg AND/OR no text field set — fall back to a class
   instead of a hard-coded hex (spec: per-field fallback, never both fields literal).
   Dark chip, not the categorical grey (that was --cat-8/--on-accent, 2.45:1) —
   --text/--surface invert correctly per theme: light ~10.6:1, dark ~13.2:1
   (computed, see task-4-report.md fix round 1). */
.page-promo-snapshot .ps-agg-default { background:var(--text); color:var(--surface); }

/* Discount pills */
.page-promo-snapshot .ps-pill { display:inline-block; padding:2px 9px; border-radius:8px; font-weight:700; font-size:10px; line-height:1.5; white-space:nowrap; }
.page-promo-snapshot .ps-pill-d20 { background:var(--info-bg); color:var(--info); }
.page-promo-snapshot .ps-pill-d30 { background:var(--success-bg); color:var(--success-ink); }
.page-promo-snapshot .ps-pill-d40 { background:var(--caution-bg); color:var(--caution); }
.page-promo-snapshot .ps-pill-d50 { background:var(--danger-bg); color:var(--danger); }
.page-promo-snapshot .ps-pill-flat { background:var(--ps-warn); color:var(--ps-warn-dark); }
/* Mechanic pills — restored to each one's ORIGINAL bold/tint character (not the
   uniform soft-tint this task first shipped), just expressed on tokens. Fill = the
   --cat-N closest to the old literal fill's hue; ink picked from
   on-accent/cta-text/text, whichever clears 4.5:1 in the light theme (darkened via
   color-mix toward --cta-text — fixed-dark in BOTH themes, unlike --text which
   flips light in dark mode — where the raw token alone didn't reach it); see
   task-4-report.md fix round 1 for the full before/after/ratio table, both themes. */
.page-promo-snapshot .ps-pill-fd { background:var(--cat-7); color:var(--cta-text); }
.page-promo-snapshot .ps-pill-bogo { background:color-mix(in srgb, var(--cat-5) 65%, var(--cta-text)); color:var(--on-accent); }
.page-promo-snapshot .ps-pill-scope { font-weight:600; border:1px solid; }
.page-promo-snapshot .ps-pill-scope-menu { background:var(--ps-accent-light); color:var(--ps-accent); border-color:var(--ps-accent-border); }
.page-promo-snapshot .ps-pill-scope-item { background:var(--ps-warn-light); color:var(--ps-warn-dark); border-color:var(--ps-warn-border); }
.page-promo-snapshot .ps-pill-cond { background:var(--surface-2); color:var(--ps-muted); font-weight:500; }
.page-promo-snapshot .ps-pill-ftu { background:color-mix(in srgb, var(--cat-5) 20%, var(--surface)); color:var(--text); }
.page-promo-snapshot .ps-pill-plus { background:color-mix(in srgb, var(--cat-6) 20%, var(--surface)); color:var(--text); }
.page-promo-snapshot .ps-pill-exp { background:var(--ps-warn); color:var(--ps-warn-dark); }

/* Offer block — clean list, thin divider between offers (no nested cards) */
.page-promo-snapshot .ps-ofr { display:flex; flex-direction:column; gap:3px; padding:6px 0; margin:0; background:transparent; border:none; border-bottom:1px solid color-mix(in srgb, var(--text) 7%, transparent); }
.page-promo-snapshot .ps-ofr:first-child { padding-top:0; }
.page-promo-snapshot .ps-ofr:last-child { padding-bottom:0; border-bottom:none; }
.page-promo-snapshot .ps-ofr-pills { display:flex; flex-wrap:wrap; gap:3px; align-items:center; }
/* Title — main color (was muted), 2-line clamp so long titles fit */
.page-promo-snapshot .ps-ofr-name { font-size:11px; color:var(--ps-text); margin:1px 0 0; line-height:1.3; font-weight:500; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; word-break:break-word; }
/* "+N more" link — click to expand hidden offers */
.page-promo-snapshot .ps-more { font-size:10px; color:var(--ps-accent); cursor:pointer; font-weight:600; margin-top:3px; padding:3px 7px; background:var(--ps-accent-light); border-radius:5px; display:inline-block; transition:all .15s; }
.page-promo-snapshot .ps-more:hover { background:var(--ps-accent); color:var(--text-inverse); }
/* Cells stay top-aligned even when row stretches (fixes empty space below short cells) */
.page-promo-snapshot table.ps-mt td.ps-td-p { vertical-align:top; }
/* Items inline tag — drill-down to modal */
.page-promo-snapshot .ps-tag-items { background:var(--ps-warn-light); color:var(--ps-warn-dark); font-weight:700; letter-spacing:.04em; cursor:pointer; border:1px solid var(--ps-warn-border); display:inline-flex; align-items:center; gap:3px; padding-block:1px; padding-inline:6px 7px; transition:all .15s; }
.page-promo-snapshot .ps-tag-items:hover { background:var(--ps-warn); border-color:var(--warn); transform:translateY(-1px); }
.page-promo-snapshot .ps-tag-items::after { content:'\203A'; font-weight:800; font-size:11px; line-height:1; }
/* Hidden-aggregators notice strip */
.page-promo-snapshot .ps-hidden-strip { display:flex; align-items:center; gap:10px; padding:9px 14px; background:var(--surface-2); border:1px dashed var(--border-strong); border-radius:8px; margin:0 0 14px; font-size:12px; color:var(--ps-muted); flex-wrap:wrap; }
.page-promo-snapshot .ps-hidden-strip strong { font-family:var(--ps-font-title); color:var(--ps-text); font-weight:700; font-size:11px; letter-spacing:.04em; text-transform:uppercase; }
.page-promo-snapshot .ps-hidden-strip .ps-hs-pills { display:flex; gap:6px; flex-wrap:wrap; }
.page-promo-snapshot .ps-hidden-strip .ps-hs-pills .ps-agg { opacity:.55; filter:grayscale(.4); font-size:10px; padding:2px 8px; }
.page-promo-snapshot .ps-hidden-strip .ps-hs-show-all { margin-inline-start:auto; font-size:11px; font-weight:600; color:var(--ps-accent); cursor:pointer; padding:4px 10px; border-radius:6px; background:var(--ps-accent-light); border:none; transition:all .15s; }
.page-promo-snapshot .ps-hidden-strip .ps-hs-show-all:hover { background:var(--ps-accent); color:var(--text-inverse); }

/* Brand Coverage Panels */
.page-promo-snapshot .ps-bcp { margin-bottom:14px; border:1px solid var(--ps-border); border-radius:var(--radius); background:var(--ps-bg); overflow:hidden; }
.page-promo-snapshot .ps-bcp-gap { border-color:var(--ps-danger); border-width:2px; }
.page-promo-snapshot .ps-bcp-hd { display:flex; justify-content:space-between; align-items:center; padding:14px 20px; background:var(--ps-card); border-bottom:1px solid var(--ps-border); }
.page-promo-snapshot .ps-bcp-name { font-family:var(--ps-font-title); font-weight:700; font-size:15px; }
.page-promo-snapshot .ps-bcp-meta { font-size:12px; color:var(--ps-muted); }
/* Ряд агрегаторов у бренда: колонка на агрегатор, минимум 180px (задаётся инлайном
   в index.php вместе с их числом). Без минимума при 5+ подключениях сумма min-content
   шапок (бейджи "not open yet"/"⏳ n/m" стоят с white-space:nowrap) превышает ~1100px
   доступной ширины карточки, fr раздаёт отрицательный остаток — и колонки без таких бейджей схлопываются
   в ленту шириной в один символ. Переполнение уводится в горизонтальную прокрутку,
   как в модалке ассортимента на /menu (.mn-mi-scroll), чтобы промо всех агрегаторов
   по-прежнему сравнивались по вертикали. */
.page-promo-snapshot .ps-bcp-cols { display:grid; gap:0; overflow-x:auto; overscroll-behavior-x:contain; }
.page-promo-snapshot .ps-bcp-cols::-webkit-scrollbar { height:8px; }
.page-promo-snapshot .ps-bcp-cols::-webkit-scrollbar-track { background:var(--surface-2); }
.page-promo-snapshot .ps-bcp-cols::-webkit-scrollbar-thumb { background:var(--border-strong); border-radius:4px; }
.page-promo-snapshot .ps-bcp-cols::-webkit-scrollbar-thumb:hover { background:var(--cat-8); }

.page-promo-snapshot .ps-bcp-col { padding:0 14px 12px; border-inline-end:1px solid var(--ps-border); border-bottom:1px solid var(--ps-border); cursor:pointer; transition:background .12s; }
.page-promo-snapshot .ps-bcp-col[data-agg]:hover { background:var(--ps-accent-light); }
.page-promo-snapshot .ps-bcp-col:last-child { border-inline-end:none; }
.page-promo-snapshot .ps-bcp-col-gap { background:var(--ps-danger-light); cursor:default; }
.page-promo-snapshot .ps-bcp-col-na { background:repeating-linear-gradient(45deg, var(--ps-bg), var(--ps-bg) 6px, var(--surface-2) 6px, var(--surface-2) 12px); cursor:default; }
.page-promo-snapshot .ps-cov-na { color:var(--ps-muted); font-weight:700; }
.page-promo-snapshot .ps-bcp-na-msg { color:var(--ps-muted) !important; text-transform:none !important; font-size:11px !important; font-weight:600 !important; letter-spacing:0 !important; font-style:italic; }
.page-promo-snapshot .ps-bcp-tot { font-size:10px; font-weight:500; color:var(--ps-muted); margin-inline-start:1px; }
.page-promo-snapshot .ps-bcp-ratio { white-space:nowrap; flex-shrink:0; }
.page-promo-snapshot .ps-bcp-cov { flex-wrap:wrap; row-gap:4px; }
/* Cell header — table TH style: tinted strip, centered, edge-to-edge */
/* flex-wrap обязателен: колонка теперь минимум 180px, а ряд «пилюля + соотношение +
   бейджи» шире — без переноса он вылезает за границы колонки и обрезается краем
   прокручиваемого ряда (ровно те бейджи, ради которых шапка и существует). */
.page-promo-snapshot .ps-bcp-col-hd { display:flex; flex-wrap:wrap; row-gap:4px; align-items:center; justify-content:center; gap:10px; padding:8px 10px; margin:0 -14px 10px; background:var(--ps-accent-light); border-bottom:2px solid var(--ps-accent-border); border-radius:0; }
.page-promo-snapshot .ps-bcp-col-gap .ps-bcp-col-hd { background:var(--danger-bg); border-bottom-color:var(--danger-border); }
.page-promo-snapshot .ps-bcp-col-na .ps-bcp-col-hd { background:var(--border); border-bottom-color:var(--cat-8); }
.page-promo-snapshot .ps-bcp-cov { display:flex; align-items:center; gap:6px; }
.page-promo-snapshot .ps-bcp-ratio { font-family:var(--ps-font-title); font-size:13px; font-weight:700; }
.page-promo-snapshot .ps-cov-full { color:var(--ps-success-dark); }
.page-promo-snapshot .ps-cov-partial { color:var(--ps-warn-dark); }
.page-promo-snapshot .ps-cov-zero { color:var(--ps-danger); }
.page-promo-snapshot .ps-bcp-bar { width:60px; height:5px; background:var(--surface-3); border-radius:3px; overflow:hidden; }
.page-promo-snapshot .ps-bcp-bar-fill { height:100%; border-radius:3px; }
.page-promo-snapshot .ps-bcp-bar-fill.ps-cov-full { background:var(--ps-success); border:1px solid var(--ps-success-dark); }
.page-promo-snapshot .ps-bcp-bar-fill.ps-cov-partial { background:var(--ps-warn); }
.page-promo-snapshot .ps-bcp-bar-fill.ps-cov-zero { background:var(--ps-danger); }
.page-promo-snapshot .ps-bcp-list { display:flex; flex-direction:column; gap:4px; }
.page-promo-snapshot .ps-bcp-promo { display:flex; align-items:baseline; gap:6px; font-size:12px; }
.page-promo-snapshot .ps-bcp-promo .ps-pill { flex-shrink:0; }
.page-promo-snapshot .ps-bcp-promo-name { color:var(--ps-text); white-space:normal; overflow-wrap:break-word; line-height:1.4; }
.page-promo-snapshot .ps-bcp-info { display:inline-flex; align-items:center; justify-content:center; width:20px; height:20px; border-radius:50%; background:var(--ps-accent-light); color:var(--ps-accent); font-size:11px; font-weight:700; cursor:pointer; margin-inline-start:4px; transition:all .15s; border:none; font-family:var(--ps-font-body); }
.page-promo-snapshot .ps-bcp-info:hover { background:var(--ps-accent); color:var(--text-inverse); }
.page-promo-snapshot .ps-varies { display:inline-block; padding:1px 7px; border-radius:6px; font-size:9px; font-weight:700; background:var(--ps-warn-light); color:var(--ps-warn-dark); text-transform:uppercase; letter-spacing:.3px; margin-inline-start:2px; }
.page-promo-snapshot .ps-td-diff { background:var(--ps-diff-bg) !important; border-inline-start-color:var(--ps-warn) !important; position:relative; }
.page-promo-snapshot .ps-td-p.ps-td-diff::after { content:'differs'; position:absolute; top:3px; inset-inline-end:4px; font-size:8px; font-weight:700; color:var(--ps-warn-dark); background:var(--ps-warn-light); padding:1px 5px; border-radius:4px; text-transform:uppercase; letter-spacing:.3px; }
.page-promo-snapshot .ps-bcp-none { font-size:12px; font-weight:700; color:var(--ps-danger); text-transform:uppercase; letter-spacing:.2px; }
.page-promo-snapshot .ps-item-deals-warn { font-size:11px; font-weight:700; color:var(--ps-danger); margin-top:3px; }

/* Main table */
.page-promo-snapshot .ps-tbl-wrap { overflow-x:auto; overflow-y:auto; max-height:78vh; position:relative; }
.page-promo-snapshot table.ps-mt { width:100%; border-collapse:collapse; table-layout:fixed; }
.page-promo-snapshot table.ps-mt thead th { position:sticky; top:0; z-index:5; }
.page-promo-snapshot table.ps-mt th { background:var(--surface-2); padding:10px 14px; text-align:start; font-size:11px; font-weight:600; color:var(--ps-muted); text-transform:uppercase; letter-spacing:.3px; border-bottom:2px solid var(--ps-border); white-space:nowrap; }
.page-promo-snapshot .ps-th-branch { width:160px; min-width:160px; max-width:160px; }
.page-promo-snapshot .ps-th-agg { text-align:center; width:185px; min-width:185px; max-width:185px; }
/* Narrow column for aggregators with 0 active promos — visible but compact */
.page-promo-snapshot .ps-th-agg.ps-th-narrow { width:88px; min-width:88px; max-width:88px; padding:10px 6px; }
.page-promo-snapshot .ps-th-agg.ps-th-narrow .ps-agg { font-size:9.5px; padding:3px 7px; }
.page-promo-snapshot .ps-td-p.ps-td-narrow { font-size:10px; padding:8px 6px; text-align:center; }
.page-promo-snapshot .ps-td-p.ps-td-narrow .ps-no-p { font-size:9.5px; letter-spacing:.04em; }
.page-promo-snapshot .ps-td-p.ps-td-narrow .ps-na { font-size:9px; padding:2px 5px; letter-spacing:.02em; word-break:break-word; }
.page-promo-snapshot .ps-td-p.ps-td-narrow .ps-no-data { font-size:9.5px; }
/* Header agg badges: minimum spacing between adjacent narrow columns */
.page-promo-snapshot table.ps-mt thead th { padding:10px 8px; }
.page-promo-snapshot table.ps-mt td { padding:10px 10px; border-bottom:1px solid var(--ps-border); vertical-align:top; font-size:12px; }
/* Branch column on every branch row gets a softer left-edge accent so the divider line continues over the sticky column */
.page-promo-snapshot table.ps-mt tbody tr:not(.ps-grp) td.ps-td-branch { border-bottom:1px solid var(--ps-border); }
.page-promo-snapshot table.ps-mt td.ps-td-p { word-wrap:break-word; overflow-wrap:break-word; position:relative; }
.page-promo-snapshot table.ps-mt tbody tr:hover { background:var(--ps-bg); }

/* Sticky Branch column — keeps context while scrolling horizontally */
.page-promo-snapshot table.ps-mt th.ps-th-branch,
.page-promo-snapshot table.ps-mt td.ps-td-branch {
    position:sticky;
    inset-inline-start:0;
    z-index:2;
    background:var(--ps-card);
    box-shadow:6px 0 8px -6px color-mix(in srgb, var(--text) 18%, transparent);
}
.page-promo-snapshot table.ps-mt th.ps-th-branch { background:var(--surface-2); top:0; z-index:6; }
.page-promo-snapshot table.ps-mt tbody tr:hover td.ps-td-branch { background:var(--ps-bg); }
.page-promo-snapshot table.ps-mt tr.ps-grp td.ps-td-branch,
.page-promo-snapshot table.ps-mt tr.ps-grp td:first-child { position:static; box-shadow:none; }

/* Right-edge fade — visual cue "more content this way" */
.page-promo-snapshot .ps-tbl-fade-r {
    position:absolute;
    top:0; inset-inline-end:0; bottom:0;
    width:60px;
    pointer-events:none;
    background:linear-gradient(to right, transparent, color-mix(in srgb, var(--surface) 95%, transparent));
    z-index:5;
    transition:opacity .2s;
}

/* Per-country section label above the branch table (multi-country accounts only) —
   was an orphaned, unscoped fragment ~370 lines away (app.css); merged back here and
   scoped like the rest of the dialect. Its --ps-fg fallback was never declared
   anywhere, so it always rendered its #1f2d3d fallback — now the real page ink. */
.page-promo-snapshot .ps-btbl-country { font-weight:700; font-size:13px; color:var(--ps-text); margin:14px 0 6px; }
.page-promo-snapshot .ps-btbl-sec + .ps-btbl-sec { margin-top:6px; }

/* Aggregator jump-to-column pills above table */
.page-promo-snapshot .ps-tbl-nav { display:flex; align-items:center; flex-wrap:wrap; gap:8px; margin:6px 0 14px; padding:10px 14px; background:var(--surface-2); border-radius:8px; }
.page-promo-snapshot .ps-tbl-nav-lbl { font-size:11px; font-weight:700; color:var(--ps-muted); text-transform:uppercase; letter-spacing:.3px; margin-inline-end:4px; }
.page-promo-snapshot .ps-tbl-nav-pill { border:none; padding:5px 12px; border-radius:14px; font-size:11px; font-weight:700; cursor:pointer; transition:all .15s; opacity:.85; box-shadow:0 1px 3px color-mix(in srgb, var(--text) 8%, transparent); }
.page-promo-snapshot .ps-tbl-nav-pill:hover { opacity:1; transform:translateY(-1px); box-shadow:0 2px 6px color-mix(in srgb, var(--text) 15%, transparent); }
.page-promo-snapshot .ps-tbl-nav-pill:active { transform:translateY(0); }
.page-promo-snapshot .ps-tbl-nav-hint { margin-inline-start:auto; font-size:11px; color:var(--ps-muted); font-style:italic; }

/* Group header */
.page-promo-snapshot .ps-grp td { background:var(--ps-accent-light) !important; padding:12px 14px !important; border-bottom:2px solid var(--ps-accent-border) !important; }
.page-promo-snapshot .ps-grp-name { font-family:var(--ps-font-title); font-weight:700; font-size:13px; color:var(--ps-accent); }
.page-promo-snapshot .ps-grp-info { font-size:11px; color:var(--ps-muted); margin-inline-start:10px; }
.page-promo-snapshot .ps-grp-cov { font-size:10px; font-weight:700; margin-inline-start:8px; }
.page-promo-snapshot .ps-cov-ok { color:var(--ps-success-dark); }
.page-promo-snapshot .ps-cov-no { color:var(--ps-danger); }
.page-promo-snapshot .ps-cov-na { color:var(--cat-8); font-weight:500; }

/* Branch cell */
.page-promo-snapshot .ps-br-nm { font-weight:600; font-size:13px; display:block; }
.page-promo-snapshot .ps-br-loc { display:block; font-size:11px; color:var(--ps-muted); margin-top:1px; }

/* Promo cell */
.page-promo-snapshot .ps-td-p { border-inline-start:1px solid var(--surface-3); padding:9px 12px !important; }
.page-promo-snapshot .ps-td-has { background:var(--success-bg); border-inline-start:3px solid var(--success-border); }
.page-promo-snapshot .ps-td-none { background:var(--ps-danger-light); border-inline-start:3px solid var(--ps-danger); }
.page-promo-snapshot .ps-no-p { font-size:11px; font-weight:700; color:var(--ps-danger); text-transform:uppercase; letter-spacing:.2px; }
.page-promo-snapshot .ps-no-data { font-size:11px; color:var(--cat-8); font-style:italic; }
/* "Collecting…" — current-day data still being gathered (calm blue, not an alarm). */
.page-promo-snapshot .ps-no-data.ps-collecting,
.page-promo-snapshot .ps-bcp-na-msg.ps-bcp-collecting { color:var(--ps-accent) !important; font-style:italic; }
.page-promo-snapshot .ps-bcp-na-msg.ps-bcp-collecting { font-weight:600 !important; }
.page-promo-snapshot .ps-td-na { background:repeating-linear-gradient(45deg, var(--ps-bg), var(--ps-bg) 6px, var(--surface-2) 6px, var(--surface-2) 12px); border-inline-start:3px solid var(--border-strong); }
.page-promo-snapshot .ps-td-missing { background:var(--ps-bg); border-inline-start:3px solid var(--ps-border); }
.page-promo-snapshot .ps-na { font-size:9.5px; font-weight:600; color:var(--ps-muted); text-transform:uppercase; letter-spacing:.04em; background:var(--ps-border); padding:3px 7px; border-radius:4px; display:inline-block; max-width:100%; white-space:normal; word-break:break-word; line-height:1.3; }

/* Feed */
.page-promo-snapshot .ps-fd-title { font-size:10px; font-weight:700; color:var(--ps-muted); text-transform:uppercase; letter-spacing:.6px; margin-bottom:10px; padding-bottom:6px; border-bottom:1px solid var(--ps-border); }
.page-promo-snapshot .ps-fd { display:flex; gap:12px; padding:10px 14px; background:var(--ps-bg); border-radius:10px; margin-bottom:6px; align-items:center; font-size:12px; }
.page-promo-snapshot .ps-fd-add { border-inline-start:3px solid var(--ps-success-dark); }
.page-promo-snapshot .ps-fd-rem { border-inline-start:3px solid var(--ps-danger); }
.page-promo-snapshot .ps-fd-dot { width:24px; height:24px; border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:12px; font-weight:800; flex-shrink:0; font-family:var(--ps-font-title); }
.page-promo-snapshot .ps-fd-dot.ps-fd-add { background:var(--success-bg); color:var(--ps-success-dark); }
.page-promo-snapshot .ps-fd-dot.ps-fd-rem { background:var(--ps-danger-light); color:var(--ps-danger); }
.page-promo-snapshot .ps-ft { color:var(--ps-muted); }
.page-promo-snapshot .ps-empty { text-align:center; padding:28px; color:var(--ps-muted); font-style:italic; }

/* Modal — background/radius/shadow/the .open toggle now come from the shared
   .kc-modal-backdrop/.kc-modal-panel layer (app.css ~716); .ps-m-bg/.ps-m-box only
   add what's specific to this page (blur, fixed width, the circular close button).
   JS still opens/closes via classList.add/remove('open') — untouched. */
.page-promo-snapshot .ps-m-bg { backdrop-filter:blur(2px); }
.page-promo-snapshot .ps-m-box { width:540px; min-width:min(480px, 92vw); max-width:92vw; max-height:90vh; display:flex; flex-direction:column; animation:psModalAnim .25s cubic-bezier(.22,1,.36,1); }
/* Upsell teaser modal — narrower, roomier body padding than the data-drilldown modal */
.page-promo-snapshot .ps-m-box--sm { width:420px; }
.page-promo-snapshot .ps-m-box--sm .ps-m-bd { padding:24px 28px; }
@keyframes psModalAnim { from{opacity:0;transform:translateY(12px) scale(.97)} to{opacity:1;transform:none} }
.page-promo-snapshot .ps-m-hd { padding:22px 26px 14px; border-bottom:1px solid var(--ps-border); position:relative; }
.page-promo-snapshot .ps-m-hd h3 { font-family:var(--ps-font-title); font-size:16px; font-weight:700; padding-inline-end:40px; }
.page-promo-snapshot .ps-m-x { position:absolute; top:18px; inset-inline-end:18px; background:color-mix(in srgb, var(--cta) 15%, var(--surface)); border:none; width:34px; height:34px; border-radius:50%; font-size:18px; cursor:pointer; color:var(--ps-muted); display:flex; align-items:center; justify-content:center; }
.page-promo-snapshot .ps-m-x:hover { background:var(--ps-danger-light); color:var(--ps-danger); }
.page-promo-snapshot .ps-m-bd { flex:1; overflow-y:auto; padding:18px 26px 26px; }
.page-promo-snapshot .ps-m-bd table { width:100%; border-collapse:collapse; font-size:12px; }
.page-promo-snapshot .ps-m-bd th { text-align:start; padding:7px 10px; font-size:10px; font-weight:700; text-transform:uppercase; color:var(--ps-muted); letter-spacing:.3px; border-bottom:2px solid var(--ps-border); }
.page-promo-snapshot .ps-m-bd td { padding:7px 10px; border-bottom:1px solid var(--ps-border); }
.page-promo-snapshot .ps-m-bd tr:hover td { background:var(--ps-accent-light); }
.page-promo-snapshot .ps-m-bd .was { text-decoration:line-through; color:var(--ps-muted); white-space:nowrap; }
.page-promo-snapshot .ps-m-bd .now { font-weight:700; color:var(--ps-success-dark); white-space:nowrap; }
/* Brand-info matrix modal: one column per unique promo */
.page-promo-snapshot .ps-mod-matrix th { text-align:center; vertical-align:bottom; padding:6px 8px; min-width:90px; max-width:140px; }
.page-promo-snapshot .ps-mod-matrix th:nth-child(1), .page-promo-snapshot .ps-mod-matrix th:nth-child(2) { text-align:start; }
.page-promo-snapshot .ps-mod-h-pill { margin-bottom:4px; display:flex; justify-content:center; }
.page-promo-snapshot .ps-mod-h-name { font-size:9px; font-weight:500; color:var(--ps-muted); text-transform:none; letter-spacing:0; line-height:1.3; word-break:break-word; }
.page-promo-snapshot .ps-mod-cell { text-align:center; font-weight:700; font-size:14px; }
.page-promo-snapshot .ps-mod-cell--gap { cursor:pointer; text-decoration:underline dotted; text-underline-offset:3px; }
.page-promo-snapshot .ps-mod-cell-yes { color:var(--ps-success-dark); }
.page-promo-snapshot .ps-mod-cell-no { color:var(--border-strong); }
.page-promo-snapshot .ps-mod-cell-na { color:var(--ps-muted); font-weight:500; }

/* JS-built HTML (item/brand drilldown modals) — small reusable ink/layout utilities so
   the <script> block stops assembling style="color:#…" strings by hand. */
.page-promo-snapshot .ps-js-red { color:var(--danger); font-weight:700; }
.page-promo-snapshot .ps-js-green { color:var(--success-ink); font-weight:700; }
.page-promo-snapshot .ps-js-muted { color:var(--ps-muted); }
.page-promo-snapshot .ps-js-nowrap { white-space:nowrap; }
.page-promo-snapshot .ps-js-sub { font-size:11px; line-height:1.35; margin-top:2px; }
/* "Items at full price" breakdown list (gapList()) */
.page-promo-snapshot .ps-gap-wrap { text-align:start; padding:4px 2px 8px; }
.page-promo-snapshot .ps-gap-head { font-size:10.5px; font-weight:700; color:var(--ps-muted); text-transform:uppercase; letter-spacing:.04em; margin-bottom:4px; }
.page-promo-snapshot .ps-gap-row { display:flex; flex-wrap:wrap; gap:2px 14px; align-items:baseline; padding:4px 0; border-top:1px solid var(--ps-border); }
.page-promo-snapshot .ps-gap-item { flex:1 1 180px; min-width:0; }
.page-promo-snapshot .ps-gap-detail-td { background:var(--ps-card); }
/* Brand-info matrix modal: per-branch status text + row tint */
.page-promo-snapshot .ps-status-inactive { color:var(--ps-muted); font-weight:600; }
.page-promo-snapshot .ps-status-active { color:var(--ps-success-dark); font-weight:700; }
.page-promo-snapshot .ps-status-none { color:var(--ps-danger); font-weight:700; }
.page-promo-snapshot .ps-status-closed { color:var(--ps-warn-dark); font-weight:600; }
.page-promo-snapshot .ps-status-row--inactive { background:var(--surface-3); color:var(--ps-muted); }
.page-promo-snapshot .ps-status-row--differs { background:var(--ps-diff-bg); }
.page-promo-snapshot .ps-diff-badge { background:var(--ps-warn-light); color:var(--ps-warn-dark); font-size:9px; font-weight:700; padding:1px 6px; border-radius:4px; text-transform:uppercase; }
/* Export link in the drilldown modal header — hidden until a brand/date context gives
   it a URL; layout modifier is the float:inline-end pair shared with the two card headers. */
.page-promo-snapshot .ps-modal-export-link { float:right; float:inline-end; margin-inline-end:34px; }

/* display:none → hidden (spec): where the class's own rule sets its own `display`,
   the attribute selector below is needed to win over it. */
.page-promo-snapshot .ps-alert-extra[hidden],
.page-promo-snapshot .ps-bcp-extra[hidden],
.page-promo-snapshot .ps-tbl-extra[hidden],
.page-promo-snapshot .ps-fd-extra[hidden],
.page-promo-snapshot .ps-ofr-extra[hidden],
.page-promo-snapshot .ps-modal-export-link[hidden] { display:none; }

@media (max-width:900px) {
    .page-promo-snapshot .ps-kpi-row { grid-template-columns:repeat(2,1fr); }
    .page-promo-snapshot .ps-flt-grid { grid-template-columns:1fr 1fr; }
    .page-promo-snapshot .ps-hdr { flex-direction:column; align-items:flex-start; }
}
@media (max-width:600px) {
    .page-promo-snapshot .ps-wrap { padding:16px 12px; }
    .page-promo-snapshot .ps-kpi-row { grid-template-columns:1fr; }
    .page-promo-snapshot .ps-flt-grid { grid-template-columns:1fr; }
    .page-promo-snapshot .ps-bcp-cols { grid-template-columns:1fr !important; }
    .page-promo-snapshot th.ps-th-branch,
    .page-promo-snapshot td.ps-td-branch { width:112px !important; min-width:112px !important; max-width:112px !important; }
    /* Brand modal on a phone: Branch, Status, a promo column and «Item deals» have to fit
       in 390px. With the desktop paddings and 90px per column the last column ran off the
       right edge, and the export button squeezed the title into three lines. */
    .page-promo-snapshot .ps-m-box { max-width:calc(100vw - 16px); }
    .page-promo-snapshot .ps-m-hd { padding:16px 16px 12px; display:flex; flex-direction:column; align-items:flex-start; }
    .page-promo-snapshot .ps-m-hd #psModalExport { order:3; margin:10px 0 0 !important; }
    .page-promo-snapshot .ps-m-bd { padding:10px 10px 16px; }
    .page-promo-snapshot .ps-m-bd th,
    .page-promo-snapshot .ps-m-bd td { padding:6px 5px; }
    .page-promo-snapshot .ps-mod-matrix th { min-width:0; }
    .page-promo-snapshot .ps-mod-cell { font-size:13px; }
}

/* Date strip in one row on phones (spec 2026-09-23-mobile-menu-promo-monitor task 2).
   ps-dt-nav's row (‹ date › Latest) overflowed the header card by a few px at 375px
   (scrollWidth 361 vs a 360px window — the Latest button got clipped and the page picked
   up a horizontal scrollbar): .ps-hdr sits in a column flex layout (align-items:flex-start,
   rule above at ~900px) where a nowrap child sizes to its own content instead of being
   capped by the card, so ‹/›/Latest plus the native date control's own min width added up
   to more room than the card had. Shrinking the card's padding and giving the date input
   min-width:0 (so it's the one thing that yields) removes the overflow — same technique as
   .mn-datebar / .snapshot-controls. */
@media (max-width:768px) {
    .page-promo-snapshot .ps-hdr { padding:14px 16px; }
    .page-promo-snapshot .ps-dt-nav,
    .page-promo-snapshot .ps-dt-nav form { width:100%; flex-wrap:nowrap; }
    .page-promo-snapshot .ps-dt-btn { width:32px; height:32px; flex-shrink:0; }
    .page-promo-snapshot .ps-dt-input { flex:1 1 auto; min-width:0; padding:8px 6px; font-size:12px; }
    .page-promo-snapshot .ps-dt-latest { flex-shrink:0; padding:8px 12px; font-size:11px; white-space:nowrap; }
    /* Branch table (task 4): on a phone the wrap scrolled BOTH axes on its own
       (max-height:78vh + overflow-y:auto) nested inside a page that already scrolls
       vertically — a two-finger scroll trap. Drop the wrap's own vertical scroll (the
       page scrolls instead) and keep only the horizontal one; narrow the fixed 185px
       aggregator columns so more of the table fits without scrolling at all. */
    .page-promo-snapshot .ps-tbl-wrap { max-height:none; overflow-y:visible; }
    .page-promo-snapshot .ps-th-agg { width:120px; min-width:120px; max-width:120px; }
    .page-promo-snapshot .ps-th-agg.ps-th-narrow { width:72px; min-width:72px; max-width:72px; }
    /* Item-count chip (.ps-tag-items, opens the drilldown modal): was only as tall as its
       10.5px text + 1px padding-block — well under the ~32px a thumb reliably hits. */
    .page-promo-snapshot .ps-tag-items { min-height:32px; padding-block:7px; }
}

/* ===== Promo Discrepancies (.page-pd) — promo/discrepancies.php =====
   --pd-* are aliases onto the real tokens (spec 2026-09-22-cabinets-ui-unification,
   wave D task 5) — no page-private colour values left. --pd-val has no 1:1 token: it's
   color-mix() off --success-ink, tuned to keep the page's original light-theme contrast
   (~5.2:1 on --surface, both as text and as a solid pill fill under white text). Solid
   fills here (--pd-diff/--pd-mix/--pd-val…) flip per theme, so text on them is
   --text-inverse, never the always-white --on-accent (ScopedCssTokensTest guards it). */
.page-pd{--pd-accent:var(--cat-1);--pd-diff:var(--danger);--pd-only:var(--caution);--pd-mix:var(--muted);--pd-depth:var(--cat-5);--pd-val:color-mix(in srgb, var(--success-ink) 90%, var(--surface));
  --pd-ink:var(--text);--pd-muted:var(--muted);--pd-line:var(--border-soft);--pd-card:var(--surface);
  --pd-ft:'Montserrat',sans-serif;--pd-fb:'Inter',sans-serif;
  /* Plain --pd-depth (--cat-5) as text is ~4.3:1 on --pd-card — under AA. .pd-rangec
     reads this ink instead; .pd-issue.is-depth keeps the pure category fill below. */
  --pd-depth-ink:color-mix(in srgb, var(--cat-5) 55%, var(--text));}
/* Фон вешаем на сам контейнер, а не через body:has(): :has() на body даёт
   инвалидационное множество на весь документ, и каждая мутация из фильтра
   поиска дёргала переоценку по всему дереву. На 3+ тыс. строк это заметно. */
.page-pd{background:var(--bg);min-height:100vh;}
.page-pd{font-family:var(--pd-fb);color:var(--pd-ink);}
.page-pd .container{max-width:1180px;margin:0 auto;padding:22px 18px 40px;}
.page-pd .card{background:var(--pd-card);border-radius:15px;box-shadow:0 2px 15px color-mix(in srgb, var(--text) 8%, transparent);margin-bottom:14px;padding:0;}
.page-pd .pd-head{padding:16px 20px;display:flex;align-items:center;gap:12px;flex-wrap:wrap;}
.page-pd .pd-head h1{font-family:var(--pd-ft);font-size:22px;font-weight:800;letter-spacing:-.5px;margin:0;}
.page-pd .pd-head .sub{color:var(--pd-muted);font-size:13px;margin-top:3px;}
.page-pd .pd-head .sp{flex:1 1 auto;}
.page-pd .pd-count{display:inline-flex;align-items:center;gap:7px;font-size:12.5px;font-weight:800;text-transform:uppercase;letter-spacing:.3px;color:var(--text-inverse);background:var(--pd-diff);border-radius:999px;padding:6px 14px;box-shadow:0 2px 8px color-mix(in srgb, var(--pd-diff) 40%, transparent);}
.page-pd .pd-count.zero{background:var(--success-bg);color:var(--success-ink);box-shadow:none;}
.page-pd .pd-btn{border:2px solid var(--pd-line);border-radius:10px;padding:7px 14px;font-size:12.5px;font-weight:700;color:var(--pd-ink);text-decoration:none;background:var(--surface);}
.page-pd .pd-btn:hover{border-color:var(--pd-accent);color:var(--pd-accent);}
.page-pd .pd-btn.export{border-color:var(--success);color:var(--success-ink);}
.page-pd .pd-btn.is-disabled{opacity:.35;pointer-events:none;}
.page-pd .pd-dtbtn{padding:6px 11px;font-size:15px;line-height:1;}
.page-pd .pd-dtnav{display:flex;align-items:center;gap:5px;}
.page-pd .pd-dateinput{border:2px solid var(--pd-line);border-radius:9px;padding:6px 9px;font:inherit;font-size:12.5px;background:var(--surface-2);color:var(--pd-ink);}
.page-pd .pd-toolbar{padding:0 20px 12px;}
.page-pd .pd-search{width:100%;max-width:380px;border:2px solid var(--pd-line);border-radius:10px;padding:8px 12px;font:inherit;font-size:13px;background:var(--surface-2);}
.page-pd .pd-search:focus{border-color:var(--pd-accent);background:var(--surface);outline:none;}
.page-pd .pd-fltcard{padding:12px 16px 14px;}
.page-pd .pd-flt-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(185px,1fr));gap:11px;margin-bottom:11px;}
.page-pd .filter-group > label{display:block;font-size:10.5px;font-weight:700;color:var(--pd-muted);text-transform:uppercase;letter-spacing:.4px;margin-bottom:5px;}
.page-pd .flt-chips{margin:0 0 11px;}
.page-pd .pd-flt-actions{display:flex;gap:8px;align-items:center;}
.page-pd .pd-flt-actions .btn-primary{padding:8px 20px;border-radius:10px;font-size:13px;font-weight:700;}
.page-pd .pd-sec-h{padding:14px 20px 6px;display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;}
.page-pd .pd-sec-h h2{font-family:var(--pd-ft);font-size:16px;font-weight:800;margin:0;}
.page-pd .pd-sec-h .n{font-size:12px;font-weight:800;color:var(--text-inverse);background:var(--pd-mix);border-radius:999px;padding:2px 9px;}
.page-pd .pd-sec-h.store .n{background:var(--pd-diff);}
.page-pd .pd-sec-h .hint{color:var(--pd-muted);font-size:12px;flex:1 1 100%;margin-top:2px;}
.page-pd .pd-wrap{overflow:auto;max-height:70vh;border-radius:0 0 15px 15px;}
/* table-layout:fixed — главный выигрыш на этой странице. При авто-раскладке
   браузер обязан промерить КАЖДУЮ ячейку обеих таблиц, чтобы вычислить ширины:
   ~22 тыс. ячеек в два прохода, и это основной разовый фриз вкладки на загрузке.
   Ширины заданы явно ниже, иначе fixed раскладывает колонки поровну. */
.page-pd table{width:100%;table-layout:fixed;border-collapse:separate;border-spacing:0;font-size:13px;}
.page-pd tbody td{overflow:hidden;text-overflow:ellipsis;}
/* Обе таблицы имеют одинаковую сетку из 7 колонок: бренд, значение/единица,
   площадка, характер расхождения, покрытие, затронутые сторы, действие.
   Проценты, а не пиксели, чтобы на узких экранах вело себя как раньше. */
.page-pd table col.c-brand{width:22%}
.page-pd table col.c-val{width:12%}
.page-pd table col.c-app{width:11%}
.page-pd table col.c-issue{width:17%}
.page-pd table col.c-cov{width:11%}
.page-pd table col.c-aff{width:20%}
.page-pd table col.c-act{width:7%}
.page-pd thead th{position:sticky;top:0;z-index:2;background:var(--surface-2);text-align:start;padding:9px 12px;font-size:10.5px;font-weight:700;text-transform:uppercase;letter-spacing:.3px;color:var(--pd-muted);border-bottom:2px solid var(--pd-line);white-space:nowrap;}
.page-pd tbody td{padding:9px 12px;border-bottom:1px solid var(--pd-line);vertical-align:middle;}
.page-pd tbody tr:hover td{background:var(--surface-2);}
.page-pd .pd-brand a{color:var(--pd-ink);font-weight:700;text-decoration:none;}
.page-pd .pd-brand a:hover{color:var(--pd-accent);}
.page-pd .pd-cc{font-size:9.5px;font-weight:700;color:var(--pd-ink);background:var(--pd-line);border-radius:5px;padding:1px 5px;margin-inline-start:6px;}
.page-pd .pd-unit{font-weight:500;}
.page-pd .pd-muted{color:var(--pd-muted);}
.page-pd .pd-pill{display:inline-flex;align-items:center;padding:2px 9px;border-radius:8px;font-size:10.5px;font-weight:700;color:var(--on-accent);}
.page-pd .pd-pill--default{background:var(--surface-3);color:var(--text);}
.page-pd .pd-issue{display:inline-block;font-size:10.5px;font-weight:800;border-radius:7px;padding:2px 9px;white-space:nowrap;color:var(--text-inverse);}
.page-pd .pd-issue.is-dropped{background:var(--pd-diff);}
.page-pd .pd-issue.is-only{background:var(--pd-only);}
.page-pd .pd-issue.is-mixed{background:var(--pd-mix);}
.page-pd .pd-issue.is-depth{background:var(--pd-depth);}
.page-pd .pd-issue.is-value{background:var(--pd-val);}
.page-pd .pd-cov{font-variant-numeric:tabular-nums;white-space:nowrap;color:var(--pd-muted);}
.page-pd .pd-cov b{color:var(--pd-ink);}
.page-pd .pd-aff{font-weight:800;font-variant-numeric:tabular-nums;color:var(--pd-diff);white-space:nowrap;cursor:help;border-bottom:1px dotted var(--pd-diff);}
.page-pd .pd-rangec{font-variant-numeric:tabular-nums;color:var(--pd-depth-ink);font-weight:700;white-space:nowrap;}
.page-pd .pd-range{font-variant-numeric:tabular-nums;color:var(--pd-val);font-weight:800;white-space:nowrap;}
.page-pd .pd-open{color:var(--pd-accent);font-weight:600;text-decoration:none;white-space:nowrap;}
.page-pd .pd-open:hover{text-decoration:underline;}
.page-pd .empty{padding:44px 20px;text-align:center;}
.page-pd .empty .big{font-family:var(--pd-ft);font-size:17px;font-weight:800;color:var(--success-ink);}
.page-pd .empty .big.is-collecting{color:var(--warn-ink);}
.page-pd .empty p{color:var(--pd-muted);margin-top:6px;font-size:13px;}
.page-pd .sec-empty{padding:18px 20px;color:var(--pd-muted);font-size:13px;font-style:italic;}
.page-pd .pd-note{color:var(--pd-muted);font-size:11.5px;font-style:italic;padding:10px 20px;}
@media (max-width:720px){
  .page-pd .container{padding:12px 8px 30px;}
  .page-pd td.hide-sm,.page-pd th.hide-sm{display:none;}
  /* min-width превращает .pd-wrap в горизонтальный скроллер: без него fixed-таблица
     ужимает бренд до ~80px и режет nowrap-пилюли Issue посреди слова. */
  .page-pd table{min-width:560px;}
}
/* Compact header on phones (spec 2026-09-23-mobile-menu-promo-monitor task 2): the title
   block, the date-nav (‹ date ›/Latest) and the count pill/export/back link each get their
   own row instead of fighting for space in one flex-wrap line. .sp (the desktop
   title<->controls spacer) is dropped — the explicit full-width rows make it redundant, and
   its own empty flex line was adding a blank gap. .pd-dtnav has no wrap (flex, nowrap by
   default); min-width:0 on the date input is what actually lets that row shrink to fit
   instead of overflowing. */
@media (max-width:768px){
  .page-pd .pd-head{padding:12px 14px;}
  .page-pd .pd-head>div:first-child{flex-basis:100%;}
  .page-pd .pd-head .sp{display:none;}
  .page-pd .pd-dtnav{flex-basis:100%;}
  .page-pd .pd-dtnav>a,.page-pd .pd-dtnav>span{flex-shrink:0;}
  .page-pd .pd-dtnav input[type=date]{flex:1 1 auto;min-width:0;}
}

/* ===== Menu Matrix (.page-mm) — menu/matrix.php =====
   --mm-* are aliases onto the real tokens (spec 2026-09-22-cabinets-ui-unification,
   wave D task 6) — no page-private colour values left; the off/not-collected stripe
   pairs and a few tints have no 1:1 token and are color-mix() off a real one. */
.page-mm{--mm-ok:var(--success);--mm-diff:var(--danger);--mm-gap:var(--warn);
  --mm-off1:color-mix(in srgb, var(--text) 12%, var(--surface));--mm-off2:color-mix(in srgb, var(--text) 4%, var(--surface));
  --mm-nc1:color-mix(in srgb, var(--warn) 30%, var(--surface));--mm-nc2:color-mix(in srgb, var(--warn) 10%, var(--surface));
  --mm-accent:var(--brand-dark);--mm-fill:var(--cta);--mm-fill-ink:var(--cta-text);--mm-ink:var(--text);--mm-muted:var(--muted);--mm-line:var(--border-soft);--mm-card:var(--surface);
  --mm-font-title:'Montserrat',sans-serif;--mm-font-body:'Inter',sans-serif;}
/* Background on the container, not body:has() — same reason as .page-pd below. */
.page-mm{background:var(--bg);font-family:var(--mm-font-body);color:var(--mm-ink);}
.page-mm .container{max-width:1360px;margin:0 auto;padding:20px 18px 40px;}

.page-mm .card{background:var(--mm-card);border-radius:15px;box-shadow:var(--shadow-card);margin-bottom:14px;padding:0;}
.page-mm .mm-head{display:flex;align-items:flex-start;gap:16px;flex-wrap:wrap;padding:16px 20px;}
.page-mm .mm-head h1{font-family:var(--mm-font-title);font-size:22px;font-weight:800;letter-spacing:-.5px;margin:0;}
.page-mm .mm-meta{color:var(--mm-muted);font-size:12.5px;margin-top:3px;}
.page-mm .mm-meta b{color:var(--mm-ink);font-weight:600;}
.page-mm .mm-head .sp{flex:1 1 auto;}

.page-mm .mm-tabs{display:inline-flex;border:2px solid var(--mm-line);border-radius:11px;overflow:hidden;align-self:center;}
.page-mm .mm-tabs a{padding:7px 15px;font-size:13px;font-weight:700;color:var(--mm-ink);text-decoration:none;}
.page-mm .mm-tabs a.on{background:var(--mm-fill);color:var(--mm-fill-ink);}
.page-mm .mm-btn{border:2px solid var(--mm-line);background:var(--surface);color:var(--mm-ink);font-size:12.5px;font-weight:700;border-radius:10px;padding:7px 14px;cursor:pointer;align-self:center;display:inline-flex;align-items:center;gap:8px;font-family:inherit;}
.page-mm .mm-datepin{display:inline-flex;align-items:center;gap:6px;align-self:center;}
.page-mm .mm-datepin input[type=date]{border:2px solid var(--mm-line);background:var(--surface);color:var(--mm-ink);font-size:12.5px;font-weight:700;border-radius:10px;padding:6px 10px;font-family:inherit;}
.page-mm .mm-datepin input[type=date]:focus{border-color:var(--mm-accent);outline:none;}
.page-mm .mm-datepin-reset{color:var(--mm-muted);font-size:16px;font-weight:700;text-decoration:none;padding:2px 6px;border-radius:8px;}
.page-mm .mm-datepin-reset:hover{background:var(--mm-line);color:var(--mm-ink);}
.page-mm .mm-btn:hover{border-color:var(--mm-accent);color:var(--mm-accent);}
.page-mm .mm-btn .sw{width:26px;height:15px;border-radius:999px;background:color-mix(in srgb, var(--muted) 30%, var(--surface));position:relative;flex:0 0 auto;}
.page-mm .mm-btn .sw::after{content:'';position:absolute;top:2px;inset-inline-start:2px;width:11px;height:11px;border-radius:50%;background:var(--surface);transition:inset-inline-start .12s;}
.page-mm .mm-btn.on{background:var(--mm-fill);border-color:var(--mm-fill);color:var(--mm-fill-ink);}
.page-mm .mm-btn.on .sw{background:color-mix(in srgb, var(--on-accent) 35%, transparent);}
.page-mm .mm-btn.on .sw::after{inset-inline-start:13px;}
.page-mm .mm-btn--link{text-decoration:none;}

/* legend */
.page-mm .mm-legend{display:flex;align-items:center;gap:13px;flex-wrap:wrap;padding:10px 20px 13px;border-top:1px solid var(--mm-line);font-size:12px;color:var(--mm-muted);}
.page-mm .mm-lg{display:inline-flex;align-items:center;gap:6px;}
.page-mm .mm-lg i{width:13px;height:13px;border-radius:4px;flex:0 0 auto;}
.page-mm .lg-ok i{background:var(--mm-ok);} .page-mm .lg-diff i{background:var(--mm-diff);}
.page-mm .lg-gap i{background:var(--mm-gap);} .page-mm .lg-off i{background:repeating-linear-gradient(45deg,var(--mm-off1) 0 3px,var(--mm-off2) 3px 6px);}
.page-mm .lg-nc i{background:repeating-linear-gradient(45deg,var(--mm-nc1) 0 3px,var(--mm-nc2) 3px 6px);}
.page-mm .lg-promo i{background:var(--surface);border:1px solid var(--border-strong);position:relative;} .page-mm .lg-promo i::after{content:'';position:absolute;inset:0;margin:auto;width:5px;height:5px;border-radius:50%;background:var(--mm-accent);}
.page-mm .lg-coverage i{background:var(--surface);border:1px solid var(--success-border);}
.page-mm .mm-legend .sep{width:1px;height:15px;background:var(--mm-line);}
.page-mm .view-items .lg-diff,.page-mm .view-items .lg-promo{display:none;}
.page-mm .view-prices .lg-listed{display:none;}
.page-mm .lg-listed i{background:var(--mm-ok);}

/* spread flag (prices view) */
.page-mm .mm-flag{display:inline-flex;align-items:center;gap:6px;font:inherit;cursor:pointer;font-size:12px;font-weight:800;letter-spacing:.3px;text-transform:uppercase;color:var(--text-inverse);background:var(--mm-diff);border:2px solid var(--mm-diff);border-radius:999px;padding:5px 12px;box-shadow:0 2px 8px color-mix(in srgb, var(--mm-diff) 45%, transparent);animation:mm-pulse 1.4s ease-in-out infinite;}
.page-mm .mm-flag .ico{font-size:12px;} .page-mm .mm-flag .n{background:var(--surface);color:var(--mm-diff);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:900;min-width:20px;text-align:center;}
.page-mm .mm-flag.none{background:var(--success-bg);border-color:var(--success-border);color:var(--success-ink);box-shadow:none;animation:none;cursor:default;}
.page-mm .mm-flag.none .ico{display:none;} .page-mm .mm-flag.none .n{background:var(--success-border);color:var(--success-ink);}
.page-mm .mm-flag.on{outline:3px solid color-mix(in srgb, var(--mm-diff) 35%, transparent);outline-offset:1px;}
@keyframes mm-pulse{0%,100%{box-shadow:0 2px 8px color-mix(in srgb, var(--mm-diff) 45%, transparent)}50%{box-shadow:0 0 0 4px color-mix(in srgb, var(--mm-diff) 28%, transparent),0 2px 8px color-mix(in srgb, var(--mm-diff) 45%, transparent)}}
@media (prefers-reduced-motion:reduce){.page-mm .mm-flag{animation:none;}}
.page-mm .view-items .prices-only{display:none;}

/* brand picker */
.page-mm .mm-picker{padding:12px 20px 14px;}
.page-mm .pick-top{display:flex;align-items:center;gap:9px;flex-wrap:wrap;}
.page-mm .pick-top input{flex:0 1 300px;min-width:170px;border:2px solid var(--mm-line);border-radius:10px;padding:8px 12px;font:inherit;font-size:13px;background:var(--surface-2);}
.page-mm .pick-top input:focus{border-color:var(--mm-accent);background:var(--surface);outline:none;}
.page-mm .mm-chips{display:flex;gap:6px;flex-wrap:wrap;} .page-mm .mm-chip{border:2px solid var(--mm-line);background:var(--surface);border-radius:999px;font:inherit;font-size:12px;font-weight:700;color:var(--mm-muted);padding:5px 12px;cursor:pointer;}
.page-mm .mm-chip.on{background:var(--mm-fill);border-color:var(--mm-fill);color:var(--mm-fill-ink);}
.page-mm .pick-total{margin-inline-start:auto;font-size:12px;color:var(--mm-muted);}
.page-mm .pick-list{margin-top:10px;max-height:190px;overflow:auto;display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:6px;}
.page-mm .pk{border:1px solid var(--border-soft);background:var(--surface-2);border-radius:10px;padding:7px 11px;text-decoration:none;color:inherit;display:flex;align-items:baseline;gap:7px;min-width:0;}
.page-mm .pk:hover{border-color:var(--mm-accent);}
.page-mm .pk.on{background:color-mix(in srgb, var(--mm-accent) 12%, var(--surface));border:2px solid var(--mm-accent);box-shadow:0 0 0 3px color-mix(in srgb, var(--brand) 20%, transparent);}
.page-mm .pk b{font-size:12.5px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.page-mm .pk .cc{font-size:9.5px;font-weight:700;color:var(--mm-muted);background:var(--mm-line);border-radius:5px;padding:1px 5px;flex:0 0 auto;}
.page-mm .pk.on .cc{background:color-mix(in srgb, var(--mm-accent) 25%, var(--surface));color:var(--success-ink);}
.page-mm .pk .n{font-size:11px;color:var(--mm-muted);margin-inline-start:auto;flex:0 0 auto;}
.page-mm .pick-current{font-size:12.5px;color:var(--mm-muted);}
.page-mm .pick-current b{color:var(--mm-ink);}

/* matrix */
.page-mm .mm-wrap{overflow:auto;max-height:76vh;border-radius:15px;position:relative;}
.page-mm .mm-table{border-collapse:separate;border-spacing:0;table-layout:fixed;width:100%;min-width:calc(230px + var(--n,1) * var(--cell,98px));}
.page-mm.mm-numbers .mm-table{--cell:150px;}
.page-mm .mm-table col.c-first{width:230px;}
.page-mm thead th{position:sticky;top:0;z-index:6;background:var(--surface);border-bottom:2px solid var(--mm-line);padding:9px 8px 8px;text-align:start;vertical-align:bottom;font-size:11.5px;font-weight:600;}
.page-mm thead th.corner{inset-inline-start:0;z-index:8;border-inline-end:1px solid var(--mm-line);}
.page-mm thead th .st-name{font-size:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.page-mm thead th .st-aggs{display:flex;gap:3px;margin-top:5px;} .page-mm thead th .st-id{color:var(--mm-muted);font-weight:400;font-size:10.5px;margin-top:3px;}
.page-mm tbody th.rowh{position:sticky;inset-inline-start:0;z-index:3;background:var(--surface);border-inline-end:1px solid var(--mm-line);border-bottom:1px solid var(--border-soft);font-weight:500;font-size:12.5px;text-align:start;padding:5px 10px;}
.page-mm th.rowh .mm-rowh-in{display:flex;align-items:center;gap:7px;min-height:24px;}
.page-mm th.rowh .it-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;}
.page-mm tbody td{border-bottom:1px solid var(--border-soft);padding:4px 8px;vertical-align:middle;background:var(--surface);}
.page-mm tr.cat th.rowh{background:color-mix(in srgb, var(--mm-accent) 15%, var(--surface));color:color-mix(in srgb, var(--mm-accent) 60%, var(--text));font-weight:700;font-size:11px;text-transform:uppercase;letter-spacing:.5px;}
.page-mm tr.cat td{background:color-mix(in srgb, var(--mm-accent) 15%, var(--surface));border-bottom:1px solid var(--mm-line);}
.page-mm tbody tr:not(.cat):hover td{background:var(--info-bg);}

/* triptych cell */
.page-mm .mm-trip{display:flex;gap:2px;}
.page-mm .mm-seg{flex:1 1 0;min-width:0;height:20px;border-radius:4px;position:relative;display:flex;align-items:center;overflow:hidden;}
.page-mm .mm-seg.s-ok{background:var(--mm-ok);} .page-mm .mm-seg.s-diff{background:var(--mm-ok);} /* diff shown red only in prices view */
.page-mm .view-prices .mm-seg.s-diff{background:var(--mm-diff);}
.page-mm .mm-seg.s-gap{background:var(--mm-gap);} .page-mm .mm-seg.s-off{background:repeating-linear-gradient(45deg,var(--mm-off1) 0 3px,var(--mm-off2) 3px 6px);}
.page-mm .mm-seg.s-nc{background:repeating-linear-gradient(45deg,var(--mm-nc1) 0 3px,var(--mm-nc2) 3px 6px);}
/* Мгновенный тултип грида. Нативный title на плотной сетке ненадёжен (задержка ~1с и
   часто не срабатывает вовсе) — заменён на data-tip + JS (public/js/menu-matrix.js).
   Висит на body, поэтому скролл-контейнер таблицы (.mm-wrap overflow:auto) его НЕ
   обрезает. Тап по ячейке открывает/закрывает тот же чип. Тёмный чип нарочно не
   меняется по теме (как нативная браузерная подсказка): фон — --appbar (уже тёмный в
   обеих темах), текст всегда белый через --on-accent. */
.mm-tip{position:fixed;z-index:1000;display:none;max-width:300px;background:var(--appbar);color:var(--on-accent);font-family:'Inter',system-ui,sans-serif;font-size:12px;font-weight:500;line-height:1.45;padding:7px 10px;border-radius:8px;box-shadow:0 4px 16px color-mix(in srgb, var(--text) 30%, transparent);pointer-events:none;white-space:normal;overflow-wrap:anywhere;}
.page-mm .mm-seg .dot{display:none;position:absolute;top:50%;inset-inline-start:50%;transform:translate(-50%,-50%);width:6px;height:6px;border-radius:50%;background:var(--surface);box-shadow:0 0 0 1px color-mix(in srgb, var(--text) 28%, transparent);}
.page-mm .view-prices .mm-seg.promo .dot{display:block;}
.page-mm .mm-seg .in-pill,.page-mm .mm-seg .pr{display:none;}
.page-mm .mm-pill{display:inline-flex;align-items:center;justify-content:center;min-width:16px;height:14px;padding:0 3px;border-radius:999px;font-size:9px;font-weight:700;color:var(--on-accent);line-height:1;flex:0 0 auto;}
.page-mm .mm-pill--default{background:var(--surface-3);color:var(--mm-ink);}
.page-mm .mm-pill--off{background:var(--surface-3);color:color-mix(in srgb, var(--muted) 60%, var(--surface));}

/* numbers mode (prices) */
.page-mm.mm-numbers.view-prices .mm-trip{flex-direction:column;gap:3px;}
.page-mm.mm-numbers.view-prices .mm-seg{flex:0 0 auto;height:auto;min-height:20px;background:var(--surface-2);border:1px solid var(--border-soft);border-radius:6px;padding:3px 7px 3px 0;gap:5px;}
.page-mm.mm-numbers.view-prices .mm-seg .in-pill{display:inline-flex;}
.page-mm.mm-numbers.view-prices .mm-seg .stripe{width:4px;align-self:stretch;min-height:16px;flex:0 0 auto;border-radius:0;}
.page-mm.mm-numbers.view-prices .mm-seg.s-ok .stripe{background:var(--mm-ok);}
.page-mm.mm-numbers.view-prices .mm-seg.s-diff .stripe{background:var(--mm-diff);}
.page-mm.mm-numbers.view-prices .mm-seg.s-gap .stripe{background:var(--mm-gap);}
.page-mm.mm-numbers.view-prices .mm-seg.s-off .stripe{background:repeating-linear-gradient(45deg,var(--mm-off1) 0 3px,var(--mm-off2) 3px 6px);}
.page-mm.mm-numbers.view-prices .mm-seg.s-nc .stripe{background:repeating-linear-gradient(45deg,var(--mm-nc1) 0 3px,var(--mm-nc2) 3px 6px);}
.page-mm.mm-numbers.view-prices .mm-seg.s-ok,.page-mm.mm-numbers.view-prices .mm-seg.s-diff{background:var(--surface);}
.page-mm.mm-numbers.view-prices .mm-seg .pr{display:flex;align-items:baseline;gap:4px;font-size:11px;font-variant-numeric:tabular-nums;white-space:nowrap;overflow:hidden;}
.page-mm .pr .base{font-weight:600;} .page-mm .pr .base.cut{font-weight:400;color:color-mix(in srgb, var(--mm-muted) 70%, var(--surface));text-decoration:line-through;}
/* .pct/.dlt: solid fills that flip per theme → --text-inverse. .pct is --mm-accent pushed
   30% toward --text (darker in light, lighter in dark) and .dlt.down sits on --success-ink:
   plain --brand-dark/--success gave 3.50/3.43:1 under white; now 4.81/6.51 light,
   12.32/8.90 dark. */
.page-mm .pr .eff{font-weight:700;color:var(--mm-accent);} .page-mm .pr .pct{font-size:9.5px;font-weight:700;color:var(--text-inverse);background:color-mix(in srgb, var(--mm-accent) 70%, var(--text));border-radius:5px;padding:1px 3px;}
.page-mm .pr .na{color:var(--warn);font-size:10.5px;} .page-mm .pr .na.off{color:color-mix(in srgb, var(--muted) 60%, var(--surface));} .page-mm .pr .na.nc{color:var(--warn-ink);}
.page-mm.mm-numbers.view-prices .mm-seg.s-diff .base{color:var(--mm-diff);}
.page-mm .pr .dlt{font-size:9.5px;font-weight:700;border-radius:5px;padding:1px 3px;color:var(--text-inverse);} .page-mm .pr .dlt.up{background:var(--mm-diff);} .page-mm .pr .dlt.down{background:var(--success-ink);}
/* seg stripe hidden in colour mode */
.page-mm .mm-seg .stripe{display:none;}
.page-mm.mm-numbers.view-prices .mm-seg .stripe{display:block;}

/* SPREAD rows (prices view only) */
.page-mm .spread-badge{display:none;align-items:center;gap:5px;flex:0 0 auto;font-size:10.5px;font-weight:900;letter-spacing:.3px;text-transform:uppercase;color:var(--text-inverse);background:var(--mm-diff);border-radius:7px;padding:2px 7px;box-shadow:0 1px 4px color-mix(in srgb, var(--mm-diff) 50%, transparent);}
.page-mm .spread-badge::before{content:"\26A0";}
.page-mm .view-prices tr.spread .spread-badge{display:inline-flex;}
.page-mm .view-prices tr.spread td,.page-mm .view-prices tr.spread th.rowh{background:var(--danger-bg);border-top:2px solid var(--mm-diff);border-bottom:2px solid var(--mm-diff);}
.page-mm .view-prices tr.spread th.rowh{box-shadow:inset 6px 0 0 var(--mm-diff);color:var(--danger);font-weight:800;}
.page-mm .view-prices tr.spread .mm-seg.s-diff{outline:2px solid var(--danger);outline-offset:-2px;}
.page-mm.mm-numbers.view-prices tr.spread .mm-seg.s-diff{background:var(--mm-diff)!important;}
.page-mm.mm-numbers.view-prices tr.spread .mm-seg.s-diff .base,.page-mm.mm-numbers.view-prices tr.spread .mm-seg.s-diff .eff{color:var(--text-inverse)!important;}
/* On the red spread segment .pct is a dark chip anchored on --appbar (dark in both themes)
   with white text: 8.49:1 light, 7.57:1 dark. The old mix toward --text went light in dark. */
.page-mm.mm-numbers.view-prices tr.spread .mm-seg.s-diff .pct{background:color-mix(in srgb, var(--danger) 35%, var(--appbar));color:var(--on-accent);}
.page-mm.mm-numbers.view-prices tr.spread .mm-seg.s-diff .dlt.up{background:var(--surface);color:var(--danger);}
/* spread-only filter */
.page-mm.mm-spread-only tbody tr:not(.spread):not(.cat){display:none;}

.page-mm .empty{padding:40px 20px;text-align:center;color:var(--mm-muted);}

/* freshness-by-app panel (collapsible, hidden by default) */
.page-mm .mm-fresh{padding:0;}
.page-mm .mmf-toggle{display:flex;align-items:center;gap:10px;width:100%;padding:14px 20px;background:none;border:0;border-radius:15px;cursor:pointer;font:inherit;color:var(--mm-ink);text-align:start;}
.page-mm .mmf-toggle:hover{background:var(--surface-2);}
.page-mm .mmf-toggle .mmf-title{font-family:var(--mm-font-title);font-weight:800;font-size:15px;letter-spacing:-.2px;}
.page-mm .mmf-toggle .mmf-sub{font-size:12px;color:var(--mm-muted);}
.page-mm .mmf-toggle .mmf-chev{margin-inline-start:auto;color:var(--mm-muted);font-size:12px;transition:transform .15s;flex:0 0 auto;}
.page-mm .mm-fresh.open .mmf-toggle .mmf-chev{transform:rotate(90deg);}
.page-mm .mmf-body{display:none;padding:0 20px 14px;}
.page-mm .mm-fresh.open .mmf-body{display:block;}
.page-mm .mmf-grid{display:grid;grid-template-columns:130px 152px minmax(0,1fr) 150px;gap:14px;align-items:center;}
.page-mm .mmf-head{padding:2px 0 8px;border-bottom:1px solid var(--mm-line);font-size:11px;color:var(--mm-muted);text-transform:uppercase;letter-spacing:.4px;}
.page-mm .mmf-row{padding:12px 0;border-bottom:1px solid var(--border-soft);}
.page-mm .mmf-app{display:flex;align-items:center;gap:9px;min-width:0;}
.page-mm .mmf-name{font-size:14px;font-weight:600;display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.page-mm .mmf-items{font-size:11.5px;color:var(--mm-muted);}
.page-mm .mmf-line{font-size:13px;display:flex;align-items:center;gap:7px;}
.page-mm .mmf-line.is-frozen{color:var(--mm-gap);}
.page-mm .mmf-dot{width:8px;height:8px;border-radius:50%;flex:0 0 auto;}
.page-mm .mmf-dot.s-ok{background:var(--mm-ok);} .page-mm .mmf-dot.s-warn{background:var(--mm-gap);} .page-mm .mmf-dot.s-bad{background:var(--mm-diff);}
.page-mm .mmf-meta{font-size:11.5px;color:var(--mm-muted);margin-top:2px;}
.page-mm .mmf-spark{display:flex;align-items:flex-end;gap:5px;height:28px;}
.page-mm .mmf-tick{flex:1;min-width:2px;height:2px;background:color-mix(in srgb, var(--mm-line) 90%, var(--text));border-radius:2px;}
.page-mm .mmf-tick.on{background:var(--mm-accent);}
.page-mm .mmf-legend{display:flex;flex-wrap:wrap;gap:10px 20px;align-items:center;margin-top:12px;font-size:11.5px;color:var(--mm-muted);}
.page-mm .mmf-legend .lg{display:inline-flex;align-items:center;gap:6px;}
.page-mm .mmf-legend-muted{color:var(--mm-muted);}
.page-mm .mmf-appname{min-width:0;}
.page-mm .mmf-sw{width:11px;height:8px;border-radius:2px;flex:0 0 auto;}
.page-mm .mmf-sw.dot{width:8px;height:8px;border-radius:50%;}
.page-mm .mmf-sw--ok{background:var(--mm-ok);}
.page-mm .mmf-sw--accent{background:var(--mm-accent);}
.page-mm .mmf-note{font-size:11px;color:var(--mm-muted);margin-top:8px;border-top:1px dashed var(--mm-line);padding-top:8px;line-height:1.5;}
/* Two identical max-width:640px blocks merged into one (were declared separately). */
@media (max-width:640px){
  .page-mm .mmf-actcol{display:none;}
  .page-mm .mmf-grid{grid-template-columns:96px 1fr 1fr;}
  .page-mm .mmf-toggle .mmf-sub{display:none;}
  .page-mm .container{padding:12px 8px 30px;}
  .page-mm .mm-head{padding:13px 14px;gap:10px;}
  .page-mm .mm-head h1{font-size:18px;}
  .page-mm .mm-table col.c-first,.page-mm tbody th.rowh,.page-mm thead th.corner{width:150px;min-width:150px;}
  .page-mm .mm-wrap{max-height:70vh;}
}

/* per-app pending marker (freshness panel); the date banner is the shared _datebanner partial */
.page-mm .mm-collecting-dot{width:7px;height:7px;border-radius:50%;background:var(--mm-accent);flex:0 0 auto;animation:mm-collect-pulse 1.5s ease-in-out infinite;}
.page-mm .mmf-pending{display:inline-flex;align-items:center;gap:5px;margin-inline-start:8px;padding:2px 9px;border-radius:999px;background:var(--mm-fill);color:var(--mm-fill-ink);font-size:10.5px;font-weight:700;}
.page-mm .mmf-pending .mm-collecting-dot{background:var(--mm-fill-ink);}
@keyframes mm-collect-pulse{0%,100%{opacity:1;}50%{opacity:.35;}}
@media (prefers-reduced-motion:reduce){.page-mm .mm-collecting-dot{animation:none;}}
/* ===== Filter bar: раскладка страницы + ОБЩИЕ цвета компонента =====
   Цвета мультиселекта, чипов, счётчиков и Apply — глобальные (app.css: --brand,
   лаймовые .flt-chip и .btn-primary), как на management-dashboard и остальных
   отчётных страницах. Здесь только то, чего у .page-mm нет: карточка формы,
   сетка, лейблы полей и нейтральная secondary-кнопка. */
.page-mm .filter-form{background:var(--mm-card);border-radius:15px;padding:16px 20px;margin-bottom:14px;box-shadow:var(--shadow-card);}
.page-mm .filter-form h3{font-family:var(--mm-font-title);font-size:15px;font-weight:800;letter-spacing:-.3px;color:var(--mm-ink);margin:0 0 12px;}
.page-mm .filter-grid,.page-mm .filter-grid-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:12px;margin-bottom:12px;}
.page-mm .filter-group > label{display:block;font-size:11px;font-weight:700;color:var(--mm-muted);text-transform:uppercase;letter-spacing:.4px;margin-bottom:6px;}
.page-mm .filter-form .flt-chips{margin:0 0 12px;}
.page-mm .filter-actions{display:flex;gap:10px;margin-top:4px;align-items:center;}
.page-mm .filter-actions .btn-primary{padding:9px 22px;border-radius:10px;font-size:13px;font-family:var(--mm-font-body);font-weight:700;display:inline-flex;align-items:center;}
.page-mm .filter-actions .btn-secondary{padding:9px 18px;border-radius:10px;border:2px solid var(--border-strong);background:var(--surface);color:var(--mm-ink);font-family:var(--mm-font-body);font-size:13px;font-weight:700;text-decoration:none;display:inline-flex;align-items:center;cursor:pointer;}
.page-mm .filter-actions .btn-secondary:hover{border-color:var(--brand);color:var(--mm-ink);}
/* Targeted override: outranks this page's own unconditional filter-form padding
   (above) on phones, where the shared compact block wants 12px instead. */
@media (max-width:768px){
  .page-mm .filter-form.filter-form--compact{padding:12px;}
}

/* ===== Menu Matrix — price spread (.page-ms) — menu/matrix_spread.php =====
   --ms-* are aliases onto the real tokens, same accent/ink/muted/line/card family as
   .page-mm (its sibling view) — no page-private colour values left. */
.page-ms{--ms-accent:var(--brand-dark);--ms-diff:var(--danger);--ms-ink:var(--text);--ms-muted:var(--muted);--ms-line:var(--border-soft);--ms-card:var(--surface);
  --ms-ft:'Montserrat',sans-serif;--ms-fb:'Inter',sans-serif;}
.page-ms{background:var(--bg);font-family:var(--ms-fb);color:var(--ms-ink);}
.page-ms .container{max-width:1100px;margin:0 auto;padding:22px 18px 40px;}
.page-ms .card{background:var(--ms-card);border-radius:15px;box-shadow:var(--shadow-card);margin-bottom:14px;padding:0;}
.page-ms .ms-head{padding:16px 20px;display:flex;align-items:flex-start;gap:14px;flex-wrap:wrap;}
.page-ms .ms-head h1{font-family:var(--ms-ft);font-size:22px;font-weight:800;letter-spacing:-.5px;margin:0;}
.page-ms .ms-head .sub{color:var(--ms-muted);font-size:13px;margin-top:3px;}
.page-ms .ms-head .sp{flex:1 1 auto;}
.page-ms .ms-back{align-self:center;border:2px solid var(--ms-line);border-radius:10px;padding:7px 14px;font-size:12.5px;font-weight:700;color:var(--ms-ink);text-decoration:none;}
.page-ms .ms-back:hover{border-color:var(--ms-accent);color:var(--ms-accent);}
.page-ms .ms-head .ms-count{align-self:center;display:inline-flex;align-items:center;gap:7px;font-size:12.5px;font-weight:800;text-transform:uppercase;letter-spacing:.3px;color:var(--text-inverse);background:var(--ms-diff);border-radius:999px;padding:6px 14px;box-shadow:0 2px 8px color-mix(in srgb, var(--ms-diff) 40%, transparent);}
.page-ms .ms-head .ms-count.zero{background:var(--success-bg);color:var(--success-ink);box-shadow:none;}
.page-ms .ms-flt{padding:2px 20px 16px;}
@media (max-width:768px){ .page-ms .ms-flt.filter-form--compact{padding:12px} }
.page-ms .ms-flt-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(175px,1fr));gap:11px;margin-bottom:12px;}
.page-ms .filter-group > label{display:block;font-size:10.5px;font-weight:700;color:var(--ms-muted);text-transform:uppercase;letter-spacing:.4px;margin-bottom:5px;}
.page-ms .ms-flt .flt-chips{margin:2px 0 12px;}
.page-ms .ms-flt .btn-primary{padding:9px 24px;border-radius:10px;font-size:13px;font-weight:700;}
.page-ms .ms-flt-actions{display:flex;gap:8px;flex-wrap:wrap;}
.page-ms .ms-btn-reset{padding:9px 16px;border-radius:10px;border:none;background:color-mix(in srgb, var(--ms-accent) 12%, var(--surface));color:var(--ms-ink);font:inherit;font-size:13px;font-weight:700;cursor:pointer;text-decoration:none;display:inline-flex;align-items:center;}
.page-ms .ms-btn-export{padding:9px 18px;border-radius:10px;border:2px solid var(--success-border);background:var(--success-bg);color:var(--success-ink);font:inherit;font-size:13px;font-weight:700;cursor:pointer;display:inline-flex;align-items:center;gap:6px;margin-inline-start:auto;}
.page-ms .ms-btn-export:hover{background:color-mix(in srgb, var(--success) 18%, var(--surface));border-color:var(--success-ink);}
.page-ms .ms-toolbar{padding:10px 20px 12px;display:flex;flex-wrap:wrap;gap:9px;align-items:center;border-top:1px solid var(--border-soft);}
.page-ms .ms-search{flex:0 0 auto;width:260px;max-width:100%;border:2px solid var(--ms-line);border-radius:10px;padding:8px 12px;font:inherit;font-size:13px;background:var(--surface-2);}
.page-ms .ms-search:focus{border-color:var(--ms-accent);background:var(--surface);outline:none;}
.page-ms .ms-showing{color:var(--ms-muted);font-size:12px;font-weight:600;margin-inline-start:auto;white-space:nowrap;}
.page-ms .ms-wrap{overflow:auto;max-height:78vh;border-radius:15px;}
.page-ms table{width:100%;border-collapse:separate;border-spacing:0;font-size:13px;}
.page-ms thead th{position:sticky;top:0;z-index:2;background:var(--surface-2);text-align:start;padding:9px 14px;font-size:10.5px;font-weight:700;text-transform:uppercase;letter-spacing:.3px;color:var(--ms-muted);border-bottom:2px solid var(--ms-line);white-space:nowrap;}
.page-ms tbody td{padding:9px 14px;border-bottom:1px solid var(--border-soft);vertical-align:middle;}
.page-ms tbody tr:hover td{background:var(--danger-bg);}
.page-ms .ms-brand a{color:var(--ms-ink);font-weight:700;text-decoration:none;}
.page-ms .ms-brand a:hover{color:var(--ms-accent);}
.page-ms .ms-cc{font-size:9.5px;font-weight:700;color:var(--ms-muted);background:var(--ms-line);border-radius:5px;padding:1px 5px;margin-inline-start:6px;}
.page-ms .ms-item{font-weight:500;}
.page-ms .ms-pill{display:inline-flex;align-items:center;padding:2px 9px;border-radius:8px;font-size:10.5px;font-weight:700;color:var(--on-accent);}
.page-ms .ms-pill--default{background:var(--surface-3);color:var(--ms-ink);}
.page-ms .ms-range{font-variant-numeric:tabular-nums;white-space:nowrap;}
.page-ms .ms-range .lo{font-weight:700;} .page-ms .ms-range .hi{font-weight:700;color:var(--ms-diff);}
.page-ms .ms-spread{font-weight:900;font-variant-numeric:tabular-nums;color:var(--text-inverse);background:var(--ms-diff);border-radius:7px;padding:2px 8px;white-space:nowrap;}
.page-ms .ms-stores{color:var(--ms-muted);white-space:nowrap;}
.page-ms .ms-open{color:var(--ms-accent);font-weight:600;text-decoration:none;white-space:nowrap;}
.page-ms .ms-open:hover{text-decoration:underline;}
.page-ms .empty{padding:44px 20px;text-align:center;}
.page-ms .empty .big{font-family:var(--ms-ft);font-size:17px;font-weight:800;color:var(--success-ink);}
.page-ms .empty p{color:var(--ms-muted);margin-top:6px;font-size:13px;}
.page-ms .ms-note{color:var(--ms-muted);font-size:11.5px;font-style:italic;padding:10px 20px;}
.page-ms .ms-noresults{padding:34px 20px;text-align:center;color:var(--ms-muted);font-size:13px;font-style:italic;}
.page-ms .ms-noresults[hidden]{display:none;}
.page-ms .ms-pager{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:10px;padding:12px 20px;border-top:1px solid var(--border-soft);}
.page-ms .ms-pginfo{color:var(--ms-muted);font-size:12.5px;font-weight:600;}
.page-ms .ms-pgnav{display:flex;align-items:center;gap:5px;}
.page-ms .ms-pg{min-width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center;border:2px solid var(--ms-line);border-radius:8px;color:var(--ms-ink);text-decoration:none;font-size:15px;font-weight:700;}
.page-ms .ms-pg:hover{border-color:var(--ms-accent);color:var(--ms-accent);}
.page-ms .ms-pg.off{opacity:.4;pointer-events:none;}
.page-ms .ms-pgcur{font-size:12.5px;font-weight:700;color:var(--ms-ink);padding:0 8px;white-space:nowrap;}
@media (max-width:640px){
  .page-ms .container{padding:12px 8px 30px;}
  .page-ms td.hide-sm,.page-ms th.hide-sm{display:none;}
}

/* ===== Menu-empty banner (.mn-emptybanner) — menu/_menu_empty_banner.php =====
   Rendered by both menu/matrix.php and menu/matrix_spread.php (a partial, no page
   wrapper of its own) — global/unprefixed by design, on --danger* tokens keeping its
   own dark-red character (a dark banner stays dark, not lightened to --danger-bg).
   --eb-fill/--eb-border mix --danger with --appbar, NOT --text: --text flips light
   in the dark theme (near-white), which would turn the fill near-white too — --appbar
   is a dark charcoal in BOTH themes (#454343 / #2a2928), keeping the fill genuinely
   dark either way. Contrast, light/dark theme: --on-accent (white) on --eb-fill ≈
   8.27:1 / 6.86:1; the danger ink mixes below (color-mix(danger, text)/(danger, muted)
   on --surface/--danger-bg — both flip together, so they stay readable) ≈ 4.77–8.32:1
   light, ≈ 5.77–9.55:1 dark — all clear 4.5:1 in both themes. */
.mn-emptybanner{--eb-fill:color-mix(in srgb, var(--danger) 40%, var(--appbar));--eb-border:color-mix(in srgb, var(--danger) 25%, var(--appbar));
  margin:0 0 14px;border-radius:11px;overflow:hidden;background:var(--eb-fill);
  box-shadow:0 2px 10px color-mix(in srgb, var(--danger) 35%, transparent);border:1px solid var(--eb-border);}
.card > .mn-emptybanner{margin:0 0 12px;}
.mn-emptybanner > summary{list-style:none;cursor:pointer;display:flex;align-items:center;gap:9px;
  padding:11px 18px;color:var(--on-accent);font-size:13px;font-weight:800;letter-spacing:.1px;}
.mn-emptybanner > summary::-webkit-details-marker{display:none;}
.mn-emptybanner > summary::before{content:"\26A0";font-size:15px;flex:0 0 auto;}
.mn-emptybanner > summary::after{content:"\25BE";margin-inline-start:auto;opacity:.85;font-size:11px;transition:transform .15s;}
.mn-emptybanner[open] > summary::after{transform:rotate(180deg);}
.mn-emptybanner .db-sub{font-weight:600;opacity:.9;}
.mn-emptybanner .mn-emptylist{background:var(--surface);color:color-mix(in srgb, var(--danger) 60%, var(--text));padding:10px 18px 14px;max-height:320px;overflow:auto;}
.mn-emptybanner .mn-emptynote{font-size:12px;color:color-mix(in srgb, var(--danger) 45%, var(--text));font-style:italic;margin-bottom:9px;}
.mn-emptybanner .mn-emptyrow{font-size:12.5px;padding:4px 0;border-bottom:1px solid var(--danger-border);}
.mn-emptybanner .mn-emptyrow:last-child{border-bottom:none;}
.mn-emptybanner .mn-emptyrow b{font-weight:700;color:var(--danger);}
.mn-emptybanner .mn-emptyrow .cc{font-size:9.5px;font-weight:700;color:color-mix(in srgb, var(--danger) 30%, var(--muted));background:var(--danger-bg);border-radius:5px;padding:1px 5px;}
.mn-emptybanner .mn-emptyrow .eid{color:color-mix(in srgb, var(--danger) 25%, var(--muted));font-variant-numeric:tabular-nums;}
.mn-emptybanner .mn-emptymore{font-size:12px;color:color-mix(in srgb, var(--danger) 45%, var(--text));font-weight:700;padding-top:8px;}

/* Brand ID display */
.page-monitor .agg-brand-id { font-size: 10px; color: var(--muted); font-weight: 600; font-variant-numeric: tabular-nums; margin-inline-start: 4px; }
.page-monitor.compact-mode .agg-brand-id { display: none !important; }
.page-monitor .mt-brand-id { font-size: 10px; color: var(--muted); margin-inline-start: 4px; }
.page-offline-report .brand-id-cell { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* transitions-cell: dead — see the .report-table note above (app.css ~1320), same
   pre-heatmap leftover; grepped, unused anywhere in app/Views or public/js. */

/* ===== StatusById: table + filters ===== */
.page-status-by-id .rest-search { position: relative; }
.page-status-by-id .rest-search-input { width: 100%; padding: 10px 12px; border: 2px solid var(--border-strong); border-radius: 8px; font-size: 14px; background: var(--surface); color: var(--text); }
.page-status-by-id .rest-search-input:focus { outline: none; border-color: var(--brand); }
.page-status-by-id .rest-search-input::placeholder { color: var(--muted); }
.page-status-by-id .rest-search-dropdown { display: none; position: absolute; top: calc(100% + 4px); left: 0; right: 0; background: var(--surface); border: 2px solid var(--border-strong); border-radius: 8px; max-height: 320px; overflow-y: auto; z-index: 50; box-shadow: var(--shadow-dropdown); }
.page-status-by-id .rest-search-dropdown.open { display: block; }
.page-status-by-id .rest-search-item { padding: 10px 14px; cursor: pointer; display: flex; justify-content: space-between; align-items: center; gap: 12px; border-bottom: 1px solid var(--border-soft); }
.page-status-by-id .rest-search-item:last-child { border-bottom: none; }
.page-status-by-id .rest-search-item:hover { background: color-mix(in srgb, var(--brand) 12%, var(--surface)); }
.page-status-by-id .rest-search-name { font-weight: 600; color: var(--text); font-size: 13px; }
.page-status-by-id .rest-search-area { font-size: 12px; color: var(--muted); white-space: nowrap; }

/* Multi-select styling comes from the shared component block near the top of this file
   (page copy removed here — Task 2: it duplicated the global look and, being declared
   later, beat .multi-select-option.ms-zero, un-muting zero-count options). */

/* ===== StatusById: Heatmap Minimal =====
   4-step status scale: hm-on (good) = --success, hm-off (a full hour offline) =
   --danger, hm-mix (had a transition but recovered within the hour) = --warn.
   hm-na (genuinely no data) is NOT a severity, so it does not get --caution (a
   step reserved for something worse than --warn) — it stays in the same warn
   FAMILY (original background was identical, #fef3c7 for both), but keeps its
   own duller/darker text so it doesn't read as the same alert as hm-mix: the
   pre-refactor colours were #b07100 (mix) vs #8a6100 (na, darker) — reproduced
   as --warn vs. --warn mixed 70% with --text (theme-aware duller version). */
.page-status-by-id .hm-wrap { overflow-x: auto; overflow-y: auto; max-height: 75vh; background: var(--surface); border-radius: 12px; box-shadow: 0 1px 6px color-mix(in srgb, var(--text) 6%, transparent); border: 1px solid var(--border); }
.page-status-by-id .hm-table { width: 100%; border-collapse: separate; border-spacing: 2px; font-size: 12px; }
.page-status-by-id .hm-table thead th { position: sticky; top: 0; z-index: 10; background: var(--surface); padding: 8px 4px; text-align: center; font-size: 11px; color: var(--muted); font-weight: 600; border-bottom: 2px solid var(--border); }
.page-status-by-id .hm-th-hour { text-align: start !important; padding-inline-start: 10px !important; width: 55px; min-width: 55px; }
.page-status-by-id .hm-badge { display: inline-block; padding: 3px 10px; border-radius: 5px; font-size: 11px; font-weight: 700; white-space: nowrap; box-shadow: inset 0 1px 0 color-mix(in srgb, var(--on-accent) 25%, transparent), 0 1px 2px color-mix(in srgb, var(--text) 8%, transparent); }
.page-status-by-id .hm-badge--default { background: var(--surface-3); color: var(--text); }
.page-status-by-id .hm-day-label td { background: var(--surface-2); font-weight: 700; color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px; padding: 7px 10px; position: sticky; top: 36px; z-index: 5; }
.page-status-by-id .hm-day-sched-range { font-weight: 400; color: var(--muted); font-size: 10px; }
.page-status-by-id .hm-day-gap td { height: 6px; background: transparent; padding: 0; }
.page-status-by-id .hm-hour { text-align: start; padding: 5px 10px !important; font-weight: 600; color: var(--muted); font-variant-numeric: tabular-nums; background: var(--bg); border-radius: 4px; }
.page-status-by-id .hm-cell { text-align: center; border-radius: 4px; padding: 5px 3px; font-weight: 700; font-size: 11px; cursor: default; position: relative; transition: outline 0.1s; }
.page-status-by-id .hm-cell[title] { cursor: pointer; }
.page-status-by-id .hm-cell:hover { outline: 2px solid var(--brand); z-index: 2; }
.page-status-by-id .hm-on { background: var(--success-bg); color: var(--success-ink); }
.page-status-by-id .hm-off { background: var(--danger-bg); color: var(--danger); }
.page-status-by-id .hm-mix { background: var(--warn-bg); color: var(--warn-ink); }
/* No data: the same tint as .hm-mix, its ink greyed toward --muted (plus italic/500) so the two
   stay apart once .hm-mix moved to --warn-ink; 5.5:1 on --warn-bg. */
.page-status-by-id .hm-na { background: var(--warn-bg); color: color-mix(in srgb, var(--warn-ink) 60%, var(--muted)); font-style: italic; font-weight: 500; }
.page-status-by-id .hm-dot { display: inline-block; width: 5px; height: 5px; background: var(--success); border-radius: 50%; margin-inline-start: 3px; vertical-align: super; }
.page-status-by-id .hm-legend { display: flex; gap: 16px; flex-wrap: wrap; padding: 10px 14px; font-size: 11px; color: var(--muted); margin-top: 8px; }
.page-status-by-id .hm-legend-item { display: flex; align-items: center; gap: 5px; }
.page-status-by-id .hm-legend i { width: 14px; height: 14px; border-radius: 3px; display: inline-block; }
.page-status-by-id .hm-leg-on { background: var(--success-bg); }
.page-status-by-id .hm-leg-off { background: var(--danger-bg); }
.page-status-by-id .hm-leg-mix { background: var(--warn-bg); }
.page-status-by-id .hm-leg-na { background: var(--warn-bg); border: 1px dashed var(--warn); }
.page-status-by-id .hm-dot-legend { display: inline-block; width: 5px; height: 5px; background: var(--success); border-radius: 50%; }

/* StatusById: single transition shown inline */
.page-status-by-id .hm-time { font-size: 10px; font-weight: 700; color: var(--success-ink); }
/* StatusById: multi transition cell (clickable) */
.page-status-by-id .hm-multi { font-size: 11px; font-weight: 800; color: var(--warn-ink); }
.page-status-by-id .hm-clickable { cursor: pointer; }
.page-status-by-id .hm-clickable:hover { outline: 2px solid var(--warn); }
/* ===== StatusById: Transition Modal v3 =====
   Wave D Task 2: #hmModal/.hm-modal also carry .kc-modal-backdrop/.kc-modal-panel
   (markup) — background/radius/shadow/backdrop tint now come from that shared layer;
   .hm-modal-backdrop's own display/position/background/z-index rule is gone entirely
   (fully superseded, including its .open companion — the shared
   .kc-modal-backdrop.open{display:flex} covers the same class toggle). .hm-modal keeps
   only its own width/overflow; `overflow: hidden` was dropped too (verified no child
   here paints an opaque background against the panel's rounded top/bottom edge, so it
   was never load-bearing) so the shared layer's ≤768px `max-height: 90dvh; overflow:
   auto;` can actually scroll instead of being fought by an unconditional `hidden`. */
.hm-modal { width: 460px; max-width: 94vw; }
.hm-modal-head { display: flex; justify-content: space-between; align-items: flex-start; padding: 20px 24px 14px; }
.hm-modal-head h3 { margin: 0; font-size: 18px; font-weight: 700; color: var(--text); }
.hm-modal-sub { font-size: 13px; color: var(--muted); margin-top: 3px; }
.hm-modal-close { background: var(--surface-2); border: none; width: 32px; height: 32px; border-radius: 8px; font-size: 18px; cursor: pointer; color: var(--muted); display: flex; align-items: center; justify-content: center; }
.hm-modal-close:hover { background: var(--border); color: var(--text); }
.hm-modal-summary { padding: 10px 24px; background: var(--surface-2); border-top: 1px solid var(--border-soft); border-bottom: 1px solid var(--border-soft); }
.hm-modal-sum-row { display: flex; justify-content: space-between; align-items: center; gap: 8px; flex-wrap: wrap; }
.hm-modal-sum-label { font-size: 13px; font-weight: 600; color: var(--text); }
.hm-modal-sum-count { font-size: 12px; color: var(--muted); }
.hm-modal-body { padding: 20px 24px; max-height: 400px; overflow-y: auto; }

/* Timeline: event rows + duration rows */
.hm-modal-item { display: grid; grid-template-columns: 28px 1fr; align-items: start; }
.hm-modal-marker { width: 14px; height: 14px; border-radius: 50%; margin: 2px auto 0; }
.hm-marker-off { background: var(--danger); box-shadow: 0 0 0 4px var(--danger-bg); }
.hm-marker-on { background: var(--success); box-shadow: 0 0 0 4px var(--success-bg); }
.hm-modal-content { padding-bottom: 2px; }
.hm-modal-time { font-size: 20px; font-weight: 800; color: var(--text); font-variant-numeric: tabular-nums; letter-spacing: -0.5px; }
.hm-modal-label { font-size: 12px; font-weight: 600; margin-top: 1px; display: block; }
.hm-modal-label.hm-ml-off { color: var(--danger); }
.hm-modal-label.hm-ml-on { color: var(--success); }

/* Duration row */
.hm-modal-dur-wrap { padding: 6px 0; }
.hm-modal-vline { width: 2px; height: 100%; min-height: 16px; background: var(--border); margin: 0 auto; border-radius: 1px; }
.hm-modal-dur { font-size: 11px; font-weight: 700; padding: 2px 10px; border-radius: 10px; }
.hm-dur-off { background: var(--danger-bg); color: var(--danger); }
.hm-dur-on { background: var(--success-bg); color: var(--success-ink); }

/* StatusById: schedule open/close lines */
.page-status-by-id .hm-outside .hm-cell { opacity: 0.3; }
.page-status-by-id .hm-outside .hm-hour { opacity: 0.4; }
.page-status-by-id .hm-sched-open td { border-top: 3px solid var(--success) !important; }
.page-status-by-id .hm-sched-open .hm-hour { color: var(--success-ink) !important; font-weight: 800; }
.page-status-by-id .hm-sched-close td { border-bottom: 3px solid var(--danger) !important; }
.page-status-by-id .hm-sched-close .hm-hour { color: var(--danger) !important; font-weight: 800; }

/* ─── Page loader (Calculating overlay) ───────────────────────────────────
   Фирменная плашка: крутится марка из kitchain-logo-lime.svg, шрифты по
   брендбуку (Montserrat на слове, Inter на подписи), громкий лайм #B8FF5A
   заливкой в паре с почти чёрным — как книга бренда и предписывает. Прежние
   синий/фиолетовый/зелёный и Share Tech Mono к бренду отношения не имели. */

.kc-loader-overlay {
    position: fixed;
    inset: 0;
    background: rgba(38, 37, 35, 0.62);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    display: none;
    align-items: center;
    justify-content: center;
    z-index: 9999;
}
.kc-loader-overlay.is-active { display: flex; }

.kc-loader-card {
    background: #262523;
    border: 1px solid rgba(184, 255, 90, 0.22);
    border-radius: 14px;
    box-shadow: 0 14px 40px rgba(0, 0, 0, 0.30);
    padding: 24px 34px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 16px;
    position: relative;
}

.kc-loader-card .corner {
    position: absolute;
    width: 9px;
    height: 9px;
    border-color: #B8FF5A;
    border-style: solid;
}
.kc-loader-card .corner.tl { top: 9px; left: 9px;     border-width: 1.5px 0 0 1.5px; }
.kc-loader-card .corner.tr { top: 9px; right: 9px;    border-width: 1.5px 1.5px 0 0; }
.kc-loader-card .corner.bl { bottom: 9px; left: 9px;  border-width: 0 0 1.5px 1.5px; }
.kc-loader-card .corner.br { bottom: 9px; right: 9px; border-width: 0 1.5px 1.5px 0; }

/* Марка вращается рывками, как секундная стрелка: ровное вращение на
   вырезанной четверти читается вяло. */
.kc-loader-card .kc-mark {
    width: 54px;
    height: 54px;
    animation: kcSpin 1.5s cubic-bezier(0.65, 0.05, 0.36, 1) infinite;
}
.kc-loader-card .kc-mark svg { width: 100%; height: 100%; display: block; }
.kc-loader-card .kc-mark .kc-mark-track {
    fill: none;
    stroke: #B8FF5A;
    stroke-opacity: 0.18;
    stroke-width: 14;
}
.kc-loader-card .kc-mark .kc-mark-disc { fill: #B8FF5A; }

@keyframes kcSpin { to { transform: rotate(360deg); } }

.kc-loader-card .text-block { text-align: center; display: flex; flex-direction: column; gap: 5px; }

.kc-loader-card .calc-label {
    font-family: 'Inter', -apple-system, sans-serif;
    font-size: 9px;
    font-weight: 600;
    letter-spacing: 0.22em;
    color: rgba(255, 255, 255, 0.45);
    text-transform: uppercase;
}

.kc-loader-card .calc-word {
    font-family: 'Montserrat', 'Inter', sans-serif;
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.22em;
    color: rgba(255, 255, 255, 0.82);
    text-transform: uppercase;
    display: flex;
    align-items: center;
}
.kc-loader-card .calc-word > span { display: inline-block; animation: kcLetterFade 2s ease-in-out infinite; }
.kc-loader-card .calc-word > span:nth-child(1)  { animation-delay: 0s; }
.kc-loader-card .calc-word > span:nth-child(2)  { animation-delay: 0.1s; }
.kc-loader-card .calc-word > span:nth-child(3)  { animation-delay: 0.2s; }
.kc-loader-card .calc-word > span:nth-child(4)  { animation-delay: 0.3s; }
.kc-loader-card .calc-word > span:nth-child(5)  { animation-delay: 0.4s; }
.kc-loader-card .calc-word > span:nth-child(6)  { animation-delay: 0.5s; }
.kc-loader-card .calc-word > span:nth-child(7)  { animation-delay: 0.6s; }
.kc-loader-card .calc-word > span:nth-child(8)  { animation-delay: 0.7s; }
.kc-loader-card .calc-word > span:nth-child(9)  { animation-delay: 0.8s; }
.kc-loader-card .calc-word > span:nth-child(10) { animation-delay: 0.9s; }
.kc-loader-card .calc-word > span:nth-child(11) { animation-delay: 1.0s; }

@keyframes kcLetterFade {
    0%, 100% { color: rgba(255, 255, 255, 0.82); }
    50%      { color: #B8FF5A; }
}

.kc-loader-card .calc-word .dots {
    color: #B8FF5A;
    width: 34px;
    text-align: start;
    display: inline-block;
    animation: none;
}

.kc-loader-card .progress-bar {
    width: 150px;
    height: 2px;
    background: rgba(184, 255, 90, 0.16);
    border-radius: 2px;
    overflow: hidden;
}
.kc-loader-card .progress-fill {
    height: 100%;
    border-radius: 2px;
    background: linear-gradient(90deg, #B8FF5A, #ffffff);
    animation: kcProgress 2.2s ease-in-out infinite;
}

@keyframes kcProgress {
    0%   { width: 0%;  margin-inline-start: 0%; }
    50%  { width: 60%; margin-inline-start: 20%; }
    100% { width: 0%;  margin-inline-start: 100%; }
}

/* Кому движение мешает — плашка остаётся, но замирает. */
@media (prefers-reduced-motion: reduce) {
    .kc-loader-card .kc-mark,
    .kc-loader-card .calc-word > span,
    .kc-loader-card .progress-fill { animation: none; }
    .kc-loader-card .progress-fill { width: 60%; }
}

/* Header global report-scope toggle (Active / All restaurants) */
.header-scope-form { display: flex; align-items: center; margin-inline-end: 14px; }
.header-scope-toggle {
    display: inline-flex;
    padding: 2px;
    border: 1px solid color-mix(in srgb, var(--on-accent) 30%, transparent);
    border-radius: 999px;
    background: transparent;
    cursor: pointer;
    opacity: 0.85;
}
.header-scope-toggle:hover { opacity: 1; }
.header-scope-toggle .scope-opt {
    padding: 1px 10px;
    border-radius: 999px;
    font-size: 12px;
    line-height: 18px;
    color: color-mix(in srgb, var(--on-accent) 55%, transparent);
}
.header-scope-toggle .scope-opt.on {
    background: color-mix(in srgb, var(--on-accent) 22%, transparent);
    color: var(--on-accent);
    font-weight: 600;
}

/* User settings: paused restaurants (informational, no controls) */
.restaurant-block--inactive { opacity: 0.55; }
.inactive-badge {
    display: inline-block;
    margin-inline-start: 8px;
    padding: 1px 8px;
    border-radius: 999px;
    background: var(--surface-3);
    color: var(--muted);
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    vertical-align: middle;
}

/* Infrastructure Map — full-bleed graph with floating overlays */
.page-infra-full { padding:0; }
/* break out of .app-main max-width to span the full viewport */
.infra-wrap { position:relative; width:100vw; margin-inline-start:calc(50% - 50vw); }
.infra-graph { width:100%; height:calc(100vh - 120px); min-height:480px; background:var(--card); border-top:1px solid var(--border); border-bottom:1px solid var(--border); }
.infra-overlay { position:absolute; z-index:6; background:color-mix(in srgb, var(--surface) 96%, transparent); border:1px solid var(--border); border-radius:10px; box-shadow:var(--shadow-dropdown); }
.infra-legend-wrap { top:14px; left:14px; min-width:172px; }
.infra-detail-wrap { top:14px; right:14px; width:248px; max-height:64%; overflow:auto; padding:10px 14px; }
/* Phones: the two overlays need 448px side by side — dock the detail card to
   the bottom edge instead of overlapping the legend. */
@media (max-width: 600px) {
  .infra-legend-wrap { min-width: 0; }
  .infra-detail-wrap { top: auto; bottom: 14px; left: 14px; right: 14px; width: auto; max-height: 40%; }
}
.infra-toggle { background:none; border:0; cursor:pointer; font-weight:600; font-size:13px; padding:9px 14px; width:100%; text-align:start; color:var(--text); }
.infra-toggle .caret { display:inline-block; width:12px; color:var(--muted); }
.infra-legend { padding:2px 14px 12px; }
.infra-legend h4 { margin:8px 0 4px; font-size:11px; text-transform:uppercase; color:var(--muted); }
.infra-legend .lg { display:flex; align-items:center; gap:8px; font-size:13px; margin:4px 0; }
.infra-legend .lg-sw { width:14px; height:14px; border-radius:4px; display:inline-block; flex:0 0 auto; }
.infra-legend .lg-ring { width:14px; height:14px; border-radius:50%; border:3px solid; background:var(--text); display:inline-block; flex:0 0 auto; box-sizing:border-box; }
.infra-detail h3 { margin:0 0 8px; font-size:15px; }
.infra-detail p { margin:4px 0; font-size:13px; }
.infra-status { position:absolute; bottom:14px; left:14px; z-index:6; background:color-mix(in srgb, var(--surface) 92%, transparent); padding:3px 9px; border-radius:6px; font-size:12px; color:var(--muted); }

/* VPN Endpoints table — self-contained. Do NOT inherit .traffic-table: its
   td:nth-child(4) column highlight breaks under rowspan node-grouping (the omitted
   node <td> shifts the child index, so the pink jumps between Status and Requests). */
.page-realtime-control-panel .vpn-table {
  width: 100%; border-collapse: collapse; font-size: 12px; font-variant-numeric: tabular-nums;
}
.page-realtime-control-panel .vpn-table th {
  text-align: end; padding: 6px 8px; font-weight: 700; color: var(--muted);
  border-bottom: 2px solid var(--border-soft); font-size: 11px; text-transform: uppercase; letter-spacing: 0.3px;
}
.page-realtime-control-panel .vpn-table td {
  text-align: end; padding: 6px 8px; vertical-align: middle; border-bottom: 1px solid var(--border-soft);
}
.page-realtime-control-panel .vpn-table .ta-left,
.page-realtime-control-panel .vpn-table .vpn-ip-cell { text-align: start; }
.page-realtime-control-panel .vpn-agg-row { background: var(--surface-2); color: var(--muted); font-style: italic; }
.page-realtime-control-panel .vpn-tag { font-size: 10px; background: var(--info-bg); color: var(--info); border-radius: 6px; padding: 1px 5px; margin-inline-start: 4px; }
.page-realtime-control-panel .vpn-okpct { color: var(--muted); font-size: 11px; }
/* node grouping: node cell spans its channels; a separator line starts each node group */
.page-realtime-control-panel .vpn-node-cell { vertical-align: top; font-weight: 600; white-space: nowrap; }
.page-realtime-control-panel .vpn-node-start > td { border-top: 2px solid var(--border-soft); }
/* grand total row (distinct from the SOAX aggregate row) */
.page-realtime-control-panel .vpn-total-row td { font-weight: 700; border-top: 2px solid var(--border-strong); background: var(--surface-2); }
/* exit-IP copy icon: hover shows IP (title), click copies */
.page-realtime-control-panel .vpn-ip-copy { cursor: pointer; color: var(--muted); display: inline-flex; vertical-align: middle; }
.page-realtime-control-panel .vpn-ip-copy:hover { color: var(--info); }
.page-realtime-control-panel .vpn-ip-copy.copied { color: var(--success); }

/* ─── Aggregator skip-status dot (used in list badges & edit form headers) ─── */
.agg-badge-wrap { position: relative; display: inline-block; }
.agg-status-dot {
  display: inline-flex; align-items: center; justify-content: center;
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--danger); color: var(--text-inverse);
  font-size: 10px; font-weight: 700; line-height: 1;
  border: 2px solid var(--surface);
  box-shadow: 0 0 0 1px var(--danger);
  cursor: help;
  vertical-align: middle;
}
.agg-badge-wrap .agg-status-dot {
  position: absolute; top: -5px; inset-inline-end: -6px;
}
.agg-header .agg-status-dot { position: static; margin-inline-start: 6px; }
.spark-show-btn {
    font-size: 11px;
    padding: 1px 6px;
    border: 1px solid var(--border);
    border-radius: 4px;
    background: var(--surface);
    color: var(--muted);
    cursor: pointer;
}
.spark-show-btn:hover { background: var(--surface-2); }

/* ============ Menu section (.page-menu) — promo-snapshot-grade styling ============ */
/* --mn-* local aliases resolve to global tokens: --mn-card/--mn-muted/--mn-radius/--mn-shadow
   have an exact global counterpart (spec 2026-09-22); --mn-accent/--mn-accent-light/--mn-warn
   have no 1:1 token and are derived with color-mix() from the nearest role token instead. */
.page-menu { --mn-accent:var(--brand-dark); --mn-accent-light:color-mix(in srgb, var(--cta) 20%, var(--surface)); --mn-fill:var(--cta); --mn-fill-ink:var(--cta-text); --mn-danger:var(--danger); --mn-danger-light:var(--danger-bg); --mn-success:var(--cta); --mn-success-dark:var(--success-ink); --mn-warn:color-mix(in srgb, var(--warn) 25%, var(--surface)); --mn-warn-dark:var(--warn-ink); --mn-warn-light:var(--warn-bg); --mn-text:var(--text); --mn-muted:var(--muted); --mn-bg:var(--bg); --mn-card:var(--surface); --mn-border:var(--border); --mn-radius:var(--radius-lg); --mn-shadow:var(--shadow-card); --mn-font-title:'Montserrat',sans-serif; --mn-font-body:'Inter',sans-serif; }
body:has(.page-menu) { background: var(--bg) !important; }
body:has(.page-menu) .app-header { background: linear-gradient(135deg, var(--appbar) 0%, color-mix(in srgb, var(--appbar) 75%, var(--text)) 100%); }
.page-menu { font-family: var(--mn-font-body); color: var(--mn-text); }
.page-menu .container { max-width:1200px; margin:0 auto; padding:28px 24px; }

/* Header card — title + meta + date navigator, like ps-hdr */
.page-menu .page-header { display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:16px; background:var(--mn-card); border-radius:var(--mn-radius); padding:24px; box-shadow:var(--mn-shadow); margin-bottom:20px; }
.page-menu .page-header h2 { font-family:var(--mn-font-title); font-size:24px; font-weight:800; letter-spacing:-.5px; color:var(--mn-text); margin:0; }
.page-menu .page-header p { font-size:14px; color:var(--mn-muted); margin-top:2px; }
.page-menu .mn-hdr-title { min-width:0; }

/* Section headings — promo typography (no markup change needed) */
.page-menu h3 { font-family:var(--mn-font-title); font-size:16px; font-weight:700; color:var(--mn-text); margin:22px 0 12px; }
.page-menu h3:first-child { margin-top:0; }
.page-menu h4 { font-family:var(--mn-font-title); font-size:12px; font-weight:700; color:var(--mn-muted); text-transform:uppercase; letter-spacing:.4px; margin:18px 0 8px; }
.page-menu .mn-country-h { font-family:var(--mn-font-title); font-size:15px; font-weight:700; color:var(--mn-accent); margin:22px 0 8px; }

/* Date navigator */
.page-menu .mn-datebar { display:flex; gap:6px; align-items:center; margin:0; flex-wrap:wrap; }
.page-menu .mn-dateform input[type=date],
.page-menu input[type=date] { padding:8px 12px; border:2px solid var(--mn-border); border-radius:10px; font-family:var(--mn-font-body); font-size:13px; font-weight:600; color:var(--mn-text); background:var(--mn-card); }
.page-menu input[type=date]:focus { border-color:var(--mn-accent); outline:none; }
.page-menu a.mn-dt-btn.btn-secondary { width:36px; height:36px; padding:0; border-radius:10px; border:2px solid var(--mn-border); background:var(--mn-card); color:var(--mn-text); font-size:16px; font-weight:700; display:inline-flex; align-items:center; justify-content:center; }
.page-menu a.mn-dt-btn.btn-secondary:hover { border-color:var(--mn-accent); color:var(--mn-accent); background:var(--mn-card); }
.page-menu a.mn-dt-latest.btn-secondary { padding:8px 18px; border-radius:10px; border:none; background:var(--cta); color:var(--cta-text); font-size:12px; font-weight:700; }
.page-menu a.mn-dt-latest.btn-secondary:hover { background:var(--cta-hover); color:var(--cta-text); }
.page-menu .mn-export { margin-inline-start:auto; }

/* Tabs — aggregator tabs pick up --mn-agg (DB brand color) when set, else accent */
.page-menu .mn-tabs { display:flex; gap:8px; align-items:center; margin:16px 0 14px; flex-wrap:wrap; }
.page-menu .mn-tab { padding:8px 16px; border-radius:10px; border-bottom:3px solid var(--mn-agg, transparent); background:var(--mn-card); box-shadow:0 1px 4px color-mix(in srgb, var(--text) 6%, transparent); text-decoration:none; color:var(--mn-text); font-size:13px; font-weight:600; transition:all .15s; }
.page-menu .mn-tab:hover { color:var(--mn-accent); }
.page-menu .mn-tab.active { background:var(--mn-agg, var(--mn-fill)); border-color:var(--mn-agg, var(--mn-fill)); color:var(--mn-agg-ink, var(--mn-fill-ink)); box-shadow:0 2px 8px color-mix(in srgb, var(--brand) 35%, transparent); }
.page-menu .mn-basis { margin-inline-start:8px; font-size:12px; color:var(--mn-muted); }
.page-menu .mn-basis a { color:var(--mn-muted); text-decoration:none; }
.page-menu .mn-basis a.active { font-weight:700; color:var(--mn-accent); text-decoration:underline; }
.page-menu .mn-meta { color:var(--mn-muted); font-size:13px; margin:8px 0 14px; }
.page-menu .mn-meta a { color:var(--mn-muted); text-decoration:none; padding:2px 4px; }
.page-menu .mn-meta a.active { font-weight:700; color:var(--mn-accent); }

/* Table card — rounded, shadowed container with sticky header (like ps-tbl-wrap) */
.page-menu .mn-table-wrap { background:var(--mn-card); border:1px solid var(--mn-border); border-radius:var(--mn-radius); box-shadow:var(--mn-shadow); overflow:auto; max-height:74vh; margin-bottom:20px; }
.page-menu .mn-table { width:100%; border-collapse:collapse; font-size:13px; }
.page-menu .mn-table th, .page-menu .mn-table td { padding:10px 14px; border-bottom:1px solid var(--border-soft); text-align:start; white-space:nowrap; }
.page-menu .mn-table th { background:var(--surface-2); position:sticky; top:0; z-index:2; font-size:11px; font-weight:600; color:var(--mn-muted); text-transform:uppercase; letter-spacing:.3px; border-bottom:2px solid var(--mn-border); }
.page-menu .mn-table tbody tr:not(.mn-cat-row):hover td { background:var(--bg); }
.page-menu .mn-table tbody tr:not(.mn-cat-row):nth-child(even) td { background:color-mix(in srgb, var(--surface) 50%, var(--bg)); }
.page-menu .mn-table tbody tr:not(.mn-cat-row):nth-child(even):hover td { background:var(--bg); }
.page-menu .mn-drill-row:nth-child(even) td { background:var(--bg); }
.page-menu .mn-matrix td, .page-menu .mn-matrix th { text-align:center; }
.page-menu .mn-matrix td:first-child, .page-menu .mn-matrix th:first-child { text-align:start; }

/* Category / item rows */
.page-menu .mn-cat-row td { background:color-mix(in srgb, var(--brand) 14%, var(--surface)) !important; font-family:var(--mn-font-title); font-weight:700; font-size:13px; color:var(--mn-accent); border-bottom:2px solid color-mix(in srgb, var(--brand) 31%, var(--surface)) !important; }
.page-menu .mn-item-row { cursor:pointer; }
.page-menu .mn-item-row:hover td { background:var(--info-bg); }
.page-menu .mn-item-drill { cursor:pointer; }
.page-menu .mn-item-drill:hover td { background:var(--info-bg); }
.page-menu .mn-was { color:var(--mn-muted); text-decoration:line-through; margin-inline-end:6px; }
.page-menu .mn-disc { color:var(--mn-warn-dark); font-weight:700; }
.page-menu .mn-period { color:color-mix(in srgb, var(--muted) 65%, var(--surface)); font-size:.85em; }

/* Freshness chips */
.page-menu .mn-chip { display:inline-block; padding:3px 12px; border-radius:999px; font-size:11px; font-weight:700; margin-block:2px; margin-inline:0 4px; background:var(--surface-2); }
.page-menu .mn-chip-ok { background:var(--success-bg); color:var(--mn-success-dark); }
.page-menu .mn-chip-part { background:var(--mn-warn-light); color:var(--mn-warn-dark); }
.page-menu .mn-chip-stale { background:var(--mn-danger-light); color:var(--mn-danger); }
.page-menu .mn-fresh-strip { display:flex; flex-wrap:wrap; gap:4px; margin:10px 0 18px; }

/* KPI tiles (like ps-kpi) */
.page-menu .mn-kpis { display:grid; grid-template-columns:repeat(auto-fit, minmax(180px,1fr)); gap:16px; margin:14px 0 24px; }
.page-menu .mn-kpi { display:flex; flex-direction:column; background:var(--mn-card); border-radius:var(--mn-radius); padding:20px 22px; box-shadow:var(--mn-shadow); text-decoration:none; color:inherit; transition:transform .15s, box-shadow .15s; }
.page-menu a.mn-kpi:hover { transform:translateY(-2px); box-shadow:0 2px 4px color-mix(in srgb, var(--text) 6%, transparent), 0 8px 20px color-mix(in srgb, var(--text) 8%, transparent); }
.page-menu .mn-kpi-num { font-family:var(--mn-font-title); font-size:30px; font-weight:800; line-height:1; letter-spacing:-1px; color:var(--mn-accent); }
.page-menu .mn-kpi-label { font-size:11px; font-weight:600; color:var(--mn-muted); text-transform:uppercase; letter-spacing:.4px; margin-top:8px; }

/* Branch drill-down inside an exception row: the only path from the landing
   screen into a branch menu card, so it stays inline and needs no request. */
/* Ленивая ценовая половина и пикер филиала */
.page-menu .mn-lazy { margin:10px 0 24px; display:flex; align-items:center; gap:12px; flex-wrap:wrap; }
.page-menu .mn-lazy [data-prices-out] { flex:1 1 100%; }
.page-menu .mn-lazy-hint { color:var(--mn-muted); font-size:12px; }
/* Пикер филиала — первый блок страницы, на зелёной подложке. Устроен как пикер
   бренда на матрице: поиск + чипы стран + список ссылок, фильтрация на клиенте. */
.page-menu .mn-picker { background:var(--mn-accent-light); border:2px solid var(--mn-fill); border-radius:var(--mn-radius); padding:16px 20px 18px; margin-bottom:20px; box-shadow:none; }
.page-menu .mn-picker h3 { margin:0; white-space:nowrap; }
.page-menu .mn-picker .pick-top { display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.page-menu .mn-picker input[type=search] { flex:0 1 320px; min-width:180px; border:2px solid var(--mn-border); border-radius:10px; padding:8px 12px; font:inherit; font-size:13px; background:var(--mn-card); }
.page-menu .mn-picker input[type=search]:focus { border-color:var(--mn-accent); outline:none; }
.page-menu .mn-chips { display:flex; gap:6px; flex-wrap:wrap; }
.page-menu .mn-chip-btn { border:2px solid var(--mn-border); background:var(--mn-card); border-radius:999px; font:inherit; font-size:12px; font-weight:700; color:var(--mn-muted); padding:5px 12px; cursor:pointer; }
.page-menu .mn-chip-btn.on { background:var(--mn-fill); border-color:var(--mn-fill); color:var(--mn-fill-ink); }
.page-menu .mn-picker .pick-total { margin-inline-start:auto; font-size:12px; font-weight:700; color:var(--mn-accent); }
.page-menu .mn-picker .pick-list { margin-top:12px; max-height:210px; overflow:auto; display:grid; grid-template-columns:repeat(auto-fill, minmax(240px,1fr)); gap:6px; }
.page-menu .mn-picker .pk { border:1px solid var(--mn-border); background:var(--mn-card); border-radius:10px; padding:7px 11px; text-decoration:none; color:inherit; display:flex; align-items:baseline; gap:7px; min-width:0; }
.page-menu .mn-picker .pk:hover { border-color:var(--mn-accent); box-shadow:0 0 0 3px color-mix(in srgb, var(--brand) 18%, transparent); }
.page-menu .mn-picker .pk b { font-size:12.5px; font-weight:600; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.page-menu .mn-picker .pk .ar { font-size:11px; color:var(--mn-muted); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.page-menu .mn-picker .pk .cc { margin-inline-start:auto; font-size:11px; font-weight:700; color:var(--mn-accent); }
.page-menu .mn-picker .mn-pick-none { margin-top:10px; }
.page-menu .mn-branches > summary { cursor:pointer; white-space:nowrap; color:var(--mn-accent); font-weight:600; }
.page-menu .mn-branches[open] > summary { margin-bottom:6px; }
.page-menu .mn-branches ul { list-style:none; margin:0; padding:0; font-size:12px; line-height:1.7; }
.page-menu .mn-branches li { white-space:nowrap; }

/* Banners / notices */
.page-menu .mn-banner-warn { background:var(--mn-warn-light); border:1px solid color-mix(in srgb, var(--warn) 40%, var(--surface)); color:var(--mn-warn-dark); border-radius:12px; padding-block:12px; padding-inline:44px 16px; margin:12px 0; font-size:13px; position:relative; }
.page-menu .mn-banner-warn::before { content:'!'; position:absolute; inset-inline-start:14px; top:50%; transform:translateY(-50%); width:22px; height:22px; border-radius:50%; background:var(--mn-warn); color:var(--mn-warn-dark); font-family:var(--mn-font-title); font-weight:800; font-size:13px; display:flex; align-items:center; justify-content:center; }
.page-menu .mn-quarantine-note { color:var(--mn-muted); font-size:12px; font-style:italic; margin:8px 0; }

/* Deltas / spreads */
.page-menu .mn-spread { color:var(--mn-danger); font-weight:700; }
.page-menu .mn-up { color:var(--mn-danger); font-weight:600; }
.page-menu .mn-down { color:var(--mn-success-dark); font-weight:600; }

/* Badges — rounded-rect pills, like ps-pill */
.page-menu .mn-badge { display:inline-block; padding:2px 9px; border-radius:8px; font-weight:700; font-size:10px; line-height:1.5; margin-inline-start:6px; white-space:nowrap; }
.page-menu .mn-badge-base { background:var(--mn-danger-light); color:var(--mn-danger); }
.page-menu .mn-badge-promo { background:var(--mn-accent-light); color:var(--mn-success-dark); }
.page-menu .mn-badge-var { background:var(--mn-warn-light); color:var(--mn-warn-dark); }
/* Конфликт цены между дублями одного блюда на одной площадке — это ошибка в меню
   клиента, а не справка, поэтому палитра тревожная а не серая. */
.page-menu .mn-badge-dup { background:var(--mn-danger-light); color:var(--mn-danger); }

/* Aggregator pill — shape/typography only; background/text color comes from DB inline style */
.page-menu .mn-aggpill { display:inline-flex; align-items:center; padding:3px 12px; border-radius:8px; font-size:11px; font-weight:700; letter-spacing:.2px; color:var(--on-accent); }
.page-menu .mn-table a { color:var(--mn-accent); font-weight:600; text-decoration:none; border-bottom:1px solid transparent; transition:border-color .12s; }
.page-menu .mn-table a:hover { border-bottom-color:var(--mn-accent); }
.page-menu .mn-drill { display:inline-flex; align-items:center; gap:6px; padding:7px 14px; border:2px solid var(--mn-accent); background:var(--mn-card); color:var(--mn-accent); border-radius:10px; font-size:12px; font-weight:700; cursor:pointer; white-space:nowrap; }
.page-menu .mn-drill svg { width:14px; height:14px; }
.page-menu .mn-drill:hover { background:var(--mn-fill); color:var(--mn-fill-ink); border-color:var(--mn-fill); }
.page-menu .mn-bc-branches { display:flex; flex-wrap:wrap; gap:6px; padding:0 20px 16px; margin-top:-4px; }
.page-menu .mn-bc-branch { text-decoration:none; color:var(--mn-accent); font-weight:600; border:1px solid var(--mn-border); }
.page-menu .mn-bc-branch:hover { border-color:var(--mn-accent); background:var(--mn-card); }
.page-menu .mn-bc-area { color:var(--mn-muted); font-weight:500; }

/* Price-matrix cell states (mn-cell-<state>) */
.page-menu .mn-cell-price { background:var(--success-bg); }
.page-menu .mn-cell-not_connected { color:var(--border-strong); background:var(--bg); }
.page-menu .mn-cell-not_collected { background:repeating-linear-gradient(45deg,var(--bg),var(--bg) 6px,var(--surface-2) 6px,var(--surface-2) 12px); }
.page-menu .mn-cell-absent { background:var(--mn-warn-light); }
.page-menu .mn-nc { color:color-mix(in srgb, var(--muted) 65%, var(--surface)); font-style:italic; font-size:.85em; }
.page-menu .mn-absent { color:var(--mn-warn-dark); font-size:.85em; }

/* Search bar */
.page-menu .mn-searchbar { display:flex; gap:8px; margin-top:12px; flex-wrap:wrap; }
.page-menu .mn-searchbar input[type=search] { flex:1; min-width:220px; padding:9px 12px; border:2px solid var(--mn-border); border-radius:10px; font-family:var(--mn-font-body); font-size:13px; }
.page-menu .mn-searchbar input[type=search]:focus { border-color:var(--mn-accent); outline:none; }

/* Modal (like ps-m-bg/ps-m-box) — JS toggles the `hidden` attribute, not a class. Also
   carries .kc-modal-backdrop/.kc-modal-backdrop--tinted (markup): the charcoal tint
   comes from that shared modifier now, this rule keeps only menu's own layout. The panel
   (.mn-modal + .kc-modal-panel) likewise takes background/radius/shadow from the layer. */
.page-menu .mn-modal-bg { position:fixed; inset:0; z-index:1000; display:flex; align-items:center; justify-content:center; backdrop-filter:blur(2px); }
.page-menu .mn-modal-bg[hidden] { display:none; }
.page-menu .mn-modal { width:640px; max-width:92vw; max-height:85vh; overflow:hidden; display:flex; flex-direction:column; position:relative; padding:0; animation:mnModalAnim .25s cubic-bezier(.22,1,.36,1); }
.page-menu .mn-modal h3 { font-family:var(--mn-font-title); font-size:16px; font-weight:700; margin:0; padding-block:22px 14px; padding-inline:26px 46px; border-bottom:1px solid var(--mn-border); }
.page-menu .mn-modal #mnModalBody { padding:18px 26px 26px; overflow-y:auto; flex:1; }
.page-menu .mn-modal #mnModalBody table { width:100%; border-collapse:collapse; font-size:12px; }
.page-menu .mn-modal #mnModalBody th { text-align:start; padding:7px 10px; font-size:10px; font-weight:700; text-transform:uppercase; color:var(--mn-muted); letter-spacing:.3px; border-bottom:2px solid var(--mn-border); }
.page-menu .mn-modal #mnModalBody td { padding:7px 10px; border-bottom:1px solid var(--border-soft); }
.page-menu .mn-modal #mnModalBody tr:hover td { background:var(--info-bg); }
.page-menu .mn-modal-close { position:absolute; top:18px; inset-inline-end:18px; background:var(--mn-accent-light); border:none; width:34px; height:34px; border-radius:50%; font-size:18px; cursor:pointer; color:var(--mn-muted); display:flex; align-items:center; justify-content:center; }
.page-menu .mn-modal-close:hover { background:var(--mn-danger-light); color:var(--mn-danger); }
@keyframes mnModalAnim { from { opacity:0; transform:translateY(12px) scale(.97); } to { opacity:1; transform:none; } }

/* Selected-date context line under section headings */
.page-menu .mn-subtitle { font-size:12px; color:var(--mn-muted); margin:-6px 0 14px; }

/* Brand cards (menu/compare parity tab) — ported from the promo-snapshot .ps-bcp card look */
.page-menu .mn-brand-card { margin-bottom:14px; border:1px solid var(--mn-border); border-radius:var(--mn-radius); background:var(--mn-card); box-shadow:var(--mn-shadow); overflow:hidden; }
.page-menu .mn-bc-hd { display:flex; flex-wrap:wrap; align-items:center; gap:12px; padding:16px 20px; }
.page-menu .mn-bc-name { font-family:var(--mn-font-title); font-weight:700; font-size:15px; color:var(--mn-text); }
.page-menu .mn-bc-chips { display:flex; flex-wrap:wrap; align-items:center; gap:6px; flex:1; min-width:200px; }
.page-menu .mn-bc-chip { display:inline-flex; align-items:center; gap:4px; padding:4px 10px; border-radius:999px; font-size:11px; font-weight:600; color:var(--mn-muted); background:var(--surface-2); white-space:nowrap; }
.page-menu .mn-bc-chip-ok { background:var(--success-bg); color:var(--mn-success-dark); }
.page-menu .mn-bc-chip-spread { background:var(--mn-danger-light); color:var(--mn-danger); white-space:normal; }
.page-menu .mn-bc-hd .mn-drill { flex-shrink:0; }

/* Assortment-gap strip on brand cards (amber = the mn-absent semantics) + missing-items modal */
.page-menu .mn-bc-cov { display:flex; flex-wrap:wrap; align-items:center; gap:6px; padding:0 20px 14px; margin-top:-6px; }
.page-menu .mn-bc-cov-label { font-size:10px; font-weight:700; text-transform:uppercase; letter-spacing:.4px; color:var(--mn-muted); margin-inline-end:2px; }
.page-menu .mn-bc-chip-miss,
.page-menu .mn-bc-chip-store { background:var(--mn-warn-light); color:var(--mn-warn-dark); border:1px solid color-mix(in srgb, var(--warn) 40%, var(--surface)); cursor:pointer; font-family:inherit; }
.page-menu .mn-bc-chip-miss:hover,
.page-menu .mn-bc-chip-store:hover { background:var(--mn-card); border-color:var(--mn-warn-dark); }
.page-menu .mn-bc-chip-miss .mn-aggpill { padding:1px 8px; font-size:10px; }
.page-menu .mn-bc-chip-store strong { font-weight:700; }
/* Используется модалкой store-gap-items (_compare_store_gap_items.php) */
.page-menu .mn-mi-src { display:inline-flex; align-items:center; gap:5px; margin-inline-end:12px; white-space:nowrap; }
.page-menu .mn-mi-src .mn-aggpill { padding:1px 8px; font-size:10px; }
/* Assortment-gap modal: колонка на агрегатор, чтобы цены сравнивались по вертикали.
   table-layout:fixed обязателен — при auto колонки меряются по содержимому и «прыгают»
   от выборки к выборке, а нам нужно одно и то же место в каждой строке. */
.page-menu .mn-mi-scroll { overflow-x:auto; }
/* min-width таблицы задаётся инлайном от числа колонок: иначе при 4-5 площадках
   сумма ширин превышает модалку и колонки просто сжимаются, вместо того чтобы
   включилась горизонтальная прокрутка. Ширины колонки товара нет намеренно —
   при table-layout:fixed она одна без width и забирает весь остаток. */
.page-menu .mn-modal #mnModalBody table.mn-mi-table { table-layout:fixed; width:100%; }
.page-menu .mn-mi-col-agg { width:92px; }
.page-menu .mn-mi-table th.mn-mi-th-agg { text-align:end; }
.page-menu .mn-mi-table .mn-aggpill { padding:1px 8px; font-size:10px; }
/* tabular-nums: иначе разряды разной ширины и колонка цен всё равно «рваная» */
.page-menu .mn-mi-table td.mn-mi-price { text-align:end; white-space:nowrap; font-variant-numeric:tabular-nums; }
.page-menu .mn-mi-table td.mn-mi-none { color:var(--mn-muted); }
.page-menu .mn-mi-note { margin-block-end:10px; }
/* Secondary "effective %" next to the base-ranked severity/delta */
.page-menu .mn-eff { color:var(--mn-muted); font-weight:500; }

/* Drill-down target (menu/compare parity tab — expands into an items table INSIDE the card) */
.page-menu .mn-drill-target { display:block; padding:0 20px 18px; background:var(--mn-card); }
.page-menu .mn-drill-target[hidden] { display:none; }
.page-menu .mn-drill-target .mn-table-wrap { margin-bottom:12px; box-shadow:none; }
.page-menu .mn-hidden-note { margin:0 0 4px; }

/* Spread column: fixed floor width + no-wrap so "Δ 0.50 KWD · +111%" never truncates */
.page-menu .mn-matrix .mn-col-spread { min-width:160px; white-space:nowrap; }

/* Filter card — replicated filter-form/multi-select rules, harmonized with the promo card look */
.page-menu .filter-form { background:var(--mn-card); border-radius:var(--mn-radius); padding:24px; margin-bottom:20px; box-shadow:var(--mn-shadow); }
.page-menu .filter-form h3 { font-family:var(--mn-font-title); font-size:16px; font-weight:700; margin:0 0 14px; }
.page-menu .filter-grid,
.page-menu .filter-grid-row { display:grid; grid-template-columns:repeat(auto-fit, minmax(200px,1fr)); gap:14px; margin-bottom:14px; }
.page-menu .filter-group > label { display:block; font-size:11px; font-weight:600; color:var(--mn-muted); text-transform:uppercase; letter-spacing:.5px; margin-bottom:6px; }
.page-menu .filter-group > input:not([type="checkbox"]):not([type="radio"]) { width:100%; padding:9px 12px; border:2px solid var(--mn-border); border-radius:10px; font-size:13px; font-family:var(--mn-font-body); }
.page-menu .filter-group > input:focus { border-color:var(--brand); outline:none; }
/* .page-menu carries its own design system (--mn-* tokens: menu/quarantine + the client
   menu/compare & menu/overview pages that share this scope) and looks deliberately
   different from the shared multi-select component — kept pixel-identical on purpose
   (Review Focus: .page-menu must not regress). Restructured as attribute/child selectors
   only, never ".multi-select…", because this scope may not define copies of those class
   names (see ViewStyleContractTest::testNoScopedMultiSelectOverrides) — [data-name] is the
   attribute the shared partial (partials/_multi_select.php) renders on its root element,
   which always has exactly one <button> (toggle) and one <div> (panel) as direct children,
   and the panel's own direct <label> children are always the option rows (search box, if
   present, is a <div>, so ':first-of-type' still lands on the first *label* — Select all).
   div[data-name], not bare [data-name]: menu/_compare_items.php puts data-name on its
   <tr class="mn-item-drill"> rows too. No colour on the option rows: it equals --text anyway
   and, at (0,2,3), would beat .multi-select-option.ms-zero and un-mute zero-count options. */
.page-menu div[data-name] { position:relative; }
.page-menu div[data-name] > button { width:100%; min-height:42px; padding:9px 12px; background:var(--mn-card); border:2px solid var(--mn-border); border-radius:10px; font-size:13px; font-family:var(--mn-font-body); color:var(--mn-text); text-align:start; cursor:pointer; }
.page-menu div[data-name] > button::after { content:"▾"; float:right; float:inline-end; color:var(--mn-muted); }
.page-menu div[data-name].open > button::after { content:"▴"; }
.page-menu div[data-name] > div { position:absolute; left:0; right:0; top:calc(100% + 6px); background:var(--mn-card); border:1px solid var(--mn-border); border-radius:10px; box-shadow:var(--shadow-dropdown); max-height:220px; overflow:auto; padding:8px 10px; display:none; z-index:10; }
.page-menu div[data-name].open > div { display:block; }
.page-menu div[data-name] > div > label { display:flex; align-items:center; gap:8px; padding:6px 4px; font-size:13px; }
.page-menu div[data-name] > div > label input { width:auto; min-width:16px; flex-shrink:0; }
.page-menu div[data-name] > div > label:first-of-type { font-weight:600; border-bottom:1px solid var(--border); margin-bottom:6px; padding-bottom:8px; }
.page-menu .filter-actions { display:flex; gap:10px; margin-top:8px; }
.page-menu .btn-primary { padding:9px 22px; border-radius:10px; border:none; background:var(--cta); color:var(--cta-text); font-family:var(--mn-font-body); font-size:13px; font-weight:600; cursor:pointer; text-decoration:none; display:inline-block; }
.page-menu .btn-primary:hover { background:var(--cta-hover); color:var(--cta-text); }
.page-menu .btn-secondary { padding:9px 18px; border-radius:10px; border:none; background:var(--mn-accent-light); color:var(--mn-text); font-family:var(--mn-font-body); font-size:13px; font-weight:600; text-decoration:none; display:inline-block; cursor:pointer; }
.page-menu .btn-secondary:hover { background:color-mix(in srgb, var(--brand) 24%, var(--surface)); }
.page-menu .empty-state { text-align:center; padding:60px 20px; color:var(--mn-muted); background:var(--mn-card); border-radius:var(--mn-radius); box-shadow:var(--mn-shadow); }
.page-menu .empty-state h3 { font-family:var(--mn-font-title); color:var(--mn-text); margin:0 0 6px; }
.page-menu .empty-state p { margin:0; font-size:13px; }

/* Pagination — accent-tinted to match the rest of the section */
.page-menu .pager-wrap { display:flex; flex-wrap:wrap; gap:6px; align-items:center; margin-top:20px; }
.page-menu .pager-wrap a { display:inline-flex; align-items:center; justify-content:center; min-width:36px; height:36px; padding:0 12px; border-radius:10px; font-size:13px; font-weight:600; color:var(--mn-accent); text-decoration:none; background:var(--mn-accent-light); border:1px solid transparent; transition:all .15s ease; }
.page-menu .pager-wrap a:hover { background:var(--mn-fill); color:var(--mn-fill-ink); }
.page-menu .pager-wrap .pager-current { display:inline-flex; align-items:center; justify-content:center; min-width:36px; height:36px; padding:0 12px; border-radius:10px; font-size:13px; font-weight:700; background:var(--mn-fill); color:var(--mn-fill-ink); }
.page-menu .mn-items-page { display:inline-flex; align-items:center; justify-content:center; min-width:36px; height:36px; padding:0 12px; border-radius:10px; font-size:13px; font-weight:600; color:var(--mn-accent); background:var(--mn-accent-light); border:1px solid transparent; cursor:pointer; transition:all .15s ease; }
.page-menu .mn-items-page:hover { background:var(--mn-fill); color:var(--mn-fill-ink); }

@media (max-width:900px) {
    .page-menu .mn-kpis { grid-template-columns:repeat(2,1fr); }
    .page-menu .filter-grid, .page-menu .filter-grid-row { grid-template-columns:1fr 1fr; }
    .page-menu .page-header { flex-direction:column; align-items:flex-start; }
}
/* Compact header + date strip on phones (spec 2026-09-23-mobile-menu-promo-monitor task 1).
   .mn-datebar stays one row — no wrap — with the ‹/› buttons shrunk to 32px, the date
   field taking the remaining space (flex:1, min-width:0 so it can actually shrink instead
   of forcing the row wide) and Latest kept compact beside it. */
@media (max-width:768px) {
    .page-menu .page-header { padding:12px 14px; }
    .page-menu .page-header h2 { font-size:18px; }
    .page-menu .mn-datebar { flex-wrap:nowrap; }
    .page-menu a.mn-dt-btn.btn-secondary { width:32px; height:32px; flex-shrink:0; }
    .page-menu .mn-dateform { flex:1 1 auto; min-width:0; }
    .page-menu .mn-dateform input[type=date] { width:100%; min-width:0; }
    .page-menu a.mn-dt-latest.btn-secondary { padding:8px 12px; white-space:nowrap; flex-shrink:0; }
    .page-menu .mn-picker { padding:12px; }
}
@media (max-width:600px) {
    .page-menu .container { padding:16px 12px; }
    .page-menu .mn-kpis { grid-template-columns:1fr; }
    .page-menu .filter-grid, .page-menu .filter-grid-row { grid-template-columns:1fr; }
    .page-menu .mn-bc-hd { flex-direction:column; align-items:flex-start; }
}
/* ===== Menu ▸ Missing Items (.page-mmiss) — nested inside .page-menu (menu/missing.php only) =====
   Moved from a <style> block in the view (Task 9, wave C). The 4-step "days gone" severity ramp
   (5/8/15/30 days) reuses the wave's 4-step status vocabulary: g5=warn, g8=caution, g15/g30=two
   danger shades (kept visually distinct — same red family, g30 darker — so the two most severe
   bands still read apart, as they did with the original two literal reds). */
.page-mmiss{--border:var(--mn-border);--muted:var(--mn-muted);--text:var(--mn-text);
  --mi-a5:color-mix(in srgb, var(--warn) 55%, var(--surface));--mi-a8:color-mix(in srgb, var(--caution) 55%, var(--surface));--mi-a15:color-mix(in srgb, var(--danger) 45%, var(--surface));--mi-a30:color-mix(in srgb, var(--danger) 75%, var(--text));
  --mi-t5:var(--warn-bg);--mi-t8:var(--caution-bg);--mi-t15:var(--danger-bg);--mi-t30:var(--danger-bg);
  --mi-ink5:var(--warn-ink);--mi-ink8:var(--caution);--mi-ink15:var(--danger);--mi-ink30:color-mix(in srgb, var(--danger) 70%, var(--text));}
.page-mmiss .mi-asof{display:flex;flex-direction:column;gap:2px;text-align:end;flex-shrink:0}
.page-mmiss .mi-asof .l{font-size:11px;text-transform:uppercase;letter-spacing:.5px;color:var(--mn-muted);font-weight:600}
.page-mmiss .mi-asof .v{font-family:var(--mn-font-title);font-weight:700;font-size:15px;font-variant-numeric:tabular-nums}
.page-mmiss .mi-asof .b{font-size:11.5px;color:var(--mi-ink8)}
.page-mmiss .mi-thr{display:flex;align-items:center;gap:14px}
/* Slider + 74px value need ~220px, more than a half-width phone column: the field
   takes its own row there, and the slider may shrink instead of pushing the page wide. */
.page-mmiss .mi-thr input[type=range]{min-width:0}
@media (max-width: 768px){ .page-mmiss .filter-group:has(.mi-thr){grid-column:1/-1} }
.page-mmiss .mi-thr input[type=range]{-webkit-appearance:none;appearance:none;flex:1;height:4px;
  background:var(--border);border-radius:20px;outline:none;accent-color:var(--brand);padding:0;border:0}
.page-mmiss .mi-thr input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:18px;height:18px;
  background:var(--brand);border-radius:50%;cursor:pointer;box-shadow:0 1px 3px color-mix(in srgb, var(--text) 18%, transparent)}
.page-mmiss .mi-thr input[type=range]::-moz-range-thumb{width:18px;height:18px;background:var(--brand);
  border-radius:50%;cursor:pointer;border:0;box-shadow:0 1px 3px color-mix(in srgb, var(--text) 18%, transparent)}
.page-mmiss .mi-thrv{font-weight:700;font-variant-numeric:tabular-nums;min-width:74px;white-space:nowrap}
/* Inside .filter-form--compact the label sits on the field's top border. The slider has no
   border of its own, so the label landed on the thumb and the value squeezed the track to
   ~90px in one 178px column: give it the same outlined 38px box as the fields beside it,
   and two columns on wide screens (phones already give it the whole row, see above). */
@media (min-width: 769px){ .page-mmiss .filter-form--compact .filter-group:has(.mi-thr){grid-column:span 2} }
.page-mmiss .filter-form--compact .mi-thr{height:38px;box-sizing:border-box;padding:0 12px;gap:12px;
  border:1px solid var(--border-strong);border-radius:var(--radius-sm);background:var(--surface)}
.page-mmiss .filter-form--compact .mi-thrv{font-size:14px;min-width:64px}
.page-mmiss .mi-more{display:block;width:100%;padding:11px 18px;border:0;border-top:1px solid var(--border-soft);
  background:color-mix(in srgb, var(--surface) 50%, var(--bg));font-size:13px;color:var(--brand-dark);font-weight:600;cursor:pointer;text-align:start;
  border-radius:0 0 12px 12px}
.page-mmiss .mi-more:hover{background:var(--surface-2)}
.page-mmiss .mi-tabs{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:16px}
.page-mmiss .mi-tab{display:inline-flex;align-items:baseline;gap:8px;padding:10px 18px;border:1px solid var(--border);
  border-radius:999px;background:var(--mn-card);font-size:13.5px;font-weight:600;color:var(--muted);text-decoration:none}
.page-mmiss .mi-tab .c{font-size:13px;font-weight:700;color:var(--text);font-variant-numeric:tabular-nums}
.page-mmiss .mi-tab.on{background:var(--appbar);border-color:var(--appbar);color:var(--on-accent)}
.page-mmiss .mi-tab.on .c{color:var(--cta)}
.page-mmiss .mi-tab:hover:not(.on){border-color:var(--border-strong);color:var(--text)}

.page-mmiss .mi-lead{margin:0 2px 12px}
.page-mmiss .mi-lead h3{font-size:16px;font-weight:600}
.page-mmiss .mi-lead p{margin-top:3px;font-size:13px;color:var(--muted);max-width:92ch}
.page-mmiss .mi-lead p b{color:var(--text);font-weight:600}
.page-mmiss .mi-note{margin:0 2px 12px;font-size:12.5px;color:var(--muted)}
.page-mmiss .mi-note a{color:var(--brand-dark);font-weight:600;margin-inline-start:6px}
.page-mmiss .mi-run{display:inline-block;margin-inline-start:6px;padding:1px 6px;border-radius:5px;
  font-size:10px;font-weight:700;background:color-mix(in srgb, var(--cat-1) 12%, var(--surface));color:color-mix(in srgb, var(--cat-1) 75%, var(--text));vertical-align:1px}
.page-mmiss .mi-legend{display:flex;align-items:center;gap:22px;flex-wrap:wrap;margin:0 2px 14px;font-size:12.5px;color:var(--muted)}
.page-mmiss .mi-legend span.li{display:inline-flex;align-items:center;gap:8px}
.page-mmiss .mi-legend b{color:var(--text);font-weight:600}

.page-mmiss .mi-card{background:var(--mn-card);border:1px solid var(--border);border-radius:12px;margin-bottom:14px;
  box-shadow:var(--shadow-card)}
.page-mmiss .mi-bhead{display:flex;align-items:center;gap:14px;padding:14px 18px;border-bottom:1px solid var(--border);
  background:color-mix(in srgb, var(--surface) 50%, var(--bg));border-radius:12px 12px 0 0}
.page-mmiss .mi-rail{width:4px;align-self:stretch;border-radius:20px;min-height:34px;flex-shrink:0}
.page-mmiss .mi-who{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}
.page-mmiss .mi-who .nm{font-weight:700;font-size:16px;display:inline-flex;align-items:center;gap:8px}
.page-mmiss .mi-cc{font-size:10.5px;font-weight:700;letter-spacing:.4px;color:var(--muted);
  background:var(--surface-2);border:1px solid var(--border);border-radius:5px;padding:1px 6px}
.page-mmiss .mi-who .meta{font-size:12.5px;color:var(--muted)}
.page-mmiss .mi-worst{display:flex;flex-direction:column;align-items:flex-end;line-height:1.15;flex-shrink:0}
.page-mmiss .mi-worst .n{font-weight:700;font-size:20px;font-variant-numeric:tabular-nums}
.page-mmiss .mi-worst .l{font-size:10px;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);font-weight:600}

/* Sticky platform header. The wrapper only becomes a scroll container on narrow
   screens: overflow-x:auto computes overflow-y to auto as well, and that kills
   position:sticky against the page — which is exactly where a long list needs it. */
.page-mmiss .mi-scroll{border-radius:0 0 12px 12px}
@media (max-width:1100px){
  .page-mmiss .mi-scroll{overflow-x:auto}
  /* Freeze the name column. Scrolled right, every row went anonymous — the dish names and,
     inside a drill, the branch names left the screen with everything else, so the numbers
     belonged to nobody. Each frozen cell needs its OWN opaque background: a transparent one
     lets the columns underneath show through as they pass. */
  .page-mmiss .mi-table thead th:first-child,
  .page-mmiss .mi-table td.mi-dish{position:sticky;inset-inline-start:0;z-index:2;
    border-inline-end:1px solid var(--border)}
  .page-mmiss .mi-table thead th:first-child{background:var(--bg)}
  .page-mmiss .mi-table td.mi-dish{background:var(--card)}
  .page-mmiss .mi-table tr.mi-row:hover td.mi-dish{background:color-mix(in srgb, var(--surface) 50%, var(--bg))}
  /* The branch cell needs the EXTRA class to land: `tr.mi-branch-row td.mi-branch-name`
     below is (0,3,2) and keeps its position:relative against a (0,3,1) rule here, so the
     names scrolled away while the dish names above them stayed. Same trap as the indent
     that rule was written to win. */
  .page-mmiss .mi-scroll tr.mi-branch-row td.mi-branch-name{position:sticky;inset-inline-start:0;
    z-index:2;border-inline-end:1px solid var(--border);background:var(--surface-2)}
}
.page-mmiss .mi-table{width:100%;border-collapse:collapse;table-layout:fixed;min-width:880px}
/* Fixed-width columns extracted from static style="" in the view (dish name + the two
   trailing numeric columns); the per-aggregator columns stay inline (their width depends
   on how many platforms the brand card has). */
.page-mmiss .mi-col-dish{width:28%}
.page-mmiss .mi-col-hit{width:12%}
.page-mmiss .mi-col-since{width:13%}
.page-mmiss .mi-table th{padding:10px 14px;text-align:start;border-bottom:1px solid var(--border);background:var(--bg);
  font-size:11px;font-weight:600;letter-spacing:.4px;text-transform:uppercase;color:var(--muted);white-space:nowrap;
  position:sticky;top:0;z-index:3;box-shadow:0 1px 0 var(--border)}
/* A platform name longer than its share of the row (HungerStation) was clipped to
   "HUNGERSTAT". Wrapping is the honest degradation; clipping renames the platform. */
.page-mmiss .mi-table th.pf{white-space:normal;padding-inline:6px;line-height:1.2}
.page-mmiss .mi-table th.pf,.page-mmiss .mi-table td.pf{text-align:center}
.page-mmiss .mi-table th.r,.page-mmiss .mi-table td.r{text-align:end}
.page-mmiss .mi-table td{padding:7px 14px;border-bottom:1px solid var(--border-soft);vertical-align:middle}
.page-mmiss .mi-table tr:last-child td{border-bottom:0}
.page-mmiss .mi-table tr.mi-row:hover{background:color-mix(in srgb, var(--surface) 50%, var(--bg))}
.page-mmiss .mi-dish{font-weight:600;font-size:14px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

.page-mmiss .mi-cell{display:inline-grid;place-items:center;min-width:44px;padding:3px 8px;border-radius:7px;
  font-weight:700;font-size:13px;font-variant-numeric:tabular-nums;line-height:1.25}
.page-mmiss .mi-cell.g30{background:var(--mi-t30);color:var(--mi-ink30);border:1px solid color-mix(in srgb, var(--danger) 20%, var(--surface))}
.page-mmiss .mi-cell.g15{background:var(--mi-t15);color:var(--mi-ink15);border:1px solid color-mix(in srgb, var(--danger) 20%, var(--surface))}
.page-mmiss .mi-cell.g8{background:var(--mi-t8);color:var(--mi-ink8);border:1px solid color-mix(in srgb, var(--caution) 25%, var(--surface))}
.page-mmiss .mi-cell.g5{background:var(--mi-t5);color:var(--mi-ink5);border:1px solid color-mix(in srgb, var(--warn) 30%, var(--surface))}
.page-mmiss .mi-cell.live{background:var(--success-bg);color:var(--success-ink);border:1px solid color-mix(in srgb, var(--success) 30%, var(--surface));font-size:12px}
.page-mmiss .mi-cell .v{white-space:nowrap}
/* opacity is what killed it: .6 of the pill's own ink on the pill's own tint measured */
/* 2.3:1 to 3.0:1, against the 4.5:1 AA needs at this size. Hierarchy comes from size and
   weight instead, so the line keeps the ink's full contrast (5.4:1 green, 6.5:1 red). */
.page-mmiss .mi-cell .of{font-weight:500;font-size:11px;line-height:1.15;letter-spacing:.1px;white-space:nowrap}
.page-mmiss .mi-scale{display:inline-flex;gap:3px}
.page-mmiss .mi-scale .mi-cell{min-width:30px;padding:3px 5px;font-size:11.5px}
.page-mmiss .mi-cell.none{background:repeating-linear-gradient(135deg,var(--surface-2),var(--surface-2) 4px,var(--surface-3) 4px,var(--surface-3) 8px);
  color:var(--muted);border:1px solid var(--border)}
.page-mmiss .mi-branches{font-weight:600;font-variant-numeric:tabular-nums;white-space:nowrap;
  border:0;background:none;border-bottom:1px dotted color-mix(in srgb, var(--muted) 50%, var(--surface));cursor:pointer;color:inherit;font-size:13px;padding:0}
.page-mmiss .mi-branches .of{color:var(--muted);font-weight:500;font-size:12.5px}
.page-mmiss .mi-since{display:inline-flex;flex-direction:column;align-items:flex-end;line-height:1.25;white-space:nowrap}
.page-mmiss .mi-since .ago{font-size:12px;font-weight:700;font-variant-numeric:tabular-nums}
.page-mmiss .c5{color:var(--mi-ink5)}.page-mmiss .c8{color:var(--mi-ink8)}
.page-mmiss .c15{color:var(--mi-ink15)}.page-mmiss .c30{color:var(--mi-ink30)}
.page-mmiss .b5{background:var(--mi-a5)}.page-mmiss .b8{background:var(--mi-a8)}
.page-mmiss .b15{background:var(--mi-a15)}.page-mmiss .b30{background:var(--mi-a30)}
/* Branch rows are rows of the dish table itself, not a table of their own: a nested
   table carried its own widths, so the same platform sat up to 240px off the column it
   belonged to. Tint and indent are what mark them as a level down. */
.page-mmiss tr.mi-detail td{background:var(--surface-2);border-bottom:1px solid var(--border-soft)}
.page-mmiss tr.mi-drill-head td{padding:11px 14px 5px 34px;font-size:10.5px;font-weight:700;
  letter-spacing:.5px;text-transform:uppercase;color:var(--mn-muted);
  border-top:1px solid var(--mn-border);border-bottom:0}
.page-mmiss tr.mi-branch-row td{padding:7px 14px}
/* `:last-of-type` looked right and matched nothing: every sibling here is a tr, so it
   only ever picks the last row of the whole tbody. The last branch row is marked. */
.page-mmiss tr.mi-branch-last td{border-bottom:1px solid var(--mn-border)}
/* has to out-specify `tr.mi-branch-row td` above (0,2,2), or the shorthand there wins
   and the indent collapses back onto the rail */
.page-mmiss tr.mi-branch-row td.mi-branch-name{padding-inline-start:34px;font-weight:500;font-size:13px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;position:relative}
/* one rail down the left of the block, so the branches read as belonging to the dish
   directly above them rather than as more dishes */
.page-mmiss tr.mi-branch-row td.mi-branch-name::before{content:"";position:absolute;inset-inline-start:20px;
  top:0;bottom:0;width:2px;background:var(--mn-border)}
.page-mmiss tr.mi-branch-last td.mi-branch-name::before{bottom:50%}
.page-mmiss tr.mi-branch-row td.r{text-align:end}
.page-mmiss tr.mi-branch-row .ago{font-size:12px;font-weight:700;font-variant-numeric:tabular-nums}
.page-mmiss tr.mi-branch-row .mi-cell{min-width:38px;font-size:12px;padding:3px 7px}

.page-mmiss .mi-pager{display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap;
  background:var(--mn-card);border:1px solid var(--border);border-radius:12px;padding:12px 18px;margin-top:4px}
.page-mmiss .mi-pcount{font-size:12.5px;color:var(--muted)}
.page-mmiss .mi-plinks{display:inline-flex;gap:6px}
.page-mmiss .mi-plinks a{min-width:32px;height:32px;display:inline-flex;align-items:center;justify-content:center;
  padding:0 10px;border:1px solid var(--border);border-radius:7px;font-size:13px;font-weight:600;
  color:var(--text);text-decoration:none;background:var(--mn-card)}
.page-mmiss .mi-plinks a:hover{border-color:var(--border-strong)}
.page-mmiss .mi-plinks a.on{background:var(--appbar);border-color:var(--appbar);color:var(--on-accent)}
.page-mmiss .mi-empty{background:var(--mn-card);border:1px solid var(--border);border-radius:12px;padding:40px 24px;text-align:center;color:var(--muted)}
.page-mmiss .mi-empty h3{color:var(--text);font-size:17px;font-weight:600;margin-bottom:6px}

/* Language switcher chrome lives in public/css/lang-switcher.css (shared with the auth layout). */
@media (max-width: 480px) {
  /* When the language globe is present the row gets tight — drop the username, keep the globe */
  .header-right:has(.lang-switcher) .header-user-name { display: none; }
}

/* Narrow phones: keep the burger (the entire nav) reachable. Longer translated
   labels + the language globe overflow the single-row header otherwise, pushing
   the burger off-screen. Drop the username and the scope toggle here (scope is
   still reachable inside the pages); shrink the logo and gaps. */
@media (max-width: 560px) {
  .app-header { padding-inline: 12px; }
  .header-right { gap: 8px; }
  .header-user-name { display: none; }
  .header-scope-form { display: none; }
  .header-logo-text { font-size: 15px; }
  .nvd-burger { flex-shrink: 0; }
  .header-user-block { gap: 8px; }
}

/* 375px phones: with the "← Dashboard" button in the row (every non-dashboard
   page) the bar still overflows after the 560px cuts — the whole page then
   side-scrolls and the fixed support fab drifts off-screen. Logout must stay
   (it exists nowhere else); the dash button is dropped here — "Dashboard" is
   reachable from the burger menu (partials/nav_menu_items.php). */
@media (max-width: 480px) {
  .app-header { padding: 10px 10px; }
  .header-content { padding-inline: 0; gap: 8px; }
  .header-right { gap: 6px; }
  .header-user-block { gap: 6px; }
  .header-logo { max-width: 34vw; }
  .header-logo-text { font-size: 13px; }
  .header-logout, .header-login { padding: 6px 9px; font-size: 12px; }
  .header-dash { display: none; }
}

/* ===== Stale shared-link notice (partials/_shared_link_notice.php) =====
   Shown on every report page opened through a `?f=` link whose saved filter set
   is gone, so the page is really on its defaults. It sits on 17 different pages,
   several of which carry their own local palette, so it is styled here globally
   and keyed off .shared-link-notice — the only class the partial carries. The .alert and
   .alert-warning it used to carry were dead everywhere and are gone, so no future global rule
   for them can silently recolour this. Warning triple is the cabinet's existing one for a
   warning alert (dashboard/index.php:22, user_restaurants/index.php); shape follows the
   .mn-banner-warn card that already lives in the menu section. */
.shared-link-notice {
  background: #fffbeb;
  color: #8a6100;
  border: 1px solid #fde68a;
  border-radius: 12px;
  padding-block: 12px;
  padding-inline: 42px 16px;
  margin-block: 0 16px;
  font-size: 13px;
  line-height: 1.45;
  position: relative;
}
.shared-link-notice::before {
  content: '!';
  position: absolute;
  inset-inline-start: 14px;
  top: 50%;
  transform: translateY(-50%);
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: #fde68a;
  color: #7c5a12;
  font-family: 'Montserrat', sans-serif;
  font-weight: 800;
  font-size: 13px;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* =========================================================================
   RTL (Arabic) — i18n Phase 1.2. Only physics that logical properties can't
   flip: box-shadow, transform, linear-gradient, content glyphs. Everything
   positional/box-model is already logical (PR-1.1) and mirrors by itself.
   dir is set on <html> by partials/html_open.php.
   ========================================================================= */

/* ---- IBM Plex Sans Arabic, self-hosted, Arabic blocks only. unicode-range
   keeps Latin/digits on the system stack and defers the download until
   Arabic glyphs actually render — LTR users fetch nothing. ---- */
@font-face {
  font-family: 'IBM Plex Sans Arabic';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/font/IBMPlexSansArabic-400.woff2') format('woff2');
  unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F;
}
@font-face {
  font-family: 'IBM Plex Sans Arabic';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/font/IBMPlexSansArabic-500.woff2') format('woff2');
  unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F;
}
@font-face {
  font-family: 'IBM Plex Sans Arabic';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/font/IBMPlexSansArabic-600.woff2') format('woff2');
  unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F;
}
@font-face {
  font-family: 'IBM Plex Sans Arabic';
  font-style: normal;
  /* 700-900 range: font-weight:800/900 requests (28 places in this file)
     match this face EXACTLY — no faux-bold, no need to edit those rules. */
  font-weight: 700 900;
  font-display: swap;
  src: url('/font/IBMPlexSansArabic-700.woff2') format('woff2');
  unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F;
}

/* ---- Font stack via variable (light-theme value lives in tokens.css :root) ---- */
html[dir="rtl"] {
  --font-body: 'IBM Plex Sans Arabic', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  /* Guard against faux-bold on FALLBACK Arabic fonts (e.g. Geeza Pro caps at
     bold). Inherited — no * selector needed. Latin keeps real 800/900. */
  font-synthesis-weight: none;
}
/* Later in cascade than the top-of-file body rule at equal specificity */
body { font-family: var(--font-body); }

/* promo-snapshot and menu run their own Inter/Montserrat stacks and don't
   inherit the body variable — without these, Arabic there falls to system. */
html[dir="rtl"] .page-promo-snapshot {
  --ps-font-title: 'IBM Plex Sans Arabic', 'Montserrat', sans-serif;
  --ps-font-body:  'IBM Plex Sans Arabic', 'Inter', sans-serif;
}
html[dir="rtl"] .page-menu {
  --mn-font-title: 'IBM Plex Sans Arabic', 'Montserrat', sans-serif;
  --mn-font-body:  'IBM Plex Sans Arabic', 'Inter', sans-serif;
}
/* Form controls (button/input/select/textarea) don't inherit font-family — under
   RTL they fell to the UA Arial, so Arabic missed IBM Plex. A few chips set an
   explicit font too. Pin them to the inherited stack (RTL-only → LTR untouched). */
html[dir="rtl"] button,
html[dir="rtl"] input,
html[dir="rtl"] select,
html[dir="rtl"] textarea,
html[dir="rtl"] .scope-opt,
html[dir="rtl"] .monitor-toolbar-title,
html[dir="rtl"] .ofs-collapse-text {
  font-family: inherit;
}

/* ---- LTR islands: URLs, IDs, phone numbers, codes, time axes ---- */
.ltr { direction: ltr; unicode-bidi: isolate; }
.ltr-block { direction: ltr; }

/* ---- Side drawer (partials/nav_drawer.php) carries its own RTL flip ---- */

/* ---- Promo-monitor drawer: same pattern ---- */
[dir="rtl"] .page-promo-monitor .drawer {
  box-shadow: 10px 0 40px color-mix(in srgb, var(--text) 20%, transparent);
  transform: translateX(-100%);
}
[dir="rtl"] .page-promo-monitor .drawer.open { transform: translateX(0); }
/* ---- Promo-monitor snapshot bar: ‹ › nav buttons point the wrong way otherwise ---- */
[dir="rtl"] .page-promo-monitor .snapshot-nav { transform: scaleX(-1); }

/* ---- Promo-snapshot sticky Branch column: shadow towards content. box-shadow has no
   logical direction, so this stays even after the scope's physical properties (below)
   are converted to logical ones — same reasoning as the drawer's shadow above. ---- */
[dir="rtl"] .page-promo-snapshot table.ps-mt th.ps-th-branch,
[dir="rtl"] .page-promo-snapshot table.ps-mt td.ps-td-branch {
  box-shadow: -6px 0 8px -6px color-mix(in srgb, var(--text) 18%, transparent);
}

/* ---- "More content" fade: linear-gradient direction has no logical property either —
   mirror it explicitly. ---- */
[dir="rtl"] .page-promo-snapshot .ps-tbl-fade-r {
  background: linear-gradient(to left, transparent, color-mix(in srgb, var(--surface) 95%, transparent));
}

/* ---- Items drilldown chevron: "forward" points left in RTL ---- */
[dir="rtl"] .page-promo-snapshot .ps-tag-items::after { content: '\2039'; }

/* VISIBILITY — Top-5, gap, zone (полироль promo-snapshot: тени, Montserrat, hover).
   Зеркалит инлайн-<style> из app/Views/visibility/index.php — менять синхронно.
   .vis-tiles/.vis-tile-…/.vis-lb-sep сюда не входят: их рендерят только
   _gap.php/_leaderboard.php внутри standalone visibility/index.php, у которой
   свои токенизированные копии этих правил в собственном <style> (app.css эта
   страница не грузит). */
.vis-note { color: var(--muted); font-size: 12px; margin: 4px 0; }
.vis-warn { color: var(--warn-ink); background: var(--warn-bg); border-radius: 8px; padding: 8px 10px; font-size: 13px; margin: 8px 0; }
.vis-me td { background: color-mix(in srgb, var(--cta) 20%, var(--surface)); font-weight: 600; }
.vis-me td:first-child { border-inline-start: 3px solid var(--cta); }
.vis-me:hover td { background: color-mix(in srgb, var(--cta) 30%, var(--surface)); }

/* VISIBILITY zone.php — рендерится через layouts/main (app.css, не инлайн).
   .card в app.css красит только своё (background/border-radius/padding/box-shadow
   у .vis-zone той же специфичности побеждают по порядку), а margin-bottom глобальный
   .card не перекрывает — снят явно ниже. Всё scoped на .vis-zone, чтобы не задеть
   .card других страниц. Зеркалит редизайн страницы карты: мягкая тень,
   Montserrat-заголовок, hover-таблица. */
.vis-zone { background: var(--surface); border: 1px solid var(--border); border-radius: 14px; box-shadow: var(--shadow-card); padding: 18px 20px; margin-bottom: 0; }
.vis-zone .card-title { font-family: 'Montserrat', sans-serif; font-size: 16px; font-weight: 700; color: var(--text); margin: 0 0 4px; letter-spacing: -.01em; }
.vis-zone .table-wrap { overflow-x: auto; border: 1px solid var(--border); border-radius: 10px; margin-top: 12px; }
.vis-zone table { font-size: 13px; }
.vis-zone th, .vis-zone td { padding: 9px 11px; }
.vis-zone thead th { background: var(--surface-2); font-size: 11px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: .3px; border-bottom: 2px solid var(--border); white-space: nowrap; }
.vis-zone tbody td { border-bottom: 1px solid var(--border); }
.vis-zone tbody tr:last-child td { border-bottom: 0; }
.vis-zone tbody tr:hover td { background: var(--surface-2); }
.vis-zone tbody tr.vis-me:hover td { background: color-mix(in srgb, var(--cta) 30%, var(--surface)); }

/* VISIBILITY points — страница управления точками (layouts/main). .vis-pts .card
   бьёт глобальный .card по специфичности для своих свойств, но padding и
   margin-bottom он раньше не объявлял — сняты явно ниже, чтобы не потянуть 24px
   от глобального компонента. Всё scoped на .vis-pts; зеркалит редизайн раздела. */
.vis-pts .page-title { font-family: 'Montserrat', sans-serif; font-size: 22px; font-weight: 800; letter-spacing: -.5px; color: var(--text); margin: 0 0 4px; }
.vis-pts .page-sub { color: var(--muted); font-size: 13px; margin: 0 0 14px; }
.vis-pts .card { background: var(--surface); border: 1px solid var(--border); border-radius: 14px; box-shadow: var(--shadow-card); padding: 0; margin-bottom: 0; }
.vis-pts .filter-form { background: var(--surface); border: 1px solid var(--border); border-radius: 14px; box-shadow: var(--shadow-card); padding: 14px 16px; margin-bottom: 14px; display: flex; flex-wrap: wrap; gap: 12px 18px; align-items: flex-end; }
.vis-pts .filter-form label { display: block; font-size: 11px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: .4px; margin-bottom: 6px; }
.vis-pts .filter-form select { font: inherit; font-size: 13px; padding: 9px 12px; border: 2px solid var(--border); border-radius: 10px; background: var(--surface); min-width: 160px; }
.vis-pts .filter-form select:focus { border-color: var(--brand); outline: none; }
.vis-pts .grid { display: grid; grid-template-columns: 1fr 320px; gap: 12px; }
@media (max-width: 900px) { .vis-pts .grid { grid-template-columns: 1fr; } }
.vis-pts #ptsMap { height: min(70vh, 620px); border-radius: 14px; border: 1px solid var(--border); }
.vis-pts .side { padding: 16px 18px; display: flex; flex-direction: column; max-height: min(70vh, 620px); }
.vis-pts .side h3 { margin: 0 0 4px; font-family: 'Montserrat', sans-serif; font-size: 15px; font-weight: 700; color: var(--text); }
.vis-pts .quota { font-family: 'Montserrat', sans-serif; font-size: 20px; font-weight: 800; letter-spacing: -.4px; color: var(--text); margin: 8px 0 2px; }
.vis-pts .quota-note { font-size: 12px; color: var(--muted); margin-bottom: 10px; }
.vis-pts .quota-note.is-full { color: var(--warn-ink); }
.vis-pts .plist { list-style: none; margin: 0; padding: 0; overflow-y: auto; flex: 1; border-top: 1px solid var(--border); }
.vis-pts .plist li { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 9px 2px; border-bottom: 1px solid var(--border); font-size: 13px; }
.vis-pts .plist li.is-on { font-weight: 600; }
.vis-pts .plist input[type="checkbox"] { width: 16px; height: 16px; flex: none; cursor: pointer; }
.vis-pts .plist input[type="checkbox"]:disabled { cursor: not-allowed; opacity: .45; }
.vis-pts .pname { flex: 1; min-width: 0; cursor: pointer; }
.vis-pts .save-row { padding-top: 12px; display: flex; align-items: center; gap: 10px; }
.vis-pts .btn-save { background: var(--cta); color: var(--cta-text); border: 0; border-radius: 10px; padding: 10px 18px; font: inherit; font-weight: 600; cursor: pointer; }
.vis-pts .btn-save:hover { background: var(--brand-dark); }
.vis-pts .empty { padding: 18px 20px; color: var(--warn-ink); background: var(--warn-bg); border: 1px solid var(--warn); border-radius: 14px; font-size: 13px; }
/* Флеш-сообщения (сессия) переиспользуют .empty: .msg добавляет отступ перед
   формой фильтров, .msg-ok перекрашивает в успех — ошибка остаётся дефолтным
   предупреждающим тоном .empty. */
.vis-pts .msg { margin-bottom: 12px; }
.vis-pts .msg-ok { color: var(--success-ink); background: var(--success-bg); border-color: var(--success-border); }
.vis-pts .lg { display: flex; align-items: center; gap: 8px; margin: 6px 0; font-size: 12.5px; color: var(--muted); }
.vis-pts .lg i { width: 12px; height: 12px; border-radius: 50%; flex: none; display: inline-block; }
/* Легенда карты точек — те же токены, что маркеры в visibility-points.js
   (icon()/outletIcon()): вкл — --brand, выкл — --surface/--cat-8, точка
   продаж — --text, чтобы легенда и пины не расходились по цвету. */
.vis-pts .lg-on { background: var(--brand); }
.vis-pts .lg-off { background: var(--surface); border: 2px solid var(--cat-8); }
.vis-pts .lg-outlet { background: var(--text); border-radius: 3px; }

/* VISIBILITY empty states (empty.php/portfolio_empty.php) — layouts/main,
   без локального <style>: раньше цвет/отступы жили в статичных style="". */
.vis-empty { max-width: 640px; margin: 24px auto; padding: 28px; }
.vis-empty-title { margin: 0 0 10px; }
.vis-empty-note { margin: 0; color: var(--muted); }
.vis-empty-body { margin: 0 0 18px; color: var(--muted); }
.vis-empty-filter { display: flex; gap: 14px; flex-wrap: wrap; margin: 0 0 18px; }
.vis-empty-label { font-size: 12px; color: var(--muted); display: flex; flex-direction: column; gap: 4px; }
.vis-pf-empty { max-width: 640px; padding: 24px 26px; }
.vis-pf-empty-title { margin: 0 0 8px; font-size: 18px; }
.vis-pf-empty-body { color: var(--muted); margin: 0 0 14px; line-height: 1.6; }
/* ── Collection Speed panel ──────────────────────────── */
.page-realtime-control-panel .panel-collection {
  background: var(--surface);
  border-radius: 14px;
  box-shadow: var(--shadow-card);
  padding: 14px 20px;
  margin-bottom: 16px;
}

.page-realtime-control-panel .collection-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
  cursor: pointer;
  user-select: none;
}

.page-realtime-control-panel .collection-header h3 {
  margin: 0;
  font-size: 14px;
  color: var(--brand-dark);
}

.page-realtime-control-panel .collection-caret {
  font-size: 10px;
  color: var(--muted);
  display: inline-block;
  transition: transform 0.2s ease;
}

.page-realtime-control-panel .panel-collection.is-collapsed .collection-caret {
  transform: rotate(-90deg);
}

.page-realtime-control-panel .panel-collection.is-collapsed .collection-body {
  display: none;
}

.page-realtime-control-panel .collection-badge {
  padding: 2px 10px;
  border-radius: 8px;
  font-size: 11px;
  font-weight: 600;
  background: var(--surface-2);
  color: var(--muted);
}

.page-realtime-control-panel .collection-badge.ok { background: var(--success-bg); color: var(--success-ink); }
.page-realtime-control-panel .collection-badge.warn { background: var(--warn-bg); color: var(--warn-ink); }
.page-realtime-control-panel .collection-badge.err { background: var(--danger-bg); color: var(--danger); }

.page-realtime-control-panel .collection-summary {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  font-size: 11px;
  color: var(--muted);
  margin-bottom: 10px;
  font-variant-numeric: tabular-nums;
}

.page-realtime-control-panel .collection-summary:empty {
  display: none;
}

.page-realtime-control-panel .collection-summary-seg strong {
  color: var(--text);
  text-transform: uppercase;
  letter-spacing: 0.3px;
  font-size: 10px;
  margin-right: 2px;
}

.page-realtime-control-panel .collection-grid {
  display: grid;
  /* min(280px,100%) — на телефоне у панели меньше 280px внутренней ширины,
     без этого карточки вылезают за скругление. */
  grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr));
  gap: 8px;
}
/* Phones: wide RCP tables scroll inside the panel instead of spilling out. */
.page-realtime-control-panel .rcp-table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.page-realtime-control-panel .rcp-table-wrap .traffic-table { min-width: 560px; }
.page-realtime-control-panel .rcp-table-wrap .vpn-table { min-width: 560px; }

.page-realtime-control-panel .collection-card {
  border: 1px solid var(--border-soft);
  border-radius: 10px;
  padding: 8px 10px;
  display: flex;
  flex-direction: column;
  gap: 5px;
  background: var(--surface);
}

.page-realtime-control-panel .collection-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.page-realtime-control-panel .collection-agg-badge {
  display: inline-block;
  min-width: 80px;
  text-align: center;
  padding: 2px 8px;
  border-radius: 7px;
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}

.page-realtime-control-panel .collection-stream {
  display: grid;
  grid-template-columns: 10px 38px 32px 58px 1fr 50px 26px;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}

.page-realtime-control-panel .collection-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex-shrink: 0;
}

.page-realtime-control-panel .collection-dot.status-live { background: var(--success); animation: vpn-pulse 1.6s infinite; }
.page-realtime-control-panel .collection-dot.status-slow { background: var(--warn); }
.page-realtime-control-panel .collection-dot.status-idle { background: var(--border-strong); }

.page-realtime-control-panel .collection-stream-label {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.4px;
  color: var(--muted);
}

.page-realtime-control-panel .collection-pct {
  text-align: end;
  font-weight: 700;
  color: var(--text);
}

.page-realtime-control-panel .collection-stream.status-idle .collection-pct {
  color: var(--muted);
  font-weight: 600;
}

.page-realtime-control-panel .collection-stores {
  text-align: end;
  color: var(--muted);
  font-size: 10px;
}

.page-realtime-control-panel .collection-bar-track {
  height: 8px;
  border-radius: 4px;
  background: var(--surface-2);
  overflow: hidden;
}

.page-realtime-control-panel .collection-bar-fill {
  height: 100%;
  border-radius: 4px;
  transition: width 0.4s ease;
  background: var(--border-strong);
}

.page-realtime-control-panel .collection-bar-fill.status-live { background: var(--success); }
.page-realtime-control-panel .collection-bar-fill.status-slow { background: var(--warn); }
.page-realtime-control-panel .collection-bar-fill.status-idle { background: var(--border-strong); }

.page-realtime-control-panel .collection-rate {
  text-align: end;
  font-weight: 600;
  color: var(--brand-dark);
}

.page-realtime-control-panel .collection-stream.status-idle .collection-rate {
  color: var(--muted);
  font-weight: 400;
}

.page-realtime-control-panel .collection-age {
  text-align: end;
  color: var(--muted);
}

.page-realtime-control-panel .collection-empty {
  grid-column: 1 / -1;
  text-align: center;
  padding: 16px;
  color: var(--muted);
  font-size: 13px;
}

/* Admin filter grid: Action History (.audit-filters) and Partners (.partners-filters). */
.audit-filters, .partners-filters { display:grid; grid-template-columns:repeat(auto-fit,minmax(160px,1fr)); gap:12px; align-items:end; margin-bottom:20px; }
.audit-filters label, .partners-filters label { display:block; font-size:12px; font-weight:600; margin-bottom:5px; }
.audit-filters select,.audit-filters input, .partners-filters select,.partners-filters input { width:100%; padding:9px; border:1px solid var(--border); border-radius:8px; background:var(--card); color:var(--text); }
.audit-filters .filter-actions, .partners-filters .filter-actions { display:flex; gap:8px; }
/* Two buttons need ~175px, more than a 160px phone column: give them their own row. */
@media (max-width: 768px) { .audit-filters .filter-actions { grid-column: 1 / -1; } }
/* Partners has three (Apply and two period presets): always a row of their own. */
.partners-filters .filter-actions { grid-column: 1 / -1; flex-wrap: wrap; }
.partners-filters .filter-check label { display:flex; align-items:center; gap:6px; font-weight:400; font-size:13px; margin:0; padding-bottom:9px; }
.partners-filters .filter-check input[type="checkbox"] { width:auto; padding:0; }
/* Partners → API usage: period totals and the chart. */
.partners-freshness { color:var(--muted); margin:0 0 12px; }
.partners-tiles { display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); gap:12px; margin-bottom:20px; }
.partners-tile { display:flex; flex-direction:column; gap:4px; padding:14px 16px; border:1px solid var(--border); border-radius:12px; background:var(--card); }
.partners-tile-label { font-size:12px; font-weight:600; color:var(--muted); }
.partners-tile-value { font-size:22px; font-weight:700; color:var(--text); font-variant-numeric:tabular-nums; }
.partners-tile-value-sm { font-size:15px; }
.partners-tile-hint { font-size:12px; color:var(--muted); }
.partners-chart { min-height:320px; margin-bottom:20px; }
.partners-page h3 { margin:24px 0 10px; }
.partners-page details { margin:10px 0 0; }
/* Accounts list (§2.1): limit bars — yellow from 90 %, red at the limit; a switched-off account is grey. */
.partners-bar { display:block; width:100%; min-width:80px; height:6px; margin-top:4px; border-radius:3px; background:var(--surface-3); overflow:hidden; }
.partners-bar > span { display:block; height:100%; border-radius:3px; background:var(--brand); }
.partners-bar.is-warn > span { background:var(--warn); }
.partners-bar.is-full > span { background:var(--danger); }
.partners-accounts tr.is-inactive td { color:var(--muted); }
.partners-accounts td { vertical-align:top; }
.partners-bad { color:var(--danger); }
/* Account card (§2.2): key–value blocks side by side; not_managed is an invariant violation. */
.partners-card-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(320px,1fr)); gap:0 24px; }
.partners-kv th { width:40%; text-align:start; font-weight:600; color:var(--muted); }
.partners-kv td .partners-bar { max-width:240px; }
.role-bad { color:var(--danger); font-weight:700; }
/* Action windows (§2.3): confirm, then the answer — and a one-time secret — in the same window. */
.partners-actions { display:flex; flex-wrap:wrap; gap:8px; margin:0 0 16px; }
/* The global reset drops the browser's margin:auto that centres a modal; a display rule
   below would beat the hidden attribute — and leave Confirm live after the answer. */
.partners-dialog [hidden] { display:none !important; }
.partners-dialog { margin:auto; max-height:calc(100vh - 32px); overflow:auto; width:min(560px, calc(100vw - 32px)); padding:20px 22px; border:1px solid var(--border); border-radius:12px; background:var(--surface); color:var(--text); box-shadow:var(--shadow-modal); }
.partners-dialog::backdrop { background:var(--overlay); }
.partners-dialog h3 { margin:0 0 10px; }
.partners-dialog-what { color:var(--muted); margin:0 0 12px; }
.partners-dialog-fields { display:flex; flex-direction:column; gap:6px; }
.partners-dialog-fields label { font-size:12px; font-weight:600; margin-top:6px; }
.partners-dialog-fields input[type="text"], .partners-dialog-fields input[type="number"], .partners-dialog-fields select { width:100%; padding:9px; border:1px solid var(--border); border-radius:8px; background:var(--card); color:var(--text); }
.partners-dialog-fields .partners-dialog-check { display:flex; align-items:center; gap:6px; font-weight:400; font-size:13px; }
.partners-dialog-fields .partners-dialog-check input { width:auto; }
.partners-dialog-warn { color:var(--warn-ink); }
.partners-dialog-result { margin-top:12px; padding:10px 12px; border-radius:8px; border:1px solid var(--border); }
.partners-dialog-result.is-ok { background:var(--success-bg); border-color:var(--success-border); }
.partners-dialog-result.is-error { background:var(--danger-bg); border-color:var(--danger-border); color:var(--danger); }
.partners-dialog-result p { margin:0 0 6px; }
.partners-secret { display:flex; flex-direction:column; gap:6px; margin-top:6px; color:var(--text); }
.partners-secret code { word-break:break-all; }
.partners-dialog-actions { display:flex; justify-content:flex-end; gap:8px; margin-top:16px; }
.partners-copy { margin-inline-start:6px; padding:2px 8px; font-size:12px; border:1px solid var(--border); border-radius:6px; background:var(--card); color:var(--text); cursor:pointer; }
.audit-filters .btn-secondary, .partners-filters .btn-secondary { border:1px solid var(--border); background:var(--card); color:var(--text); }
.audit-page small { display:block; color:var(--muted); margin-top:3px; }
.audit-table-wrap { overflow:visible; }
.audit-table { width:100%; table-layout:fixed; }
.audit-table .audit-col-time { width:16%; }
.audit-table .audit-col-actor { width:20%; }
.audit-table .audit-col-action { width:15%; }
.audit-table .audit-col-entity { width:19%; }
.audit-table .audit-col-owner { width:21%; }
.audit-table .audit-col-changes { width:9%; }
.audit-table th,.audit-table td { padding:13px 12px; vertical-align:top; overflow-wrap:anywhere; }
.audit-table th { white-space:nowrap; }
.audit-time { color:var(--muted); font-size:13px; font-variant-numeric:tabular-nums; white-space:nowrap; }
.audit-person span,.audit-entity span { display:-webkit-box; overflow:hidden; -webkit-box-orient:vertical; -webkit-line-clamp:2; line-clamp:2; line-height:1.35; }
.audit-entity-link { color:var(--brand); text-decoration:none; text-underline-offset:2px; }
.audit-entity-link:hover,.audit-entity-link:focus-visible { text-decoration:underline; }
.audit-action-badge { display:inline-block; max-width:100%; padding:4px 7px; border:1px solid var(--border); border-radius:6px; background:var(--info-bg); color:var(--info); font-size:11px; line-height:1.25; overflow-wrap:anywhere; }
.audit-changes-cell { position:relative; overflow:visible !important; }
.audit-changes-cell summary { display:inline-flex; align-items:center; justify-content:center; min-width:52px; padding:5px 9px; border:1px solid var(--border); border-radius:7px; background:var(--card); color:var(--brand); font-size:12px; font-weight:600; cursor:pointer; list-style:none; }
.audit-changes-cell summary::-webkit-details-marker { display:none; }
.audit-changes-cell details[open] summary { background:var(--brand); color:var(--text-inverse); }
.audit-diff-panel { position:absolute; z-index:20; top:42px; inset-inline-end:10px; width:min(720px,calc(100vw - 80px)); padding:16px; border:1px solid var(--border); border-radius:12px; background:var(--card); box-shadow:var(--shadow-card); }
.audit-diff { display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr); gap:12px; }
.audit-diff pre { width:100%; max-height:300px; overflow:auto; margin:7px 0 0; padding:11px; border-radius:8px; background:var(--bg); white-space:pre-wrap; word-break:break-word; font-size:12px; }
@media (max-width:900px) {
  .audit-table-wrap { overflow-x:auto; }
  .audit-table { min-width:900px; }
  .audit-diff-panel { position:fixed; top:80px; inset-inline:20px; width:auto; max-width:calc(100vw - 24px); max-height:calc(100vh - 110px); overflow:auto; }
}
@media (max-width:700px) { .audit-diff { grid-template-columns:1fr; } }

/* ── Collection SLA (realtime control panel) ─────────────────────────────
   Monthly per-aggregator collection availability. Mirrors .panel-collection
   so the two blocks read as one family. */
.page-realtime-control-panel .panel-sla {
  background: var(--surface);
  border-radius: 14px;
  box-shadow: var(--shadow-card);
  padding: 14px 20px;
  margin-bottom: 16px;
}

.page-realtime-control-panel .sla-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
  cursor: pointer;
  user-select: none;
}

.page-realtime-control-panel .sla-header h3 {
  margin: 0;
  font-size: 14px;
  color: var(--brand-dark);
}

.page-realtime-control-panel .sla-caret {
  font-size: 10px;
  color: var(--muted);
  display: inline-block;
  transition: transform 0.2s ease;
}

.page-realtime-control-panel .panel-sla.is-collapsed .sla-caret { transform: rotate(-90deg); }
.page-realtime-control-panel .panel-sla.is-collapsed .sla-body { display: none; }

.page-realtime-control-panel .sla-badge {
  padding: 2px 10px;
  border-radius: 8px;
  font-size: 12px;
  font-weight: 600;
  background: var(--surface-2);
  color: var(--muted);
}
.page-realtime-control-panel .sla-badge[data-empty="0"] { background: var(--success-bg); color: var(--success-ink); }

/* The table can outgrow a narrow column; it scrolls inside its own box
   rather than pushing the page sideways. */
.page-realtime-control-panel .sla-table-wrap { overflow-x: auto; }

.page-realtime-control-panel .sla-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
}

.page-realtime-control-panel .sla-table th {
  text-align: end;
  font-weight: 600;
  color: var(--muted);
  padding: 4px 8px;
  border-bottom: 1px solid var(--border-soft);
  white-space: nowrap;
}

.page-realtime-control-panel .sla-table th.sla-th-name { text-align: start; }

.page-realtime-control-panel .sla-name {
  text-align: start;
  padding: 5px 8px;
  color: var(--text);
  white-space: nowrap;
}

.page-realtime-control-panel .sla-cell {
  text-align: end;
  padding: 5px 8px;
  white-space: nowrap;
  border-bottom: 1px solid var(--border-soft);
}

.page-realtime-control-panel .sla-pct {
  display: block;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.page-realtime-control-panel .sla-sub {
  display: block;
  font-size: 10px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.page-realtime-control-panel .sla-cell.tone-good .sla-pct { color: var(--success); }
.page-realtime-control-panel .sla-cell.tone-warn .sla-pct { color: var(--warn); }
.page-realtime-control-panel .sla-cell.tone-bad  .sla-pct { color: var(--danger); }
.page-realtime-control-panel .sla-cell.tone-none .sla-pct { color: var(--muted); }

.page-realtime-control-panel .sla-table tfoot td {
  border-top: 2px solid var(--border-soft);
  border-bottom: none;
  padding-top: 7px;
}
.page-realtime-control-panel .sla-total-name { font-weight: 700; }

.page-realtime-control-panel .sla-note {
  margin: 8px 0 0;
  font-size: 11px;
  line-height: 1.45;
  color: var(--muted);
}

/* The header column carries the legend, so a cell's three figures are named
   without a separate row of labels above the table. */
.page-realtime-control-panel .sla-legend {
  display: block;
  font-weight: 400;
  font-size: 10px;
  color: var(--muted);
  margin-top: 2px;
}

/* The two percentages in a cell diverge often enough that the block needs a
   place to say why. Collapsed by default: reference material, not something to
   re-read on every visit. */
.page-realtime-control-panel .sla-help-bar { margin: 0 0 8px; }

.page-realtime-control-panel .sla-help-btn {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  font-size: 11px;
  color: var(--muted);
  text-decoration: underline dotted;
  text-underline-offset: 2px;
  cursor: pointer;
}

.page-realtime-control-panel .sla-help-btn:hover { color: var(--brand-dark); }

.page-realtime-control-panel .sla-help {
  margin: 0 0 12px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
  font-size: 11px;
  line-height: 1.5;
  color: var(--muted);
}

.page-realtime-control-panel .sla-help-h {
  margin: 10px 0 4px;
  font-size: 11px;
  color: var(--brand-dark);
}

.page-realtime-control-panel .sla-help-h:first-child { margin-top: 0; }

.page-realtime-control-panel .sla-help-list { margin: 0; padding-inline-start: 16px; }
.page-realtime-control-panel .sla-help-list li { margin: 2px 0; }
.page-realtime-control-panel .sla-help-list b { color: var(--brand-dark); font-weight: 600; }

.page-realtime-control-panel .sla-cell { cursor: help; }

/* ── Action History tabs (Changes / Visits) ───────────────────────────── */
.eng-tabs {
  display: flex;
  gap: 4px;
  margin: 0 0 14px;
  border-bottom: 1px solid var(--border-soft);
}
.eng-tabs a {
  padding: 8px 16px;
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.eng-tabs a:hover { color: var(--text); }
.eng-tabs a.is-active { color: var(--brand-dark); border-bottom-color: var(--brand-dark); }

.audit-page .eng-note {
  margin: 0 0 10px;
  font-size: 11px;
  line-height: 1.5;
  color: var(--muted);
}
/* One card per page: scroll depth on the left, blocks in page order on the
   right, so "how far down do they get" and "which block did they reach" read
   as the same question. */
.audit-page .eng-page {
  background: var(--surface);
  border-radius: 14px;
  box-shadow: var(--shadow-card);
  padding: 14px 20px 16px;
  margin-bottom: 14px;
}
.audit-page .eng-page-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}
.audit-page .eng-page-head h3 { margin: 0; font-size: 14px; }
.audit-page .eng-page-head h3 code { font-size: 14px; color: var(--brand-dark); }
.audit-page .eng-page-head span { font-size: 12px; color: var(--muted); }

.audit-page .eng-split { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; }
@media (max-width: 860px) { .audit-page .eng-split { grid-template-columns: 1fr; } }

.audit-page .eng-split h4 {
  margin: 0 0 8px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .3px;
  text-transform: uppercase;
  color: var(--muted);
}

/* label · bar · number · footnote, so rows line up down the column */
.audit-page .eng-row {
  display: grid;
  grid-template-columns: minmax(90px, 1.1fr) 3fr 42px auto;
  align-items: center;
  gap: 8px;
  padding: 3px 0;
  font-size: 12px;
}
.audit-page .eng-label { color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.audit-page .eng-bar {
  height: 8px;
  border-radius: 5px;
  background: var(--surface-3);
  overflow: hidden;
}
.audit-page .eng-bar i { display: block; height: 100%; background: var(--brand); border-radius: 5px; }
.audit-page .eng-val { text-align: end; font-weight: 600; font-variant-numeric: tabular-nums; }
.audit-page .eng-sub { font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }
.audit-page p.eng-sub { margin: 8px 0 0; }
/* Two summary cards above the per-page breakdown: pages with their counters,
   and the people behind those counters. */
.audit-page .eng-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-bottom: 14px; }
@media (max-width: 980px) { .audit-page .eng-cols { grid-template-columns: 1fr; } }
.audit-page .eng-card {
  background: var(--surface);
  border-radius: 14px;
  box-shadow: var(--shadow-card);
  padding: 14px 18px 16px;
  overflow-x: auto;
}
.audit-page .eng-card h4 {
  margin: 0 0 8px; font-size: 11px; font-weight: 600; letter-spacing: .3px;
  text-transform: uppercase; color: var(--muted);
}
.audit-page .eng-mini { width: 100%; border-collapse: collapse; font-size: 12px; }
.audit-page .eng-mini th {
  text-align: end; font-weight: 600; color: var(--muted); padding: 3px 6px;
  border-bottom: 1px solid var(--border-soft); white-space: nowrap;
}
.audit-page .eng-mini th:first-child { text-align: start; }
.audit-page .eng-mini td {
  text-align: end; padding: 4px 6px; border-bottom: 1px solid var(--surface-2);
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
.audit-page .eng-mini td:first-child { text-align: start; }
/* Marks an account that never runs the page script — a poller, not a reader. */
.audit-page .eng-bot {
  display: inline-block; margin-inline-start: 6px; padding: 0 6px;
  border-radius: 6px; background: var(--warn-bg); color: var(--warn-ink);
  font-size: 10px; font-weight: 600; cursor: help;
}
.audit-page .eng-visits { margin-bottom: 14px; }
.audit-page .eng-visits h4 code { font-size: 12px; text-transform: none; color: var(--brand-dark); }
.audit-page .eng-clear {
  margin-inline-start: 8px; font-size: 10px; font-weight: 600;
  text-transform: none; color: var(--muted);
}
.audit-page .eng-mini a { color: var(--brand-dark); text-decoration: none; }
.audit-page .eng-mini a:hover { text-decoration: underline; }
/* A page with no blocks marked has nothing to put beside the depth, so the
   depth takes the width rather than leaving an empty column. */
.audit-page .eng-split.is-single { grid-template-columns: 1fr; }

/* ── Compact filter bar (spec 2026-09-23-mobile-reports-compact) ──────────
   Opt-in: .filter-form.filter-form--compact. Kept at the END of app.css so it
   wins over page-scoped filter rules of equal specificity by source order.
   Label sits on the control's top border (outlined field). */
.filter-form.filter-form--compact { padding: 14px 16px; }
/* lost_revenue wraps its heading in .filter-form-inner (a required layout wrapper on
   that page), so the direct-child selector alone misses it — match both shapes. */
.filter-form.filter-form--compact > h3,
.filter-form.filter-form--compact .filter-form-inner > h3 { font-size: 14px; margin: 0 0 14px; }
.filter-form.filter-form--compact .filter-grid,
.filter-form.filter-form--compact .filter-grid-row {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: 16px 10px;
  margin: 8px 0 14px;
}
.filter-form.filter-form--compact .filter-group { position: relative; margin: 0; min-width: 0; }
.filter-form.filter-form--compact .filter-group > label {
  position: absolute;
  top: -7px;
  inset-inline-start: 9px;
  z-index: 2;
  max-width: calc(100% - 18px);
  margin: 0;
  padding: 0 4px;
  background: var(--surface);
  color: var(--muted);
  font-size: 11px;
  font-weight: 600;
  line-height: 14px;
  letter-spacing: 0.2px;
  text-transform: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none;
}
/* Groups without a text-like control (checkbox rows) keep a normal label. */
.filter-form.filter-form--compact .filter-group:not(:has(.multi-select, select, input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]))) > label {
  position: static;
  padding: 0;
  background: none;
}
/* :not([type="range"]) — the duration dual-slider (offline_report/offline_summary) is a
   text-like input by DOM type, but must keep its own track/thumb styling, not the 38px
   bordered field look (that opaque background + border was hiding the thumb and fill).
   :not(.multi-select-search input) — the multi-select's own in-panel search box keeps its
   panel styling (app.css ~752), not the compact field one. */
.filter-form.filter-form--compact .filter-group input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):not([type="range"]):not(.multi-select-search input),
.filter-form.filter-form--compact .filter-group select,
.filter-form.filter-form--compact .multi-select-toggle {
  width: 100%;
  height: 38px;
  min-height: 38px;
  padding: 0 10px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background-color: var(--surface);
  color: var(--text);
  font-size: 14px;
}
/* :focus-visible (not :focus), scoped to the same text-like/select/toggle set above:
   checkboxes, radios and the range thumbs keep their native focus ring instead of losing
   it to a blanket outline:none, and mouse-click focus no longer draws a ring at all. */
.filter-form.filter-form--compact .filter-group input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):not([type="range"]):not(.multi-select-search input):focus-visible,
.filter-form.filter-form--compact .filter-group select:focus-visible,
.filter-form.filter-form--compact .multi-select-toggle:focus-visible {
  border-color: var(--brand);
  outline: 2px solid var(--brand);
  outline-offset: 1px;
}
.filter-form.filter-form--compact .filter-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 4px; }
.filter-form.filter-form--compact .filter-actions .btn-primary,
.filter-form.filter-form--compact .filter-actions .btn-secondary,
.filter-form.filter-form--compact .filter-actions .ms-btn-reset,
.filter-form.filter-form--compact .filter-actions .ms-btn-export,
.filter-form.filter-form--compact .filter-actions .pd-btn {
  display: inline-flex;
  align-items: center;
  height: 38px;
  padding: 0 18px;
}
.filter-more-toggle { display: none; }

@media (max-width: 768px) {
  .filter-form.filter-form--compact { padding: 12px; }
  .filter-form.filter-form--compact > h3,
  .filter-form.filter-form--compact .filter-form-inner > h3 { display: none; }
  .filter-form.filter-form--compact .filter-grid,
  .filter-form.filter-form--compact .filter-grid-row { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px 8px; margin: 8px 0 10px; }
  .filter-form.filter-form--compact .filter-group.is-primary { order: -1; }
  .filter-form.filter-form--compact.is-compact-ready:not(.is-expanded) .filter-group.is-extra { display: none; }
  /* A grid whose every group just collapsed above (e.g. status_by_id's --times row when
     both time fields are non-primary) still keeps its own margin/gap — hide it too. */
  .filter-form.filter-form--compact.is-compact-ready:not(.is-expanded) .filter-grid:not(:has(.filter-group:not(.is-extra))),
  .filter-form.filter-form--compact.is-compact-ready:not(.is-expanded) .filter-grid-row:not(:has(.filter-group:not(.is-extra))) { display: none; }
  .filter-form.filter-form--compact .filter-more-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 36px;
    margin: 0 0 10px;
    border: 1px dashed var(--border-strong);
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text);
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
  }
  /* flex: 1 1 auto (not 1 1 0) so a button first tries its own content width; nowrap +
     min-width: 0 keep "Apply Filters · 0" on one line instead of breaking inside the
     fixed 38px height — if the pair doesn't fit one row, flex-wrap (on .filter-actions,
     above) drops the second button to its own full-width row instead of overflowing. */
  .filter-form.filter-form--compact .filter-actions .btn-primary,
  .filter-form.filter-form--compact .filter-actions .btn-secondary {
    flex: 1 1 auto;
    justify-content: center;
    white-space: nowrap;
    min-width: 0;
    font-size: 13px;
  }
}

/* offline_report / offline_summary: the duration-filter-group packs a range slider AND
   a checkbox toggle (data-filter-primary not applicable — it's never forced primary).
   Its own <label> keeps the outlined-field treatment (correct — it labels the slider),
   but the OTHER direct-child label (.duration-still-toggle) just wraps a checkbox: the
   outlined absolute/ellipsis/pointer-events:none styling would swallow its click target
   and truncate "Include still offline" to nothing. Reset that one label back to normal. */
.filter-form.filter-form--compact .filter-group > label:has(input[type="checkbox"]) {
  position: static;
  max-width: none;
  margin: 6px 0 0; /* keeps the page's own gap under the slider above (.duration-still-toggle) */
  padding: 0;
  background: none;
  color: var(--text);
  font-size: 13px;
  font-weight: 400;
  letter-spacing: normal;
  text-transform: none;
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
  pointer-events: auto;
}
/* Same two pages: the slider's own page CSS gives it an unconditional min-width:240px,
   wider than a single 170px (desktop auto-fill) or ~170px (mobile 2-col) grid track —
   it would overflow its column. Let it span the full row instead. */
.filter-form.filter-form--compact .filter-group.duration-filter-group { grid-column: 1 / -1; }

/* status_by_id: the compact grid replaces filter-grid--rest's own 1fr/280px split (app.css
   ~2193) with same-width auto-fill tracks, squeezing the forced restaurant-search group
   (data-filter-primary) into a single ~170px column. Let it take the full row instead. */
.page-status-by-id .filter-form.filter-form--compact .filter-grid--rest .filter-group[data-filter-primary] { grid-column: 1 / -1; }

/* ═══════════════════════════════════════════════
   WhatsApp Outreach (admin_outreach/index.php) — chat-style conversation view.
   WhatsApp's own bubble/wallpaper palette has no matching token, so it is
   mapped onto the nearest existing role (brand for the accent green, success
   for the outgoing-bubble tint, info for read/manual blues) rather than
   inventing new tokens; shadows/tints use color-mix() from --text so they
   invert correctly in dark mode.
   ═══════════════════════════════════════════════ */
.page-admin-outreach .outreach-layout { display: flex; gap: 20px; min-height: calc(100vh - 140px); }
.page-admin-outreach .outreach-sidebar { width: 420px; flex-shrink: 0; display: flex; flex-direction: column; }
.page-admin-outreach .outreach-main { flex: 1; min-width: 0; }

/* Filter toolbar */
.page-admin-outreach .outreach-filters { background: var(--card); border-radius: 12px; padding: 16px; margin-bottom: 16px; box-shadow: var(--shadow-card); }
.page-admin-outreach .outreach-filters form { display: flex; gap: 12px; flex-wrap: wrap; align-items: flex-end; }
.page-admin-outreach .outreach-filters .filter-group { display: flex; flex-direction: column; gap: 4px; }
.page-admin-outreach .outreach-filters .filter-group--search { flex: 1; min-width: 200px; }
.page-admin-outreach .outreach-filters .filter-group label { font-size: 11px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.5px; }
.page-admin-outreach .outreach-filters input[type="text"],
.page-admin-outreach .outreach-filters select { padding: 8px 12px; border: 1px solid var(--border); border-radius: 8px; font-size: 13px; background: var(--bg); min-width: 160px; }
.page-admin-outreach .outreach-filters .btn-filter { padding: 8px 16px; background: var(--brand); color: var(--text-inverse); border: none; border-radius: 8px; font-size: 13px; font-weight: 600; cursor: pointer; }
.page-admin-outreach .outreach-filters .btn-filter:hover { background: var(--brand-dark); }
.page-admin-outreach .outreach-filters .btn-clear { padding: 8px 12px; background: transparent; color: var(--muted); border: 1px solid var(--border); border-radius: 8px; font-size: 13px; cursor: pointer; text-decoration: none; }

/* Stats bar + header link */
.page-admin-outreach .outreach-stats { display: flex; gap: 16px; margin-bottom: 12px; font-size: 13px; color: var(--muted); flex-wrap: wrap; }
.page-admin-outreach .outreach-stats strong { color: var(--text); }
.page-admin-outreach .outreach-stats-link {
  padding: 8px 20px;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 700;
  text-decoration: none;
  color: var(--text-inverse);
  background: var(--info);
  box-shadow: 0 2px 8px color-mix(in srgb, var(--info) 30%, transparent);
}
.page-admin-outreach .outreach-stats-link:hover { background: color-mix(in srgb, var(--info) 85%, var(--text) 15%); }
.page-admin-outreach .outreach-empty { padding: 40px; text-align: center; color: var(--muted); }

/* Contact cards */
.page-admin-outreach .outreach-cards { display: flex; flex-direction: column; gap: 4px; overflow-y: auto; max-height: calc(100vh - 320px); padding-inline-end: 4px; }
.page-admin-outreach .outreach-cards::-webkit-scrollbar { width: 5px; }
.page-admin-outreach .outreach-cards::-webkit-scrollbar-track { background: transparent; }
.page-admin-outreach .outreach-cards::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--text) 12%, transparent); border-radius: 3px; }
.page-admin-outreach .outreach-cards::-webkit-scrollbar-thumb:hover { background: color-mix(in srgb, var(--text) 20%, transparent); }
.page-admin-outreach .outreach-card {
    display: flex;
    align-items: stretch;
    gap: 12px;
    padding: 12px 16px;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 10px;
    cursor: pointer;
    transition: border-color 0.2s, box-shadow 0.2s;
    text-decoration: none;
    color: inherit;
}
.page-admin-outreach .outreach-card:hover { border-color: var(--brand); }
.page-admin-outreach .outreach-card.active {
    border-color: var(--brand);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--brand) 35%, transparent);
    background: color-mix(in srgb, var(--brand) 6%, transparent);
}
.page-admin-outreach .outreach-card-stripe { width: 4px; min-height: 100%; border-radius: 2px; flex-shrink: 0; }
.page-admin-outreach .outreach-card-stripe--default { background: var(--muted); }
.page-admin-outreach .outreach-card-body { flex: 1; min-width: 0; }
.page-admin-outreach .outreach-card-header { display: flex; align-items: center; gap: 8px; margin-bottom: 2px; }
.page-admin-outreach .outreach-card-header strong { font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.page-admin-outreach .outreach-card-badge {
    font-size: 10px;
    font-weight: 700;
    padding: 2px 8px;
    border-radius: 999px;
    color: var(--on-accent);
    white-space: nowrap;
    text-transform: uppercase;
    letter-spacing: 0.3px;
}
/* Muted default (no per-status colour): the background is a token, not
   data, so it keeps the theme-aware inverse instead of the always-white
   --on-accent the base rule uses for real DB colours. */
.page-admin-outreach .outreach-card-badge--default { background: var(--muted); color: var(--text-inverse); }
.page-admin-outreach .outreach-card-meta { font-size: 12px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-bottom: 2px; }
.page-admin-outreach .outreach-card-meta--strong { font-weight: 600; }
.page-admin-outreach .outreach-card-meta--reply { color: var(--success); font-style: italic; }
.page-admin-outreach .outreach-card-sender { font-size: 11px; color: var(--muted); }
.page-admin-outreach .outreach-card-tags { display: flex; gap: 3px; flex-wrap: wrap; margin-top: 2px; }
.page-admin-outreach .outreach-card-time { font-size: 11px; color: var(--muted); white-space: nowrap; flex-shrink: 0; align-self: flex-start; margin-top: 2px; }
.page-admin-outreach .outreach-card-time-wrap { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }

.page-admin-outreach .tag-pill {
    display: inline-block;
    font-size: 9px;
    font-weight: 700;
    padding: 1px 7px;
    border-radius: 999px;
    color: var(--on-accent);
    letter-spacing: 0.2px;
    text-transform: uppercase;
}
.page-admin-outreach .tag-pill--default { background: var(--muted); color: var(--text-inverse); }

/* Tag toggles in thread header */
.page-admin-outreach .thread-tags { display: flex; gap: 6px; padding: 8px 20px; border-bottom: 1px solid var(--border); flex-wrap: wrap; background: var(--card); }
.page-admin-outreach .tag-toggle {
    font-size: 11px;
    font-weight: 600;
    padding: 3px 12px;
    border-radius: 999px;
    cursor: pointer;
    border: 2px solid;
    transition: all 0.15s;
    text-transform: uppercase;
    letter-spacing: 0.3px;
}
/* Background is the DB tag colour (data-driven, not theme-aware) — text on it
   needs the theme-invariant --on-accent, not --text-inverse (which flips dark
   in dark mode and would vanish against a still-light tag colour). */
.page-admin-outreach .tag-toggle.active { color: var(--on-accent); }
.page-admin-outreach .tag-toggle:hover { opacity: 0.8; }

/* Unread indicator */
@keyframes pulse-unread {
    0%, 100% { opacity: 1; transform: scale(1); }
    50% { opacity: 0.4; transform: scale(0.85); }
}
.page-admin-outreach .outreach-card-unread {
    width: 12px;
    height: 12px;
    background: var(--danger);
    border-radius: 50%;
    animation: pulse-unread 1.2s ease-in-out infinite;
    flex-shrink: 0;
    align-self: center;
    box-shadow: 0 0 6px color-mix(in srgb, var(--danger) 50%, transparent);
}
.page-admin-outreach .outreach-card.has-unread {
    border-color: color-mix(in srgb, var(--danger) 50%, var(--surface) 50%);
    background: color-mix(in srgb, var(--danger) 3%, transparent);
}

/* Thread panel */
.page-admin-outreach .thread-panel {
    background: var(--card);
    border-radius: 12px;
    box-shadow: var(--shadow-card);
    display: flex;
    flex-direction: column;
    min-height: 400px;
    height: calc(100vh - 140px);
    position: sticky;
    top: 16px;
    overflow: hidden;
}
.page-admin-outreach .thread-header { padding: 14px 20px; border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 14px; background: var(--card); }
.page-admin-outreach .thread-avatar {
    width: 42px;
    height: 42px;
    border-radius: 50%;
    background: linear-gradient(135deg, var(--brand), var(--brand-dark));
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-inverse);
    font-weight: 700;
    font-size: 17px;
    flex-shrink: 0;
    text-transform: uppercase;
}
.page-admin-outreach .thread-header-info { flex: 1; min-width: 0; }
.page-admin-outreach .thread-header-info h3 { font-size: 17px; font-weight: 700; margin: 0 0 2px; line-height: 1.3; }
.page-admin-outreach .thread-header-info .thread-meta { font-size: 12px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.page-admin-outreach .thread-header-status {
    font-size: 10px;
    font-weight: 700;
    padding: 3px 10px;
    border-radius: 999px;
    color: var(--on-accent);
    text-transform: uppercase;
    letter-spacing: 0.3px;
    flex-shrink: 0;
}
.page-admin-outreach .thread-empty { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; color: var(--muted); gap: 12px; }
.page-admin-outreach .thread-empty-icon { font-size: 48px; opacity: 0.3; }
.page-admin-outreach .thread-empty-text { font-size: 15px; }
.page-admin-outreach .thread-messages-empty { text-align: center; color: var(--muted); padding: 40px; font-size: 14px; }
.page-admin-outreach .thread-messages {
    flex: 1;
    overflow-y: auto;
    padding: 16px 20px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    background: var(--surface-2);
    /* Faint dot texture baked into the SVG (%23 is the url-encoded hash before the fill's
       hex digits, opacity .15); not tokenised — a decorative pattern fill, not a themed colour. */
    background-image: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23ccc4b7' fill-opacity='0.15'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
}
.page-admin-outreach .thread-messages::-webkit-scrollbar { width: 6px; }
.page-admin-outreach .thread-messages::-webkit-scrollbar-track { background: transparent; }
.page-admin-outreach .thread-messages::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--text) 15%, transparent); border-radius: 3px; }
.page-admin-outreach .thread-messages::-webkit-scrollbar-thumb:hover { background: color-mix(in srgb, var(--text) 25%, transparent); }

/* System messages (reactions, etc.) */
.page-admin-outreach .bubble-system {
    align-self: center;
    font-size: 12px;
    color: var(--muted);
    padding: 3px 12px;
    background: color-mix(in srgb, var(--surface-3) 60%, transparent);
    border-radius: 8px;
    margin: 2px 0;
}

/* Date separator */
.page-admin-outreach .bubble-date-sep {
    align-self: center;
    background: color-mix(in srgb, var(--surface-3) 90%, transparent);
    color: var(--muted);
    font-size: 12px;
    font-weight: 600;
    padding: 5px 14px;
    border-radius: 8px;
    margin: 8px 0;
    box-shadow: 0 1px 1px color-mix(in srgb, var(--text) 6%, transparent);
}

/* Bubbles */
.page-admin-outreach .bubble {
    max-width: 70%;
    padding: 8px 12px;
    border-radius: 10px;
    font-size: 15px;
    line-height: 1.5;
    position: relative;
    word-wrap: break-word;
    white-space: pre-wrap;
    box-shadow: 0 1px 1px color-mix(in srgb, var(--text) 8%, transparent);
}
.page-admin-outreach .bubble-out {
    align-self: flex-end;
    background: var(--success-bg);
    border-start-end-radius: 3px;
    margin-inline-start: 40px;
}
.page-admin-outreach .bubble-in {
    align-self: flex-start;
    background: var(--surface);
    border-start-start-radius: 3px;
    margin-inline-end: 40px;
}
.page-admin-outreach .bubble-in.opt-out { border-inline-start: 3px solid var(--danger); }
.page-admin-outreach .bubble-step { font-size: 11px; font-weight: 700; color: var(--brand-dark); text-transform: uppercase; margin-bottom: 3px; letter-spacing: 0.3px; }
.page-admin-outreach .bubble-footer { display: flex; align-items: center; gap: 4px; justify-content: flex-end; margin-top: 2px; }
.page-admin-outreach .bubble-time { font-size: 11px; color: color-mix(in srgb, var(--text) 40%, transparent); }
.page-admin-outreach .bubble-status { font-size: 12px; color: color-mix(in srgb, var(--text) 30%, transparent); }
.page-admin-outreach .bubble-status.delivered { color: var(--muted); }
.page-admin-outreach .bubble-status.read { color: var(--info); }
.page-admin-outreach .bubble-status.failed { color: var(--danger); }
.page-admin-outreach .bubble-manual { background: var(--info-bg); border-start-end-radius: 3px; }
.page-admin-outreach .bubble-manual .bubble-step { color: var(--info); }
.page-admin-outreach .bubble-scheduled { opacity: 0.6; border: 1px dashed var(--muted); background: var(--surface-2); }
.page-admin-outreach .opt-out-badge { color: var(--danger); font-size: 10px; font-weight: 700; }

/* Send input */
.page-admin-outreach .thread-input { display: flex; gap: 10px; padding: 10px 16px; background: var(--surface-2); align-items: flex-end; }
.page-admin-outreach .thread-input textarea {
    flex: 1;
    resize: none;
    border: none;
    border-radius: 22px;
    padding: 10px 16px;
    font-size: 15px;
    font-family: inherit;
    background: var(--surface);
    max-height: 100px;
    box-shadow: 0 1px 2px color-mix(in srgb, var(--text) 8%, transparent);
    line-height: 1.4;
}
.page-admin-outreach .thread-input textarea:focus { outline: none; box-shadow: 0 1px 4px color-mix(in srgb, var(--text) 12%, transparent); }
.page-admin-outreach .thread-input textarea::placeholder { color: var(--muted); }
.page-admin-outreach .thread-input button {
    width: 44px;
    height: 44px;
    padding: 0;
    background: var(--brand);
    color: var(--text-inverse);
    border: none;
    border-radius: 50%;
    font-size: 18px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: background 0.15s;
}
.page-admin-outreach .thread-input button:hover { background: var(--brand-dark); }
.page-admin-outreach .thread-input button:disabled { opacity: 0.5; cursor: not-allowed; }

/* Pagination */
.page-admin-outreach .outreach-pagination { display: flex; gap: 4px; justify-content: center; margin-top: 12px; flex-wrap: wrap; }
.page-admin-outreach .outreach-pagination a,
.page-admin-outreach .outreach-pagination span {
    padding: 6px 12px;
    font-size: 13px;
    border-radius: 6px;
    text-decoration: none;
    color: var(--text);
    border: 1px solid var(--border);
    background: var(--card);
}
.page-admin-outreach .outreach-pagination span.current { background: var(--brand); color: var(--text-inverse); border-color: var(--brand); }
.page-admin-outreach .outreach-pagination a:hover { border-color: var(--brand); }

/* Browser-notification permission prompt (built in JS, no inline cssText).
   JS appends it to document.body (not inside .page-admin-outreach) so the
   fixed position escapes any positioned ancestor — the selector stays
   unscoped to match; the class name is unique enough not to leak. */
.outreach-notify-btn {
    position: fixed;
    inset-block-end: 20px;
    inset-inline-end: 20px;
    padding: 10px 20px;
    background: var(--brand);
    color: var(--text-inverse);
    border: none;
    border-radius: 8px;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    z-index: 9999;
    box-shadow: 0 2px 10px color-mix(in srgb, var(--text) 20%, transparent);
}

/* Responsive */
@media (max-width: 900px) {
    .page-admin-outreach .outreach-layout { flex-direction: column; }
    .page-admin-outreach .outreach-sidebar { width: 100%; }
    .page-admin-outreach .outreach-cards { max-height: 50vh; }
    .page-admin-outreach .thread-panel { position: static; height: auto; min-height: 300px; }
}

/* ═══════════════════════════════════════════════
   Outreach Statistics (admin_outreach/stats.php)
   ═══════════════════════════════════════════════ */
.page-admin-outreach .container { max-width: 1400px; }
.page-admin-outreach-stats .stats-nav { display: flex; gap: 8px; align-items: center; }
.page-admin-outreach-stats .stats-nav a { padding: 6px 14px; border-radius: 6px; font-size: 13px; text-decoration: none; color: var(--text); border: 1px solid var(--border); }
.page-admin-outreach-stats .stats-nav a:hover { border-color: var(--brand); }

.page-admin-outreach-stats .stats-filters {
    display: flex; gap: 12px; align-items: flex-end; flex-wrap: wrap;
    background: var(--card); padding: 14px 16px; border-radius: 10px;
    margin-bottom: 20px; box-shadow: var(--shadow-card);
}
.page-admin-outreach-stats .stats-filters label { font-size: 11px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.5px; }
.page-admin-outreach-stats .stats-filters input[type="date"] { padding: 6px 10px; border: 1px solid var(--border); border-radius: 6px; font-size: 13px; background: var(--bg); }
.page-admin-outreach-stats .stats-filters button { padding: 6px 16px; background: var(--brand); color: var(--text-inverse); border: none; border-radius: 6px; font-size: 13px; font-weight: 600; cursor: pointer; }
.page-admin-outreach-stats .stats-filter-form { display: flex; gap: 12px; align-items: flex-end; flex-wrap: wrap; }
.page-admin-outreach-stats .stats-field { display: flex; flex-direction: column; gap: 4px; }

.page-admin-outreach-stats .kpi-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 14px; margin-bottom: 24px; }
.page-admin-outreach-stats .kpi-card { background: var(--card); border-radius: 10px; padding: 18px 20px; box-shadow: var(--shadow-card); }
.page-admin-outreach-stats .kpi-value { font-size: 28px; font-weight: 700; color: var(--text); line-height: 1.2; }
.page-admin-outreach-stats .kpi-label { font-size: 12px; color: var(--muted); margin-top: 4px; text-transform: uppercase; letter-spacing: 0.5px; }
.page-admin-outreach-stats .kpi-sub { font-size: 12px; color: var(--success); margin-top: 2px; }
.page-admin-outreach-stats .kpi-sub.warn { color: var(--danger); }

.page-admin-outreach-stats .charts-row { display: grid; grid-template-columns: 2fr 1fr; gap: 20px; margin-bottom: 24px; }
/* Grid items default to min-width:auto, so a grid item won't shrink below its
   content's intrinsic width. ApexCharts sizes its SVG canvas off the
   container's own width at render time; on a narrow phone that intrinsic
   width can end up fractionally wider than the 1fr track (.charts-row goes
   single-column at <=768px), pushing .chart-box past the viewport edge.
   min-width:0 lets the grid item shrink to its track; max-width/overflow
   contain whatever the chart library doesn't resize back down in time. */
.page-admin-outreach-stats .chart-box { background: var(--card); border-radius: 10px; padding: 18px 20px; box-shadow: var(--shadow-card); min-width: 0; max-width: 100%; overflow: hidden; }
.page-admin-outreach-stats .chart-box h3 { font-size: 14px; margin: 0 0 12px; color: var(--text); }

.page-admin-outreach-stats .followups-body { padding: 16px 0; }
.page-admin-outreach-stats .followups-tiles { display: flex; gap: 16px; margin-bottom: 16px; }
.page-admin-outreach-stats .followup-tile { flex: 1; text-align: center; padding: 12px; background: var(--bg); border-radius: 8px; }
.page-admin-outreach-stats .followup-tile__value { font-size: 24px; font-weight: 700; }
.page-admin-outreach-stats .followup-tile__value--pending { color: var(--info); }
.page-admin-outreach-stats .followup-tile__value--sent { color: var(--success); }
.page-admin-outreach-stats .followup-tile__value--cancelled { color: var(--danger); }
.page-admin-outreach-stats .followup-tile__label { font-size: 11px; color: var(--muted); text-transform: uppercase; }
.page-admin-outreach-stats .next-followup { font-size: 12px; color: var(--muted); }
.page-admin-outreach-stats .section-subhead { font-size: 13px; margin: 16px 0 8px; color: var(--text); }
.page-admin-outreach-stats .sender-empty { font-size: 12px; color: var(--muted); }
.page-admin-outreach-stats .sender-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid var(--border); font-size: 12px; }
.page-admin-outreach-stats .sender-row__label { font-weight: 600; }

.page-admin-outreach-stats .tag-empty { padding: 20px; text-align: center; color: var(--muted); font-size: 13px; }
.page-admin-outreach-stats .tag-breakdown-body { padding: 12px 0; }
.page-admin-outreach-stats .tag-status-block { margin-bottom: 12px; }
.page-admin-outreach-stats .tag-status-row { display: flex; justify-content: space-between; margin-bottom: 4px; }
.page-admin-outreach-stats .tag-status-name { font-weight: 700; font-size: 13px; }
.page-admin-outreach-stats .tag-status-dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; margin-inline-end: 6px; }
.page-admin-outreach-stats .tag-status-count { font-size: 12px; color: var(--muted); }
.page-admin-outreach-stats .tag-status-bar { display: flex; height: 8px; border-radius: 4px; overflow: hidden; background: var(--surface-3); }
.page-admin-outreach-stats .tag-status-bar__seg--replied { background: var(--success); }
.page-admin-outreach-stats .tag-status-bar__seg--opted-out { background: var(--danger); }
.page-admin-outreach-stats .tag-status-bar__seg--other { background: var(--muted); }
.page-admin-outreach-stats .tag-status-caption { display: flex; gap: 12px; font-size: 11px; color: var(--muted); margin-top: 2px; }
.page-admin-outreach-stats .tag-status-caption__replied { color: var(--success); }
.page-admin-outreach-stats .tag-status-caption__opted-out { color: var(--danger); }

@media (max-width: 768px) {
  .page-admin-outreach-stats .charts-row { grid-template-columns: 1fr; }
  .page-admin-outreach-stats .kpi-grid { grid-template-columns: repeat(2, 1fr); }
}

/* ── Traffic & Costs (admin) ───────────────────────────────────────────── */
.page-admin-traffic-costs .tc-params-title { margin: 0 0 16px; font-size: 15px; font-weight: 600; }
.page-admin-traffic-costs .tc-w-sm { width: 100px; max-width: 100%; }
.page-admin-traffic-costs .tc-w-md { width: 120px; max-width: 100%; }

.page-admin-traffic-costs .tc-params {
  display: flex; flex-wrap: wrap; gap: 24px; align-items: flex-end;
}
.page-admin-traffic-costs .tc-params label {
  display: flex; flex-direction: column; gap: 4px; font-size: 13px; font-weight: 500;
}
.page-admin-traffic-costs .tc-params input[type="number"] {
  padding: 6px 8px; border: 1px solid var(--border-strong); border-radius: 6px; font-size: 14px;
  background: var(--surface); color: var(--text);
}
.page-admin-traffic-costs .tc-params .tc-computed {
  font-size: 13px; font-weight: 500; padding-bottom: 4px;
}

.page-admin-traffic-costs .tc-card {
  background: var(--surface); border-radius: 14px; box-shadow: var(--shadow-card);
  overflow: hidden; margin-bottom: 20px;
}
.page-admin-traffic-costs .tc-card-header {
  padding: 14px 18px; font-size: 15px; font-weight: 700;
  background: var(--surface-2); border-bottom: 1px solid var(--border);
  display: flex; align-items: center; gap: 8px;
}
.page-admin-traffic-costs .tc-table {
  width: 100%; border-collapse: collapse; font-size: 13px;
}
.page-admin-traffic-costs .tc-table th,
.page-admin-traffic-costs .tc-table td {
  padding: 9px 14px; text-align: start; border-bottom: 1px solid var(--border-soft); white-space: nowrap;
}
.page-admin-traffic-costs .tc-table th {
  background: var(--surface-2); font-weight: 700; font-size: 11px;
  text-transform: uppercase; color: var(--muted); letter-spacing: .4px;
}
.page-admin-traffic-costs .tc-table .num { text-align: end; font-family: monospace; }
.page-admin-traffic-costs .tc-table tbody tr:hover { background: var(--surface-2); }
.page-admin-traffic-costs .tc-table tfoot { font-weight: 700; }
.page-admin-traffic-costs .tc-table tfoot td { border-top: 2px solid var(--border); background: var(--surface-2); }

/* Country summary row — bold */
.page-admin-traffic-costs .tc-summary-row td { font-weight: 700; font-size: 13px; }

/* Cost/Rest/Month highlight column — brand tint via colour-mix, no new token */
.page-admin-traffic-costs .tc-table .col-cost-rest {
  background: color-mix(in srgb, var(--brand) 8%, transparent);
}
.page-admin-traffic-costs .tc-table th.col-cost-rest-head {
  background: color-mix(in srgb, var(--brand) 16%, transparent);
}
/* Cost/Rest in country footer — accent */
.page-admin-traffic-costs .tc-summary-row .tc-sum-cost-rest {
  font-size: 20px; background: color-mix(in srgb, var(--danger) 10%, transparent); color: var(--danger);
}

/* Aggregator rows */
.page-admin-traffic-costs .tc-agg-row td { font-size: 12px; padding: 7px 14px; }
.page-admin-traffic-costs .tc-agg-row td:first-child { padding-inline-start: 18px; }

.page-admin-traffic-costs .tc-agg-badge {
  display: inline-block; padding: 2px 8px; border-radius: 4px;
  font-size: 11px; font-weight: 600;
}
.page-admin-traffic-costs .tc-agg-check {
  width: 15px; height: 15px; vertical-align: middle; margin-inline-end: 6px; cursor: pointer;
  accent-color: var(--brand);
}

/* Global summary card */
.page-admin-traffic-costs .tc-global-card {
  background: var(--surface); border-radius: 14px; box-shadow: var(--shadow-card);
  overflow: hidden; margin-bottom: 24px;
}
.page-admin-traffic-costs .tc-global-card .tc-table tfoot td { background: color-mix(in srgb, var(--brand) 12%, var(--surface)); }

/* ── Admin Dashboard ────────────────────────────────────────────────────
   .page-dashboard stays shared with the client dashboard (untouched here);
   this scope only carries the admin-only Careem converter tool and the
   inline stat highlights that used to be raw style="" on <strong>. */
.page-admin-dashboard .info-stat--danger { color: var(--danger); }
.page-admin-dashboard .info-stat--success { color: var(--success); }
.page-admin-dashboard .careem-tool-card { cursor: default; }
.page-admin-dashboard .careem-tool-desc { margin-bottom: 8px; }
.page-admin-dashboard .careem-tool-row { display: flex; gap: 6px; margin-bottom: 6px; align-items: center; }
.page-admin-dashboard .careem-tool-input {
  flex: 1; padding: 6px 8px; border: 1px solid var(--border); border-radius: 6px;
  font-size: 13px; background: var(--bg); color: var(--text);
}
.page-admin-dashboard .careem-result { font-size: 12px; word-break: break-all; }
.page-admin-dashboard .careem-result-row { display: flex; align-items: center; gap: 6px; }
.page-admin-dashboard .careem-deep-link { flex: 1; padding: 4px 6px; background: var(--bg); border-radius: 4px; display: block; }
.page-admin-dashboard .careem-copy-btn { border: none; background: none; cursor: pointer; padding: 2px; color: var(--brand); }
.page-admin-dashboard .careem-copy-btn svg[hidden] { display: none; }
.page-admin-dashboard .careem-check-icon { stroke: var(--success); }
.page-admin-dashboard .careem-error { font-size: 12px; color: var(--danger); }

/* ── Report header + card header (spec 2026-09-23-mobile-reports-compact,
   2026-09-cabinets-ui-unification) ────────────────────────────────────────
   One look for every report page; the description collapses behind "i".
   .page-header--card is the same card shell for every other client page
   header (report pages keep .report-header instead — they carry the "i"
   toggle and collapsible description that plain client pages don't need).
   Kept at the END of app.css (after the compact filter bar) so it wins over
   page-scoped .page-header rules of equal specificity by source order. */
.page-header.page-header--card,
.page-header.report-header {
  background: var(--surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  padding: 16px 20px;
  margin-bottom: 16px;
}
.page-header.report-header .report-header-row { display: flex; align-items: center; gap: 10px; }
.page-header.report-header h1,
.page-header.report-header h2 { margin: 0; font-size: 22px; line-height: 1.25; color: var(--text); }
.report-info-toggle {
  flex: 0 0 auto;
  margin-inline-start: auto; /* spec: the "i" toggle sits on the right of the header row */
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 1px solid var(--border-strong);
  background: var(--surface-2);
  color: var(--muted);
  font: italic 700 14px/1 Georgia, 'Times New Roman', serif;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.report-info-toggle:hover { border-color: var(--brand); color: var(--text); }
.report-info-toggle[aria-expanded="true"] { background: var(--cta); color: var(--cta-text); border-color: var(--cta-hover); }
.page-header.report-header .report-info { margin-top: 10px; }
.page-header.report-header .report-info p { margin: 0 0 6px; color: var(--muted); font-size: 14px; line-height: 1.5; }
.page-header.report-header .report-info p:last-child { margin-bottom: 0; }
@media (max-width: 768px) {
  .page-header.report-header { padding: 12px 14px; margin-bottom: 12px; }
  .page-header.report-header h1,
  .page-header.report-header h2 { font-size: 18px; }
}

.page-header.page-header--card h1,
.page-header.page-header--card h2 { margin: 0; font-size: 22px; line-height: 1.25; color: var(--text); }
.page-header.page-header--card p { margin: 6px 0 0; color: var(--muted); font-size: 14px; line-height: 1.5; }
@media (max-width: 768px) {
  .page-header.page-header--card { padding: 12px 14px; margin-bottom: 12px; }
  .page-header.page-header--card h1,
  .page-header.page-header--card h2 { font-size: 18px; }
}

/* Targeted override: menu/compare carries both .page-menu (row flexbox header) and
   .report-header (stacked header); outrank .page-menu's flex row so the report-header
   layout wins here. */
.page-menu .page-header.report-header { display: block; }

/* Phones: one side gutter, not three. .app-main already keeps content 12px off the
   screen edge; the page containers (the shared one and every page-scoped copy, 8 to
   24px) stacked a second gutter on top of it, and cards a third: 52px a side on
   /admin/restaurants at 375px. The element in main.app-main outranks every
   page-scoped container rule, including the ones in a view's own <style> that load
   after this file; only the side padding goes, their vertical rhythm stays. */
@media (max-width: 768px) {
  main.app-main .container,
  main.app-main .ps-wrap,
  main.app-main .page-promo-alerts,
  main.app-main .cb-page { padding-inline: 0; }
  /* The monitor's filter panel is its card: same 12px inside as .card. */
  .page-monitor .monitor-toolbar { padding-inline: 12px; }
}

/* iOS Safari only (the feature query matches nothing else): its native date field keeps
   an intrinsic minimum width that ignores width:100%, so "Date To" stuck out of its
   half-width filter column, and it centres the value. Dropping the native appearance
   lets the field shrink to its column; the value is aligned like every other field.
   The display format stays the phone's own ("28 Aug 2026") — that is the system picker. */
@supports (-webkit-touch-callout: none) {
  input[type="date"],
  input[type="datetime-local"],
  input[type="month"],
  input[type="time"] { -webkit-appearance: none; appearance: none; min-width: 0; max-width: 100%; }
  input::-webkit-date-and-time-value { text-align: start; margin: 0; }
}

/* Outage start times from the metrics endpoint are missing or behind (partials/_downtime_source_notice.php). */
.downtime-source-notice { background: var(--warn-bg); border: 1px solid var(--warn); border-radius: 10px; padding: 10px 16px; margin: 0 0 16px; font-size: 14px; color: var(--warn-ink); }

/* ── .table-stack: a table that turns into cards on phones ─────────────────────────
   Shared class (first used by Alert History, spec 2026-11-11-notifications §6.7): under
   768px the header row hides, every row becomes a card and every cell a "label — value"
   line, the label coming from the cell's data-label. Same markup at every width, so no
   second template and no horizontal scroll on a phone. */
@media (max-width: 767px) {
  .table-stack thead { display: none; }
  .table-stack,
  .table-stack tbody { display: block; width: 100%; }
  .table-stack tr {
    display: block;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface);
    padding: 8px 12px;
    margin-bottom: 10px;
  }
  .table-stack td {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    padding: 4px 0;
    border-bottom: 0;
    text-align: end;
    overflow-wrap: anywhere;
  }
  .table-stack td::before {
    content: attr(data-label);
    color: var(--muted);
    font-size: 12px;
    text-align: start;
    flex-shrink: 0;
  }
  .table-stack td:empty { display: none; }
}

/* ── .filters-panel: report filters in a <details> ────────────────────────────────
   Folded on phones with a 36px+ summary; opened from 768px by the page's script (a
   closed <details> cannot be opened by CSS). The Apply button sticks to the bottom of
   the screen while the open panel is scrolled on a phone. */
.filters-panel {
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  margin-bottom: 16px;
}
.filters-panel > summary {
  min-height: 44px;
  display: flex;
  align-items: center;
  padding: 0 16px;
  font-weight: 600;
  color: var(--text);
  cursor: pointer;
}
.filters-panel > form { padding: 4px 16px 16px; }
.filters-panel .filter-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 16px;
  margin-bottom: 16px;
}
.filters-panel .filter-group label { display: block; margin-bottom: 6px; font-size: 13px; color: var(--muted); }
.filters-panel input[type="date"] { width: 100%; min-height: 40px; }
.filters-panel .filters-panel-apply .btn { min-height: 40px; }
@media (max-width: 767px) {
  .filters-panel .filter-grid { grid-template-columns: 1fr; }
  .filters-panel .filters-panel-apply {
    position: sticky;
    bottom: 0;
    background: var(--surface);
    padding: 8px 0 calc(8px + env(safe-area-inset-bottom, 0px));
  }
  .filters-panel .filters-panel-apply .btn { width: 100%; }
}

/* ── Alert History (notifications/index.php) ───────────────────────────────────── */
.page-notifications .notif-notice { margin-bottom: 12px; }
.page-notifications .notif-tabs {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  padding-bottom: 4px;
  margin-bottom: 16px;
}
.page-notifications .notif-tab {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 36px;
  padding: 0 14px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text);
  text-decoration: none;
  white-space: nowrap;
}
.page-notifications .notif-tab.is-active { background: var(--brand); border-color: var(--brand); color: var(--cta-text); }
.page-notifications .notif-tab-count { font-size: 12px; color: inherit; opacity: 0.75; }
.page-notifications .notif-table-wrap { background: var(--surface); border-radius: var(--radius); box-shadow: var(--shadow-card); overflow-x: auto; }
.page-notifications .notif-table td { vertical-align: top; }
.page-notifications .notif-cell-time { white-space: nowrap; }
.page-notifications .notif-agg {
  display: inline-block;
  padding: 2px 8px;
  border-radius: var(--radius-sm);
  font-size: 12px;
  font-weight: 600;
}
.page-notifications .notif-agg--default { background: var(--border-soft); color: var(--text); }
.page-notifications .notif-event--not_opened,
.page-notifications .notif-event--intraday_off,
.page-notifications .notif-event--closing { color: var(--danger); }
.page-notifications .notif-event--late_opening { color: var(--warn-ink); }
.page-notifications .notif-event--intraday_recovery,
.page-notifications .notif-event--daily_opening { color: var(--success-ink); }
.page-notifications .notif-cell-push { color: var(--muted); font-size: 13px; }
.page-notifications .notif-push--failed,
.page-notifications .notif-push--partial { color: var(--danger); }
.page-notifications .notif-more { display: flex; justify-content: center; margin: 16px 0; }
.page-notifications .notif-more .btn { min-height: 40px; display: inline-flex; align-items: center; }
/* The card of one alert (notifications/alert.php) — where a push tap lands. One glance,
   no field labels: name and city, the lead line (the one loud thing), a quiet line of
   context, the buttons. */
.page-notifications .notif-card-page { max-width: 560px; padding-top: 16px; padding-bottom: 24px; }
.page-notifications .notif-card { background: var(--surface); border-radius: var(--radius); box-shadow: var(--shadow-card); padding: 16px 18px 18px; }
.page-notifications .notif-card-name { margin: 0; font-size: 17px; font-weight: 600; line-height: 1.3; }
.page-notifications .notif-card-name a { color: var(--text); text-decoration: underline; text-decoration-color: var(--border-strong); text-decoration-thickness: 1px; text-underline-offset: 3px; }
.page-notifications .notif-card-name a:hover,
.page-notifications .notif-card-name a:focus-visible { text-decoration-color: currentColor; }
.page-notifications .notif-card-city { margin: 2px 0 0; font-size: 13px; color: var(--muted); }
.page-notifications .notif-card-lead { margin: 14px 0 0; font-size: 22px; font-weight: 700; line-height: 1.2; letter-spacing: -0.01em; color: var(--text); }
.page-notifications .notif-card-lead--offline,
.page-notifications .notif-card-lead--closing { color: var(--danger); }
.page-notifications .notif-card-lead--opening { color: var(--warn-ink); }
.page-notifications .notif-card-lead--recovery,
.page-notifications .notif-card-lead--ok { color: var(--success-ink); }
.page-notifications .notif-card-reminder { margin: 4px 0 0; font-size: 13px; color: var(--muted); }
.page-notifications .notif-card-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; margin: 10px 0 0; font-size: 13px; color: var(--muted); }
.page-notifications .notif-card-meta .notif-event { font-weight: 600; }
.page-notifications .notif-card-links { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
.page-notifications .notif-card-links .btn { min-height: 38px; display: inline-flex; align-items: center; justify-content: center; padding: 8px 14px; font-size: 13px; }
.page-notifications .notif-card-links .btn-primary { min-height: 44px; font-size: 14px; }
.page-notifications .notif-card-back { display: inline-flex; align-items: center; gap: 6px; min-height: 36px; margin-top: 12px; padding: 6px 14px; font-size: 13px; }
.page-notifications .notif-card-note { margin: 10px 0 0; font-size: 12px; line-height: 1.4; color: var(--muted); }
.page-notifications .notif-card-note--error { color: var(--danger); }
@media (max-width: 767px) {
  /* Phone: the answering report across the card, the rest two to a row. */
  .page-notifications .notif-card-links .btn { flex: 1 1 calc(50% - 4px); }
  .page-notifications .notif-card-links .btn-primary { flex-basis: 100%; }
  .page-notifications .notif-table-wrap { background: none; box-shadow: none; overflow: visible; }
  /* One alert = two plain lines, no field labels and no brand (it repeats the name),
     owner 2026-11-12: name and time, then event, aggregator and details; staff see push below. */
  .page-notifications .table-stack tr {
    display: grid;
    grid-template-columns: auto auto minmax(0, 1fr) auto;
    align-items: baseline;
    gap: 4px 8px;
    padding: 10px 12px;
    margin-bottom: 8px;
  }
  .page-notifications .table-stack td { padding: 0; text-align: start; }
  .page-notifications .table-stack td::before { content: none; }
  .page-notifications .notif-cell-brand { display: none; }
  .page-notifications .notif-cell-restaurant { grid-row: 1; grid-column: 1 / 4; font-weight: 600; }
  .page-notifications .notif-cell-time { grid-row: 1; grid-column: 4; justify-self: end; font-size: 12px; color: var(--muted); }
  .page-notifications .notif-cell-event { grid-row: 2; grid-column: 1; font-weight: 600; }
  .page-notifications .notif-cell-agg { grid-row: 2; grid-column: 2; }
  .page-notifications .notif-cell-details { grid-row: 2; grid-column: 3 / 5; font-size: 13px; color: var(--muted); }
  .page-notifications .notif-cell-push { grid-row: 3; grid-column: 1 / -1; font-size: 12px; }
}
