/* MIDE OS · ui/components.css — styles of ui/components.js and ui/templates.js.
   Colours, type, spacing and radii come only from ui/tokens.css (no colour literals here).
   Layers are declared in ui/tokens.css: base and components win over `legacy` without
   !important. Visual reference: docs/design-references/client/01–10. */

/* ================================================================ base */
@layer base {
  /* One content frame for every view: the gutter is .mx-content's padding (shell), never a
     second padding on the view, so every module lines up the same way. */
  .mx-content > .view { padding: 0; }
  .mx-content > .view.active { display: block; }

  /* Official typeface everywhere, including legacy sheets that still name another family. */
  html, body, button, input, select, textarea { font-family: var(--mide-font); }
  h1, h2, h3, .topbar-title, .ui-page-title { letter-spacing: var(--mide-tracking-heading); }
  /* Official logo files (ui/brand/). Never redraw the mark with text or CSS (Manual §5). */
  img.brand-mark, img.mide-logo { display: block; flex: 0 0 auto; background: none; box-shadow: none; border-radius: 0; object-fit: contain; }
  img.brand-mark { width: 36px; height: 36px; }
  /* Manual §2: horizontal signature never below 120 px wide (32 px high ≈ 126 px). */
  img.mide-logo { width: auto; height: 32px; min-width: 120px; }
  /* Operations Center sidebar (UX pase 3): the official COLOUR imagotipo (approved for compact
     spaces) beside the surface name, the same pattern as the client portal. The white monochrome
     lockup is not used here; the full colour lockup stays on the login. */
  .provider-brand > img.brand-mark { display: block; flex: 0 0 36px; width: 36px; height: 36px; padding: 0; background: none; box-shadow: none; border-radius: 0; object-fit: contain; }
  .provider-brand strong { font-size: var(--mide-text-sm); font-weight: 700; letter-spacing: 0; line-height: 1.2; color: var(--mx-side-ink, var(--mide-white)); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .provider-brand small { margin-top: 2px; font-size: var(--mide-text-xs); color: var(--mx-side-ink-3); }

  .ui-sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
}

/* ================================================================ components */
@layer components {
  /* ---------- tones (scoped to ui-* elements so legacy data-tone users are untouched) ---------- */
  :is([class^="ui-"], [class*=" ui-"])[data-series="1"] { --tone: var(--mide-blue-700); --tone-bg: var(--mide-blue-50); }
  :is([class^="ui-"], [class*=" ui-"])[data-series="2"] { --tone: var(--mide-violet-600); --tone-bg: var(--mide-violet-50); }
  :is([class^="ui-"], [class*=" ui-"])[data-series="3"] { --tone: var(--mide-pink-700); --tone-bg: var(--mide-pink-50); }
  :is([class^="ui-"], [class*=" ui-"])[data-series="4"] { --tone: var(--mide-orange-700); --tone-bg: var(--mide-orange-50); }
  :is([class^="ui-"], [class*=" ui-"])[data-series="5"] { --tone: var(--mide-cyan-700); --tone-bg: var(--mide-cyan-50); }
  :is([class^="ui-"], [class*=" ui-"])[data-tone="blue"], :is([class^="ui-"], [class*=" ui-"])[data-tone="info"] { --tone: var(--mide-blue-700); --tone-bg: var(--mide-blue-50); }
  :is([class^="ui-"], [class*=" ui-"])[data-tone="violet"] { --tone: var(--mide-data-ai); --tone-bg: var(--mide-data-ai-bg); }
  :is([class^="ui-"], [class*=" ui-"])[data-tone="ai"] { --tone: var(--mide-data-ai); --tone-bg: var(--mide-data-ai-bg); }
  :is([class^="ui-"], [class*=" ui-"])[data-tone="human"] { --tone: var(--mide-blue-700); --tone-bg: var(--mide-data-human-bg); }
  :is([class^="ui-"], [class*=" ui-"])[data-tone="green"], :is([class^="ui-"], [class*=" ui-"])[data-tone="ok"] { --tone: var(--mide-ok); --tone-bg: var(--mide-ok-bg); }
  :is([class^="ui-"], [class*=" ui-"])[data-tone="amber"], :is([class^="ui-"], [class*=" ui-"])[data-tone="warn"] { --tone: var(--mide-warn); --tone-bg: var(--mide-warn-bg); }
  :is([class^="ui-"], [class*=" ui-"])[data-tone="red"], :is([class^="ui-"], [class*=" ui-"])[data-tone="danger"] { --tone: var(--mide-danger); --tone-bg: var(--mide-danger-bg); }
  :is([class^="ui-"], [class*=" ui-"])[data-tone="sandbox"] { --tone: var(--mide-sandbox); --tone-bg: var(--mide-sandbox-bg); }
  :is([class^="ui-"], [class*=" ui-"])[data-tone="teal"] { --tone: var(--mide-teal); --tone-bg: var(--mide-teal-50); }
  :is([class^="ui-"], [class*=" ui-"])[data-tone="slate"], :is([class^="ui-"], [class*=" ui-"])[data-tone="neutral"] { --tone: var(--mide-neutral); --tone-bg: var(--mide-neutral-bg); }

  /* ---------- icon ---------- */
  .ui-icon { display: inline-grid; place-items: center; flex: 0 0 auto; width: 20px; height: 20px; }
  .ui-icon .mide-icon { width: 100%; height: 100%; }

  /* ---------- buttons ---------- */
  .ui-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--mide-space-2); }
  .ui-button { display: inline-flex; align-items: center; justify-content: center; gap: var(--mide-space-2); min-height: 40px; padding: 0 var(--mide-space-4); border: 1px solid var(--mide-line); border-radius: var(--mide-radius-pill); background: var(--mide-surface); color: var(--mide-ink); font: var(--mide-weight-semibold) var(--mide-text-md)/1.2 var(--mide-font); cursor: pointer; white-space: nowrap; box-shadow: none; transition: background var(--mide-duration) var(--mide-ease), border-color var(--mide-duration) var(--mide-ease), color var(--mide-duration) var(--mide-ease), filter var(--mide-duration) var(--mide-ease); }
  .ui-button .ui-icon { width: 18px; height: 18px; }
  .ui-button-label + .ui-icon { margin-left: -2px; transition: transform .12s; }
  .ui-button:hover:not(:disabled) .ui-button-label + .ui-icon { transform: translateX(2px); }
  .ui-button:hover:not(:disabled) { background: var(--mide-surface-hover); }
  .ui-button:focus-visible { outline: 2px solid var(--mide-focus-ring); outline-offset: 2px; box-shadow: none; }
  .ui-button:disabled { cursor: not-allowed; opacity: .55; }
  /* aria-disabled: looks unavailable but stays focusable and clickable to show why (e.g. «Asignar», PR 1164). */
  .ui-button[aria-disabled="true"] { cursor: help; opacity: .55; }
  .ui-button[aria-disabled="true"]:hover { background: inherit; }
  /* The account does not serve this action (issue 1133/1172): flat, neutral and readable (AA text on a light surface), not a faded
     primary; the reason is text with a lock right next to it. */
  .ui-button[data-account-limited] { background: var(--mide-surface-100); background-image: none; color: var(--mide-ink-2); border: 1px solid var(--mide-line); opacity: 1; cursor: not-allowed; box-shadow: none; }
  .ui-button[data-account-limited]:hover { background: var(--mide-surface-100); }
  .ui-button-primary { background: var(--mide-accent); background-image: var(--mide-accent-gradient); border-color: transparent; color: var(--mide-on-accent); }
  .ui-button-primary:hover:not(:disabled) { background: var(--mide-accent-hover); background-image: var(--mide-accent-gradient); filter: brightness(.92); border-color: transparent; }
  .ui-button-danger { background: var(--mide-surface); border-color: var(--mide-danger); color: var(--mide-danger); }
  .ui-button-danger:hover:not(:disabled) { background: var(--mide-danger-bg); }
  .ui-button-ghost { border-color: transparent; background: transparent; color: var(--mide-accent); }
  .ui-button-ghost:hover:not(:disabled) { background: var(--mide-accent-soft); }
  .ui-button-sm { min-height: 32px; padding: 0 var(--mide-space-3); font-size: var(--mide-text-sm); }
  .ui-button-icon { width: 40px; padding: 0; }
  /* Why a button is disabled, as help text right after it (button({ disabledReason })). It disappears as soon as the
     button is enabled again; inside a row of actions it takes its own line. */
  .ui-disabled-reason { flex: 1 0 100%; margin: 0; color: var(--mide-ink-2); font-size: var(--mide-text-sm); line-height: 1.4; }
  .ui-disabled-reason:has(.ui-icon), .ui-account-note { display: flex; align-items: flex-start; gap: var(--mide-space-2, 8px); }
  .ui-account-note { margin: 0; color: var(--mide-ink-2); font-size: var(--mide-text-sm); line-height: 1.4; }
  .ui-disabled-reason .ui-icon, .ui-account-note .ui-icon { flex: 0 0 auto; width: 16px; height: 16px; margin-top: 1px; color: var(--mide-ink-2); }
  .ui-button:enabled + .ui-disabled-reason, .ui-button[data-clean] + .ui-disabled-reason { display: none; }
  .ui-button-icon.ui-button-sm { width: 32px; }
  .ui-button-ghost.ui-button-icon { color: var(--mide-muted); }

  /* ---------- chips ---------- */
  .ui-chip { display: inline-flex; align-items: center; gap: 6px; min-height: 24px; padding: 2px 10px; border-radius: var(--mide-radius-pill); background: var(--tone-bg); color: var(--tone); font: var(--mide-weight-semibold) var(--mide-text-xs)/1.3 var(--mide-font); white-space: nowrap; }
  .ui-chip .ui-icon { width: 14px; height: 14px; }
  .ui-chip[data-tone="sandbox"] { border: 1px dashed var(--tone); }
  .ui-chip-dot i, .ui-status-dot i { width: 7px; height: 7px; border-radius: 50%; background: var(--tone); flex: 0 0 7px; }
  .ui-status-dot { display: inline-flex; align-items: center; gap: 7px; color: var(--mide-ink-2); font-size: var(--mide-text-sm); }

  /* ---------- avatar and tiles ---------- */
  .ui-avatar { display: inline-grid; place-items: center; flex: 0 0 36px; width: 36px; height: 36px; border-radius: 50%; background: var(--mide-blue-100); color: var(--mide-navy-700); font: var(--mide-weight-bold) var(--mide-text-sm)/1 var(--mide-font); }
  .ui-avatar .ui-icon { width: 60%; height: 60%; }
  .ui-avatar-sm { flex-basis: 28px; width: 28px; height: 28px; font-size: var(--mide-text-xs); }
  .ui-avatar-lg { flex-basis: 56px; width: 56px; height: 56px; font-size: var(--mide-text-lg); }
  .ui-tile { display: grid; place-items: center; flex: 0 0 40px; width: 40px; height: 40px; border-radius: var(--mide-radius); background: var(--tone-bg); color: var(--tone); }

  /* ---------- page header ---------- */
  .ui-page-header { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: var(--mide-space-4) var(--mide-space-5); margin: 0 0 var(--mide-space-6); }
  .ui-page-header-tile { display: grid; place-items: center; width: 64px; height: 64px; border-radius: var(--mide-radius-lg); background: var(--tone-bg); color: var(--tone); }
  .ui-page-header-tile .ui-icon { width: 30px; height: 30px; }
  .ui-page-header-text { min-width: 0; }
  .ui-page-header-eyebrow { margin: 0 0 var(--mide-space-1); color: var(--mide-ink-2); font-size: var(--mide-text-sm); font-weight: var(--mide-weight-medium); }
  .ui-page-header-title { margin: 0; color: var(--mide-heading); font: var(--mide-weight-heavy) var(--mide-text-3xl)/var(--mide-leading-tight) var(--mide-font); letter-spacing: -.02em; overflow-wrap: anywhere; }
  .ui-page-header-subtitle { margin: var(--mide-space-1) 0 0; color: var(--mide-ink-2); font-size: var(--mide-text-lg); line-height: var(--mide-leading); }
  @media (max-width: 720px) {
    .ui-page-header { grid-template-columns: auto minmax(0, 1fr); }
    .ui-page-header-tile { width: 48px; height: 48px; border-radius: var(--mide-radius); }
    .ui-page-header-tile .ui-icon { width: 24px; height: 24px; }
    .ui-page-header-title { font-size: var(--mide-text-2xl); }
    .ui-page-header-subtitle { font-size: var(--mide-text-md); }
    .ui-page-header > .ui-actions { grid-column: 1 / -1; }
    /* Only icon buttons left to show (e.g. «Actualizar» when the role has no status chip): they stay
       on the title row instead of taking a row of their own (review #6, N7). */
    .ui-page-header:has(> .ui-actions:not(:has(> :not(.ui-button-icon):not(:empty)))) { grid-template-columns: auto minmax(0, 1fr) auto; }
    .ui-page-header > .ui-actions:not(:has(> :not(.ui-button-icon):not(:empty))) { grid-column: 3; align-self: start; }
  }

  /* ---------- card ---------- */
  .ui-card { display: grid; align-content: start; gap: var(--mide-space-4); min-width: 0; padding: var(--mide-space-5) var(--mide-space-6); border: 1px solid var(--mide-panel-line); border-radius: var(--mide-radius-lg); background: var(--mide-surface); box-shadow: var(--mide-shadow); }
  .ui-card-head { display: flex; align-items: flex-start; gap: var(--mide-space-3); min-width: 0; }
  .ui-card-head-text { flex: 1 1 auto; min-width: 0; }
  .ui-card-title { margin: 0; color: var(--mide-heading); font: var(--mide-weight-bold) var(--mide-text-lg)/1.3 var(--mide-font); }
  .ui-card-subtitle { margin: 2px 0 0; color: var(--mide-muted); font-size: var(--mide-text-sm); }
  .ui-card-body { min-width: 0; }
  .ui-card-foot { display: flex; justify-content: flex-end; gap: var(--mide-space-2); padding-top: var(--mide-space-3); border-top: 1px solid var(--mide-line-2); }
  @media (max-width: 720px) { .ui-card { padding: var(--mide-space-4); } }

  /* ---------- KPI card (horizontal: icon left, value, delta, optional sparkline) ---------- */
  /* Label, figure and the line under it share their row tracks with every KPI of the row
     (subgrid), so they stay aligned even when a label wraps (e.g. with a wider fallback font). */
  .ui-kpi { display: grid; grid-row: span 3; grid-template-columns: auto minmax(0, 1fr) auto; grid-template-rows: subgrid; align-items: start; gap: 2px var(--mide-space-3); min-width: 0; padding: var(--mide-space-4) var(--mide-space-5); border: 1px solid var(--mide-panel-line); border-radius: var(--mide-radius-lg); background: var(--mide-surface); box-shadow: var(--mide-shadow); color: inherit; font: inherit; text-align: left; }
  .ui-kpi-action { cursor: pointer; }
  .ui-kpi-action:hover { border-color: var(--mide-blue-100); }
  .ui-kpi-action:focus-visible { outline: 2px solid var(--mide-focus-ring); outline-offset: 2px; }
  /* Icon beside the label, figure across the card: long labels («Conversaciones», «Mensajes
     recibidos») never break mid-word, and the figure gets the full width (UX pase 2). */
  .ui-kpi-tile { display: grid; place-items: center; width: 36px; height: 36px; border-radius: var(--mide-radius-sm); background: var(--tone-bg); color: var(--tone); }
  .ui-kpi-tile .ui-icon { width: 20px; height: 20px; }
  .ui-kpi-text, .ui-kpi-body, .ui-kpi-main { display: contents; }
  /* Labels end together (a wrapped label grows upward) so every figure shares one line. */
  .ui-kpi-tile { grid-column: 1; grid-row: 1; align-self: end; }
  .ui-kpi-label { grid-column: 2 / -1; grid-row: 1; align-self: end; padding-bottom: 8px; }
  .ui-kpi-value { grid-column: 1 / 3; grid-row: 2; margin-top: var(--mide-space-3); }
  .ui-kpi-sub { grid-column: 1 / 3; grid-row: 3; }
  .ui-kpi .ui-spark { grid-column: 3; grid-row: 2 / span 2; align-self: end; }
  /* Labels and values wrap instead of being truncated (reference client/01). */
  .ui-kpi-label { color: var(--mide-ink-2); font-size: var(--mide-text-sm); font-weight: var(--mide-weight-medium); line-height: 1.3; overflow-wrap: normal; hyphens: auto; }
  .ui-kpi-value { color: var(--mide-heading); font: var(--mide-weight-heavy) var(--mide-text-2xl)/1.1 var(--mide-font); letter-spacing: -.02em; font-variant-numeric: tabular-nums; overflow-wrap: break-word; }
  /* Change on one line, its reference period on the next (reference client/01). */
  /* The line under the figure is always reserved (two text lines): delta or note. */
  .ui-kpi-sub { display: block; min-width: 0; min-height: calc(2 * 1.35 * var(--mide-text-xs)); margin-top: 2px; font-size: var(--mide-text-xs); line-height: 1.35; }
  .ui-kpi-delta { display: grid; min-width: 0; margin: 0; font-size: var(--mide-text-xs); line-height: 1.35; }
  .ui-kpi-delta-value { color: var(--tone); font-weight: var(--mide-weight-bold); }
  .ui-kpi-delta-label, .ui-kpi-note { color: var(--mide-muted); font-size: var(--mide-text-xs); line-height: 1.35; }
  /* Notes are short (2–3 words); if one is longer it wraps to a second line, never an ellipsis. */
  .ui-kpi-note { display: -webkit-box; min-width: 0; overflow: hidden; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; }
  .ui-spark { flex: 0 0 auto; }
  .ui-spark .ui-spark-bar { fill: var(--tone); }
  .ui-spark .ui-spark-empty { fill: var(--tone-bg); }
  @media (max-width: 1100px) { .ui-kpi .ui-spark { display: none; } }

  /* ---------- tabs ---------- */
  .ui-tabs { display: flex; gap: var(--mide-space-6); overflow-x: auto; border-bottom: 1px solid var(--mide-line); scrollbar-width: thin; }
  .ui-tab { position: relative; display: inline-flex; align-items: center; gap: 6px; padding: var(--mide-space-3) 2px; border: 0; background: none; color: var(--mide-ink-2); font: var(--mide-weight-medium) var(--mide-text-md)/1.2 var(--mide-font); white-space: nowrap; cursor: pointer; }
  .ui-tab::after { content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; border-radius: 2px; background: transparent; }
  .ui-tab[aria-selected="true"] { color: var(--mide-accent); font-weight: var(--mide-weight-bold); }
  .ui-tab[aria-selected="true"]::after { background: var(--mide-accent); }
  .ui-tab:hover:not(:disabled) { color: var(--mide-accent); }
  .ui-tab:disabled { color: var(--mide-subtle); cursor: not-allowed; }
  .ui-tab:focus-visible { outline: 2px solid var(--mide-focus-ring); outline-offset: -2px; border-radius: var(--mide-radius-sm); }
  .ui-tab-count:empty { display: none; }
  @media (max-width: 720px) {
    .ui-tabs { gap: var(--mide-space-5); scrollbar-width: none; scroll-padding-inline: var(--mide-space-4); }
    .ui-tabs::-webkit-scrollbar { display: none; }
  }
  /* Tabs that do not fit fade out on the side that hides more of them (data-overflow, set by tabs()). */
  .ui-tabs[data-overflow="end"] { -webkit-mask-image: linear-gradient(to right, black calc(100% - 56px), transparent); mask-image: linear-gradient(to right, black calc(100% - 56px), transparent); }
  .ui-tabs[data-overflow="start"] { -webkit-mask-image: linear-gradient(to left, black calc(100% - 56px), transparent); mask-image: linear-gradient(to left, black calc(100% - 56px), transparent); }
  .ui-tabs[data-overflow="start end"] { -webkit-mask-image: linear-gradient(to right, transparent, black 56px, black calc(100% - 56px), transparent); mask-image: linear-gradient(to right, transparent, black 56px, black calc(100% - 56px), transparent); }

  /* ---------- forms ---------- */
  .ui-field { display: grid; align-content: start; gap: 6px; min-width: 0; }
  .ui-field-label { color: var(--mide-ink); font-size: var(--mide-text-sm); font-weight: var(--mide-weight-semibold); }
  .ui-field-required { color: var(--mide-danger); }
  .ui-field-hint { margin: 0; color: var(--mide-muted); font-size: var(--mide-text-xs); }
  /* Field error (issue 1133): icon + text at 14 px in the danger token; the control gets aria-invalid and its border. */
  .ui-field-error { display: flex; align-items: flex-start; gap: 6px; margin: 0; color: var(--mide-danger); font-size: var(--mide-text-md); font-weight: var(--mide-weight-semibold); line-height: 1.4; }
  .ui-field-error > .ui-icon { flex: 0 0 18px; width: 18px; height: 18px; margin-top: 1px; }
  .ui-field-error-text { min-width: 0; overflow-wrap: anywhere; }
  .ui-field-error[hidden] { display: none; }
  :is(input, select, textarea, button)[aria-invalid="true"] { border-color: var(--mide-danger); }
  [data-field-wrap][data-invalid="true"] > :is(input, select, textarea) { border-color: var(--mide-danger); }
  .ui-input, .ui-select, .ui-textarea { width: 100%; min-height: 40px; padding: 0 var(--mide-space-3); border: 1px solid var(--mide-line); border-radius: var(--mide-radius-sm); background: var(--mide-surface); color: var(--mide-ink); font: var(--mide-weight-regular) var(--mide-text-md)/1.4 var(--mide-font); box-shadow: none; }
  .ui-textarea { padding: var(--mide-space-2) var(--mide-space-3); resize: vertical; }
  .ui-input:focus-visible, .ui-select:focus-visible, .ui-textarea:focus-visible { outline: none; border-color: var(--mide-accent); box-shadow: var(--mide-focus); }
  .ui-input[aria-invalid="true"], .ui-select[aria-invalid="true"], .ui-textarea[aria-invalid="true"], .ui-select-menu-trigger[aria-invalid="true"] { border-color: var(--mide-danger); box-shadow: inset 0 0 0 1px var(--mide-danger); }
  .ui-input:disabled, .ui-select:disabled, .ui-textarea:disabled { background: var(--mide-surface-2); color: var(--mide-muted); cursor: not-allowed; }
  /* Placeholders with the secondary text token (≥ 4.5:1 on white and on niebla, PR 1164 visual QA). */
  .ui-filter-search-input::placeholder { color: var(--mide-muted); opacity: 1; }
  /* A filter bar with nothing to filter: every control visibly off (dashed border, niebla, no shadow). */
  .ui-filter-bar[data-disabled="true"] :is(.ui-input, .ui-select-menu-trigger) { border-style: dashed; border-color: var(--mide-line-strong); background: var(--mide-surface-2); box-shadow: none; cursor: not-allowed; }
  .ui-filter-bar[data-disabled="true"] :is(.ui-filter-label, .ui-filter-search .ui-icon) { color: var(--mide-muted); }
  .ui-textarea-wrap { display: grid; gap: 4px; }
  .ui-counter { justify-self: end; color: var(--mide-muted); font-size: var(--mide-text-xs); font-variant-numeric: tabular-nums; }
  .ui-toggle { display: flex; align-items: center; justify-content: space-between; gap: var(--mide-space-4); min-width: 0; }
  .ui-toggle-text { display: grid; gap: 2px; min-width: 0; }
  .ui-toggle-label { color: var(--mide-ink); font-size: var(--mide-text-md); font-weight: var(--mide-weight-semibold); }
  .ui-toggle-description { color: var(--mide-muted); font-size: var(--mide-text-sm); }
  /* Switch (issue 1133): the 44 × 24 track is drawn inside a larger transparent button, so the hit area is
     48 × 32 on desktop and 48 × 44 on phones (ui/components.css, layer controls) without changing the look. */
  .ui-switch { position: relative; flex: 0 0 48px; width: 48px; min-width: 48px; height: 32px; padding: 0; border: 0; border-radius: var(--mide-radius-pill); background: transparent; cursor: pointer; }
  .ui-switch::before { content: ""; position: absolute; top: calc(50% - 12px); left: 2px; width: 44px; height: 24px; border-radius: var(--mide-radius-pill); background: var(--mide-line); transition: background .15s; }
  .ui-switch-thumb { position: absolute; z-index: 1; top: calc(50% - 9px); left: 5px; width: 18px; height: 18px; border-radius: 50%; background: var(--mide-surface); box-shadow: var(--mide-shadow); transition: transform .15s; }
  .ui-switch[aria-checked="true"]::before { background: var(--mide-accent); }
  .ui-switch[aria-checked="true"] .ui-switch-thumb { transform: translateX(20px); }
  .ui-switch:focus-visible { outline: none; }
  .ui-switch:focus-visible::before { outline: 2px solid var(--mide-focus-ring); outline-offset: 2px; }
  .ui-switch:disabled { cursor: not-allowed; opacity: .5; }

  /* ---------- select menu (own listbox select) ---------- */
  .ui-select-menu { position: relative; display: inline-grid; min-width: 0; }
  .ui-field > .ui-select-menu { display: grid; } /* inside a form it takes the field width */
  .ui-select-menu-trigger { display: inline-flex; align-items: center; gap: var(--mide-space-2); min-height: 40px; width: 100%; padding: 0 var(--mide-space-3); border: 1px solid var(--mide-line); border-radius: var(--mide-radius-sm); background: var(--mide-surface); color: var(--mide-ink); font: var(--mide-weight-semibold) var(--mide-text-sm)/1.2 var(--mide-font); text-align: left; white-space: nowrap; cursor: pointer; }
  .ui-select-menu-trigger > .ui-icon:first-child { width: 18px; height: 18px; color: var(--mide-muted); }
  .ui-select-menu-text { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
  .ui-template-id { color: var(--mide-ink-2); }
  .ui-template-id code { padding: 1px 6px; border-radius: 4px; background: var(--mide-surface-hover); color: var(--mide-ink); font: var(--mide-weight-medium) 0.92em/1.4 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
  .ui-select-menu-text.is-placeholder { color: var(--mide-muted); font-weight: var(--mide-weight-regular); }
  .ui-select-menu-caret { display: inline-grid; color: var(--mide-muted); transition: transform .12s; }
  .ui-select-menu-caret .ui-icon { width: 16px; height: 16px; }
  .ui-select-menu-trigger[aria-expanded="true"] .ui-select-menu-caret { transform: rotate(180deg); }
  .ui-select-menu-trigger:hover:not(:disabled) { border-color: var(--mide-blue-100); background: var(--mide-surface-hover); }
  .ui-select-menu-trigger:focus-visible { outline: none; border-color: var(--mide-accent); box-shadow: var(--mide-focus); }
  .ui-select-menu-trigger:disabled { background: var(--mide-surface-2); color: var(--mide-muted); cursor: not-allowed; }
  .ui-select-menu-list { position: absolute; top: calc(100% + 6px); left: 0; z-index: 50; display: grid; gap: 2px; min-width: 100%; width: max-content; max-width: min(320px, calc(100vw - 32px)); max-height: 320px; margin: 0; padding: var(--mide-space-1); overflow-y: auto; border: 1px solid var(--mide-line); border-radius: var(--mide-radius); background: var(--mide-surface); box-shadow: var(--mide-shadow-lg); list-style: none; }
  .ui-select-menu-list[data-align="end"] { left: auto; right: 0; }
  .ui-select-menu-list[data-placement="top"] { top: auto; bottom: calc(100% + 6px); }
  .ui-select-menu-sm .ui-select-menu-trigger { min-height: 34px; min-width: 72px; }
  .ui-select-menu-option { display: flex; align-items: center; justify-content: space-between; gap: var(--mide-space-3); min-height: 36px; padding: var(--mide-space-2) var(--mide-space-3); border-radius: var(--mide-radius-sm); color: var(--mide-ink); font-size: var(--mide-text-sm); cursor: pointer; }
  .ui-select-menu-option-text { display: grid; gap: 1px; }
  .ui-select-menu-option-text small { color: var(--mide-muted); font-size: var(--mide-text-xs); }
  .ui-select-menu-option > .ui-icon { width: 16px; height: 16px; color: var(--mide-accent); visibility: hidden; }
  .ui-select-menu-option[aria-selected="true"] { color: var(--mide-accent); font-weight: var(--mide-weight-semibold); }
  .ui-select-menu-option[aria-selected="true"] > .ui-icon { visibility: visible; }
  .ui-select-menu-option.is-active { background: var(--mide-surface-hover); }

  /* ---------- connections (shared block) ---------- */
  .ui-connection-list { display: grid; margin: 0; padding: 0; list-style: none; }
  .ui-connection { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: var(--mide-space-3); padding: var(--mide-space-3) 0; }
  .ui-connection + .ui-connection { border-top: 1px solid var(--mide-line-2); }
  .ui-connection-text { display: grid; gap: 2px; min-width: 0; }
  .ui-connection-text strong { color: var(--mide-ink); font-size: var(--mide-text-md); font-weight: var(--mide-weight-semibold); }
  .ui-connection-text small { color: var(--mide-muted); font-size: var(--mide-text-xs); }
  /* Phones keep the status on the same line (one row per connection); only below 360 px it drops. */
  @media (max-width: 359px) { .ui-connection { grid-template-columns: auto minmax(0, 1fr); } .ui-connection > .ui-chip { grid-column: 2; justify-self: start; } }

  /* ---------- step meter (segmented progress) ---------- */
  .ui-step-meter { display: grid; gap: var(--mide-space-2); min-width: 0; }
  .ui-step-track { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 4px; }
  .ui-step-segment { display: block; height: 8px; border-radius: var(--mide-radius-pill); background: var(--mide-line-2); }
  .ui-step-segment[data-state="done"] { background: var(--mide-ok); }
  .ui-step-segment[data-state="pending"] { background: var(--mide-warn-bg); box-shadow: inset 0 0 0 1px var(--mide-warn); }
  .ui-step-segment[data-state="locked"] { background: repeating-linear-gradient(135deg, var(--mide-line-2) 0 4px, var(--mide-surface-2) 4px 8px); }
  .ui-step-note { display: inline-flex; align-items: center; gap: 6px; color: var(--mide-muted); font-size: var(--mide-text-xs); }
  .ui-step-note .ui-icon { width: 14px; height: 14px; }

  /* ---------- meter ---------- */
  .ui-meter { display: grid; gap: var(--mide-space-2); min-width: 0; }
  .ui-meter-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--mide-space-3); font-size: var(--mide-text-sm); }
  .ui-meter-label { color: var(--mide-ink-2); }
  .ui-meter-detail { color: var(--mide-ink); font-variant-numeric: tabular-nums; }
  .ui-meter .ui-progress-track { display: block; }

  /* ---------- filter bar ---------- */
  .ui-filter-bar { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--mide-space-3) var(--mide-space-4); }
  .ui-filter-search { position: relative; flex: 1 1 260px; min-width: 0; }
  .ui-filter-search > .ui-icon { position: absolute; left: var(--mide-space-3); top: 50%; width: 18px; height: 18px; color: var(--mide-muted); transform: translateY(-50%); pointer-events: none; }
  .ui-filter-search-input { padding-left: 38px; }
  .ui-filter-select { display: grid; grid-template-columns: minmax(0, 1fr); gap: 4px; flex: 0 1 180px; min-width: 140px; }
  /* The own select takes its filter cell and never its text width (no control overflows the card). */
  .ui-filter-select > .ui-select-menu { display: grid; width: 100%; min-width: 0; }
  .ui-filter-select .ui-select-menu-trigger { min-width: 0; }
  .ui-filter-label { color: var(--mide-ink-2); font-size: var(--mide-text-xs); font-weight: var(--mide-weight-semibold); }
  .ui-filter-clear { margin-left: auto; }
  @media (max-width: 720px) { .ui-filter-select { flex: 1 1 140px; min-width: 0; } .ui-filter-clear { margin-left: 0; } }
  /* Narrow phones: each filter takes the whole row, so its label and value are never truncated. */
  @media (max-width: 420px) { .ui-filter-select { flex: 1 1 100%; } }

  /* ---------- data table ---------- */
  .ui-data-table { display: grid; gap: var(--mide-space-3); min-width: 0; }
  .ui-table-scroll { min-width: 0; overflow-x: auto; }
  /* Sideways overflow is never silent: soft edge shadows that follow the scroll position, plus the hint line below. */
  .ui-table-scroll[data-overflow="true"] {
    background:
      linear-gradient(to right, var(--mide-surface) 30%, transparent) left center / 24px 100% no-repeat local,
      linear-gradient(to left, var(--mide-surface) 30%, transparent) right center / 24px 100% no-repeat local,
      radial-gradient(farthest-side at 0 50%, color-mix(in srgb, var(--mide-ink) 22%, transparent), transparent) left center / 12px 100% no-repeat scroll,
      radial-gradient(farthest-side at 100% 50%, color-mix(in srgb, var(--mide-ink) 22%, transparent), transparent) right center / 12px 100% no-repeat scroll;
  }
  .ui-table-hint { margin: 0; color: var(--mide-ink-2); font-size: var(--mide-text-sm); line-height: 1.4; }
  .ui-table-hint[hidden], .ui-data-table:not([data-state="ready"]) .ui-table-hint { display: none; }
  .ui-table { width: 100%; border-collapse: collapse; font-size: var(--mide-text-sm); color: var(--mide-ink); }
  .ui-table th { padding: var(--mide-space-3); border-bottom: 1px solid var(--mide-line); background: transparent; color: var(--mide-ink-2); font-size: var(--mide-text-sm); font-weight: var(--mide-weight-semibold); text-align: left; text-transform: none; letter-spacing: 0; white-space: nowrap; }
  .ui-table td { padding: var(--mide-space-3); border-bottom: 1px solid var(--mide-line-2); vertical-align: middle; white-space: nowrap; }
  .ui-table td.ui-wrap { min-width: 16ch; white-space: normal; overflow-wrap: anywhere; }
  .ui-table .ui-align-end { text-align: right; }
  /* The last column keeps air before the card edge (a button never touches it). */
  .ui-table th:last-child, .ui-table td:last-child { padding-right: var(--mide-space-4); }
  .ui-table tbody tr:last-child td { border-bottom: 0; }
  .ui-row-selectable { cursor: pointer; }
  .ui-row-selectable:hover td { background: var(--mide-surface-2); }
  .ui-row-selectable:focus-visible { outline: 2px solid var(--mide-focus-ring); outline-offset: -2px; }
  .ui-table tr.is-selected td { background: var(--mide-accent-soft); }
  .ui-data-table:not([data-state="ready"]) .ui-table tbody { display: none; }
  .ui-table-state:empty { display: none; }
  .ui-table-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--mide-space-3); }
  .ui-data-table:not([data-state="ready"]) .ui-table-foot { display: none; }
  .ui-table-status { margin: 0; color: var(--mide-muted); font-size: var(--mide-text-sm); }
  .ui-table-foot-controls { display: flex; flex-wrap: wrap; align-items: center; gap: var(--mide-space-4); }
  .ui-pager-size { display: inline-flex; align-items: center; gap: var(--mide-space-2); color: var(--mide-ink-2); font-size: var(--mide-text-sm); }
  .ui-pager-size .ui-select { width: auto; min-height: 34px; }
  .ui-pager-size .ui-select-menu-list { min-width: 88px; }
  .ui-pager { display: flex; align-items: center; gap: var(--mide-space-1); }
  .ui-pager-button { min-width: 34px; height: 34px; padding: 0 var(--mide-space-2); border: 1px solid transparent; border-radius: var(--mide-radius-sm); background: transparent; color: var(--mide-ink-2); font: var(--mide-weight-semibold) var(--mide-text-sm)/1 var(--mide-font); cursor: pointer; }
  .ui-pager-button:hover:not(:disabled) { background: var(--mide-surface-hover); }
  .ui-pager-button.is-current { border-color: var(--mide-accent); color: var(--mide-accent); background: var(--mide-accent-soft); }
  .ui-pager-button:disabled { color: var(--mide-subtle); cursor: not-allowed; }
  .ui-pager-button:focus-visible { outline: 2px solid var(--mide-focus-ring); outline-offset: 1px; }
  .ui-pager-gap { padding: 0 var(--mide-space-1); color: var(--mide-muted); }

  /* Phone cards switch on the table's own width (container query), not the viewport: a table in
     a narrow column (e.g. beside an inspector) becomes cards too. mobileCards: 'wide' switches
     earlier, for tables with many columns (Contactos). One set of rules for every view. */
  .ui-data-table-cards { container: ui-table / inline-size; }
  @container ui-table (max-width: 640px) {
    .ui-data-table-cards .ui-table-scroll { overflow: visible; }
    .ui-data-table-cards .ui-table, .ui-data-table-cards .ui-table tbody { display: block; }
    .ui-data-table-cards .ui-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
    .ui-data-table-cards .ui-table tbody { display: grid; gap: var(--mide-space-3); }
    .ui-data-table-cards .ui-table tr { display: grid; gap: var(--mide-space-2); padding: var(--mide-space-3) var(--mide-space-4); border: 1px solid var(--mide-panel-line); border-radius: var(--mide-radius); background: var(--mide-surface); }
    /* Each cell is a dt/dd pair: label column (its own width, at least 5.5rem) and value column
       (the rest). A long value wraps between words inside its column; it is never squeezed to a
       letter per line (overflow-wrap: break-word, not anywhere). */
    .ui-data-table-cards .ui-table td { display: grid; grid-template-columns: minmax(5.5rem, max-content) minmax(0, 1fr); align-items: baseline; gap: var(--mide-space-3); min-width: 0; padding: 0; border: 0; white-space: normal; overflow-wrap: break-word; text-align: right; }
    .ui-data-table-cards .ui-table td > * { justify-self: end; min-width: 0; max-width: 100%; }
    .ui-data-table-cards .ui-table td::before { content: attr(data-label); color: var(--mide-muted); font-size: var(--mide-text-xs); font-weight: var(--mide-weight-semibold); text-align: left; }
    .ui-data-table-cards .ui-table td.ui-wrap { min-width: 0; overflow-wrap: break-word; }
    .ui-data-table-cards .ui-table tr { grid-template-columns: minmax(0, 1fr) auto; }
    .ui-data-table-cards .ui-table td { grid-column: 1 / -1; }
    .ui-data-table-cards .ui-table td.ui-cell-title { display: flex; grid-row: 1; grid-column: 1; justify-content: flex-start; text-align: left; }
    .ui-data-table-cards .ui-table td.ui-cell-title > * { justify-self: auto; }
    /* The header date never wraps: it keeps one line beside the title (or its own row when narrow). */
    .ui-data-table-cards .ui-table td.ui-cell-meta { display: block; grid-row: 1; grid-column: 2; color: var(--mide-muted); font-size: var(--mide-text-xs); white-space: nowrap; }
    .ui-data-table-cards .ui-table td.ui-cell-title::before, .ui-data-table-cards .ui-table td.ui-cell-meta::before { content: none; }
    .ui-data-table-cards .ui-table tr.is-selected td { background: transparent; }
    .ui-data-table-cards .ui-table tr.is-selected { border-color: var(--mide-accent); background: var(--mide-accent-soft); }
    .ui-data-table-cards .ui-row-selectable:hover td { background: transparent; }
    .ui-data-table-cards .ui-table-foot { justify-content: center; }
  }
  @container ui-table (min-width: 641px) and (max-width: 860px) {
    .ui-data-table-cards[data-cards="wide"] .ui-table-scroll { overflow: visible; }
    .ui-data-table-cards[data-cards="wide"] .ui-table, .ui-data-table-cards[data-cards="wide"] .ui-table tbody { display: block; }
    .ui-data-table-cards[data-cards="wide"] .ui-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
    .ui-data-table-cards[data-cards="wide"] .ui-table tbody { display: grid; gap: var(--mide-space-3); }
    .ui-data-table-cards[data-cards="wide"] .ui-table tr { display: grid; gap: var(--mide-space-2); padding: var(--mide-space-3) var(--mide-space-4); border: 1px solid var(--mide-panel-line); border-radius: var(--mide-radius); background: var(--mide-surface); }
    /* Each cell is a dt/dd pair: label column (its own width, at least 5.5rem) and value column
       (the rest). A long value wraps between words inside its column; it is never squeezed to a
       letter per line (overflow-wrap: break-word, not anywhere). */
    .ui-data-table-cards[data-cards="wide"] .ui-table td { display: grid; grid-template-columns: minmax(5.5rem, max-content) minmax(0, 1fr); align-items: baseline; gap: var(--mide-space-3); min-width: 0; padding: 0; border: 0; white-space: normal; overflow-wrap: break-word; text-align: right; }
    .ui-data-table-cards[data-cards="wide"] .ui-table td > * { justify-self: end; min-width: 0; max-width: 100%; }
    .ui-data-table-cards[data-cards="wide"] .ui-table td::before { content: attr(data-label); color: var(--mide-muted); font-size: var(--mide-text-xs); font-weight: var(--mide-weight-semibold); text-align: left; }
    .ui-data-table-cards[data-cards="wide"] .ui-table td.ui-wrap { min-width: 0; overflow-wrap: break-word; }
    .ui-data-table-cards[data-cards="wide"] .ui-table tr { grid-template-columns: minmax(0, 1fr) auto; }
    .ui-data-table-cards[data-cards="wide"] .ui-table td { grid-column: 1 / -1; }
    .ui-data-table-cards[data-cards="wide"] .ui-table td.ui-cell-title { display: flex; grid-row: 1; grid-column: 1; justify-content: flex-start; text-align: left; }
    .ui-data-table-cards[data-cards="wide"] .ui-table td.ui-cell-title > * { justify-self: auto; }
    /* The header date never wraps: it keeps one line beside the title (or its own row when narrow). */
    .ui-data-table-cards[data-cards="wide"] .ui-table td.ui-cell-meta { display: block; grid-row: 1; grid-column: 2; color: var(--mide-muted); font-size: var(--mide-text-xs); white-space: nowrap; }
    .ui-data-table-cards[data-cards="wide"] .ui-table td.ui-cell-title::before, .ui-data-table-cards[data-cards="wide"] .ui-table td.ui-cell-meta::before { content: none; }
    .ui-data-table-cards[data-cards="wide"] .ui-table tr.is-selected td { background: transparent; }
    .ui-data-table-cards[data-cards="wide"] .ui-table tr.is-selected { border-color: var(--mide-accent); background: var(--mide-accent-soft); }
    .ui-data-table-cards[data-cards="wide"] .ui-row-selectable:hover td { background: transparent; }
    .ui-data-table-cards[data-cards="wide"] .ui-table-foot { justify-content: center; }
  }
  /* Narrow cards: the header date takes its own row under the title. */
  @container ui-table (max-width: 399px) {
    .ui-data-table-cards .ui-table td.ui-cell-meta { grid-row: 2; grid-column: 1 / -1; text-align: left; }
  }

  /* ---------- inspector ---------- */
  .ui-inspector-host { min-width: 0; }
  .ui-inspector { display: grid; align-content: start; gap: var(--mide-space-4); min-width: 0; padding: var(--mide-space-5); border: 1px solid var(--mide-panel-line); border-radius: var(--mide-radius-lg); background: var(--mide-surface); box-shadow: var(--mide-shadow); }
  .ui-inspector:focus-visible { outline: none; }
  .ui-inspector-head { display: flex; align-items: flex-start; gap: var(--mide-space-3); }
  .ui-inspector-head-text { flex: 1 1 auto; min-width: 0; }
  .ui-inspector-title { margin: 0; color: var(--mide-heading); font: var(--mide-weight-bold) var(--mide-text-xl)/1.25 var(--mide-font); overflow-wrap: anywhere; }
  .ui-inspector-subtitle { margin: 2px 0 0; color: var(--mide-muted); font-size: var(--mide-text-sm); }
  .ui-inspector-body { display: grid; gap: var(--mide-space-4); min-width: 0; }
  /* Sticky footer (issue 1133, one pattern for every drawer/inspector): solid background, solid top border, and the
     panel's scroll padding equals the measured footer height (--ui-foot-h, ui/components.js keepClearOfFooter),
     so a focused or scrolled-to control never lands under it. */
  .ui-inspector-foot { position: sticky; bottom: calc(var(--mide-space-5) * -1); z-index: 2; display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--mide-space-2); margin-bottom: calc(var(--mide-space-5) * -1); padding: var(--mide-space-4) 0 var(--mide-space-5); border-top: 1px solid var(--mide-line); background: var(--mide-surface); }
  .ui-inspector { scroll-padding-bottom: calc(var(--ui-foot-h, 0px) + var(--mide-space-3)); scroll-padding-top: var(--mide-space-3); }
  .ui-inspector-backdrop { position: fixed; inset: 0; z-index: 60; background: var(--mide-overlay); }
  @media (min-width: 901px) { .ui-inspector { position: sticky; top: calc(var(--mx-topbar-h, 72px) + var(--mide-space-3)); max-height: calc(100vh - var(--mx-topbar-h, 72px) - var(--mide-space-6)); overflow-y: auto; } }
  @media (max-width: 900px) {
    .ui-inspector { position: fixed; top: 0; right: 0; bottom: 0; z-index: 61; width: min(440px, calc(100% - 40px)); border-radius: 0; overflow-y: auto; box-shadow: var(--mide-shadow-lg); }
  }

  /* ---------- modal ---------- */
  /* Modal (issue 1133): never taller than the screen; header and footer stay put and only the body scrolls, so the
     actions are always reachable and never cover a field or a message. */
  .ui-modal { width: min(560px, calc(100vw - 32px)); max-height: calc(100dvh - 32px); padding: 0; border: 0; border-radius: var(--mide-radius-lg); background: var(--mide-surface); color: var(--mide-ink); box-shadow: var(--mide-shadow-lg); overflow: hidden; }
  .ui-modal[open] { display: flex; flex-direction: column; }
  .ui-modal-sm { width: min(420px, calc(100vw - 32px)); }
  .ui-modal-lg { width: min(760px, calc(100vw - 32px)); }
  .ui-modal::backdrop { background: var(--mide-overlay); position: fixed; inset: 0; }
  /* An open modal owns the viewport: the page behind it does not scroll, so the overlay always covers the full height. */
  html:has(dialog.ui-modal[open]), body:has(dialog.ui-modal[open]) { overflow: hidden; }
  .ui-modal-head { flex: 0 0 auto; display: flex; align-items: flex-start; justify-content: space-between; gap: var(--mide-space-3); padding: var(--mide-space-6) var(--mide-space-6) 0; }
  .ui-modal-title { margin: 0; color: var(--mide-heading); font: var(--mide-weight-bold) var(--mide-text-xl)/1.25 var(--mide-font); }
  .ui-modal-description { flex: 0 0 auto; margin: var(--mide-space-2) 0 0; padding: 0 var(--mide-space-6); color: var(--mide-ink-2); font-size: var(--mide-text-md); }
  .ui-modal-body { flex: 1 1 auto; min-height: 0; display: grid; align-content: start; gap: var(--mide-space-4); margin-top: var(--mide-space-4); padding: 4px var(--mide-space-6) var(--mide-space-6); overflow-y: auto; overscroll-behavior: contain; scroll-padding-block: var(--mide-space-4); }
  .ui-modal-foot { flex: 0 0 auto; position: sticky; bottom: 0; z-index: 2; display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--mide-space-2); margin: 0; padding: var(--mide-space-4) var(--mide-space-6); border-top: 1px solid var(--mide-line); background: var(--mide-surface); }
  .ui-modal > .ui-discard-confirm { flex: 0 0 auto; margin: 0 var(--mide-space-6) var(--mide-space-3); }
  @media (max-width: 640px) {
    .ui-modal-head { padding: var(--mide-space-4) var(--mide-space-4) 0; }
    .ui-modal-description { padding: 0 var(--mide-space-4); }
    .ui-modal-body { padding: 4px var(--mide-space-4) var(--mide-space-6); scroll-padding-block-end: var(--mide-space-6); }
    .ui-modal-foot { padding: var(--mide-space-3) var(--mide-space-4); }
    .ui-modal > .ui-discard-confirm { margin: 0 var(--mide-space-4) var(--mide-space-3); }
  }

  /* ---------- notices, form messages, unsaved-changes confirmation (issue 1133) ---------- */
  .ui-notice-region:empty { display: block; height: 0; margin: 0; }
  .ui-notice-region:not(:empty) { margin: 0 0 var(--mide-space-3); }
  .ui-inspector .ui-notice-region:not(:empty), .ui-modal .ui-notice-region:not(:empty) { margin: 0; }
  .ui-notice-icon { display: inline-grid; flex: 0 0 18px; width: 18px; height: 18px; margin-top: 2px; color: var(--tone, var(--mide-info)); }
  .ui-notice-icon .ui-icon { width: 18px; height: 18px; }
  .ui-notice-body { display: grid; flex: 1 1 auto; gap: 2px; min-width: 0; color: var(--mide-ink); font-size: var(--mide-text-md); line-height: var(--mide-leading); overflow-wrap: anywhere; }
  .ui-notice-title { color: var(--mide-heading); font-weight: var(--mide-weight-bold); }
  .ui-notice-actions { display: flex; flex-wrap: wrap; gap: var(--mide-space-2); margin-top: var(--mide-space-2); }
  .ui-notice-inline { border-left: 3px solid var(--tone, var(--mide-info)); }
  .ui-notice > .ui-button { flex: 0 0 auto; margin: -6px -6px -6px 0; }
  .ui-form-message { display: flex; align-items: flex-start; gap: 6px; margin: 0; color: var(--mide-danger); font-size: var(--mide-text-md); font-weight: var(--mide-weight-semibold); line-height: 1.4; }
  .ui-form-message[data-tone="info"], .ui-form-message[data-tone="ok"] { color: var(--mide-ink-2); }
  .ui-form-message > .ui-icon { flex: 0 0 18px; width: 18px; height: 18px; margin-top: 1px; }
  .ui-form-message[hidden] { display: none; }
  /* Footer messages sit on their own row above the buttons. */
  :is(.ui-modal-foot, .ui-inspector-foot, .ui-card-foot) > .ui-form-message { flex: 1 0 100%; }
  .ui-discard-confirm { display: flex; align-items: flex-start; gap: var(--mide-space-3); padding: var(--mide-space-3) var(--mide-space-4); border: 1px solid var(--mide-line); border-left: 3px solid var(--mide-warn); border-radius: var(--mide-radius-sm); background: var(--mide-warn-bg); color: var(--mide-ink); }
  .ui-discard-confirm .ui-notice-icon { color: var(--mide-ink-2); }
  .ui-discard-confirm strong { color: var(--mide-heading); }
  .ui-discard-confirm .ui-actions { margin-top: var(--mide-space-2); }
  /* A disabled save with nothing to save is neutral («Sin cambios»), not a faded primary that looks broken. */
  .ui-button[data-clean]:disabled, .primary-button[data-clean]:disabled { opacity: 1; background: var(--mide-surface-2); background-image: none; border-color: var(--mide-line); color: var(--mide-ink-2); filter: none; }

  /* ---------- states ---------- */
  .ui-state { display: grid; justify-items: center; gap: var(--mide-space-2); padding: var(--mide-space-8) var(--mide-space-4); text-align: center; }
  .ui-state-icon { display: grid; place-items: center; width: 48px; height: 48px; border-radius: 50%; background: var(--mide-neutral-bg); color: var(--mide-neutral); }
  .ui-error-state .ui-state-icon { background: var(--mide-danger-bg); color: var(--mide-danger); }
  .ui-state-icon .ui-icon { width: 24px; height: 24px; }
  .ui-state-title { color: var(--mide-ink); font-size: var(--mide-text-lg); font-weight: var(--mide-weight-bold); }
  .ui-state-text { max-width: 46ch; margin: 0; color: var(--mide-muted); font-size: var(--mide-text-md); }
  /* Inside a card an empty/error state is compact: it explains, it does not fill the card. */
  .ui-card .ui-state { padding: var(--mide-space-5) var(--mide-space-4); }
  .ui-skeleton { display: grid; gap: var(--mide-space-3); padding: var(--mide-space-2) 0; }
  .ui-skeleton-line { display: block; height: 14px; border-radius: var(--mide-radius-sm); background: linear-gradient(90deg, var(--mide-skeleton) 25%, var(--mide-skeleton-shine) 50%, var(--mide-skeleton) 75%); background-size: 200% 100%; animation: ui-shimmer 1.4s ease-in-out infinite; }
  .ui-skeleton-line:last-child { width: 60%; }
  .ui-skeleton-table .ui-skeleton-line { height: 36px; }
  .ui-skeleton-table .ui-skeleton-line:last-child, .ui-skeleton-card .ui-skeleton-line:last-child { width: 100%; }
  .ui-skeleton-card .ui-skeleton-line { height: 72px; border-radius: var(--mide-radius); }
  .ui-skeleton-kpi { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
  .ui-skeleton-kpi .ui-skeleton-line, .ui-skeleton-kpi .ui-skeleton-line:last-child { width: 100%; height: 88px; border-radius: var(--mide-radius-lg); }
  @keyframes ui-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }

  /* ---------- charts ---------- */
  .ui-chart { display: grid; gap: var(--mide-space-3); margin: 0; min-width: 0; }
  .ui-chart-plot { position: relative; min-width: 0; }
  .ui-chart-svg { display: block; max-width: 100%; overflow: visible; }
  .ui-chart-grid { stroke: var(--mide-chart-grid); stroke-width: 1; }
  .ui-chart-axis { fill: var(--mide-chart-axis); font: var(--mide-weight-medium) 11px var(--mide-font); }
  .ui-chart-line { fill: none; stroke: var(--tone); stroke-width: 2.4; stroke-linejoin: round; stroke-linecap: round; }
  .ui-chart-area { fill: var(--tone); fill-opacity: .1; stroke: none; }
  .ui-chart-dot { fill: var(--mide-surface); stroke: var(--tone); stroke-width: 2; }
  .ui-chart-bar { fill: var(--tone); }
  .ui-legend { display: flex; flex-wrap: wrap; gap: 6px var(--mide-space-5); margin: 0; padding: 0; list-style: none; color: var(--mide-ink-2); font-size: var(--mide-text-sm); }
  .ui-legend-item { display: inline-flex; align-items: center; gap: 7px; }
  .ui-legend-item i { flex: 0 0 9px; width: 9px; height: 9px; border-radius: 50%; background: var(--tone); }
  .ui-legend-table { display: grid; gap: var(--mide-space-3); }
  .ui-legend-table .ui-legend-item { display: grid; grid-template-columns: 9px minmax(0, 1fr) auto auto; gap: var(--mide-space-2); }
  .ui-legend-table b { color: var(--mide-ink); font-variant-numeric: tabular-nums; }
  .ui-legend-table small { min-width: 3ch; color: var(--mide-muted); font-size: var(--mide-text-xs); text-align: right; font-variant-numeric: tabular-nums; }
  .ui-donut-block { display: flex; flex-wrap: wrap; align-items: center; gap: var(--mide-space-6); }
  /* The legend keeps its values next to their labels, also in a full-width card (review #6, N4). */
  .ui-donut-block > .ui-legend { flex: 1 1 140px; max-width: 360px; }
  .ui-donut-block { gap: var(--mide-space-5); }
  .ui-donut-track { stroke: var(--mide-line-2); }
  .ui-donut-segment { stroke: var(--tone); }
  .ui-donut-value { fill: var(--mide-heading); font: var(--mide-weight-heavy) var(--mide-text-2xl) var(--mide-font); }
  .ui-donut-label { fill: var(--mide-muted); font: var(--mide-weight-medium) var(--mide-text-xs) var(--mide-font); }
  .ui-progress-list { display: grid; gap: var(--mide-space-3); margin: 0; padding: 0; list-style: none; }
  .ui-progress-item { display: grid; grid-template-columns: minmax(0, 10rem) minmax(0, 1fr) auto; align-items: center; gap: var(--mide-space-3); font-size: var(--mide-text-sm); }
  .ui-progress-label { color: var(--mide-ink); overflow-wrap: anywhere; }
  .ui-progress-track { height: 10px; border-radius: var(--mide-radius-pill); background: var(--mide-line-2); overflow: hidden; }
  .ui-progress-bar { display: block; width: var(--ui-progress, 0%); height: 100%; border-radius: inherit; background: var(--tone); }
  .ui-progress-value { color: var(--mide-ink-2); font-variant-numeric: tabular-nums; }

  /* ---------- view templates (ui/templates.js) ---------- */
  .ui-template { display: grid; gap: var(--mide-space-6); min-width: 0; }
  .ui-template > .ui-page-header { margin: 0; }
  .ui-kpi-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr)); gap: var(--mide-space-4); }
  /* As many columns as KPIs (never 3 + 2 or 3 + 1) once there is room for them. */
  @media (min-width: 1101px) {
    .ui-kpi-row:has(> :nth-child(2):last-child) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .ui-kpi-row:has(> :nth-child(3):last-child) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .ui-kpi-row:has(> :nth-child(4):last-child) { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  }
  @media (min-width: 1280px) { .ui-kpi-row:has(> :nth-child(5):last-child) { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
  @media (min-width: 1280px) and (max-width: 1439px) { .ui-kpi-row:has(> :nth-child(5):last-child) .ui-kpi { gap: var(--mide-space-3); padding: var(--mide-space-4); } }
  /* Phones: compact 2 × 2 cards (an odd last card takes the whole row). Small icon beside the label,
     the figure and its caption below across the card; rows stay aligned (subgrid). */
  @media (max-width: 720px) {
    .ui-kpi-row { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--mide-space-3); }
    .ui-kpi-row > .ui-kpi:last-child:nth-child(odd) { grid-column: 1 / -1; }
    .ui-kpi { grid-template-columns: auto minmax(0, 1fr); gap: 2px var(--mide-space-2); padding: var(--mide-space-3); }
    .ui-kpi-tile { grid-row: 1; width: 28px; height: 28px; border-radius: var(--mide-radius-sm); align-self: center; }
    .ui-kpi-tile .ui-icon { width: 16px; height: 16px; }
    .ui-kpi-label { align-self: center; font-size: var(--mide-text-xs); }
    .ui-kpi-value { grid-column: 1 / -1; margin-top: 2px; font-size: var(--mide-text-xl); }
    .ui-kpi-label { padding-bottom: 0; }
    .ui-kpi-sub { grid-column: 1 / -1; min-height: calc(1.35 * var(--mide-text-xs)); }
    .ui-kpi-delta { display: flex; flex-wrap: wrap; gap: 0 6px; }
  }
  @media (min-width: 721px) and (max-width: 1100px) { .ui-kpi-row { grid-template-columns: repeat(2, minmax(0, 1fr)); } .ui-kpi-row:has(> :nth-child(3):last-child) { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
  /* Rows are sized by their content (no stretched empty cards). A column that needs more
     height stacks several cards (.ui-dashboard-stack) instead of leaving a gap. */
  .ui-dashboard-grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: var(--mide-space-5); align-items: start; }
  .ui-dashboard-stack { display: grid; align-content: start; gap: var(--mide-space-5); min-width: 0; }
  .ui-dashboard-pair { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: stretch; gap: var(--mide-space-5); min-width: 0; }
  .ui-dashboard-pair > .ui-card { height: 100%; }
  @media (max-width: 720px) { .ui-dashboard-pair { grid-template-columns: minmax(0, 1fr); } }
  .ui-dashboard-grid > * { grid-column: span 12; min-width: 0; }
  .ui-dashboard-grid > [data-span="4"] { grid-column: span 4; }
  .ui-dashboard-grid > [data-span="5"] { grid-column: span 5; }
  .ui-dashboard-grid > [data-span="6"] { grid-column: span 6; }
  .ui-dashboard-grid > [data-span="7"] { grid-column: span 7; }
  .ui-dashboard-grid > [data-span="8"] { grid-column: span 8; }
  @media (max-width: 1100px) { .ui-dashboard-grid > [data-span] { grid-column: span 12; } }
  .ui-list-inspector { display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: var(--mide-space-5); align-items: start; }
  .ui-list-inspector[data-inspector="closed"] { grid-template-columns: minmax(0, 1fr); }
  .ui-list-inspector[data-inspector="closed"] > .ui-inspector-host { display: none; }
  .ui-list-main { display: grid; gap: var(--mide-space-4); }
  @media (max-width: 1180px) { .ui-list-inspector { grid-template-columns: minmax(0, 1fr) 320px; } }
  @media (max-width: 900px) { .ui-list-inspector, .ui-list-inspector[data-inspector] { grid-template-columns: minmax(0, 1fr); } .ui-list-inspector > .ui-inspector-host { display: contents; } }
  .ui-tabs-form { display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: var(--mide-space-5); align-items: start; }
  .ui-tabs-form[data-aside="off"] { grid-template-columns: minmax(0, 1fr); }
  .ui-tabs-form[data-aside="off"] > .ui-tabs-form-aside { display: none; }
  @media (min-width: 1101px) { .ui-tabs-form-aside { position: sticky; top: calc(var(--mx-topbar-h, 72px) + var(--mide-space-3)); } }
  .ui-tabs-form-main, .ui-tabs-form-aside { display: grid; gap: var(--mide-space-5); min-width: 0; }
  /* Beside a rail the main column is narrower than the page: four KPIs go 2 × 2 below 1000 px
     of column, so no label breaks inside a word («Conversacion/es»). */
  .ui-tabs-form[data-aside="on"] > .ui-tabs-form-main { container: ui-main / inline-size; }
  /* …and from review #6 (N5) they stay in one row as compact cards (small icon beside the label,
     the figure below, as on phones): the 2 × 2 grid made the main column ~150 px taller. */
  @container ui-main (min-width: 600px) and (max-width: 999px) {
    .ui-kpi-row:has(> :nth-child(4):last-child) { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--mide-space-3); }
    .ui-kpi-row:has(> :nth-child(4):last-child) .ui-kpi { grid-template-columns: auto minmax(0, 1fr); gap: 2px var(--mide-space-2); padding: var(--mide-space-3) var(--mide-space-4); }
    .ui-kpi-row:has(> :nth-child(4):last-child) .ui-kpi-tile { grid-row: 1; width: 28px; height: 28px; border-radius: var(--mide-radius-sm); align-self: center; }
    .ui-kpi-row:has(> :nth-child(4):last-child) .ui-kpi-tile .ui-icon { width: 16px; height: 16px; }
    .ui-kpi-row:has(> :nth-child(4):last-child) .ui-kpi-label { align-self: center; }
    .ui-kpi-row:has(> :nth-child(4):last-child) :is(.ui-kpi-value, .ui-kpi-sub) { grid-column: 1 / -1; }
  }
  @container ui-main (max-width: 599px) {
    .ui-kpi-row:has(> :nth-child(4):last-child) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  }
  .ui-tabs-form-panel { display: grid; gap: var(--mide-space-5); min-width: 0; }
  .ui-form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--mide-space-4) var(--mide-space-5); }
  .ui-form-grid > .ui-span-2 { grid-column: 1 / -1; }
  @media (max-width: 1100px) { .ui-tabs-form { grid-template-columns: minmax(0, 1fr); } }
  @media (max-width: 640px) { .ui-form-grid { grid-template-columns: minmax(0, 1fr); } }

  /* ---------- shell additions owned by the ui/ layer ---------- */
  .mx-sidebar nav .nav-lock { display: inline-grid; flex: 0 0 auto; margin-left: auto; color: var(--mx-side-ink-3); }
  .mx-sidebar nav .nav-lock .mide-icon { width: 14px; height: 14px; }
  .mx-sidebar nav button.is-locked:not(.nav-active):not(.active) .nav-label { color: var(--mx-side-ink-2); }
  .mx-sidebar nav button.is-locked:is(.nav-active, .active) .nav-label, .mx-sidebar nav button.is-locked:is(.nav-active, .active) .nav-lock { color: var(--mx-side-ink); }
  /* Portal Cliente footer (UX pase 3): ONE quiet line — the environment chip (outside production
     only, in words, opens the version details) and the operational state. The company is named at
     the top of the sidebar, so the footer never repeats it (layout in client-shell.css). */
  :where(.mx-shell:not(.provider-shell)) .mx-side-foot { display: flex; flex-wrap: wrap; align-items: center; gap: var(--mide-space-2); margin-top: var(--mide-space-2); padding: var(--mide-space-3) var(--mide-space-2) 0; border: 0; border-top: 1px solid var(--mx-side-line); border-radius: 0; background: transparent; }
  :where(.mx-shell:not(.provider-shell)) .mx-side-foot > .mx-company { border: 0; border-radius: 0; background: transparent; padding: 0; }
  :where(.mx-shell:not(.provider-shell)) .mx-side-foot > .mx-env { order: -1; flex: 0 0 auto; width: auto; min-height: 24px; padding: 0 var(--mide-space-3) 0 var(--mide-space-2); gap: 6px; border: 1px solid color-mix(in srgb, var(--mide-amber) 55%, transparent); border-radius: var(--mide-radius-pill); background: color-mix(in srgb, var(--mide-amber) 14%, transparent); }
  :where(.mx-shell:not(.provider-shell)) .mx-side-foot > .mx-env:hover { background: color-mix(in srgb, var(--mide-amber) 24%, transparent); }
  /* One block, as in the reference: the company and its environment. The account (profile and
     sign-out) lives in the top bar (#clientUserButton opens the same menu), so it is not repeated here.
     Portal Cliente only: the Centro de Operaciones (.provider-shell) keeps its own sidebar footer. */
  :where(.mx-shell:not(.provider-shell)) .mx-side-foot > .mx-profile { display: none; }
  .mx-env-text { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  /* ---------- sidebar badge (MIDE_VIEWS.register({ badge })) ---------- */
  .mx-sidebar nav .nav-badge { margin-left: auto; padding: 1px 8px; border-radius: var(--mide-radius-pill); background: var(--mide-info-bg); color: var(--mide-info); font: var(--mide-weight-bold) 11px/1.6 var(--mide-font); flex: 0 0 auto; } /* same tone and word as the «Pronto» chip */
  .mx-sidebar nav .nav-section-label[hidden] { display: none; }

  /* Any ui-* element with the hidden attribute stays hidden, whatever display it declares. */
  :is([class^="ui-"], [class*=" ui-"])[hidden] { display: none; }

  @media (prefers-reduced-motion: reduce) {
    .ui-skeleton-line { animation: none; }
    .ui-switch, .ui-switch::before, .ui-switch-thumb, .ui-button { transition: none; }
  }

  /* ---------- tenant brand zone (docs/design/TENANT_BRANDING.md) ----------
     Only inside [data-brand-zone="tenant"]: client documents such as OH SUNNY! quotes.
     Typography, spacing, radii and states stay MIDE; only the brand colours change. */
  [data-brand-zone="tenant"] { --mide-accent: var(--tenant-brand-primary); --mide-accent-gradient: none; --mide-on-accent: var(--tenant-brand-on-primary); }
  [data-brand-zone="tenant"] :is(.ui-button-primary, .primary-button),
  [data-brand-zone="tenant"] :is(.ui-button-primary, .primary-button):hover:not(:disabled) { background: var(--tenant-brand-primary); background-image: none; border-color: transparent; color: var(--tenant-brand-on-primary); }
  [data-brand-zone="tenant"] :is(.ui-button-primary, .primary-button):hover:not(:disabled) { filter: brightness(.92); }
  [data-brand-zone="tenant"] .ui-brand-zone-bar { height: 6px; border-radius: var(--mide-radius-pill); background: var(--tenant-brand-primary); }
  [data-brand-zone="tenant"] .ui-brand-zone-title { color: var(--tenant-brand-ink); letter-spacing: var(--mide-tracking-heading); }

  /* ---------- tenant theme of the Portal Cliente (ui/tenant-theme.js, docs/design/TENANT_BRANDING.md) ----------
     Active only when <html data-tenant-theme> is set on my.mide.lat. The legacy shell paints some
     sidebar text in white; under a tenant theme every sidebar colour follows --mx-side-* so light
     and dark navigation schemes both keep WCAG AA. */
  html[data-tenant-theme] .mx-sidebar :is(.mx-brand strong, .mx-env strong, .mx-profile-text strong, .mx-company-text strong) { color: var(--mx-side-ink); }
  html[data-tenant-theme] .mx-sidebar :is(nav button:hover:not(:disabled), .mx-collapse:hover) { color: var(--mx-side-ink); }
  html[data-tenant-theme] .mx-sidebar nav button:is(.active, .nav-active), html[data-tenant-theme] .mx-sidebar nav button:is(.active, .nav-active):hover:not(:disabled) { background: var(--tenant-nav-active-bg); color: var(--tenant-nav-active-ink); box-shadow: inset 3px 0 0 var(--tenant-nav-active-bar); }
  html[data-tenant-theme] .mx-sidebar :is(.mx-profile:hover, .mx-profile[aria-expanded="true"]) { background: var(--mx-side-hover); }
  html[data-tenant-theme] .mx-sidebar nav button .nav-count { background: var(--mx-side-hover); color: var(--mx-side-ink); }
  html[data-tenant-theme] .mx-sidebar :is(nav button, .mx-profile, .mx-env, .mx-collapse):focus-visible { outline-color: var(--mx-side-ink); }
  html[data-tenant-theme] .mx-company-mark { background: var(--mide-accent); color: var(--mide-on-accent); }
  .tenant-logo { display: block; flex: 0 0 auto; width: auto; height: 36px; max-width: 150px; object-fit: contain; }
  .mide-topbar-brand > .tenant-logo, .login-brand > .tenant-logo { height: 40px; max-width: 180px; }
  .tenant-monogram { display: inline-grid; place-items: center; flex: 0 0 36px; width: 36px; height: 36px; border-radius: var(--mide-radius-sm); background: var(--mide-accent); color: var(--mide-on-accent); font: var(--mide-weight-bold) var(--mide-text-sm)/1 var(--mide-font); letter-spacing: .02em; }
  /* The tenant logo already carries the company name: the brand copy stays for assistive tech
     only, and the logo gets the whole row next to the collapse button. */
  html[data-tenant-theme] .mx-brand:has(> .tenant-logo) .brand-copy { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .mx-brand > .tenant-logo { max-width: min(168px, 100%); }
  /* Long company names never run under the collapse button. */
  html[data-tenant-theme] .mx-brand .brand-copy { min-width: 0; }
  html[data-tenant-theme] .mx-brand .brand-copy strong { display: block; overflow: hidden; text-overflow: ellipsis; font-size: var(--mide-text-lg); letter-spacing: 0; }
  .is-collapsed .mx-brand > .tenant-logo { width: 40px; height: 40px; object-fit: cover; object-position: left center; }
  /* Issue 1198 visual review: the company in the phone top bar, like the sidebar brand row at 1440 (mark + name). Without a
     company (before sign-in) the MIDE logo stays alone; with a tenant logo the logo carries the name (as in the sidebar). */
  .mide-topbar-brand > .mide-topbar-mark, .mide-topbar-brand > .mide-topbar-company { display: none; }
  .mide-topbar-brand[data-company] { min-width: 0; gap: 8px; }
  .mide-topbar-brand[data-company] > img.mide-logo { display: none; }
  .mide-topbar-brand[data-company] > .mide-topbar-mark { display: block; flex: 0 0 auto; width: 32px; height: 32px; }
  .mide-topbar-brand[data-company]:has(> [data-tenant-slot]) > .mide-topbar-mark { display: none; }
  .mide-topbar-brand[data-company] > .mide-topbar-company { display: block; min-width: 0; max-width: 150px; }
  .mide-topbar-brand[data-company]:has(> .tenant-logo) > .mide-topbar-company { display: none; }
  .mx-topbar .mide-topbar-brand[data-company] > .mide-topbar-company strong { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 15px; font-weight: 700; line-height: 1.2; color: var(--mide-ink-900); }
  .mide-topbar-brand > .tenant-monogram { flex: 0 0 32px; width: 32px; height: 32px; }
}

/* ---------------------------------------------------------------------------------------------
   Acceso (login): UNA sola experiencia para os.mide.lat y my.mide.lat. Pantalla completa sobre
   ciruela, por encima de todo el shell (nunca deja ver la navegación detrás), tarjeta clara con
   tipografía legible y acción primaria en gradiente. En my.mide.lat el tema del tenant cambia el
   logo y el color de acción; el fondo sigue siendo el de la marca del tenant o el de MIDE.
   --------------------------------------------------------------------------------------------- */
@layer components {
  .login-overlay {
    position: fixed; inset: 0; z-index: 1000;
    display: grid; place-items: center; padding: var(--mide-space-6);
    background-color: var(--mide-plum-900);
    background-image:
      radial-gradient(60rem 40rem at 12% -10%, color-mix(in srgb, var(--mide-violet-600) 34%, transparent), transparent 62%),
      radial-gradient(48rem 36rem at 110% 115%, color-mix(in srgb, var(--mide-blue-brand) 26%, transparent), transparent 60%),
      linear-gradient(160deg, var(--mide-navy-800), var(--mide-plum-900) 55%, var(--mide-navy-950));
    overflow-y: auto;
  }
  .login-overlay.hidden { display: none; }
  /* Signed out (ui/session-restore.js sets html[data-login="open"] and makes the shell inert): the login is the
     whole document, ciruela edge to edge at any height, and nothing of the shell is laid out, scrolled or focused. */
  .login-overlay { min-height: 100dvh; }
  html[data-login="open"], html[data-login="open"] body { overflow: hidden; background-color: var(--mide-plum-900); }
  html[data-login="open"] body > :not(.login-overlay) { display: none; }
  .login-card {
    width: min(440px, 100%); padding: 40px 40px 32px;
    background: var(--mide-white); border: 0; border-radius: var(--mide-radius-lg);
    box-shadow: 0 32px 90px -20px color-mix(in srgb, var(--mide-navy-950) 80%, transparent);
  }
  .login-brand { display: flex; align-items: center; gap: var(--mide-space-3); margin-bottom: var(--mide-space-8); }
  .login-brand > div:last-child { display: flex; flex-direction: column; padding-left: var(--mide-space-3); border-left: 1px solid var(--mide-line); }
  /* Three weights on the login card (#1133, QA): 800 the title; 600 eyebrow, brand name, field labels, the session
     label and buttons; 500 everything else (brand line, subtitle, fields, hint, footnote, messages). Hierarchy:
     title > subtitle (14 px · 500 · ink-2) > labels (600) > small print (13 px · 500). */
  .login-brand strong { font-weight: 600; }
  .login-brand span { font-size: var(--mide-text-sm); font-weight: 500; color: var(--mide-muted); }
  .login-copy .eyebrow { font-size: var(--mide-text-xs); letter-spacing: .12em; text-transform: uppercase; font-weight: 600; color: var(--mide-violet-700); margin: 0; }
  .login-copy h2 { font-size: 30px; line-height: 1.15; letter-spacing: -.02em; font-weight: 800; color: var(--mide-ink-900); margin: var(--mide-space-2) 0 var(--mide-space-2); }
  .login-copy > p:last-child { font-size: var(--mide-text-md); font-weight: 500; line-height: 1.5; color: var(--mide-ink-2); margin: 0 0 var(--mide-space-6); text-wrap: balance; }
  .login-copy h2, .login-error { text-wrap: balance; }
  .login-card form { display: flex; flex-direction: column; gap: var(--mide-space-4); margin: 0; }
  .login-card label { display: flex; flex-direction: column; gap: var(--mide-space-2); font-size: var(--mide-text-sm); font-weight: 600; color: var(--mide-ink-2); }
  .login-card button { font-weight: 600; }
  .login-card input:not([type="checkbox"]) {
    width: 100%; min-height: 48px; padding: 0 var(--mide-space-4);
    font: inherit; font-size: var(--mide-text-md); font-weight: 500; color: var(--mide-ink-900);
    background: var(--mide-white); border: 1px solid var(--mide-line-strong); border-radius: var(--mide-radius-sm); outline: none;
    transition: border-color var(--mide-duration), box-shadow var(--mide-duration);
  }
  .login-card input:not([type="checkbox"]):focus-visible { border-color: var(--mide-focus-ring); box-shadow: var(--mide-focus); }
  /* «Mantener mi sesión» and its hint are ONE label: a single touch target of at least 44 px (#1133). */
  .login-card .login-remember { flex-direction: row; align-items: flex-start; gap: var(--mide-space-2); min-height: 44px; font-size: var(--mide-text-md); font-weight: 600; line-height: 1.4; color: var(--mide-ink-2); cursor: pointer; }
  .login-card .login-remember input { flex: 0 0 auto; width: 18px; height: 18px; margin: 0; accent-color: var(--mide-violet-600); }
  .login-card .login-remember-text { display: flex; flex-direction: column; gap: 2px; }
  /* Small print of the login (session hint and footnote): 13 px, 500 (the label's weight, no new weight) and the
     darkest neutral token, --mide-ink-2 (ink with gray, ≥ 10:1 on white): --mide-muted read too light at 13 px. */
  .login-card .login-remember-hint { display: block; font-size: var(--mide-text-sm); font-weight: 500; line-height: 1.4; color: var(--mide-ink-2); text-wrap: balance; }
  .login-card .login-recovery { min-height: 44px; }
  .login-card form[hidden], .login-unavailable[hidden] { display: none; }
  /* No configuration (the Client Portal could not prepare the secure access): the card says it and offers «Reintentar». */
  .login-unavailable { display: flex; flex-direction: column; gap: var(--mide-space-4); }
  .login-unavailable .ui-notice { align-items: flex-start; }
  .login-unavailable-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; font-size: var(--mide-text-sm); line-height: 1.4; color: var(--mide-ink); text-wrap: pretty; }
  .login-unavailable-body strong { font-weight: 600; }
  .login-unavailable-body span { font-weight: 500; color: var(--mide-ink-2); }
  .login-error { min-height: 0; margin: 0; font-size: var(--mide-text-sm); font-weight: 500; line-height: 1.4; color: var(--mide-danger); }
  .login-error:empty { display: none; }
  .login-submit { width: 100%; min-height: 48px; margin-top: var(--mide-space-2); font-size: var(--mide-text-md); }
  /* «Entrar» while it waits (#1133): never faded. A solid dark violet of the tokens (white text ≥ 4.5:1), a spinner,
     aria-busy and aria-disabled (not `disabled`, so the focus stays on the button with a visible ring). */
  .login-card .login-submit[aria-busy="true"] {
    display: inline-flex; align-items: center; justify-content: center; gap: var(--mide-space-2);
    opacity: 1; filter: none; cursor: progress;
    background: var(--mide-violet-700); background-image: none; border-color: var(--mide-violet-700); color: var(--mide-white);
  }
  .login-card .login-submit[aria-busy="true"]::before {
    content: ""; flex: 0 0 auto; width: 16px; height: 16px; border-radius: 50%;
    border: 2px solid color-mix(in srgb, var(--mide-white) 40%, transparent); border-top-color: var(--mide-white);
    animation: mx-login-spin .8s linear infinite;
  }
  /* One ring, 2 px, 2 px away from the button (focus token colour), for mouse and keyboard alike: the focus stays here. */
  .login-card .login-submit[aria-busy="true"]:focus { outline: 2px solid var(--mide-focus-ring); outline-offset: 2px; box-shadow: none; }
  @media (prefers-reduced-motion: reduce) { .login-card .login-submit[aria-busy="true"]::before { animation-duration: 2.4s; } }
  .login-footnote { display: block; margin-top: var(--mide-space-6); text-align: center; font-size: var(--mide-text-sm); font-weight: 500; line-height: 1.4; color: var(--mide-ink-2); }
  @keyframes mx-login-spin { to { transform: rotate(360deg); } }
  @media (max-width: 560px) {
    .login-overlay { padding: var(--mide-space-4); align-items: start; padding-top: 12vh; }
    .login-card { padding: 28px 22px 24px; }
    .login-copy h2 { font-size: 26px; }
  }

  /* «Restaurando sesión» (H0.1, X-02; ui/session-restore.js). With a stored session the load starts
     in <html data-auth="restoring">: the login and the views stay hidden and the shell shows one
     neutral, announced loading state, never the signed-out copy. The login comes back as soon as
     the restore settles without a valid session. Layered here (above legacy and base) with enough
     specificity to win over every view's own display rule; a view sheet must not override it. */
  .mx-session-restoring { display: none; }
  html[data-auth="restoring"] .mx-session-restoring { display: grid; gap: var(--mide-space-5); align-content: start; }
  html[data-auth="restoring"] .mx-content > :not(.mx-session-restoring) { display: none; }
  html[data-auth="restoring"] .login-overlay { display: none; }
  /* C1 (#1162): before the session is verified, nothing says "someone is signed in": no account,
     presence, environment, role navigation or top actions. Logo and skeletons only. */
  html[data-auth="restoring"] .mx-sidebar nav,
  html[data-auth="restoring"] .mx-side-foot,
  html[data-auth="restoring"] .mx-topbar { display: none; }
  html[data-auth="restoring"] .mx-session-restoring { padding-top: var(--mide-space-6, 24px); }
  .mx-session-restoring-logo { display: none; height: 32px; width: auto; }
  @media (max-width: 720px) { .mx-session-restoring-logo { display: block; } }
  .mx-session-restoring-label { margin: 0; font-size: var(--mide-text-md); font-weight: var(--mide-weight-semibold); color: var(--mide-ink-2); }
}

