/* ============================================================
   Panel Tires Import — sistema de diseño
   Marca: negro #1D1D1B, amarillo #FFC71B, gris #757570, Poppins.
   ============================================================ */

/* --- Fuente de marca (auto-hosteada, sin CDN) --- */
@font-face {
  font-family: "Poppins"; font-style: normal; font-weight: 400; font-display: swap;
  src: url("fonts/poppins-400.woff2") format("woff2");
}
@font-face {
  font-family: "Poppins"; font-style: normal; font-weight: 500; font-display: swap;
  src: url("fonts/poppins-500.woff2") format("woff2");
}
@font-face {
  font-family: "Poppins"; font-style: normal; font-weight: 600; font-display: swap;
  src: url("fonts/poppins-600.woff2") format("woff2");
}

/* --- Tokens de tema --- */
:root {
  --bg: #f7f7f5;
  --surface: #ffffff;
  --surface-2: #f1f1ed;
  --surface-hover: #f6f6f2;
  --text: #1d1d1b;
  --muted: #757570;
  --border: #e8e8e4;
  --border-strong: #d9d9d3;

  --accent: #ffc71b;
  --accent-hover: #f0b800;
  --on-accent: #1d1d1b;

  --ok-bg: #e7f5ec;   --ok-fg: #1b7a43;
  --warn-bg: #fdf1df; --warn-fg: #9a6100;
  --bad-bg: #fbeae8;  --bad-fg: #b4271b;

  --shadow-sm: 0 1px 2px rgba(29, 29, 27, .06);
  --shadow-md: 0 4px 14px rgba(29, 29, 27, .08);
  --shadow-lg: 0 12px 32px rgba(29, 29, 27, .14);

  --radius: 14px;
  --radius-sm: 10px;
  --radius-pill: 999px;

  --sidebar-w: 240px;
  --ease: cubic-bezier(.22, .61, .36, 1);
  color-scheme: light;
}

[data-theme="dark"] {
  --bg: #141413;
  --surface: #1d1d1b;
  --surface-2: #262624;
  --surface-hover: #2b2b28;
  --text: #f4f4f2;
  --muted: #a3a39e;
  --border: #333330;
  --border-strong: #403f3b;

  --accent: #ffc71b;
  --accent-hover: #ffd24a;
  --on-accent: #1d1d1b;

  --ok-bg: #16301f;   --ok-fg: #59d98a;
  --warn-bg: #33280f; --warn-fg: #f5c451;
  --bad-bg: #331c1a;  --bad-fg: #f2857a;

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .3);
  --shadow-md: 0 4px 14px rgba(0, 0, 0, .38);
  --shadow-lg: 0 14px 36px rgba(0, 0, 0, .5);
  color-scheme: dark;
}

/* --- Reset / base --- */
* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  font-family: "Poppins", system-ui, "Segoe UI", Roboto, sans-serif;
  font-size: 14px;
  line-height: 1.5;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  transition: background-color .25s var(--ease), color .25s var(--ease);
}
h1, h2, h3, h4, p { margin: 0; }
button { font-family: inherit; }
::selection { background: var(--accent); color: var(--on-accent); }

/* Scrollbars finas y de marca */
* { scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }
*::-webkit-scrollbar { width: 9px; height: 9px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
  background: var(--border-strong); border-radius: var(--radius-pill);
  border: 2px solid transparent; background-clip: padding-box;
}
*::-webkit-scrollbar-thumb:hover { background: var(--muted); background-clip: padding-box; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 6px;
}

/* ============================================================
   Login
   ============================================================ */
.login {
  position: fixed; inset: 0; display: grid; place-items: center;
  padding: 24px; background: var(--bg); z-index: 50;
}
.login-card {
  width: 100%; max-width: 360px; text-align: center;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 40px 32px; box-shadow: var(--shadow-md);
  animation: rise .5s var(--ease);
}
.login-card .brand-logo { width: 72px; height: 72px; margin: 0 auto 20px; }
.login-card h1 { font-size: 19px; font-weight: 600; }
.login-card p { color: var(--muted); font-size: 13px; margin-top: 6px; margin-bottom: 24px; }
.login-card .field { text-align: left; }
.login-error { color: var(--bad-fg); font-size: 13px; min-height: 18px; margin-top: 12px; }

/* ============================================================
   Shell: sidebar + contenido
   ============================================================ */
.shell { display: flex; min-height: 100vh; }

.sidebar {
  width: var(--sidebar-w); flex-shrink: 0;
  background: var(--surface); border-right: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 8px;
  padding: 20px 14px; position: sticky; top: 0; height: 100vh;
  transition: transform .3s var(--ease);
}
.sidebar-brand {
  display: flex; align-items: center; gap: 12px;
  padding: 4px 8px 18px; margin-bottom: 4px;
}
.sidebar-brand img { width: 40px; height: 40px; border-radius: 9px; }
[data-theme="dark"] .sidebar-brand img,
[data-theme="dark"] .login-card .brand-logo {
  background: #fff; padding: 4px;
}
.sidebar-brand .name { font-weight: 600; font-size: 15px; letter-spacing: .2px; }
.sidebar-brand .sub { font-size: 11px; color: var(--muted); }

.nav { display: flex; flex-direction: column; gap: 3px; flex: 1; }
.nav-item {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 10px 12px; border: none; border-radius: var(--radius-sm);
  background: transparent; color: var(--muted); cursor: pointer;
  font-size: 14px; font-weight: 500; text-align: left;
  transition: background-color .15s var(--ease), color .15s var(--ease);
}
.nav-item svg { width: 19px; height: 19px; flex-shrink: 0; }
.nav-item:hover { background: var(--surface-hover); color: var(--text); }
.nav-item.active { background: var(--accent); color: var(--on-accent); }
.nav-item .badge {
  margin-left: auto; background: var(--bad-fg); color: #fff;
  font-size: 11px; font-weight: 600; min-width: 18px; height: 18px;
  border-radius: var(--radius-pill); display: grid; place-items: center; padding: 0 5px;
}
.nav-item.active .badge { background: var(--on-accent); color: var(--accent); }

.sidebar-footer { display: flex; flex-direction: column; gap: 3px; border-top: 1px solid var(--border); padding-top: 10px; }

