/*
  MASAR 360 — Design System v2 — Component library
  Component-scoped classes only, predictable specificity (single class,
  no deep nesting, no !important except the documented escapes below).
  Everything reads from frontend/ds/tokens.css.
*/

/* The native [hidden] attribute must always win over a component's own
   display rule (e.g. .ds-btn{display:inline-flex}, .ds-empty-state{
   display:flex}) — otherwise any element that is both a styled
   component AND toggled via the standard `el.hidden = true/false` API
   silently stays visible, since an author class rule beats the UA
   stylesheet's unqualified `[hidden]{display:none}` by cascade origin.
   Found this exact bug twice (a collapsible alert-detail row, an
   empty-state toggle) before deciding to fix the whole class at once
   rather than patch each component individually. */
[hidden]{ display:none !important; }

/* ---------------------------------------------------------------- */
/* Icon base                                                         */
/* ---------------------------------------------------------------- */
.ds-icon{ display:inline-flex; align-items:center; justify-content:center; flex:none; color:currentColor; }
.ds-icon-svg{ display:block; }
[dir="rtl"] .ds-icon-svg[data-rtl-mirror="1"]{ transform:scaleX(-1); }

/* ---------------------------------------------------------------- */
/* Buttons — one system: primary / secondary / tertiary / ghost /   */
/* danger / success / icon-only. Every state defined once.          */
/* ---------------------------------------------------------------- */
.ds-btn{
  display:inline-flex; align-items:center; justify-content:center; gap:var(--space-2);
  height:40px; padding:0 var(--space-4); border-radius:var(--radius-md);
  font:var(--fw-card-heading) var(--fs-body)/1 var(--font-ui); white-space:nowrap;
  border:1.5px solid transparent; cursor:pointer; user-select:none;
  transition:background-color var(--duration-fast) var(--ease-standard),
             border-color var(--duration-fast) var(--ease-standard),
             box-shadow var(--duration-fast) var(--ease-standard),
             transform var(--duration-fast) var(--ease-standard),
             opacity var(--duration-fast) var(--ease-standard);
}
.ds-btn:active{ transform:translateY(1px); }
.ds-btn:focus-visible{ outline:none; box-shadow:var(--focus-ring); }
.ds-btn:disabled,.ds-btn[aria-disabled="true"]{ opacity:.5; cursor:not-allowed; pointer-events:none; }
.ds-btn-sm{ height:32px; padding:0 var(--space-3); font-size:var(--fs-caption); gap:var(--space-1); border-radius:var(--radius-sm); }
.ds-btn-lg{ height:48px; padding:0 var(--space-6); font-size:15px; border-radius:var(--radius-lg); }
.ds-btn-block{ width:100%; }