/* ---------------------------------------------------------------------------------------------
   «Continuar con Google» (ADR 005 PR 5, ui/google-sign-in.js). Solo existe si runtime-config
   anuncia identity.google. El botón es el OFICIAL de Google (iframe de GIS): aquí solo se
   acomoda su contenedor; nunca se reestiliza. Divisor «o», mensajes con código (role=alert,
   el texto basta sin el color) y «Seguridad › Vincular Google». Solo tokens.
   --------------------------------------------------------------------------------------------- */
@layer components {
  .mx-google-auth { display: flex; flex-direction: column; gap: var(--mide-space-4); margin-top: var(--mide-space-5); }
  .mx-google-auth[hidden] { display: none; }
  .mx-auth-divider { display: flex; align-items: center; gap: var(--mide-space-3); font-size: var(--mide-text-md); font-weight: var(--mide-weight-semibold); line-height: 1; color: var(--mide-ink-2); }
  .mx-auth-divider::before, .mx-auth-divider::after { content: ""; flex: 1 1 auto; height: 1px; background: var(--mide-line-strong); }
  .mx-google-button { display: flex; justify-content: center; width: 100%; min-width: 0; max-width: 100%; min-height: 44px; }

  /* Notice: the shared tone system (--tone / --tone-bg from [data-tone] on ui-*), icon + text + secondary code. */
  .ui-notice { display: flex; align-items: flex-start; gap: var(--mide-space-3); margin: 0; padding: var(--mide-space-3) var(--mide-space-4); border: 1px solid color-mix(in srgb, var(--tone, var(--mide-info)) 30%, transparent); border-radius: var(--mide-radius-sm); background: var(--tone-bg, var(--mide-info-bg)); color: var(--mide-ink); font-size: var(--mide-text-sm); line-height: var(--mide-leading); text-align: left; }
  .ui-notice[hidden] { display: none; }
  /* A notice that receives focus programmatically (tabindex -1) shows a ring only for keyboard focus, and a light one. */
  .ui-notice:focus { outline: none; }
  .ui-notice:focus-visible { outline: 1px solid color-mix(in srgb, var(--mide-focus-ring) 55%, transparent); outline-offset: 2px; }
  .ui-notice .mx-google-alert-icon { flex: 0 0 18px; width: 18px; height: 18px; margin-top: 1px; color: var(--tone, var(--mide-info)); }
  .ui-notice .mx-google-alert-icon svg { width: 18px; height: 18px; }
  .mx-google-alert-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; text-wrap: pretty; }
  .mx-google-alert-text { color: var(--mide-ink); }
  /* Reference code: secondary (smaller, muted) but still AA on every tone background (--mide-ink-2 ≥ 7:1). */
  .mx-google-alert-code { font-size: var(--mide-text-xs); font-weight: var(--mide-weight-semibold); color: var(--mide-ink-2); letter-spacing: .01em; }

  /* «Olvidé mi contraseña» becomes a text link ONLY while Google is on (ui/google-sign-in.js marks the card), so the
     card keeps one pill (primary) + Google's official button. With Google off the login stays exactly as before.
     Colour is --mide-link in every state (hover/focus change the underline or ring, never the colour). */
  .login-card[data-google-sign-in="on"] .login-recovery { display: inline-flex; align-items: center; align-self: center; width: auto; min-width: 0; height: auto; min-height: 44px; margin: calc(-1 * var(--mide-space-1)) 0 0; padding: var(--mide-space-1) var(--mide-space-2); border: 0; border-radius: var(--mide-radius-sm); background: none; box-shadow: none; font: inherit; font-size: var(--mide-text-sm); font-weight: var(--mide-weight-semibold); line-height: 1.4; color: var(--mide-link); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; cursor: pointer; filter: none; }
  .login-card[data-google-sign-in="on"] .login-recovery:hover:not(:disabled) { background: none; color: var(--mide-link); text-decoration-thickness: 2px; filter: none; }
  .login-card[data-google-sign-in="on"] .login-recovery:focus-visible { outline: none; color: var(--mide-link); box-shadow: var(--mide-focus); }
  .login-card[data-google-sign-in="on"] .login-recovery:disabled { color: var(--mide-muted); cursor: progress; }

  .mx-google-link { display: flex; flex-direction: column; gap: var(--mide-space-4); }
  .mx-google-link-status { display: flex; flex-wrap: wrap; align-items: center; gap: var(--mide-space-2); margin: 0; font-size: var(--mide-text-sm); color: var(--mide-ink-2); }
  .mx-google-link-body { display: flex; flex-direction: column; align-items: flex-start; gap: var(--mide-space-3); }
  .mx-google-link-body > .mx-google-button { justify-content: flex-start; max-width: 400px; }
  .mx-google-link-hint, .mx-google-confirm-text { margin: 0; font-size: var(--mide-text-sm); line-height: var(--mide-leading); color: var(--mide-ink-2); }
  .mx-google-confirm { display: flex; flex-direction: column; gap: var(--mide-space-3); width: 100%; padding: var(--mide-space-4); border: 1px solid var(--mide-line); border-radius: var(--mide-radius-sm); background: var(--mide-surface-2); }
  .mx-google-actions { display: flex; flex-wrap: wrap; gap: var(--mide-space-2); }
  /* Configuración on phones. Portal Cliente: the section tabs wrap, so no tab is clipped. Centro de Operaciones: one
     row in the desktop order that scrolls sideways with snap; the selected tab is scrolled into view (provider-team-view.js). */
  @media (max-width: 560px) {
    .settings-view .ui-tabs { flex-wrap: wrap; overflow-x: visible; column-gap: var(--mide-space-4); row-gap: 0; padding-inline: 0; }
    #providerSettings .mide-detail-tabs { flex-wrap: nowrap; overflow-x: auto; scroll-snap-type: x proximity; scroll-padding-inline: var(--mide-space-4); }
    #providerSettings .mide-detail-tabs > button { scroll-snap-align: start; }
  }
  .mx-google-reauth { display: flex; flex-direction: column; gap: var(--mide-space-4); width: min(400px, 100%); }
}