.content { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.topbar {
  display: flex; align-items: center; gap: 16px;
  padding: 16px 28px; border-bottom: 1px solid var(--border);
  background: color-mix(in srgb, var(--bg) 80%, transparent);
  backdrop-filter: blur(8px);
  position: sticky; top: 0; z-index: 20;
}
.topbar h2 { font-size: 18px; font-weight: 600; }
.topbar .spacer { flex: 1; }
/* Los dos indicadores viven juntos en un grupo: en desktop van a la derecha; en
   móvil el grupo baja completo a su propia fila (ver media query ≤640px). */
.topbar-status { display: inline-flex; align-items: center; gap: 10px; }
.hamburger {
  display: none; background: transparent; border: 1px solid var(--border);
  border-radius: var(--radius-sm); width: 38px; height: 38px; cursor: pointer;
  color: var(--text); align-items: center; justify-content: center;
}
.hamburger svg { width: 20px; height: 20px; }

/* `margin-inline: auto`: sin él, en un monitor ancho todo el panel quedaba
   pegado al borde izquierdo con un vacío enorme a la derecha. */
.view-wrap { padding: 24px 28px 48px; max-width: 1400px; width: 100%; margin-inline: auto; }
.view { animation: rise .35s var(--ease); }
.view[hidden] { display: none; }

/* ============================================================
   Indicadores de estado (pills)
   ============================================================ */
.pill {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 5px 12px; border-radius: var(--radius-pill);
  font-size: 12px; font-weight: 600; white-space: nowrap;
}
.pill .dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.pill.ok  { background: var(--ok-bg);  color: var(--ok-fg); }
.pill.ok .dot  { background: var(--ok-fg); }
.pill.warn { background: var(--warn-bg); color: var(--warn-fg); }
.pill.warn .dot { background: var(--warn-fg); }
.pill.bad { background: var(--bad-bg); color: var(--bad-fg); }
.pill.bad .dot { background: var(--bad-fg); }
/* Amarillo de marca: reservado para la derivación manual a un ejecutivo
   (--accent/--on-accent ya están definidos en claro y oscuro). */
.pill.accent { background: var(--accent); color: var(--on-accent); }
.pill.accent .dot { background: var(--on-accent); }
.pill .dot.live { animation: pulse 2s infinite; }

/* ============================================================
   Cards y grillas
   ============================================================ */
.kpi-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 16px; margin-bottom: 28px;
}
.card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 18px 20px; box-shadow: var(--shadow-sm);
}
.kpi { position: relative; }
.kpi .kpi-label { color: var(--muted); font-size: 13px; display: flex; align-items: center; gap: 8px; }
.kpi .kpi-label svg { width: 16px; height: 16px; opacity: .7; }
.kpi .kpi-value { font-size: 30px; font-weight: 600; margin-top: 8px; line-height: 1.1; letter-spacing: -.5px; }
.kpi .kpi-sub { font-size: 12px; color: var(--muted); margin-top: 4px; }
/* Número con el color del estado (sección Chats abandonados del Resumen). */
.kpi .kpi-value.tone-ok { color: var(--ok-fg); }
.kpi .kpi-value.tone-warn { color: var(--warn-fg); }
.kpi .kpi-value.tone-bad { color: var(--bad-fg); }

.section-title {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  font-size: 15px; font-weight: 600; margin: 8px 0 14px;
}
.section-title .muted-count { font-size: 12px; font-weight: 500; color: var(--muted); }
.block { margin-bottom: 30px; }

/* ============================================================
   Botones y controles
   ============================================================ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 9px 16px; border-radius: var(--radius-sm); border: 1px solid transparent;
  background: var(--accent); color: var(--on-accent);
  font-size: 13.5px; font-weight: 600; cursor: pointer;
  transition: transform .16s var(--ease), background-color .16s var(--ease), box-shadow .16s var(--ease);
}
.btn svg { width: 16px; height: 16px; }
.btn:hover { background: var(--accent-hover); transform: translateY(-1px); box-shadow: var(--shadow-sm); }
.btn:active { transform: translateY(0); }
.btn:disabled { opacity: .55; cursor: not-allowed; transform: none; box-shadow: none; }
.btn.ghost { background: transparent; color: var(--text); border-color: var(--border-strong); }
.btn.ghost:hover { background: var(--surface-hover); }
.btn.danger { background: transparent; color: var(--bad-fg); border-color: color-mix(in srgb, var(--bad-fg) 35%, transparent); }
.btn.danger:hover { background: var(--bad-bg); }
.btn.sm { padding: 6px 12px; font-size: 12.5px; }
.btn.icon { padding: 8px; }
.btn.icon svg { width: 18px; height: 18px; }

.input, select.input {
  width: 100%; padding: 10px 12px; font-size: 14px; color: var(--text);
  background: var(--surface); border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm); transition: border-color .16s var(--ease), box-shadow .16s var(--ease);
}
.input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 25%, transparent); }
.input::placeholder { color: var(--muted); }
select.input { cursor: pointer; appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23757570' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center; padding-right: 34px;
}
.select-inline {
  padding: 6px 28px 6px 10px; font-size: 12.5px; border-radius: 8px;
  color: var(--text); background: var(--surface-2); border: 1px solid var(--border);
  appearance: none; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23757570' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 8px center;
}

.toolbar { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: 14px; }
.toolbar .grow { flex: 1; min-width: 180px; }
/* Los selects de la toolbar (ej. filtro por columna de Leads) se ajustan a su
   contenido en vez de estirarse al 100% como el resto de `.input`. Va por clase
   y no por id ni por `style=` inline: así las media queries pueden vencerlo
   (un `style` inline no lo vence nada, y un `#id` gana por especificidad). */
.toolbar select.input { width: auto; min-width: 150px; }

/* Chips de filtro */
.chips { display: inline-flex; gap: 6px; background: var(--surface-2); padding: 4px; border-radius: var(--radius-pill); }
.chip {
  padding: 6px 14px; border: none; background: transparent; color: var(--muted);
  border-radius: var(--radius-pill); font-size: 12.5px; font-weight: 500; cursor: pointer;
  transition: background-color .16s var(--ease), color .16s var(--ease);
}
.chip:hover { color: var(--text); }
.chip.active { background: var(--surface); color: var(--text); box-shadow: var(--shadow-sm); }
[data-theme="dark"] .chip.active { background: var(--surface-hover); }