.ds-btn-primary{ background:var(--brand-primary); border-color:var(--brand-primary); color:#fff; box-shadow:var(--shadow-sm); }
.ds-btn-primary:hover{ background:var(--brand-primary-strong); border-color:var(--brand-primary-strong); }

.ds-btn-secondary{ background:var(--surface-1); border-color:var(--border-strong); color:var(--text-primary); }
.ds-btn-secondary:hover{ background:var(--surface-sunken); border-color:var(--brand-primary); }

.ds-btn-tertiary{ background:var(--brand-primary-soft); border-color:transparent; color:var(--brand-primary-strong); }
.ds-btn-tertiary:hover{ background:var(--brand-accent-soft); }

.ds-btn-ghost{ background:transparent; border-color:transparent; color:var(--text-secondary); }
.ds-btn-ghost:hover{ background:var(--surface-sunken); color:var(--text-primary); }

.ds-btn-danger{ background:var(--status-critical); border-color:var(--status-critical); color:#fff; }
.ds-btn-danger:hover{ filter:brightness(1.08); }
.ds-btn-danger-ghost{ background:var(--status-critical-soft); border-color:transparent; color:var(--status-critical); }
.ds-btn-danger-ghost:hover{ background:var(--status-critical); color:#fff; }

.ds-btn-success{ background:var(--status-good); border-color:var(--status-good); color:#fff; }

.ds-btn-icon{ width:40px; height:40px; padding:0; border-radius:var(--radius-md); flex:none; }
.ds-btn-icon.ds-btn-sm{ width:32px; height:32px; border-radius:var(--radius-sm); }
.ds-btn-icon.ds-btn-ghost{ color:var(--text-secondary); }

.ds-btn.is-loading{ color:transparent; pointer-events:none; position:relative; }
.ds-btn.is-loading::after{
  content:''; position:absolute; width:16px; height:16px; border-radius:50%;
  border:2px solid rgba(255,255,255,.4); border-top-color:#fff; animation:ds-spin .7s linear infinite;
}
.ds-btn-secondary.is-loading::after,.ds-btn-ghost.is-loading::after,.ds-btn-tertiary.is-loading::after{
  border-color:var(--border-strong); border-top-color:var(--brand-primary);
}
@keyframes ds-spin{ to{ transform:rotate(360deg); } }

/* ---------------------------------------------------------------- */
/* R1 systemic bridge: legacy button class names used across the      */
/* pre-DS overlay files (v7-v17-features.js, uiux-commercial.js, etc) */
/* get the real DS button treatment directly, without requiring every */
/* template to be dual-classed by hand. This is the single highest-   */
/* leverage fix for the "white-on-white / invisible button" bug class */
/* — one file, every legacy button, everywhere, at once.              */
/* ---------------------------------------------------------------- */
.primary-button,.secondary-button,.mini-button,.ghost-button,.danger-button,
.success-button,.warning-button,.icon-button,.pill-button{
  display:inline-flex; align-items:center; justify-content:center; gap:var(--space-2);
  height:40px; padding:0 var(--space-4); border-radius:var(--radius-md);
  font:var(--fw-card-heading) var(--fs-body)/1 var(--font-ui); white-space:nowrap;
  border:1.5px solid transparent; cursor:pointer; user-select:none;
  transition:background-color var(--duration-fast) var(--ease-standard),
             border-color var(--duration-fast) var(--ease-standard),
             box-shadow var(--duration-fast) var(--ease-standard),
             transform var(--duration-fast) var(--ease-standard),
             opacity var(--duration-fast) var(--ease-standard);
}
.primary-button:active,.secondary-button:active,.mini-button:active,.ghost-button:active,
.danger-button:active,.success-button:active,.warning-button:active,.icon-button:active,.pill-button:active{ transform:translateY(1px); }
.primary-button:focus-visible,.secondary-button:focus-visible,.mini-button:focus-visible,.ghost-button:focus-visible,
.danger-button:focus-visible,.success-button:focus-visible,.warning-button:focus-visible,.icon-button:focus-visible,.pill-button:focus-visible{ outline:none; box-shadow:var(--focus-ring); }
.primary-button:disabled,.secondary-button:disabled,.mini-button:disabled,.ghost-button:disabled,
.danger-button:disabled,.success-button:disabled,.warning-button:disabled,.icon-button:disabled,.pill-button:disabled{ opacity:.5; cursor:not-allowed; pointer-events:none; }

.primary-button{ background:var(--brand-primary); border-color:var(--brand-primary); color:#fff; box-shadow:var(--shadow-sm); }
.primary-button:hover{ background:var(--brand-primary-strong); border-color:var(--brand-primary-strong); }

.secondary-button,.ghost-button{ background:var(--surface-1); border-color:var(--border-strong); color:var(--text-primary); }
.secondary-button:hover,.ghost-button:hover{ background:var(--surface-sunken); border-color:var(--brand-primary); }

.mini-button,.pill-button{ height:32px; padding:0 var(--space-3); font-size:var(--fs-caption); gap:var(--space-1); border-radius:var(--radius-pill,999px); background:var(--surface-1); border-color:var(--border-strong); color:var(--text-primary); }
.mini-button:hover,.pill-button:hover{ background:var(--surface-sunken); border-color:var(--brand-primary); }
.mini-button.danger{ background:var(--status-critical-soft); border-color:transparent; color:var(--status-critical); }
.mini-button.danger:hover{ background:var(--status-critical); color:#fff; }
.mini-button.success{ background:var(--status-good-soft); border-color:transparent; color:var(--status-good); }

.danger-button{ background:var(--status-critical); border-color:var(--status-critical); color:#fff; }
.danger-button:hover{ filter:brightness(1.08); }

.success-button{ background:var(--status-good); border-color:var(--status-good); color:#fff; }
.success-button:hover{ filter:brightness(1.08); }

.warning-button{ background:var(--status-warning); border-color:var(--status-warning); color:var(--text-on-amber,#3a2405); }
.warning-button:hover{ filter:brightness(1.05); }

.icon-button{ width:40px; height:40px; padding:0; border-radius:var(--radius-md); flex:none; background:transparent; border-color:transparent; color:var(--text-secondary); }
.icon-button:hover{ background:var(--surface-sunken); color:var(--text-primary); }

/* Legacy generic .card/.kpi-card/.panel/.form-control/.status/.badge     */
/* class names get the same real-DS treatment for the same reason.       */
.card,.kpi-card,.panel{ background:var(--surface-raised); border:1px solid var(--border-hairline); border-radius:var(--radius-lg); box-shadow:var(--shadow-sm); }
input.form-control,select.form-control,textarea.form-control{
  width:100%; height:42px; padding:0 var(--space-3); border-radius:var(--radius-md);
  border:1.5px solid var(--border-strong); background:var(--surface-1); color:var(--text-primary);
  font:var(--fw-body) var(--fs-body)/1 var(--font-ui);
}
textarea.form-control{ height:auto; min-height:96px; padding-block:var(--space-2); }
input.form-control:focus,select.form-control:focus,textarea.form-control:focus{ outline:none; border-color:var(--brand-primary); box-shadow:var(--focus-ring); }
input.form-control::placeholder,textarea.form-control::placeholder{ color:var(--text-muted); }
input.form-control:disabled,select.form-control:disabled,textarea.form-control:disabled{ background:var(--surface-sunken); color:var(--text-muted); }

/* ---------------------------------------------------------------- */
/* Inputs / selects / textarea / search / checkbox / radio / switch */
/* ---------------------------------------------------------------- */
.ds-field{ display:flex; flex-direction:column; gap:6px; }
.ds-field-label{ font:var(--fw-label) var(--fs-label)/var(--lh-label) var(--font-ui); color:var(--text-secondary); display:flex; gap:4px; }
.ds-field-label .ds-required{ color:var(--status-critical); }
.ds-field-helper{ font:var(--fw-helper) var(--fs-helper)/var(--lh-helper) var(--font-ui); color:var(--text-muted); }
.ds-field-error-text{ font:var(--fw-helper) var(--fs-helper)/var(--lh-helper) var(--font-ui); color:var(--status-critical); display:flex; align-items:center; gap:4px; }

.ds-input,.ds-select,.ds-textarea{
  width:100%; height:42px; padding:0 var(--space-3); border-radius:var(--radius-md);
  border:1.5px solid var(--border-strong); background:var(--surface-1); color:var(--text-primary);
  font:var(--fw-body) var(--fs-body)/1 var(--font-ui);
  transition:border-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard);
}
.ds-textarea{ height:auto; min-height:96px; padding-block:var(--space-2); resize:vertical; }
.ds-input::placeholder,.ds-textarea::placeholder{ color:var(--text-muted); }
.ds-input:hover,.ds-select:hover,.ds-textarea:hover{ border-color:var(--neutral-400); }
.ds-input:focus,.ds-select:focus,.ds-textarea:focus{ outline:none; border-color:var(--brand-primary); box-shadow:var(--focus-ring); }
.ds-input:disabled,.ds-select:disabled,.ds-textarea:disabled{ background:var(--surface-sunken); color:var(--text-muted); cursor:not-allowed; }
.ds-field.is-error .ds-input,.ds-field.is-error .ds-select,.ds-field.is-error .ds-textarea{ border-color:var(--status-critical); }
.ds-field.is-error .ds-input:focus{ box-shadow:0 0 0 3px rgba(208,59,59,.22); }

.ds-input-group{ position:relative; display:flex; align-items:center; }
.ds-input-group .ds-input{ padding-inline-start:46px; }
.ds-input-group > .ds-icon{ position:absolute; inset-inline-start:11px; color:var(--text-muted); pointer-events:none; }
.ds-input-group .ds-input-suffix-btn{ position:absolute; inset-inline-end:6px; }
.ds-input-group:has(.ds-input-suffix-btn) .ds-input{ padding-inline-end:46px; }

.ds-select{ appearance:none; background-image:none; padding-inline-end:36px; }
.ds-select-wrap{ position:relative; }
.ds-select-wrap .ds-icon{ position:absolute; inset-inline-end:11px; top:50%; transform:translateY(-50%); color:var(--text-muted); pointer-events:none; }

.ds-checkbox,.ds-radio{ display:inline-flex; align-items:center; gap:var(--space-2); cursor:pointer; font:var(--fw-body) var(--fs-body)/1 var(--font-ui); color:var(--text-primary); }
.ds-checkbox input,.ds-radio input{ width:18px; height:18px; accent-color:var(--brand-primary); cursor:pointer; }

.ds-switch{ position:relative; display:inline-flex; align-items:center; width:42px; height:24px; }
.ds-switch input{ position:absolute; inset:0; opacity:0; cursor:pointer; margin:0; }
.ds-switch-track{ position:absolute; inset:0; background:var(--neutral-300); border-radius:var(--radius-pill); transition:background var(--duration-fast); }
.ds-switch-thumb{ position:absolute; inset-inline-start:3px; top:3px; width:18px; height:18px; border-radius:50%; background:#fff; box-shadow:var(--shadow-sm); transition:inset-inline-start var(--duration-fast) var(--ease-standard); }
.ds-switch input:checked ~ .ds-switch-track{ background:var(--brand-primary); }
.ds-switch input:checked ~ .ds-switch-thumb{ inset-inline-start:21px; }
.ds-switch input:focus-visible ~ .ds-switch-track{ box-shadow:var(--focus-ring); }

/* ---------------------------------------------------------------- */
/* Badges / status chips (icon + label, never color alone)          */
/* ---------------------------------------------------------------- */
.ds-badge{ display:inline-flex; align-items:center; gap:5px; height:24px; padding:0 var(--space-2); border-radius:var(--radius-pill); font:var(--fw-caption) var(--fs-caption)/1 var(--font-ui); white-space:nowrap; }
.ds-badge .ds-icon-svg{ width:13px; height:13px; }
.ds-badge-neutral{ background:var(--surface-sunken); color:var(--text-secondary); }
.ds-badge-good{ background:var(--status-good-soft); color:var(--status-good); }
.ds-badge-warning{ background:var(--status-warning-soft); color:var(--status-warning); }
.ds-badge-serious{ background:var(--status-serious-soft); color:var(--status-serious); }
.ds-badge-critical{ background:var(--status-critical-soft); color:var(--status-critical); }
.ds-badge-brand{ background:var(--brand-primary-soft); color:var(--brand-primary-strong); }

/* ---------------------------------------------------------------- */
/* Cards / KPI cards / chart cards                                  */
/* ---------------------------------------------------------------- */
.ds-card{ background:var(--surface-raised); border:1px solid var(--border-hairline); border-radius:var(--radius-lg); box-shadow:var(--shadow-sm); }
.ds-card-pad{ padding:var(--space-5); }
.ds-card-header{ display:flex; align-items:center; justify-content:space-between; gap:var(--space-3); padding:var(--space-4) var(--space-5); border-bottom:1px solid var(--border-hairline); }
.ds-card-title{ font:var(--fw-card-heading) var(--fs-card-heading)/var(--lh-card-heading) var(--font-ui); color:var(--text-primary); margin:0; }
.ds-card-subtitle{ font:var(--fw-helper) var(--fs-helper)/var(--lh-helper) var(--font-ui); color:var(--text-muted); margin-top:2px; }
.ds-card-body{ padding:var(--space-5); }

.ds-kpi-card{ display:flex; flex-direction:column; gap:10px; background:var(--surface-raised); border:1px solid var(--border-hairline); border-radius:var(--radius-lg); padding:var(--space-4); box-shadow:var(--shadow-sm); position:relative; overflow:hidden; }
.ds-kpi-top{ display:flex; align-items:flex-start; justify-content:space-between; gap:var(--space-2); }
.ds-kpi-label{ font:var(--fw-label) var(--fs-label)/var(--lh-label) var(--font-ui); color:var(--text-secondary); }
.ds-kpi-icon{ width:36px; height:36px; border-radius:var(--radius-md); display:flex; align-items:center; justify-content:center; flex:none; background:var(--brand-primary-soft); color:var(--brand-primary-strong); }
.ds-kpi-value{ font:var(--fw-kpi) var(--fs-kpi)/var(--lh-kpi) var(--font-ui); color:var(--text-primary); font-variant-numeric:tabular-nums; }
.ds-kpi-delta{ display:inline-flex; align-items:center; gap:4px; font:var(--fw-caption) var(--fs-caption)/1 var(--font-ui); width:fit-content; padding:3px var(--space-2); border-radius:var(--radius-pill); }
.ds-kpi-delta.is-up{ color:var(--status-good); background:var(--status-good-soft); }
.ds-kpi-delta.is-down{ color:var(--status-critical); background:var(--status-critical-soft); }
.ds-kpi-delta .ds-icon-svg{ width:12px; height:12px; }
.ds-kpi-card.tone-critical .ds-kpi-icon{ background:var(--status-critical-soft); color:var(--status-critical); }
.ds-kpi-card.tone-warning .ds-kpi-icon{ background:var(--status-warning-soft); color:var(--status-warning); }
.ds-kpi-card.tone-good .ds-kpi-icon{ background:var(--status-good-soft); color:var(--status-good); }

.ds-chart-card{ background:var(--surface-raised); border:1px solid var(--border-hairline); border-radius:var(--radius-lg); box-shadow:var(--shadow-sm); overflow:hidden; }
.ds-chart-card-head{ display:flex; align-items:flex-start; justify-content:space-between; gap:var(--space-3); padding:var(--space-4) var(--space-4) var(--space-2); }
.ds-chart-card-body{ padding:0 var(--space-4) var(--space-4); }

/* §7: domain composition signature — a thin top accent + small dot before the
   card title, so cards from different domains sharing one dashboard row read
   as distinct at a glance. Composition-only: no card is recolored. */
.ds-chart-card[data-domain]{ border-top:3px solid var(--domain-accent, var(--border-hairline)); }
.ds-chart-card[data-domain="hr"]{ --domain-accent:var(--domain-hr); }
.ds-chart-card[data-domain="fleet"]{ --domain-accent:var(--domain-fleet); }
.ds-chart-card[data-domain="alerts"]{ --domain-accent:var(--domain-alerts); }
.ds-chart-card[data-domain="finance"]{ --domain-accent:var(--domain-finance); }
.ds-chart-card[data-domain="documents"]{ --domain-accent:var(--domain-documents); }
.ds-chart-card[data-domain] .ds-card-title{ display:flex; align-items:center; gap:6px; }
.ds-chart-card[data-domain] .ds-card-title::before{ content:""; width:7px; height:7px; border-radius:50%; background:var(--domain-accent); flex:none; }

/* progress bar */
.ds-progress{ height:8px; border-radius:var(--radius-pill); background:var(--surface-sunken); overflow:hidden; }
.ds-progress-bar{ height:100%; border-radius:var(--radius-pill); background:var(--brand-primary); transition:width var(--duration-slow) var(--ease-standard); }
.ds-progress-bar.tone-good{ background:var(--status-good); }
.ds-progress-bar.tone-warning{ background:var(--status-warning); }
.ds-progress-bar.tone-critical{ background:var(--status-critical); }

/* ---------------------------------------------------------------- */
/* Tables — desktop hierarchy + contained scroll + mobile cards     */
/* ---------------------------------------------------------------- */
.ds-table-wrap{ background:var(--surface-raised); border:1px solid var(--border-hairline); border-radius:var(--radius-lg); overflow:hidden; }
.ds-table-scroll{ overflow-x:auto; max-width:100%; }
.ds-table{ width:100%; border-collapse:separate; border-spacing:0; font:var(--fw-body) var(--fs-body)/1.4 var(--font-ui); }
.ds-table thead th{
  position:sticky; top:0; z-index:1; background:var(--surface-2); color:var(--text-secondary);
  font:var(--fw-label) var(--fs-label)/1 var(--font-ui);
  text-align:start; padding:var(--space-3) var(--space-4); border-bottom:1px solid var(--border-hairline); white-space:nowrap;
}
.ds-table tbody td{ padding:var(--space-3) var(--space-4); border-bottom:1px solid var(--border-hairline); color:var(--text-primary); vertical-align:middle; }
.ds-table tbody tr:last-child td{ border-bottom:none; }
.ds-table tbody tr:hover td{ background:var(--surface-2); }
.ds-table-actions{ display:flex; align-items:center; gap:var(--space-1); justify-content:flex-end; }

.ds-cards-list{ display:none; flex-direction:column; gap:var(--space-3); padding:var(--space-4); }
.ds-record-card{ background:var(--surface-raised); border:1px solid var(--border-hairline); border-radius:var(--radius-md); padding:var(--space-4); display:flex; flex-direction:column; gap:var(--space-2); }
.ds-record-card-top{ display:flex; align-items:center; justify-content:space-between; gap:var(--space-2); }
.ds-record-card-title{ font:var(--fw-card-heading) var(--fs-body)/1.3 var(--font-ui); color:var(--text-primary); }
.ds-record-card-row{ display:flex; align-items:center; justify-content:space-between; gap:var(--space-2); font:var(--fw-body) var(--fs-caption)/1 var(--font-ui); color:var(--text-secondary); }
.ds-record-card-actions{ display:flex; gap:var(--space-2); margin-top:var(--space-2); }

@media (max-width:767px){
  .ds-table-wrap.ds-has-mobile-cards .ds-table-scroll{ display:none; }
  .ds-table-wrap.ds-has-mobile-cards .ds-cards-list{ display:flex; }
}

/* avatar */
.ds-avatar{ width:32px; height:32px; border-radius:50%; display:inline-flex; align-items:center; justify-content:center; background:var(--brand-primary-soft); color:var(--brand-primary-strong); font:var(--fw-card-heading) 13px/1 var(--font-ui); flex:none; overflow:hidden; }
.ds-avatar img{ width:100%; height:100%; object-fit:cover; }

/* ---------------------------------------------------------------- */
/* Tabs / dropdown / breadcrumbs / page header                      */
/* ---------------------------------------------------------------- */
.ds-tabs{ display:flex; gap:var(--space-1); border-bottom:1px solid var(--border-hairline); overflow-x:auto; }
.ds-tab{ padding:var(--space-3) var(--space-4); font:var(--fw-card-heading) var(--fs-body)/1 var(--font-ui); color:var(--text-secondary); border-bottom:2px solid transparent; white-space:nowrap; cursor:pointer; background:none; border-inline:none; border-top:none; }
.ds-tab:hover{ color:var(--text-primary); }
.ds-tab.is-active{ color:var(--brand-primary-strong); border-bottom-color:var(--brand-primary); }
.ds-tab:focus-visible{ outline:none; box-shadow:var(--focus-ring); border-radius:var(--radius-sm); }

.ds-breadcrumbs{ display:flex; align-items:center; gap:var(--space-2); font:var(--fw-body) var(--fs-caption)/1 var(--font-ui); color:var(--text-muted); }
.ds-breadcrumbs a{ color:var(--text-muted); text-decoration:none; }
.ds-breadcrumbs a:hover{ color:var(--brand-primary); }
.ds-breadcrumbs .ds-icon-svg{ width:14px; height:14px; }

.ds-page-head{ display:flex; align-items:flex-start; justify-content:space-between; gap:var(--space-4); flex-wrap:wrap; margin-bottom:var(--space-5); }
.ds-page-title{ font:var(--fw-page-title) var(--fs-page-title)/var(--lh-page-title) var(--font-ui); color:var(--text-primary); margin:0 0 2px; }
.ds-page-subtitle{ font:var(--fw-body) var(--fs-body)/var(--lh-body) var(--font-ui); color:var(--text-muted); margin:0; }
.ds-page-actions{ display:flex; gap:var(--space-2); flex-wrap:wrap; }

.ds-dropdown{ position:relative; display:inline-block; }
.ds-dropdown-menu{
  position:absolute; inset-inline-end:0; top:calc(100% + 6px); min-width:200px; background:var(--surface-raised);
  border:1px solid var(--border-hairline); border-radius:var(--radius-md); box-shadow:var(--shadow-lg); padding:var(--space-2);
  z-index:var(--z-dropdown); opacity:0; visibility:hidden; transform:translateY(-4px);
  transition:opacity var(--duration-fast) var(--ease-standard), transform var(--duration-fast) var(--ease-standard), visibility var(--duration-fast);
}
.ds-dropdown.is-open .ds-dropdown-menu{ opacity:1; visibility:visible; transform:translateY(0); }
/* Found live via real hit-testing (2026-08-24): a transformed ancestor
   (e.g. a card with a hover/entry transform) creates a new containing
   block for position:fixed descendants, so the menu's JS-computed
   viewport-relative coordinates land somewhere else entirely once the
   browser actually paints it (often on top of the NEXT row's own
   trigger button). Fixed by reparenting the open menu to <body> in JS
   (components.js), which escapes any such ancestor -- but that breaks
   the `.ds-dropdown.is-open .ds-dropdown-menu` descendant selector above
   (the menu is no longer inside .ds-dropdown once moved), so open/close
   is ALSO toggled via this standalone class directly on the menu itself. */
.ds-dropdown-menu.is-open{ opacity:1; visibility:visible; transform:translateY(0); }
.ds-dropdown-item{ display:flex; align-items:center; gap:var(--space-2); padding:var(--space-2) var(--space-3); border-radius:var(--radius-sm); font:var(--fw-body) var(--fs-body)/1 var(--font-ui); color:var(--text-primary); cursor:pointer; background:none; border:none; width:100%; text-align:start; }
.ds-dropdown-item:hover{ background:var(--surface-sunken); }
.ds-dropdown-item.is-danger{ color:var(--status-critical); }

/* ---------------------------------------------------------------- */
/* Empty / loading / error states                                   */
/* ---------------------------------------------------------------- */
.ds-empty-state{ display:flex; flex-direction:column; align-items:center; text-align:center; gap:var(--space-3); padding:var(--space-9) var(--space-5); color:var(--text-muted); }
.ds-empty-state .ds-icon{ width:52px; height:52px; border-radius:50%; background:var(--surface-sunken); color:var(--text-muted); }
.ds-empty-state .ds-icon-svg{ width:26px; height:26px; }
.ds-empty-state-title{ font:var(--fw-card-heading) var(--fs-card-heading)/var(--lh-card-heading) var(--font-ui); color:var(--text-primary); }
.ds-empty-state-text{ font:var(--fw-body) var(--fs-body)/var(--lh-body) var(--font-ui); max-width:360px; }

.ds-skeleton{ position:relative; overflow:hidden; background:var(--surface-sunken); border-radius:var(--radius-sm); }
.ds-skeleton::after{
  content:''; position:absolute; inset:0; transform:translateX(-100%);
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.55),transparent);
  animation:ds-shimmer 1.4s infinite;
}
@keyframes ds-shimmer{ to{ transform:translateX(100%); } }
[dir="rtl"] .ds-skeleton::after{ transform:translateX(100%); animation-name:ds-shimmer-rtl; }
@keyframes ds-shimmer-rtl{ to{ transform:translateX(-100%); } }
@media (prefers-reduced-motion:reduce){ .ds-skeleton::after{ animation:none; display:none; } }

.ds-error-state{ display:flex; align-items:flex-start; gap:var(--space-3); padding:var(--space-4); border-radius:var(--radius-md); background:var(--status-critical-soft); color:var(--status-critical); }
.ds-error-state .ds-icon-svg{ width:20px; height:20px; flex:none; margin-top:2px; }

/* ---------------------------------------------------------------- */
/* R2: Welcome Banner + AI Assistant Card (dashboard row 1)          */
/* No photographic skyline asset exists locally yet (see checkpoint  */
/* asset gap) -- brand-gradient navy instead of an external fetch.   */
/* ---------------------------------------------------------------- */
.ds-welcome-ai-row{ display:grid; grid-template-columns:1.6fr 1fr; gap:var(--space-4); margin-bottom:var(--space-5); }
@media (max-width:1023px){ .ds-welcome-ai-row{ grid-template-columns:1fr; } }
.ds-welcome-banner{
  position:relative; overflow:hidden; border-radius:var(--radius-xl); padding:var(--space-7) var(--space-6);
  min-height:150px; display:flex; align-items:center;
  background:
    radial-gradient(700px 400px at 100% -20%, rgba(11,207,174,.20), transparent 60%),
    radial-gradient(600px 380px at -10% 120%, rgba(10,132,201,.22), transparent 55%),
    linear-gradient(120deg,var(--brand-ink) 0%,#0a2d52 60%,#0a3a5f 100%);
  color:#fff;
}
.ds-welcome-banner-copy h2{ font:var(--fw-page-title) 24px/1.3 var(--font-ui); margin:0 0 6px; }
.ds-welcome-banner-copy p{ font:var(--fw-body) var(--fs-body)/1.5 var(--font-ui); color:rgba(255,255,255,.78); margin:0 0 8px; }
.ds-welcome-banner-copy small{ color:rgba(255,255,255,.55); font-size:12.5px; }
.ds-ai-assistant-card{
  border-radius:var(--radius-xl); padding:var(--space-6); display:flex; flex-direction:column; gap:8px;
  background:linear-gradient(160deg,#1a1440 0%,#152057 55%,#0a2d6e 100%); color:#fff;
  border:1px solid rgba(108,76,255,.35); box-shadow:var(--shadow-md);
}
.ds-ai-assistant-icon{ width:40px; height:40px; border-radius:var(--radius-md); background:linear-gradient(120deg,#00c6ff,#6c4cff); display:flex; align-items:center; justify-content:center; color:#fff; margin-bottom:4px; }
.ds-ai-assistant-card h3{ margin:0; font:var(--fw-card-heading) 16px/1.3 var(--font-ui); }
.ds-ai-assistant-card p{ margin:0 0 8px; font-size:13px; color:rgba(255,255,255,.7); flex:1; }

/* ---------------------------------------------------------------- */
/* Alerts / toasts                                                  */
/* ---------------------------------------------------------------- */
.ds-toast-region{ position:fixed; inset-block-end:var(--space-5); inset-inline-end:var(--space-5); z-index:var(--z-toast); display:flex; flex-direction:column; gap:var(--space-2); max-width:360px; }
.ds-toast{ display:flex; align-items:flex-start; gap:var(--space-2); background:var(--surface-raised); border:1px solid var(--border-hairline); border-inline-start:3px solid var(--brand-primary); border-radius:var(--radius-md); box-shadow:var(--shadow-lg); padding:var(--space-3) var(--space-4); animation:ds-toast-in var(--duration-base) var(--ease-standard); }
.ds-toast.tone-good{ border-inline-start-color:var(--status-good); }
.ds-toast.tone-warning{ border-inline-start-color:var(--status-warning); }
.ds-toast.tone-critical{ border-inline-start-color:var(--status-critical); }
@keyframes ds-toast-in{ from{ opacity:0; transform:translateY(8px); } to{ opacity:1; transform:none; } }

/* ---------------------------------------------------------------- */
/* Modal / drawer                                                   */
/* R1: scroll-lock must apply at every viewport, not just mobile —   */
/* the legacy rule above is scoped to max-width:1023px for the nav   */
/* drawer; modals need the same class to work identically on desktop. */
/* ---------------------------------------------------------------- */
body.ds-scroll-locked{ overflow:hidden; }
.ds-modal-backdrop{ position:fixed; inset:0; background:var(--surface-overlay); z-index:var(--z-modal-backdrop); opacity:0; visibility:hidden; transition:opacity var(--duration-base) var(--ease-standard),visibility var(--duration-base); }
.ds-modal-backdrop.is-open{ opacity:1; visibility:visible; }
.ds-modal{ position:fixed; inset:0; z-index:var(--z-modal); display:flex; align-items:center; justify-content:center; padding:var(--space-4); pointer-events:none; }
.ds-modal-panel{ pointer-events:auto; width:min(560px,100%); max-height:85vh; overflow:auto; background:var(--surface-raised); border-radius:var(--radius-xl); box-shadow:var(--shadow-lg); opacity:0; transform:scale(.96) translateY(8px); transition:opacity var(--duration-base) var(--ease-standard),transform var(--duration-base) var(--ease-standard); }
.ds-modal.is-open .ds-modal-panel{ opacity:1; transform:none; }
.ds-modal-head{ display:flex; align-items:center; justify-content:space-between; padding:var(--space-5); border-bottom:1px solid var(--border-hairline); }
.ds-modal-body{ padding:var(--space-5); }
.ds-modal-foot{ display:flex; justify-content:flex-end; gap:var(--space-2); padding:var(--space-4) var(--space-5); border-top:1px solid var(--border-hairline); }

.ds-drawer{ position:fixed; inset-block:0; inset-inline-end:0; z-index:var(--z-modal); width:min(420px,90vw); background:var(--surface-raised); box-shadow:var(--shadow-lg); transform:translateX(100%); transition:transform var(--duration-base) var(--ease-standard); display:flex; flex-direction:column; }
[dir="rtl"] .ds-drawer{ inset-inline-end:0; transform:translateX(-100%); }
.ds-drawer.is-open{ transform:none; }

/* ---------------------------------------------------------------- */
/* App shell — topbar, desktop sidebar, mobile off-canvas nav        */
/* Rebuilt from scratch: solid surfaces (never transparent), real    */
/* elevation, explicit scroll-lock class, real close control.        */
/* ---------------------------------------------------------------- */
.ds-shell{ display:flex; min-height:100vh; background:var(--surface-page); }
.ds-topbar{
  position:sticky; top:0; z-index:var(--z-topbar); height:64px; display:flex; align-items:center; gap:var(--space-3);
  padding-inline:var(--space-5); background:var(--surface-1); border-bottom:1px solid var(--border-hairline);
}
.ds-topbar-search{ flex:1; min-width:0; max-width:420px; }
.ds-topbar-search .global-search{ width:100%!important; min-width:0!important; max-width:100%; box-sizing:border-box; }
.ds-topbar-search .global-search input{ min-width:0; }
.ds-topbar-actions{ display:flex; align-items:center; gap:var(--space-1); margin-inline-start:auto; }
.ds-topbar-user{ display:flex; align-items:center; gap:var(--space-2); padding-inline-start:var(--space-2); border-inline-start:1px solid var(--border-hairline); }

/* PASS J §8 mobile matrix fix (2026-08-21): confirmed live via
   document.body.scrollWidth > window.innerWidth on the real Schools
   Dashboard at 430/390/360 -- lang-toggle + theme-toggle + notifications +
   support-link + the profile button's own name label together exceed the
   viewport width at small phone sizes (topbar-actions measured 176px wide
   against a 360px viewport, pushing body.scrollWidth to 397px). The
   profile name label is the one purely decorative element here (the
   avatar + tap target still fully work without it) so it is the single
   safe thing to drop -- every other topbar control keeps its full tap
   target and function on mobile. */
@media (max-width:480px){
  .ds-topbar{ padding-inline:var(--space-3); gap:var(--space-2); }
  .ds-topbar-actions{ gap:2px; }
  .ds-topbar-user span{ display:none; }
  .ds-topbar-user{ padding-inline-start:var(--space-1); gap:0; }
  /* Still 31px over at 360px wide even with the profile name hidden --
     the profile button itself was already display:none here via
     masar360-p203r-shell.css's own pre-existing rule, so it contributed
     nothing to shrink. Support center is the one action here that is
     also reachable from /support.html directly and is the least-used of
     the four remaining icons, so it is the one dropped at this width --
     language, theme, and notifications all keep their full tap target. */
  #support-center-link{ display:none; }
}

.ds-sidebar{
  width:264px; flex:none; background:linear-gradient(180deg,var(--brand-ink) 0%,color-mix(in srgb,var(--brand-ink) 82%,black) 60%,color-mix(in srgb,var(--brand-ink) 65%,black) 100%);
  color:var(--neutral-100); display:flex; flex-direction:column; position:sticky; top:0; height:100vh; z-index:var(--z-nav);
}
.ds-sidebar-brand{ display:flex; align-items:center; gap:var(--space-2); padding:var(--space-5) var(--space-4); }
.ds-sidebar-nav{ flex:1; overflow-y:auto; padding:var(--space-2); display:flex; flex-direction:column; gap:2px; }
.ds-nav-group-label{ padding:var(--space-3) var(--space-3) var(--space-1); font:var(--fw-label) var(--fs-helper)/1.3 var(--font-ui); color:rgba(238,243,247,.58); }
.ds-nav-item{
  display:flex; align-items:center; gap:10px; padding:11px var(--space-3); border-radius:var(--radius-md);
  color:rgba(238,243,247,.86)!important; font:var(--fw-card-heading) var(--fs-body)/1.3 var(--font-ui); text-decoration:none; cursor:pointer;
  border:1px solid transparent; background:none; width:100%; text-align:start;
}
.ds-nav-item:hover{ background:rgba(238,243,247,.08); color:#fff!important; }
.ds-nav-item.is-active{ background:color-mix(in srgb,var(--brand-active,var(--brand-teal)) 16%,transparent); color:#fff!important; border-color:color-mix(in srgb,var(--brand-active,var(--brand-teal)) 35%,transparent); }
.ds-nav-item.is-active .ds-icon{ color:var(--brand-active,var(--brand-teal))!important; }
.ds-nav-item:focus-visible{ outline:none; box-shadow:0 0 0 2px color-mix(in srgb,var(--brand-active,var(--brand-teal)) 50%,transparent); }
.ds-sidebar-foot{ padding:var(--space-3); border-top:1px solid rgba(238,243,247,.10); }

/* A picked identity's sidebar color can be light (several presets use a
   white sidebar by design -- see DESIGN_PRESETS in app.js). .ds-nav-item's
   near-white text/icon colors above are correct for the dark-sidebar
   default but become near-invisible on a light one; applyBrandVars() sets
   [data-sidebar-tone="light"] on <html> for exactly this case -- without
   this block the identity system's own "light sidebar" choice produced an
   unreadable sidebar, the real cause behind "weak or invisible contrast". */
/* !important on the color declarations specifically (not the whole
   block) because a pre-existing, unrelated rule --
   .owner-sidebar nav button{color:#b9d3e5!important} in masar360-p203r-
   shell.css -- turned out to also match these buttons (confirmed live:
   the exact #b9d3e5 was what was actually rendering) and, being
   !important, silently beat this block's higher specificity. */
html[data-sidebar-tone="light"] .ds-sidebar{ background:linear-gradient(180deg,var(--sidebar-bg,#fff) 0%,color-mix(in srgb,var(--sidebar-bg,#fff) 96%,#000) 100%)!important; color:var(--ink,#1a1a1a)!important; border-inline-end:1px solid var(--border-hairline); }
html[data-sidebar-tone="light"] .ds-sidebar-brand{ border-block-end:1px solid var(--border-hairline); }
html[data-sidebar-tone="light"] .ds-nav-group-label{ color:rgba(6,27,51,.55)!important; }
html[data-sidebar-tone="light"] .ds-nav-item{ color:rgba(6,27,51,.82)!important; }
html[data-sidebar-tone="light"] .ds-nav-item:hover{ background:rgba(6,27,51,.06); color:var(--ink,#1a1a1a)!important; }
html[data-sidebar-tone="light"] .ds-nav-item.is-active{ background:color-mix(in srgb,var(--brand-active,var(--brand-teal)) 14%,transparent); color:var(--ink,#1a1a1a)!important; border-color:color-mix(in srgb,var(--brand-active,var(--brand-teal)) 40%,transparent); }
html[data-sidebar-tone="light"] .ds-nav-item.is-active .ds-icon{ color:var(--brand-active,var(--brand-teal))!important; }
html[data-sidebar-tone="light"] .ds-sidebar-foot{ border-block-start-color:rgba(6,27,51,.10); }
/* Product name, tenant identity card and profile block are hardcoded
   inline (color:#fff etc.) directly in frontend/index.html -- kept as
   plain inline style there rather than edited in place, since app.js's
   bindStatic() and the file's own preservation comment rely on these
   exact elements; an !important stylesheet override is the correct,
   lower-risk way to make them tone-aware without touching that markup.
   This is the real, confirmed cause of owner-reported defects #3-7
   (white/faint logo area, unreadable organization name, weak identity
   card contrast) on a light sidebar. */
html[data-sidebar-tone="light"] #sidebar [data-app-name]{ color:var(--ink,#1a1a1a)!important; }
html[data-sidebar-tone="light"] #sidebar .ds-sidebar-close{ color:var(--ink,#1a1a1a)!important; }
html[data-sidebar-tone="light"] #sidebar .tenant-brand-card{ background:rgba(6,27,51,.045); border:1px solid rgba(6,27,51,.09); border-radius:var(--radius-md); }
html[data-sidebar-tone="light"] #sidebar .tenant-brand-copy small{ color:rgba(6,27,51,.55)!important; }
html[data-sidebar-tone="light"] #sidebar [data-accredited-company]{ color:var(--ink,#1a1a1a)!important; }
html[data-sidebar-tone="light"] #sidebar .tenant-logo-fallback{ color:var(--ink,#1a1a1a)!important; background:rgba(6,27,51,.08); }
html[data-sidebar-tone="light"] #sidebar .profile-mini strong{ color:var(--ink,#1a1a1a)!important; }
html[data-sidebar-tone="light"] #sidebar .profile-mini small{ color:rgba(6,27,51,.55)!important; }
html[data-sidebar-tone="light"] #sidebar .avatar.ds-avatar{ background:rgba(6,27,51,.08); color:var(--ink,#1a1a1a); }

.ds-mobile-nav-toggle{ display:none; }
.ds-mobile-backdrop{ display:none; }

@media (max-width:1023px){
  .ds-sidebar{
    position:fixed; inset-block:0; inset-inline-start:0; transform:translateX(-100%);
    transition:transform var(--duration-base) var(--ease-standard); z-index:var(--z-mobile-nav);
    box-shadow:var(--shadow-lg); width:min(300px,84vw);
  }
  [dir="rtl"] .ds-sidebar{ transform:translateX(100%); }
  .ds-sidebar.is-open{ transform:none; }
  .ds-mobile-nav-toggle{ display:inline-flex; }
  .ds-mobile-backdrop{
    display:block; position:fixed; inset:0; background:rgba(6,27,51,.55); backdrop-filter:blur(1px);
    z-index:calc(var(--z-mobile-nav) - 1); opacity:0; visibility:hidden;
    transition:opacity var(--duration-base) var(--ease-standard),visibility var(--duration-base);
  }
  .ds-mobile-backdrop.is-open{ opacity:1; visibility:visible; }
  body.ds-scroll-locked{ overflow:hidden; }
}
.ds-sidebar-close{ display:none; }
@media (max-width:1023px){ .ds-sidebar-close{ display:inline-flex; margin-inline-start:auto; } }

.ds-shell-main{ flex:1; min-width:0; display:flex; flex-direction:column; }
.ds-shell-content{ flex:1; min-width:0; padding:var(--space-6); max-width:100%; }
@media (max-width:767px){ .ds-shell-content{ padding:var(--space-4); } }

/* ---------------------------------------------------------------- */
/* Chart primitives moved to frontend/ds/charts.css (pairs with     */
/* charts.js) to keep this file scoped to general UI components.    */
/* Load both tokens.css + components.css + charts.css together.     */
/* ---------------------------------------------------------------- */

/* ---------------------------------------------------------------- */
/* Legacy-cascade kill switch — scoped, documented, not a giant      */
/* override file: neutralizes the two highest-specificity legacy     */
/* selectors that fight the new shell, nothing else.                 */
/* ---------------------------------------------------------------- */
body.ds-shell-active .r1-dashboard-hero{ all:revert; }