/* ---------------------------------------------------------------------------------------------
   Touch targets (issue 1133 Fase 1, WCAG 2.5.5 / 2.5.8). Phones (≤ 640 px) and coarse pointers:
   every button, input, select, textarea, tab, switch, chip action and file button is at least
   44 × 44 px (a switch keeps its 44 × 24 track; its hit area is the 44 px button around it).
   Two levels:
   - `components`: any control inside the portals (generic elements and legacy markup) gets the
     minimum; a view may still make one LARGER (a conversation row, a shortcut card).
   - `controls` (last layer, ui/tokens.css): the shared control classes keep 44 px whatever a
     legacy or view sheet says, so no module can shrink them again.
   Desktop keeps its density (≥ 32 px).
   --------------------------------------------------------------------------------------------- */
@layer components {
  /* Focus and scroll never leave a control under the sticky top bar. */
  html { scroll-padding-top: calc(var(--ui-topbar-h, var(--mx-topbar-h, 72px)) + var(--mide-space-3)); }
  @media (max-width: 640px), (pointer: coarse) {
    :where(.mx-content, .mx-topbar, dialog, .ui-inspector, .mx-workspace) :where(
      button, [role="button"], [role="tab"], select, textarea, a.ui-button, summary,
      input:not([type="checkbox"], [type="radio"], [type="hidden"], [type="range"], [type="file"], [type="color"])
    ) { min-height: 44px; }
    /* Radios and checkboxes are hit through their label row. */
    :where(.mx-content, dialog, .ui-inspector, .mx-workspace) :where(label:has(> input:is([type="radio"], [type="checkbox"]))) { min-height: 44px; }
    .ui-textarea { min-height: 44px; }
    .ui-select-menu-option { min-height: 44px; }
  }
}