/* Switch */
.switch { position: relative; display: inline-block; width: 46px; height: 26px; flex-shrink: 0; }
.switch input { opacity: 0; width: 0; height: 0; }
.switch .track {
  position: absolute; inset: 0; background: var(--border-strong); border-radius: var(--radius-pill);
  transition: background-color .2s var(--ease); cursor: pointer;
}
.switch .track::before {
  content: ""; position: absolute; height: 20px; width: 20px; left: 3px; top: 3px;
  background: #fff; border-radius: 50%; transition: transform .2s var(--ease); box-shadow: var(--shadow-sm);
}
.switch input:checked + .track { background: var(--ok-fg); }
.switch input:checked + .track::before { transform: translateX(20px); }
.switch input:focus-visible + .track { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ============================================================
   Tablas (siempre con scroll interno)
   ============================================================ */
.scroll-panel {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); overflow: auto; box-shadow: var(--shadow-sm);
  max-height: 440px;
}
.scroll-panel.tall { max-height: 560px; }
table { width: 100%; border-collapse: collapse; }
thead th {
  position: sticky; top: 0; z-index: 1;
  background: var(--surface-2); color: var(--muted);
  font-size: 12px; font-weight: 600; text-align: center; letter-spacing: .2px;
  padding: 11px 14px; white-space: nowrap; border-bottom: 1px solid var(--border);
}
tbody td {
  padding: 11px 14px; font-size: 13px; text-align: center;
  border-bottom: 1px solid var(--border); vertical-align: middle;
}
tbody tr:last-child td { border-bottom: none; }
tbody tr { transition: background-color .12s var(--ease); }
tbody tr:hover { background: var(--surface-hover); }
tbody tr.clickable { cursor: pointer; }
td .mono { font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Celda de texto libre recortada a 2 líneas, con el texto completo en el tooltip
   nativo (title). El clamp va en un SPAN interno a propósito: un max-width sobre
   un <td> con table-layout auto es indefinido, y cambiar el display del td
   rompería el layout de la tabla. Sin esto, el Requerimiento de un lead acapara
   el ancho y estira la fila varias líneas. */
/* `overflow-wrap: anywhere` y NO `word-break: break-word`: el segundo permite
   partir dentro de una palabra corta aunque quepa, y con celdas angostas cortaba
   un teléfono dígito a dígito. `anywhere` solo parte cuando no hay otra salida. */
.cell-clip {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  line-clamp: 2; overflow: hidden; max-width: 100%; margin: 0 auto;
  overflow-wrap: anywhere;
}

/* ---- Tabla de Leads: entra SIEMPRE en el ancho disponible ----
   Con `table-layout: auto` el navegador repartía el ancho según el contenido y
   las 10 columnas empujaban la tabla más allá del panel (barra horizontal). Con
   layout FIJO el ancho total es el del panel y cada columna respeta lo que se le
   asigna acá; el texto largo lo absorbe `.cell-clip` (2 líneas + tooltip). Las
   columnas sin ancho declarado (Requerimiento, Vehículo) se reparten el resto.
   Los anchos van SOLO en % y suman 78%: el 22% restante se lo reparten esas dos
   columnas de texto libre, y la tabla acompaña al viewport. Sin `min-width` a
   propósito — bajo layout fijo el ancho sale de la primera fila y un min-width
   que sumara más de 100% reintroduciría el desborde que esto viene a eliminar.

   TODO EL BLOQUE VA DENTRO DE `min-width: 641px` A PROPÓSITO. Los selectores
   llevan el id `#view-leads` (especificidad 1,1,0) y las media queries NO
   aportan especificidad: fuera de este envoltorio, `width: 11.5%` le ganaba a
   la regla de tarjetas apiladas `.scroll-panel.has-table … td { width: 100% }`
   (0,3,2) y en el teléfono la celda del teléfono medía ~25px de contenido —
   el número salía en columna, un dígito por línea (incidente 2026-07-25).
   Debajo de 641px la tabla NO es una tabla: es una lista de tarjetas y estos
   anchos no deben existir. Regla general en `.claude/PROJECT_CONTEXT.md`. */
@media (min-width: 641px) {
  #view-leads table { table-layout: fixed; }
  #view-leads thead th, #view-leads tbody td { padding: 10px 8px; }
  /* El encabezado envuelve en vez de cortarse: con `white-space: nowrap` y ancho
     fijo, "Última actividad" se veía como "Última activida". */
  #view-leads thead th { white-space: normal; }
  /* Anchos derivados del MÍNIMO MEDIDO de cada columna, no elegidos a ojo. El
     mínimo es el min-content de su encabezado (varios son una palabra suelta que
     no puede envolver: "Número" 65px, "Requerimiento" 106px) o el del control
     que contiene, que manda cuando es más ancho: el select de Estado necesita
     179px para "Pendiente de contacto" y el botón de Acciones 95px para
     "derivaciones". El caso crítico es 1280px, donde la tabla mide 982px: ahí la
     suma de los 11 mínimos da 94.8%, así que entran, pero sin margen.
     Los declarados suman 78.2%; el 21.8% libre se lo reparten Requerimiento y
     Vehículo (10.9% = 107px cada una a 1280px, sobre un mínimo de 106).
     Verificado a 1280/1366/1440/1920 px con el medidor por columna.
     ANTES de tocar cualquiera de estos números, re-medí: bajar uno solo corta
     su encabezado (a 5% "Número" se leía "Númer") y subirlo le roba al pool
     libre, que es quien sostiene a Requerimiento. */
  #view-leads .col-numero    { width: 6.7%; }
  #view-leads .col-nombre    { width: 6.7%; }
  #view-leads .col-telefono  { width: 7.5%; }
  #view-leads .col-medidas   { width: 7%; }
  #view-leads .col-ejecutivo { width: 7.5%; }
  #view-leads .col-sucursal  { width: 7%; }
  #view-leads .col-estado    { width: 18.5%; }
  #view-leads .col-actividad { width: 7.5%; }
  /* Medido de nuevo el 2026-07-28 al pasar de un botón "Ver derivaciones" a un menú
     "Acciones ⌄": a 1280px la celda necesita 105px (contenido 75 + padding del botón
     14 + padding de la celda 16) = 8.51%. Con 8.8% quedan ~4px de margen y el 1%
     liberado cae solo en el pool libre, que es quien sostiene a Requerimiento.
     Los anchos de las media queries más angostas NO se tocaron: ahí la etiqueta ya
     envolvía, y "Acciones" es más corta que "Ver derivaciones". */
  #view-leads .col-acciones  { width: 8.8%; }
  /* Teléfono y fecha son `.mono` (nowrap): con layout fijo deben poder envolver
     antes que desbordar su celda. */
  #view-leads tbody td .mono { white-space: normal; overflow-wrap: anywhere; }
  #view-leads .col-estado .estado-select {
    width: 100%; max-width: 100%; padding: 6px 22px 6px 9px; font-size: 11.5px;
    background-position: right 6px center;
  }
  #view-leads .col-acciones .btn { width: 100%; padding: 6px 6px; font-size: 11.5px; }
}

/* ---- Prioridad de columnas (tablet y laptop angosta) ----
   Una columna marcada `prio-3` en su <th> es secundaria: mientras la tabla no
   dé para todas, se ocultan las menos consultadas. `labelizeTable` (app.js)
   copia la clase del <th> a cada <td>, así se declara una sola vez.

   El corte va en 1280px y no en 1024: a 1025px el sidebar vuelve a ocupar
   240px, así que la tabla mide ~730px — MENOS que en una tablet de 1024 sin
   sidebar. Con las 10 columnas ahí, "Pendiente de contacto" (179px con sus
   paddings) no entra en ninguna repartición razonable.
   Debajo de 641px NO se oculta nada: la fila ya es una tarjeta y cabe todo. */