@layer controls {
  @media (max-width: 640px), (pointer: coarse) {
    :is(.ui-button, .ui-button-sm, .ui-input, .ui-select, .ui-select-menu-trigger, .ui-select-menu-sm .ui-select-menu-trigger, .ui-tab, .ui-pager-button,
        .primary-button, .secondary-button, .ghost-button, .danger-button, .mide-icon-button, .mx-nav-toggle) { min-height: 44px; }
    /* Width: only controls that can be narrower than 44 px get a minimum (a min-width on a text button would let a
       flex row shrink it below its label). Text buttons are wider than 44 px by their label and padding. */
    :is(.ui-pager-button) { min-width: 44px; }
    .ui-tab { min-width: 44px; flex-shrink: 0; }
    /* Actions that show only their icon on phones (the label stays for assistive technology). */
    .conv-chat-actions .ui-button { min-width: 44px; }
    /* Fixed-size icon buttons grow to the target (their icon stays centred). */
    :is(.ui-button-icon, .ui-button-icon.ui-button-sm, .mide-icon-button, .mx-nav-toggle) { width: 44px; height: 44px; flex-basis: 44px; }
    .ui-pager-button { height: 44px; }
    .ui-tab { padding-block: var(--mide-space-2); }
    .ui-switch { height: 44px; }
    /* Topbar presence selector: the whole pill is the 44 px target. */
    .mx-topbar .agent-presence-control { min-height: 44px; padding-block: 0; }
    .mx-topbar .agent-presence-select { min-height: 44px; }
  }
}
@layer controls {
  /* Desktop: the presence selector in the top bar is a 32 px target (it measured 20 px). */
  @media (min-width: 641px) and (pointer: fine) {
    .mx-topbar .agent-presence-control { padding-block: 0; }
    .mx-topbar .agent-presence-select { min-height: 32px; }
  }
}
@layer controls {
  /* Disabled actions (issue 1133 Fase 2): a neutral fill with muted ink (≥ 4.5:1 on niebla) instead of a 55 % faded
     colour, so «Importando…» or a primary waiting for a valid value stays legible, with or without a tenant theme.
     The disabled reason (button({ disabledReason })) keeps saying why. */
  :is(.ui-button-primary, .ui-button-danger):disabled,
  [data-brand-zone="tenant"] .ui-button-primary:disabled { opacity: 1; background: var(--mide-surface-2); background-image: none; border-color: var(--mide-line); color: var(--mide-muted); filter: none; }
  :is(.ui-button-secondary, .ui-button-ghost):disabled { opacity: 1; color: var(--mide-muted); }
}