@media (min-width: 641px) and (max-width: 1279px) {
  .prio-3 { display: none; }
}

.empty-state, .loading-state {
  padding: 40px 16px; text-align: center; color: var(--muted); font-size: 13.5px;
}
.loading-state .spinner { margin: 0 auto 12px; }

.spinner {
  width: 22px; height: 22px; border-radius: 50%;
  border: 2.5px solid var(--border-strong); border-top-color: var(--accent);
  animation: spin .7s linear infinite;
}

/* ============================================================
   Embudo (barras horizontales)
   ============================================================ */
.funnel { display: flex; flex-direction: column; gap: 12px; }
.funnel-row { display: grid; grid-template-columns: 150px 1fr 46px; align-items: center; gap: 12px; }
.funnel-row .fl-label { font-size: 13px; color: var(--muted); }
.funnel-row .fl-bar-bg { background: var(--surface-2); border-radius: var(--radius-pill); height: 12px; overflow: hidden; }
.funnel-row .fl-bar { height: 100%; background: var(--accent); border-radius: var(--radius-pill); transition: width .5s var(--ease); }
.funnel-row .fl-val { font-size: 13px; font-weight: 600; text-align: right; }

/* ============================================================
   Conversaciones (burbujas)
   ============================================================ */
#conv-list td:first-child { font-weight: 500; }
.chat-panel { max-height: 520px; }
.chat { padding: 16px; display: flex; flex-direction: column; gap: 10px; }
.bubble { max-width: 78%; padding: 9px 13px; border-radius: 14px; font-size: 13px; line-height: 1.45; }
.bubble .bt { display: block; font-size: 10.5px; color: var(--muted); margin-top: 5px; }
.bubble.user { align-self: flex-start; background: var(--surface-2); border-bottom-left-radius: 4px; }
.bubble.assistant { align-self: flex-end; background: var(--accent); color: var(--on-accent); border-bottom-right-radius: 4px; }
.bubble.assistant .bt { color: color-mix(in srgb, var(--on-accent) 60%, transparent); }
.chat-head {
  position: sticky; top: 0; z-index: 1; margin: -16px -16px 4px; padding: 12px 16px;
  background: var(--surface-2); border-bottom: 1px solid var(--border);
  font-size: 12.5px; color: var(--muted); font-weight: 500;
}
.chat-head .mono { color: var(--text); font-weight: 600; }
.chat-empty { display: grid; place-items: center; height: 100%; min-height: 200px; color: var(--muted); text-align: center; padding: 24px; }

/* Modal "Ver derivaciones" */
.deriv-item { border: 1px solid var(--border); border-radius: 12px; padding: 12px 14px; background: var(--surface-2); }
.deriv-item .deriv-meta { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; font-size: 12px; color: var(--muted); margin-bottom: 8px; }
.deriv-item .deriv-card { white-space: pre-wrap; font-size: 13px; line-height: 1.45; color: var(--text); }

/* ============================================================
   Consumo
   ============================================================ */
.progress { background: var(--surface-2); border-radius: var(--radius-pill); height: 10px; overflow: hidden; margin-top: 10px; }
.progress .bar { height: 100%; background: var(--ok-fg); border-radius: var(--radius-pill); transition: width .5s var(--ease); }
.progress .bar.warn { background: var(--warn-fg); }
.progress .bar.bad { background: var(--bad-fg); }

/* Radio-cards (ajustes) */
.radio-cards { display: flex; flex-direction: column; gap: 10px; }
.radio-card {
  display: flex; gap: 12px; align-items: flex-start; padding: 14px 16px;
  border: 1px solid var(--border-strong); border-radius: var(--radius); cursor: pointer;
  transition: border-color .16s var(--ease), background-color .16s var(--ease);
}
.radio-card:hover { background: var(--surface-hover); }
.radio-card.selected { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent); }
.radio-card input { margin-top: 3px; accent-color: var(--accent); }
.radio-card .rc-title { font-weight: 600; font-size: 14px; }
.radio-card .rc-desc { font-size: 12.5px; color: var(--muted); margin-top: 2px; }

.setting-row {
  display: flex; align-items: center; gap: 16px; padding: 16px 0;
  border-bottom: 1px solid var(--border);
}
.setting-row:last-child { border-bottom: none; }
.setting-row .sr-text { flex: 1; }
.setting-row .sr-title { font-weight: 600; font-size: 14px; }
.setting-row .sr-desc { font-size: 12.5px; color: var(--muted); margin-top: 2px; }

/* Sucursales — grilla responsive: dos (o más) sucursales lado a lado; en
   pantallas angostas colapsa a una sola columna (auto-fit, sin media query). */
/* `min(340px, 100%)`: en un teléfono de 320px el minmax fijo desbordaba la
   pantalla (la pista no puede ser más ancha que el contenedor). */
#sucursales-list {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(340px, 100%), 1fr));
  gap: 16px; align-items: start;
}
.suc-card { margin-bottom: 0; }
.suc-card .suc-group {
  font-size: 12px; font-weight: 600; text-transform: uppercase;
  letter-spacing: .5px; color: var(--muted); margin: 16px 0 0;
}
.suc-maps {
  display: inline-block; margin-top: 6px; font-size: 12.5px;
  color: var(--accent); text-decoration: none; font-weight: 600;
}
.suc-maps:hover { text-decoration: underline; }
.switch input:disabled + .track { opacity: .45; cursor: not-allowed; }
/* Acciones de la card de sucursal (editar/eliminar) e iconos por servicio */
.suc-actions { display: inline-flex; gap: 4px; margin-left: 6px; }
.svc-actions { display: inline-flex; gap: 2px; margin-right: 4px; }
.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; padding: 0; border-radius: var(--radius-sm);
  border: 1px solid transparent; background: transparent; color: var(--muted);
  cursor: pointer; transition: background-color .16s var(--ease), color .16s var(--ease);
}
.icon-btn svg { width: 16px; height: 16px; }
.icon-btn:hover { background: var(--surface-hover); color: var(--text); }
.icon-btn.danger:hover { background: var(--bad-bg); color: var(--bad-fg); }
.field-hint { font-size: 11.5px; color: var(--muted); font-weight: 400; margin-top: 2px; }

/* Cabecera de sucursal: nombre + badge de estado en una línea. */
.suc-head-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

/* Editor de horarios por día (estilo WhatsApp Business). Cada día apila: arriba el
   nombre + "Cerrado"; debajo el rango horario. Así NUNCA desborda el modal (móvil
   incluido) y el checkbox queda siempre dentro del recuadro. */
.hours-grid { display: flex; flex-direction: column; gap: 10px; }
.hours-row { display: flex; flex-direction: column; gap: 6px; font-weight: 400; color: var(--text); }
.hours-row-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.hours-row-head .hours-day { font-size: 13px; font-weight: 500; }
.hours-times { display: flex; align-items: center; gap: 8px; }
.hours-times .input { flex: 1 1 0; width: auto; min-width: 0; max-width: 150px; padding: 8px 8px; }
.hours-times .hours-sep { flex: 0 0 auto; color: var(--muted); font-size: 12px; }
.hours-row input:disabled { opacity: .5; }
.hours-row.is-closed .hours-times { display: none; }
.hours-closed { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 5px;
  font-size: 12.5px; color: var(--muted); cursor: pointer; white-space: nowrap; }
.hours-closed input { accent-color: var(--accent); }

/* ============================================================
   Toast + modal
   ============================================================ */
.toast-stack { position: fixed; bottom: 22px; right: 22px; z-index: 90; display: flex; flex-direction: column; gap: 10px; }
.toast {
  min-width: 240px; max-width: 360px; padding: 12px 16px; border-radius: var(--radius-sm);
  background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow-lg);
  font-size: 13.5px; display: flex; align-items: center; gap: 10px;
  animation: toast-in .3s var(--ease);
}
.toast.hide { animation: toast-out .25s var(--ease) forwards; }
.toast .ic { width: 20px; height: 20px; flex-shrink: 0; }
.toast.ok .ic { color: var(--ok-fg); }
.toast.bad .ic { color: var(--bad-fg); }

.modal-backdrop {
  position: fixed; inset: 0; background: rgba(20, 20, 19, .5);
  display: grid; place-items: center; z-index: 80; padding: 24px;
  animation: fade .2s var(--ease);
}
.modal-backdrop[hidden] { display: none; }
.modal {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  /* Sin padding-bottom a propósito: el footer sticky de `.actions` es el último
     elemento y aporta él su propio espaciado. Con padding-bottom, el footer se
     pegaba al borde del *padding box* y quedaba flotando 24px por encima del
     fondo real del modal — el hueco por el que se veía el contenido pasar por
     debajo (reporte "crear sucursal", 2026-07-24). */
  padding: 24px 24px 0; max-width: 380px; width: 100%; box-shadow: var(--shadow-lg);
  animation: rise .28s var(--ease);
  /* Nunca más alto que el viewport: el cuerpo scrollea por dentro (con la grilla
     de horarios el modal crecía y los botones quedaban fuera de pantalla). */
  max-height: calc(100vh - 48px);
  max-height: calc(100dvh - 48px);
  overflow-y: auto; overflow-x: hidden;
}
/* Los DOS modales sin footer de acciones (cabecera + contenido) recuperan el
   espacio inferior que el footer habría aportado. Explícitos por id en vez de
   `:not(:has(.actions))`: se lee de una y no depende del soporte de :has(). */
#conv-modal .modal, #deriv-modal .modal { padding-bottom: 24px; }
.modal h3 { font-size: 16px; font-weight: 600; margin-bottom: 8px; }
.modal p { font-size: 13.5px; color: var(--muted); margin-bottom: 20px; }
/* Footer de acciones SIEMPRE visible (pegado al fondo del modal aunque se
   scrollee): así Guardar/Cancelar nunca quedan fuera de vista. */
.modal .actions {
  display: flex; gap: 10px; justify-content: flex-end; flex-wrap: wrap;
  position: sticky; bottom: 0; z-index: 1;
  margin: 16px -24px 0; padding: 14px 24px;
  background: var(--surface); border-top: 1px solid var(--border);
  border-radius: 0 0 calc(var(--radius) - 1px) calc(var(--radius) - 1px);
}
/* Con 3 acciones ("Cancelar · Descartar · Derivar a ejecutivo") el texto se
   partía en dos líneas y se amontonaba: los botones no se parten y, si no
   entran, la fila envuelve limpio (flex-wrap arriba). */
.modal .actions .btn { white-space: nowrap; }
.modal.modal-wide { max-width: 680px; }
/* Anchos por id DENTRO de `min-width`: un `#id` (1,1,0) le gana a `.modal`
   (0,1,0) aunque la otra regla esté en una media query, así que sin este
   envoltorio el modal de 468px seguía midiendo 468px en un teléfono de 320px
   y se salía de pantalla. Misma trampa de especificidad que rompió Leads. */
@media (min-width: 641px) {
  #ab-bulk-modal .modal { max-width: 468px; }
  #suc-modal .modal { max-width: 468px; }
}
.modal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.modal-head h3 { margin-bottom: 0; }

/* ============================================================
   Menú de acciones de una fila (Leads)

   Va con el atributo `popover`, así el navegador lo dibuja en su CAPA SUPERIOR: el
   `.scroll-panel` de la tabla tiene `overflow: auto` y recortaría cualquier menú
   normal justo en la última fila. `position: fixed` + top/left calculados en JS
   porque el anclaje al botón lo daría CSS anchor positioning, que todavía no es
   universal. TODO por clases: un `#id` con ancho/alto acá rompería
   tests/test_dashboard_responsive.py y, peor, le ganaría a las media queries.
   ============================================================ */
.row-menu {
  position: fixed; inset: auto; margin: 0; padding: 6px;
  min-width: 208px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-sm); box-shadow: var(--shadow-md);
}
.row-menu .menu-item {
  display: flex; align-items: center; gap: 10px;
  width: 100%; padding: 9px 12px;
  background: transparent; border: none; border-radius: 8px;
  font-family: inherit; font-size: 13px; font-weight: 500; color: var(--text);
  text-align: left; cursor: pointer;
  transition: background-color .12s var(--ease);
}
/* El amarillo de marca entra por el hover, no por el relleno: cuatro botones
   sólidos en la columna de acciones le competían al semáforo de Estado, que es lo
   único que el ejecutivo escanea. */
.row-menu .menu-item:hover:not(:disabled) { background: var(--accent); color: var(--on-accent); }
.row-menu .menu-item:disabled { color: var(--muted); cursor: not-allowed; }
.row-menu .menu-item svg { width: 15px; height: 15px; flex-shrink: 0; }
/* Un ítem deshabilitado y mudo obliga a adivinar: la razón va debajo, alineada al
   texto del ítem. */
.row-menu .menu-note {
  padding: 2px 12px 8px 34px; margin: 0;
  font-size: 11.5px; line-height: 1.35; color: var(--muted);
}
/* Los mismos ítems dentro del modal de respaldo (navegador sin popover). */
.row-menu-plano {
  position: static; padding: 0; min-width: 0;
  background: transparent; border: none; box-shadow: none;
}
/* Disparador: el chevron gira al abrir. */
.btn .chev { width: 13px; height: 13px; transition: transform .16s var(--ease); }
.btn[aria-expanded="true"] .chev { transform: rotate(180deg); }

/* Fila recién reasignada: en tablet la columna "Ejecutivo asignado" está oculta
   (prio-3), así que sin esta señal el operador no ve que algo cambió. */
tbody tr.row-flash { animation: row-flash 1.2s var(--ease); }
@keyframes row-flash {
  0%, 55% { background-color: color-mix(in srgb, var(--accent) 30%, transparent); }
  100% { background-color: transparent; }
}

.backdrop-mobile { display: none; }

/* ============================================================
   Tooltip informativo (icono i sobre las tarjetas)
   ============================================================ */
/* El globo se ancla a la TARJETA (`.kpi` ya es position:relative), no al icono:
   centrado sobre el icono, el de la última tarjeta de la fila se salía por la
   derecha y hacía scrollear la página entera (768px y 1024px). Anclado a la
   tarjeta ocupa su ancho y nunca puede exceder la grilla. `position: static` en
   `.info` es lo que traslada el bloque contenedor a la tarjeta. */
.info { position: static; display: inline-flex; align-items: center; color: var(--muted); cursor: help; }
.info svg { width: 15px; height: 15px; }
.info:hover, .info:focus-visible { color: var(--accent); outline: none; }
.info .tip {
  position: absolute; top: calc(100% + 9px); left: 0; right: 0;
  transform: translateY(-4px);
  width: auto; padding: 10px 12px; border-radius: 10px;
  background: var(--surface); color: var(--text); border: 1px solid var(--border);
  box-shadow: var(--shadow-lg); font-size: 12px; line-height: 1.45; font-weight: 400;
  text-align: left; white-space: normal;
  opacity: 0; visibility: hidden; pointer-events: none; z-index: 45;
  transition: opacity .16s var(--ease), transform .16s var(--ease);
}
.info .tip::after {
  content: ""; position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%);
  border: 6px solid transparent; border-bottom-color: var(--surface);
}
.info:hover .tip, .info:focus-visible .tip {
  opacity: 1; visibility: visible; transform: translateY(0);
}

/* ============================================================
   Estados de lead (badges de color, en negrita)
   ============================================================ */
.estado-select {
  appearance: none; border: none; cursor: pointer; color: #fff;
  font-family: inherit; font-weight: 700; font-size: 12px; letter-spacing: .2px;
  padding: 6px 28px 6px 13px; border-radius: var(--radius-pill);
  background-repeat: no-repeat; background-position: right 9px center;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  transition: background-color .16s var(--ease), transform .12s var(--ease);
}
.estado-select:hover { transform: translateY(-1px); }
.estado-select option { color: var(--text); background: var(--surface); font-weight: 500; }
.estado-select.est-pendiente_contacto { background-color: #dc3b3b; }
.estado-select.est-contactado { background-color: #de7c00; }
.estado-select.est-venta_realizada { background-color: #2f9e44; }
.estado-select.est-cerrada_sin_venta { background-color: #6b7280; }
/* Compat: leads legacy que sigan en 'cerrado' (verde, hasta reclasificarse). */
.estado-select.est-cerrado { background-color: #2f9e44; }

/* Selector de ACCIONES (Chats abandonados). No comunica un estado, así que va
   neutro: reusar `.estado-select` lo dejaba con `color:#fff` y sin
   background-color (ninguna clase `est-*`) → texto blanco sobre blanco, la
   columna se veía vacía. Minimalista, con el amarillo de marca solo al
   interactuar. */
.action-select {
  /* Ancho FIJO: un <select> se dimensiona por su opción MÁS LARGA, y las filas
     ofrecen distintas acciones ("Descartar" vs "Derivar a ejecutivo"), así que
     sin ancho fijo cada botón quedaba de un tamaño distinto. Fijo = todos
     iguales; el texto visible siempre es "Acciones…" y entra holgado. */
  appearance: none; cursor: pointer; box-sizing: border-box;
  width: 148px; max-width: 100%;
  font-family: inherit; font-size: 12px; font-weight: 600; color: var(--text);
  background-color: var(--surface-2);
  border: 1px solid var(--border-strong); border-radius: var(--radius-pill);
  padding: 6px 26px 6px 12px;
  text-overflow: ellipsis;
  background-repeat: no-repeat; background-position: right 9px center;
  /* Caret gris medio: legible sobre la superficie clara y la oscura. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23888880' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  transition: border-color .16s var(--ease), background-color .16s var(--ease);
}
.action-select:hover { border-color: var(--accent); background-color: var(--surface); }
.action-select:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.action-select option { color: var(--text); background: var(--surface); font-weight: 500; }

/* ============================================================
   Paginación (todos los listados)
   ============================================================ */
.pager-wrap:empty { display: none; }
.pager { display: flex; align-items: center; justify-content: center; gap: 14px;
  padding: 12px 4px 2px; flex-wrap: wrap; }
.pager-label { font-size: 12.5px; color: var(--muted); font-weight: 500; }
.pager-note { text-align: center; font-size: 12px; color: var(--muted); padding: 6px 4px 0; }

/* Columna de selección (Medidas): checkbox angosto y centrado. */
.col-check { width: 34px; text-align: center; }
.col-check input { cursor: pointer; }

/* Contactos de derivación (modal de sucursal): filas de {teléfono, ejecutivo}. */
.suc-contactos, #suc-contactos { display: flex; flex-direction: column; gap: 10px; margin-top: 4px; }
.contacto-row { display: flex; flex-direction: column; gap: 8px; padding: 10px 12px;
  border: 1px solid var(--border); border-radius: var(--radius-sm); }
.contacto-row.disabled { opacity: .5; }
.contacto-head { display: flex; align-items: center; justify-content: space-between; }
.contacto-title { font-size: 12.5px; font-weight: 700; color: var(--text); }

/* ============================================================
   Control de presupuesto (Ajustes) + formulario del modal
   ============================================================ */
.budget-control { display: flex; align-items: center; gap: 8px; }
.budget-control .input { width: 116px; }
.budget-prefix { color: var(--muted); font-size: 13px; font-weight: 500; }

/* Celda editable de medidas (tabla de Medidas por vehículo): textarea que
   envuelve y crece con su contenido (la altura la ajusta autoGrow en JS), para
   que el valor completo se lea siempre, también en móvil. */
.medidas-cell {
  width: 100%; resize: none; overflow: hidden;
  line-height: 1.35; min-height: 32px; white-space: pre-wrap; overflow-wrap: anywhere;
  font-family: inherit;
}
/* Donde exista field-sizing (Chrome/Edge de escritorio), el textarea se
   auto-dimensiona a su contenido de forma nativa: elimina el problema de timing
   del ancho de columna en la tabla. autoGrow (JS) queda de fallback (móvil/Safari). */
@supports (field-sizing: content) {
  .medidas-cell { field-sizing: content; }
}

/* Medida APROBADA: mismo texto, sin caja de input. Un campo con borde invita a
   escribir; el valor curado por el ejecutivo ya está cerrado y no se edita. */
.medidas-ro {
  display: block; width: 100%; font-size: 12.5px; line-height: 1.35;
  padding: 6px 0; white-space: pre-wrap; overflow-wrap: anywhere; text-align: left;
}

/* Estado + eliminar en la misma celda (Medidas): quedan JUNTOS, en escritorio y
   en la tarjeta apilada de móvil (antes el borrar caía a su propia fila). */
.fit-actions { display: flex; align-items: center; gap: 10px; justify-content: center; }

.form-grid { display: flex; flex-direction: column; gap: 12px; margin-bottom: 6px; }
.field-label { display: flex; flex-direction: column; gap: 5px; font-size: 12.5px; font-weight: 500; color: var(--muted); }
.field-label .input { font-weight: 400; color: var(--text); }
.field-row { display: flex; gap: 10px; }
.field-row .field-label { flex: 1; }

/* ============================================================
   Animaciones
   ============================================================ */
@keyframes rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
@keyframes toast-in { from { opacity: 0; transform: translateY(12px) scale(.98); } to { opacity: 1; transform: translateY(0) scale(1); } }
@keyframes toast-out { to { opacity: 0; transform: translateX(20px); } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}

/* ============================================================
   Responsive — tres tamaños, un solo contrato

   >= 1025px  COMPUTADOR  tabla completa, sidebar fijo
   641-1024px TABLET      tabla real sin las columnas `prio-3`; drawer < 900px
   <= 640px   TELÉFONO    cada fila es una tarjeta con TODAS sus columnas

   REGLA DURA: ninguna regla con `#id` puede fijar ancho/alto/display de una
   celda fuera de un `@media (min-width: …)`. Un id (1,1,0) le gana a cualquier
   selector de clases dentro de una media query, porque las media queries no
   aportan especificidad — así se rompió la vista de Leads en el teléfono.
   Lo vigila tests/test_dashboard_responsive.py.
   ============================================================ */
@media (max-width: 900px) {
  .sidebar {
    position: fixed; top: 0; left: 0; z-index: 70; height: 100dvh;
    transform: translateX(-100%); box-shadow: var(--shadow-lg);
  }
  .sidebar.open { transform: translateX(0); }
  .hamburger { display: inline-flex; }
  .backdrop-mobile.show {
    display: block; position: fixed; inset: 0; background: rgba(20, 20, 19, .45); z-index: 60;
    animation: fade .2s var(--ease);
  }
  .view-wrap { padding: 20px 16px 40px; }
  .topbar { padding: 14px 16px; }
  .funnel-row { grid-template-columns: 110px 1fr 40px; }
}

/* Tablet: la tabla sigue siendo tabla (comparar filas es lo útil acá), pero con
   menos aire y sin las columnas secundarias. */
@media (min-width: 641px) and (max-width: 1024px) {
  thead th { padding: 10px 10px; font-size: 11.5px; }
  tbody td { padding: 10px 10px; font-size: 12.5px; }
  .kpi .kpi-value { font-size: 26px; }
  /* El buscador manda en la fila; los botones se acomodan debajo si no caben. */
  .toolbar .grow { flex: 1 1 100%; min-width: 0; }
  .toolbar .input:not(.grow) { flex: 0 1 auto; min-width: 0; }
}

/* Leads con las 3 columnas secundarias ocultas (tablet + laptop angosta):
   sobra ancho y los porcentajes de escritorio dejaban "#123", la fecha y el
   estado cortados. Se reparte entre las que quedan; Requerimiento toma el
   resto. `col-estado` es la que manda: tiene que caber "Pendiente de contacto"
   (132px de texto + 31 del select + 16 de la celda = 179px). */
@media (min-width: 641px) and (max-width: 1279px) {
  #view-leads .col-numero    { width: 8%; }
  #view-leads .col-nombre    { width: 12%; }
  #view-leads .col-telefono  { width: 15%; }
  #view-leads .col-estado    { width: 25%; }
  #view-leads .col-actividad { width: 13%; }
  #view-leads .col-acciones  { width: 11%; }
}

/* Tablet chica en vertical (~640-760px): la tabla mide ~600px y ni el 25% le
   alcanza al estado. Se aprieta todo lo demás un punto; Requerimiento conserva
   lo suyo porque su propio encabezado es una palabra de 100px que no envuelve. */
@media (min-width: 641px) and (max-width: 759px) {
  #view-leads .col-numero    { width: 7%; }
  #view-leads .col-nombre    { width: 10%; }
  #view-leads .col-telefono  { width: 13%; }
  #view-leads .col-estado    { width: 30%; }
  #view-leads .col-actividad { width: 12%; }
  #view-leads .col-acciones  { width: 10%; }
}

/* Táctil (teléfono y tablet): objetivos de toque cómodos. Los tamaños compactos
   están pensados para el mouse; con el dedo, 30px es un blanco frustrante. */
@media (pointer: coarse) {
  .btn { padding: 11px 16px; }
  .btn.sm { padding: 9px 14px; font-size: 13px; }
  .btn.icon { padding: 10px; }
  .chip { padding: 9px 15px; font-size: 13px; }
  .icon-btn { width: 40px; height: 40px; }
  .nav-item { padding: 12px; }
  /* Los ítems del menú de fila llegan a los 44px recomendados: uno de los dos
     reasigna un cliente, y ahí un blanco chico se paga caro. Queda más cómodo que
     el resto de los botones del panel a propósito: es un componente nuevo y la
     inconsistencia va en la dirección correcta. */
  .row-menu .menu-item { min-height: 44px; padding: 11px 14px; font-size: 13.5px; }
  .row-menu .menu-note { padding-left: 38px; }
  /* El tooltip informativo solo abría con :hover, que en táctil no existe. */
  .info:focus-within .tip { opacity: 1; visibility: visible; transform: translateY(0); }
}

/* Teléfonos: header en 2 filas y tablas como TARJETAS apiladas (con sentido útil,
   sin scroll horizontal ni columnas cortadas). */
@media (max-width: 640px) {
  .view-wrap { padding: 16px 12px 40px; }

  /* Topbar: hamburguesa + título en la 1ª fila; el grupo de indicadores SIEMPRE
     baja completo a la 2ª fila (flex-basis:100%), sin importar el largo del
     título — así los dos pills quedan juntos y alineados debajo. */
  .topbar { flex-wrap: wrap; gap: 8px 10px; padding: 12px 14px; }
  .topbar .spacer { display: none; }
  .topbar h2 { flex: 1 1 auto; min-width: 0; font-size: 16px; line-height: 1.25; }
  .topbar-status { flex: 0 0 100%; width: 100%; gap: 8px; }
  .topbar .pill { font-size: 11px; padding: 4px 10px; }

  .kpi-grid { gap: 12px; margin-bottom: 20px; }
  .section-title { font-size: 15px; }

  /* Chips de filtro: más compactos y con scroll horizontal si no caben. El
     degradado del borde derecho es la ÚNICA pista de que hay más chips (la
     barra va oculta): con 7 estados en Abandonados, los últimos eran invisibles
     y nadie sabía que existían. */
  .chips {
    max-width: 100%; overflow-x: auto; scrollbar-width: none;
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 22px), transparent);
    mask-image: linear-gradient(to right, #000 calc(100% - 22px), transparent);
  }
  .chips::-webkit-scrollbar { display: none; }
  .chips .chip { padding: 6px 11px; white-space: nowrap; }

  /* Toolbars: el buscador toma la fila entera y los botones se reparten la
     siguiente en partes iguales (patrón que ya funcionaba en Sucursales). Sin
     esto quedaban de anchos dispares, con huecos, en 3-4 filas sueltas. */
  .toolbar { gap: 8px; }
  .toolbar .grow { flex: 1 1 100%; min-width: 0; }
  .toolbar > .btn { flex: 1 1 0; min-width: 0; }
  .toolbar > .input:not(.grow) { flex: 1 1 100%; width: 100%; }

  /* --- Tabla -> tarjetas apiladas: cada fila es una card; cada celda muestra su
     etiqueta (data-label) + el valor. Excluye el chat (sin tabla) y la tabla de
     Consumo (.no-stack, ya es etiqueta:valor). --- */
  .scroll-panel.has-table:not(.no-stack) {
    max-height: none; overflow: visible; border: none;
    background: transparent; box-shadow: none; border-radius: 0;
  }
  .scroll-panel.has-table:not(.no-stack) table,
  .scroll-panel.has-table:not(.no-stack) tbody,
  .scroll-panel.has-table:not(.no-stack) tr,
  .scroll-panel.has-table:not(.no-stack) td { display: block; width: 100%; }
  .scroll-panel.has-table:not(.no-stack) thead { display: none; }
  .scroll-panel.has-table:not(.no-stack) tbody tr {
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius); box-shadow: var(--shadow-sm);
    margin-bottom: 10px; padding: 4px 2px;
  }
  .scroll-panel.has-table:not(.no-stack) tbody tr:hover { background: var(--surface); }
  .scroll-panel.has-table:not(.no-stack) tbody td {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px; text-align: right; padding: 9px 14px;
    border-bottom: 1px solid var(--border);
  }
  .scroll-panel.has-table:not(.no-stack) tbody td:last-child { border-bottom: none; }
  /* La etiqueta CEDE ancho (`flex: 0 1 auto` + tope): con `0 0 auto` no encogía
     nunca y "Ejecutivo asignado" o "Vehículo / servicio" se comían la celda
     entera, dejando al valor un hilo de 1 carácter.
     SIN `min-width: 0` a propósito (bug 2026-07-25, lead #12): ese valor anula
     el piso automático de min-content del ítem flex, así que con un valor largo
     el navegador encogía la CAJA de la etiqueta a ~13px mientras su texto seguía
     midiendo 90px — y el sobrante se dibujaba ENCIMA del valor. Con el piso por
     defecto la etiqueta nunca baja de su palabra más larga. */
  .scroll-panel.has-table:not(.no-stack) tbody td::before {
    content: attr(data-label); flex: 0 1 auto; max-width: 45%;
    text-align: left;
    color: var(--muted); font-size: 12px; font-weight: 600;
  }
  /* ...y el valor se queda con el resto, sin encogerse por debajo de su contenido. */
  .scroll-panel.has-table:not(.no-stack) tbody td > * { min-width: 0; }
  /* Estado vacío / cargando (colspan): ancho completo, centrado, sin etiqueta. */
  .scroll-panel.has-table:not(.no-stack) tbody td[colspan] { justify-content: center; text-align: center; }
  .scroll-panel.has-table:not(.no-stack) tbody td[colspan]::before { content: none; }
  /* Texto largo (requerimiento) envuelve a la derecha en vez de cortarse.
     `overflow-wrap: anywhere` y NO `word-break: break-word`: el segundo parte
     dentro de una palabra corta aunque quepa, y así el teléfono salía en
     columna, un dígito por línea (incidente 2026-07-25). */
  .scroll-panel.has-table:not(.no-stack) tbody td .mono { white-space: normal; overflow-wrap: anywhere; }
  /* En táctil no hay hover (el title no se ve): en la tarjeta apilada el texto va
     COMPLETO en vez de recortado a 2 líneas. */
  .scroll-panel.has-table:not(.no-stack) tbody td .cell-clip {
    display: block; -webkit-line-clamp: unset; line-clamp: unset;
    max-width: 100%; margin: 0; text-align: right;
  }
  /* Controles (select de estado, inputs) no ocupan todo el ancho de la celda. */
  .scroll-panel.has-table:not(.no-stack) tbody td select,
  .scroll-panel.has-table:not(.no-stack) tbody td .input { width: auto; max-width: 62%; }

  /* Celda "en bloque" (ej. Medidas): la etiqueta va arriba y el control ocupa el
     ancho completo debajo, para que el contenido largo se lea entero (no cortado). */
  .scroll-panel.has-table:not(.no-stack) tbody td.cell-block {
    flex-direction: column; align-items: stretch; text-align: left; gap: 6px;
  }
  .scroll-panel.has-table:not(.no-stack) tbody td.cell-block .input { width: 100%; max-width: 100%; }

  /* Sucursales: los botones superiores (Crear sucursal / Crear servicio) se
     reparten la fila en partes iguales, sin el espaciador que los descuadraba. */
  #view-sucursales .toolbar .grow { display: none; }
  #view-sucursales .toolbar .btn { flex: 1 1 0; }

  .bubble { max-width: 86%; }

  /* Modales como hoja inferior: pegados al fondo, a ancho completo y con los
     botones repartidos. A 320px el modal quedaba de 272px con el footer
     amontonado, y el de sucursal (grilla de 7 días) era el peor. */
  .modal-backdrop { padding: 10px; align-items: end; }
  .modal, .modal.modal-wide { max-width: 100%; }
  .modal .actions .btn { flex: 1 1 auto; }

  /* Paginación: la etiqueta baja a su propia línea en vez de exprimir los
     botones ("Página 1 de 9 · 173 en total" no cabe al lado de los dos). */
  .pager { gap: 8px 12px; }
  .pager-label { flex: 1 1 100%; order: 1; text-align: center; }

  /* Los toasts ocupan el ancho del teléfono en vez de una tarjeta flotante
     angosta pegada a la esquina. */
  .toast-stack { left: 12px; right: 12px; bottom: 12px; }
  .toast { min-width: 0; max-width: none; }
}
