@import url("./torre-layout.css");
@import url('./voz.css');
/* La URL relativa conserva el SHA de styles.css en cada release. */

/* =====================================================
   SURFIA — Panel del negocio
   Estética: marino/océano/aqua, tipografía Sora + IBM Plex Mono.
   Claro y oscuro desde el día 1 (DASHBOARD-SPEC §6).
   ============================================================ */

/* Tipografías propias (épico #404, PR 9b). Antes venían de Google Fonts: sin
   señal el panel cambiaba de letra y la bienvenida esperaba a otro servidor.
   Subconjunto latino en woff2 (~55 KB en total); Sora es variable (400-700).
   URLs absolutas bajo /assets/fonts/: la release copia frontend/ entero y el
   builder solo fija los assets del index, no los del CSS. */
@font-face {
  font-family: 'Sora'; font-style: normal; font-weight: 400 700; font-display: swap;
  src: url(/assets/fonts/sora-latin.woff2) format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 500; font-display: swap;
  src: url(/assets/fonts/ibm-plex-mono-500-latin.woff2) format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 600; font-display: swap;
  src: url(/assets/fonts/ibm-plex-mono-600-latin.woff2) format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 700; font-display: swap;
  src: url(/assets/fonts/ibm-plex-mono-700-latin.woff2) format('woff2');
}

:root {
  /* marca — mismos valores que el logo Flujo v2 */
  --marino: #0A1628;
  --brand: #0284C7;        /* océano */
  --brand-deep: #0E7490;   /* cian-marino */
  --aqua: #22D3EE;
  --aqua-soft: rgba(34, 211, 238, .12);
  --brand-grad: linear-gradient(135deg, #0284C7, #22D3EE);

  /* Las tres corrientes del logo. En claro NO pueden ser los colores de marca:
     el aqua da 1,7:1 contra el fondo y la corriente de arriba desaparece. Esta
     escala baja un paso y deja las tres sobre 3:1 sin perder la profundidad. */
  --logo-1: #0891B2;
  --logo-2: #0369A1;
  --logo-3: #0C4A6E;

  /* El marco de la loseta «Cresta». No cambia con el tema a propósito: no es un
     color de fondo, es el aviso de que al tocarla el panel se pone blanco. */
  --cresta-marco: #FFFFFF;

  /* El plato bajo el logo del negocio en la barra. Tampoco cambia con el tema,
     y por la misma clase de razón: es el MISMO archivo que se imprime sobre el
     blanco de su cotización. Sobre el degradado de marca un logo transparente
     se pierde, y sobre el --card oscuro desaparece uno de tinta negra. */
  --logo-plate: #FFFFFF;

  --bg: #F2F6FA;
  --bg-glow: radial-gradient(1200px 600px at 85% -10%, rgba(34, 211, 238, .14), transparent 60%),
             radial-gradient(900px 500px at -10% 110%, rgba(2, 132, 199, .10), transparent 55%);
  --card: #FFFFFF;
  --card-2: #F7FAFC;
  --ink: #0A1628;
  --ink-2: #3B4B61;
  --ink-3: #7C8BA1;
  --line: #E3EAF2;
  --line-2: #EDF2F7;

  /* semántico — independiente de la marca, a propósito */
  --ok: #0E9F6E;   --ok-soft: #E6F6F0;
  --warn: #C98A2B; --warn-soft: #FBF3E4;
  --sobre-marino: #E9F1F9;   /* tinta clara sobre --marino (toast, tooltip): igual en los dos temas */
  --bad: #D64545;  --bad-soft: #FBEAEA;
  --bad-ink: #FFFFFF;   /* tinta legible ENCIMA de --bad (el contador de pendientes) */
  /* tinta legible sobre los fondos suaves (el --warn puro da 2.66:1 en claro) */
  --warn-ink: #8A5A14;
  --hl-ink: #0E7490;

  /* canales */
  --wa: #1FAF5A;   --wa-soft: #E7F6EC;
  --ig: #DD2A7B;   --ig-soft: #FBE9F2;
  --ig-grad: linear-gradient(135deg, #F58529, #DD2A7B, #8134AF);

  --shadow: 0 1px 2px rgba(10, 22, 40, .04), 0 8px 24px -12px rgba(2, 132, 199, .12);
  --shadow-lift: 0 2px 4px rgba(10, 22, 40, .05), 0 16px 40px -16px rgba(2, 132, 199, .22);
  --r: 16px;
  --r-sm: 12px;      /* controles: botones, campos, alertas */
  --r-pill: 999px;   /* todo lo que es una etiqueta: cápsula, sin excepción */

  /* Movimiento: dos duraciones y una curva para toda la hoja. Antes había
     ocho combinaciones distintas y la interfaz se sentía de varias manos. */
  --t-fast: .15s;
  --t-med: .3s;
  --ease: cubic-bezier(.2, .8, .2, 1);

  /* Acentos translúcidos con nombre: estaban escritos crudos en ~20 sitios. */
  --aqua-25: rgba(34, 211, 238, .25);
  --aqua-35: rgba(34, 211, 238, .35);

  /* Sombras que no dependen del tema claro. La de la barra inferior y la de
     los flotantes iban en rgba(10,22,40): sobre el marino son invisibles. */
  --shadow-up: 0 -8px 24px -12px rgba(10, 22, 40, .15);
  --shadow-pop: 0 12px 32px -8px rgba(10, 22, 40, .55);

  --font: Sora, "Avenir Next", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;
}

/* ⚠️ Este bloque y el `[data-theme="dark"]` de abajo son GEMELOS y hay que
   mantenerlos a la vez: son la misma lista de variables escrita dos veces,
   porque CSS no deja compartir un bloque entre una media query y un selector.
   Llegué a borrar este por parecer código muerto —hoy no se evalúa, ya que el
   HTML fija `data-theme="dark"`— y el eval `panel-entrada.test.js` lo cazó:
   es el que hace que el panel siga el tema del sistema si algún día se quita
   ese atributo. Si tocas un color aquí, tócalo también abajo. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    /* sobre el marino sí lucen los colores de marca */
    --logo-1: #22D3EE; --logo-2: #0284C7; --logo-3: #0E7490;
    --bg: #07101E;
    --bg-glow: radial-gradient(1200px 600px at 85% -10%, rgba(34, 211, 238, .08), transparent 60%),
               radial-gradient(900px 500px at -10% 110%, rgba(2, 132, 199, .07), transparent 55%);
    --card: #0C1930; --card-2: #0A1526;
    --ink: var(--sobre-marino); --ink-2: #B4C4D8; --ink-3: #7C90AB;
    --line: #1A2C46; --line-2: #14243B;
    /* Sobre el marino, el azul, el rojo y el verde de marca tienen que subir un
       paso — el mismo motivo por el que suben --logo-1/2/3, solo que al revés.
       Con los valores del tema claro daban 4,28 y 4,01 sobre la tarjeta: por
       debajo del 4,5 que exige un texto pequeño. Ahora dan 8,19 y 6,34.
       Se puede cambiar --brand sin miedo porque en toda la hoja NO se usa ni
       una vez como fondo: los rellenos son --brand-grad. */
    --brand: #38BDF8;
    --bad: #F87171;
    --bad-ink: #0A1628;   /* el rojo del tema oscuro es claro: la tinta va oscura */
    --ok: #34D399;
    --aqua-soft: rgba(34, 211, 238, .10);
    --ok-soft: rgba(14, 159, 110, .14);
    --warn-soft: rgba(201, 138, 43, .14);
    --bad-soft: rgba(214, 69, 69, .14);
    --wa-soft: rgba(31, 175, 90, .13);
    --ig-soft: rgba(221, 42, 123, .13);
    --warn-ink: #DFAF63;
    --hl-ink: #22D3EE;
    --shadow: 0 1px 2px rgba(0, 0, 0, .2), 0 8px 24px -12px rgba(0, 0, 0, .4);
    --shadow-lift: 0 2px 4px rgba(0, 0, 0, .25), 0 16px 40px -16px rgba(34, 211, 238, .15);
  }
}

:root[data-theme="dark"] {
  /* sobre el marino sí lucen los colores de marca */
  --logo-1: #22D3EE; --logo-2: #0284C7; --logo-3: #0E7490;
  --bg: #07101E;
  --bg-glow: radial-gradient(1200px 600px at 85% -10%, rgba(34, 211, 238, .08), transparent 60%),
             radial-gradient(900px 500px at -10% 110%, rgba(2, 132, 199, .07), transparent 55%);
  --card: #0C1930; --card-2: #0A1526;
  --ink: var(--sobre-marino); --ink-2: #B4C4D8; --ink-3: #7C90AB;
  --line: #1A2C46; --line-2: #14243B;
  /* ver la nota de contraste en el bloque de arriba */
  --brand: #38BDF8;
  --bad: #F87171;
  --bad-ink: #0A1628;   /* el rojo del tema oscuro es claro: la tinta va oscura */
  --ok: #34D399;
  --aqua-soft: rgba(34, 211, 238, .10);
  --ok-soft: rgba(14, 159, 110, .14);
  --warn-soft: rgba(201, 138, 43, .14);
  --bad-soft: rgba(214, 69, 69, .14);
  --wa-soft: rgba(31, 175, 90, .13);
  --ig-soft: rgba(221, 42, 123, .13);
  --warn-ink: #DFAF63;
  --hl-ink: #22D3EE;
  --shadow: 0 1px 2px rgba(0, 0, 0, .2), 0 8px 24px -12px rgba(0, 0, 0, .4);
  --shadow-lift: 0 2px 4px rgba(0, 0, 0, .25), 0 16px 40px -16px rgba(34, 211, 238, .15);
  --shadow-up: 0 -8px 24px -12px rgba(0, 0, 0, .55);
  --shadow-pop: 0 12px 32px -8px rgba(0, 0, 0, .7);
}

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

/* `hidden` tiene que ganarle a cualquier `display` que declaremos después: si
   no, una regla como `.side .foot button { display:block }` revive un botón ya
   marcado como oculto. Pasó con "Salir" y con el banner de negocio pendiente. */
[hidden] { display: none !important }
html, body { height: 100% }
body {
  font-family: var(--font);
  background: var(--bg); color: var(--ink); line-height: 1.45;
  -webkit-font-smoothing: antialiased;
}
body::before { content: ""; position: fixed; inset: 0; background: var(--bg-glow); pointer-events: none; z-index: 0 }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer }
input { font: inherit }

/* En el teléfono ningún campo de texto baja de 16px. iOS amplía la página
   entera al enfocar un input/textarea/select más pequeño —y no la vuelve a
   encoger al salir—: el hilo se veía ampliado ~1,2× con «Atiendo yo» y
   «Enviar» cortados por la derecha (captura de Luis, 2-sep-2026). Es una regla
   del dispositivo, no de un componente, y por eso lleva !important: tiene que
   ganarle a cualquier tamaño que declare una hoja que carga después
   (thread-mobile.css, fuentes.css) y a cualquier componente futuro. Ojo: también
   es un techo — un control móvil que quiera MÁS de 16px lo declara con
   !important. La otra salida, maximum-scale=1 en el viewport, deja sin
   pellizco a Android y se descarta. */
@media (max-width: 820px) {
  input, textarea, select { font-size: 16px !important }
}

.app { position: relative; z-index: 1; display: grid; grid-template-columns: 232px minmax(0, 1fr); min-height: 100vh }
.main { min-width: 0; padding: 20px 26px 90px; max-width: 1060px; width: 100%; margin: 0 auto }

/* ---------- logo (Flujo v2) ---------- */
.logo { display: flex; align-items: center; gap: 10px; padding: 0 8px }
.logo .mark { width: 34px; height: 30px; display: grid; place-items: center }
.logo .mark svg { width: 32px; height: 28px }
.logo .word { font-size: 20px; font-weight: 700; letter-spacing: -.03em }

/* ---------- sidebar ---------- */
.side {
  padding: 22px 14px; border-right: 1px solid var(--line);
  display: flex; flex-direction: column; gap: 26px; position: sticky; top: 0; height: 100vh;
}
.nav { display: flex; flex-direction: column; gap: 2px }
.nav button {
  display: flex; align-items: center; gap: 11px; padding: 10px 12px; border-radius: 10px;
  font-size: 14.5px; font-weight: 500; color: var(--ink-2); text-align: left; transition: all .15s;
}
.nav button svg { width: 18px; height: 18px; opacity: .75; flex: none }
/* «Mi Surfia» lleva el logo, no un icono de línea, y el logo no juega con las
   mismas reglas: su viewBox es 52×46 —no cuadrado— y sus trazos salen de
   --logo-1/2/3, no de currentColor. Se le conserva el ANCHO de 18px para que
   el texto del menú siga alineado en columna, y opacidad plena: al .75 del
   resto las tres corrientes se empastan y el logo se lee como una mancha. */
.nav button[data-screen="probar"] svg { width: 18px; height: 16px; opacity: 1 }
.nav button:hover { background: var(--card-2); color: var(--ink) }
.nav button.on { background: var(--aqua-soft); color: var(--brand); font-weight: 600 }
.nav button.on svg { opacity: 1 }
.nav .badge {
  margin-left: auto; background: var(--bad); color: var(--bad-ink); font-size: 10.5px; font-weight: 700;
  min-width: 17px; height: 17px; border-radius: 9px; display: grid; place-items: center; padding: 0 5px;
}
.side .foot {
  margin-top: auto; padding: 12px; border-radius: var(--r-sm); background: var(--card-2);
  border: 1px solid var(--line-2); font-size: 12px; color: var(--ink-3);
}
.side .foot b { color: var(--ink-2); display: block; font-size: 12.5px; margin-bottom: 2px }
.side .foot .dot {
  display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: var(--ok);
  margin-right: 5px;
}
.side .foot button { display: block; font-size: 12px; color: var(--brand); font-weight: 600; margin-top: 9px }
.side .foot #agent-line { display: block }
/* La ficha del cliente bajo el nombre del hilo (épico #404, PR 8). */
.who .ficha { display: block; font-size: 11.5px; color: var(--ink-3); margin-top: 2px; white-space: normal; line-height: 1.35 }
/* Corregir la ficha a mano (#404). El correo es un BOTÓN porque copiarlo es la
   acción —el dueño viene de hacer el presupuesto y le falta el destinatario—,
   no un texto que haya que seleccionar a dedo en un teléfono. */
.who .ficha .ficha-correo, .who .ficha .ficha-editar {
  font: inherit; color: var(--brand); background: none; border: 0; padding: 0 0 0 6px; cursor: pointer;
}
.who .ficha .ficha-sep { color: var(--ink-3) }
.who .ficha .ficha-editar { text-decoration: underline; text-underline-offset: 2px }
.who .ficha .ficha-correo:hover, .who .ficha .ficha-editar:hover { text-decoration: underline }
/* El formulario vive DENTRO de la cabecera: corregir el dato es parte de mirar
   el chat, no una pantalla aparte a la que haya que ir y volver. */
.ficha-form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin-top: 8px; max-width: 520px }
.ficha-campo { display: flex; flex-direction: column; gap: 2px; min-width: 0 }
.ficha-campo span { font-size: 11px; color: var(--ink-3); font-weight: 600 }
.ficha-campo input, .ficha-campo select {
  font-size: 13px; padding: 6px 8px; border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--card); color: var(--ink); min-width: 0; width: 100%;
}
.ficha-campo input:focus, .ficha-campo select:focus { outline: 2px solid var(--brand); outline-offset: -1px }
.ficha-nota, .ficha-acciones { grid-column: 1 / -1 }
.ficha-nota { font-size: 11px; color: var(--ink-3); margin: 0 }
.ficha-acciones { display: flex; align-items: center; gap: 8px }
.ficha-msg { font-size: 11.5px; color: var(--ink-2) }
/* En el teléfono los cuatro campos van uno debajo de otro: dos columnas de
   170 px dejan el RIF y el correo ilegibles justo donde más se teclean. */
@media (max-width: 620px) { .ficha-form { grid-template-columns: minmax(0, 1fr) } }
.cuenta-acciones { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px }
/* Los enlaces legales (la política de privacidad hay que poder encontrarla desde la app) llevaban el azul por defecto del
   navegador, casi ilegible sobre el fondo oscuro. */
.cuenta-legal a { color: var(--brand); text-underline-offset: 2px }
button.cuenta-eliminar.linkish { color: var(--bad); font-size: 12.5px }
/* Cortina de Face ID de la app de iPhone (#802): tapa el panel entero. */
.bloqueo-faceid {
  position: fixed; inset: 0; z-index: 2000; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 22px;
  background: #0A1628; color: #E6EEF7; text-align: center; padding: env(safe-area-inset-top) 24px env(safe-area-inset-bottom);
}
.bloqueo-faceid[hidden] { display: none }
.bloqueo-faceid svg { width: 88px; height: 88px }
.bloqueo-faceid p { margin: 0; font-size: 17px }
/* Te pidieron y no tiene precio (épico #404) */
.sin-precio-lista { margin-top: 8px }
.sin-precio-fila { display: flex; align-items: center; gap: 12px; padding: 9px 0; border-top: 1px solid var(--line) }
.sin-precio-fila:first-child { border-top: 0 }
.sin-precio-fila .what { flex: 1; min-width: 0 }
.sin-precio-fila .what b { display: block; font-size: 14px }
.sin-precio-fila .what span { color: var(--ink-3); font-size: 12.5px }
.sin-precio-fila .lnk { color: var(--brand); font-weight: 600; font-size: 12.5px; background: none; border: 0; padding: 0; cursor: pointer }
.sin-precio .pill { font-size: 12px; color: var(--ink-3) }
/* Estado del canal y del sistema (épico #404) */
.setup-status.warning { color: var(--warn) }
.setup-status.expired { color: var(--bad) }
.install-bar.estado-offline { border-color: var(--warn) }
.magazine-hoja { width: min(720px, calc(100vw - 24px)); max-height: calc(100vh - 24px); display: flex; flex-direction: column; padding: 14px }
.magazine-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 10px }
.magazine-head h3 { margin: 0 }
.magazine-marco { flex: 1; width: 100%; min-height: min(70vh, 720px); border: 1px solid var(--line); border-radius: 10px; background: #fff }
.consumo-aviso { color: var(--warn); font-weight: 600 }
/* «Cómo quieres ver a Surfia»: Ola · Cresta · Marea (épico #404). Cada loseta
   enseña un trozo del logo y el nombre vive en su lienzo — ver tema.js. */
.tema-titulo { display: block; color: var(--ink); font-size: 21px; letter-spacing: -.01em }
.tema-losetas { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; margin-top: 12px }
.tema-loseta {
  position: relative; height: 156px; padding: 0; text-align: left;
  background: var(--bg); border: 1px solid var(--line); border-radius: 14px;
  transition: border-color var(--t-fast) var(--ease);
}
.tema-loseta:hover { border-color: var(--aqua-35) }
.tema-lienzo { position: absolute; inset: 0; overflow: hidden; border-radius: 13px; background: var(--bg) }
.tema-art { position: absolute; left: 50%; transform: translateX(-50%); width: 148px }
.tema-loseta[data-tema="oscuro"] .tema-art { top: 34px }
.tema-loseta[data-tema="claro"] .tema-art { top: 6px }
.tema-loseta[data-tema="sistema"] .tema-art { top: 2px }
/* El rótulo trae su propio suelo. Sin él el nombre cae sobre la corriente y
   «como el teléfono», a 11,5 px sobre el marino, da 4,49:1 — por debajo del 4,5
   que pide un texto pequeño. El degradado deja que la ola se hunda detrás. */
.tema-lab {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 26px 12px 11px;
  background: linear-gradient(to top, var(--bg) 62%, transparent);
}
.tema-lab b { display: block; color: var(--ink); font-size: 16px; line-height: 1.2 }
.tema-lab span { display: block; color: var(--ink-3); font-size: 11.5px; margin-top: 2px }
/* La elegida va en --brand y no en --aqua: sobre el blanco el aqua da 1,7:1 y
   el aro se perdería justo en el tema que Cresta enciende. */
.tema-loseta.on { border-color: var(--brand); box-shadow: inset 0 0 0 1px var(--brand) }
.tema-check {
  position: absolute; top: 9px; right: 9px; z-index: 2; width: 20px; height: 20px;
  border-radius: var(--r-pill); background: var(--brand); color: var(--marino); display: grid; place-items: center;
}
.tema-check svg { width: 12px; height: 12px; fill: none; stroke: currentColor; stroke-width: 2.5 }

/* El marco blanco de Cresta cuelga de la OPCIÓN, no de «la elegida»: avisa de
   que al tocarla el panel se pone blanco, y eso es verdad esté elegida o no. */
.tema-loseta[data-tema="claro"] { background: var(--cresta-marco); padding: 12px }
.tema-loseta[data-tema="claro"] .tema-lienzo { inset: 12px; border-radius: 6px }
.tema-loseta[data-tema="claro"] .tema-art { width: 118px }

/* En el teléfono la loseta es ancha y baja: el dibujo se encoge y sube, o el
   suelo del rótulo se traga la corriente de abajo de Ola y parece que solo
   tuviera una. */
@media (max-width: 820px) {
  .tema-losetas { grid-template-columns: 1fr }
  .tema-loseta { height: 140px }
  .tema-art { width: 130px }
  .tema-loseta[data-tema="oscuro"] .tema-art { top: 12px }
  .tema-loseta[data-tema="sistema"] .tema-art { top: 2px }
}
.actualizado { font-size: 11.5px; color: var(--ink-3); background: none; border: 0; padding: 4px 8px; cursor: pointer; white-space: nowrap }
.actualizado:hover { color: var(--ink-2) }

/* ---------- barra de estado de datos ---------- */
.databar {
  display: flex; align-items: center; gap: 10px; padding: 9px 14px; border-radius: var(--r-sm);
  font-size: 12.5px; margin-bottom: 16px; border: 1px solid;
}
.databar.demo { background: var(--aqua-soft); border-color: rgba(34, 211, 238, .3); color: var(--ink-2) }
.databar.live { background: var(--ok-soft); border-color: rgba(14, 159, 110, .3); color: var(--ink-2) }
.databar.err  { background: var(--bad-soft); border-color: rgba(214, 69, 69, .3); color: var(--ink-2) }
.databar b { color: var(--ink) }
.databar button { margin-left: auto; font-size: 12px; font-weight: 700; color: var(--brand); white-space: nowrap }

/* ---------- topbar ---------- */
.top { display: flex; align-items: center; gap: 14px; margin-bottom: 18px; flex-wrap: wrap }
.top .biz { display: flex; align-items: center; gap: 10px }
.top .biz .av {
  width: 38px; height: 38px; border-radius: 12px; background: var(--brand-grad); color: #fff;
  display: grid; place-items: center; font-weight: 700; font-size: 15px;
}
.top .biz .nm { font-weight: 700; font-size: 16px; letter-spacing: -.01em }
.top .biz .sub { font-size: 12.5px; color: var(--ink-3) }
.top .sp { flex: 1 }
.seg { display: flex; background: var(--card); border: 1px solid var(--line); border-radius: var(--r-sm); padding: 3px; box-shadow: var(--shadow) }
.seg button { padding: 6px 13px; border-radius: 8px; font-size: 12.5px; font-weight: 600; color: var(--ink-3); transition: all .15s }
.seg button.on { background: var(--aqua-soft); color: var(--brand) }

.chips { display: flex; gap: 8px; margin-bottom: 20px; overflow-x: auto; padding-bottom: 2px; scrollbar-width: none }
.chips::-webkit-scrollbar { display: none }
/* Las categorías del catálogo (#inv-cats) en ESCRITORIO se ven enteras y bajan
   de línea. Con el scrollbar oculto y sin el degradé del móvil, la fila que se
   deslizaba parecía cortada a secas: «Food Storage Containe» (Chez Toto,
   15-sep-2026). Una categoría que no se ve es una categoría que no se filtra.
   En el móvil sigue deslizándose con su degradé (regla de más abajo). */
@media (min-width: 821px) {
  #inv-cats { flex-wrap: wrap; overflow-x: visible; row-gap: 8px }
}
.chip {
  display: flex; align-items: center; gap: 7px; padding: 7px 14px; border-radius: var(--r-pill); white-space: nowrap;
  background: var(--card); border: 1px solid var(--line); font-size: 13px; font-weight: 600; color: var(--ink-2);
  transition: all .15s; box-shadow: var(--shadow); scroll-snap-align: start;
}
.chip svg { width: 14px; height: 14px }
.chip.on { border-color: var(--brand); color: var(--brand); background: var(--aqua-soft) }
.chip .n { font-size: 12px; font-weight: 600; color: var(--ink-3) }
.chip.on .n { color: var(--brand) }
/* Canal de pruebas: se ve, pero en segundo plano y con borde punteado — que
 * nadie lo confunda con un canal por el que llegan clientes. */
.chip.tech { border-style: dashed; color: var(--ink-3); opacity: .75 }
.chip.tech.on { opacity: 1 }

h1 { font-size: 22px; font-weight: 700; letter-spacing: -.02em; margin-bottom: 4px }
.sub-h { color: var(--ink-3); font-size: 14px; margin-bottom: 20px }
.sub-h b { color: var(--brand); font-weight: 600 }
/* La tasa BCV de hoy, bajo el saludo de Inicio (tasa-hoy.js): un dato, no una tarjeta. */
.tasa-hoy { color: var(--ink-2); font-size: 13px; margin: -14px 0 18px; font-variant-numeric: tabular-nums }
/* Antes: 12px, gris y en MAYÚSCULAS — el rótulo pesaba MENOS que el contenido
   que estaba separando, así que bajar por Inicio era recorrer una lista plana.
   Ahora se lee primero y en tinta plena: la pantalla tiene capítulos. */
h2 { font-size: 15px; font-weight: 600; letter-spacing: -.01em; color: var(--ink); margin: 30px 0 12px }

.screen { display: none; animation: in .3s ease }
.screen.on { display: block }
@keyframes in { from { opacity: 0; transform: translateY(6px) } to { opacity: 1; transform: none } }

.empty { text-align: center; color: var(--ink-3); font-size: 13.5px; padding: 26px 16px }

/* ---------- el número que preside ----------
   Una sola cifra manda en la pantalla. Antes había seis tarjetas iguales y
   ninguna era la primera que se miraba.

   El orden se cambia con flexbox y no moviendo el HTML: el saludo se encoge a
   una línea de entrada, el número sube inmediatamente detrás —tiene que caber
   en el primer vistazo, sin desplazar— y la frase de contexto baja a
   explicarlo. Todo lo demás conserva su orden de origen. */
/* ⚠️ `.on` es obligatorio: las pantallas se conmutan con `.screen.on { display:
   block }`, y un `#s-inicio { display: flex }` a secas le gana por
   especificidad — Inicio se quedaba pegado encima de Chats, Ventas y las demás. */
#s-inicio.on { display: flex; flex-direction: column }
#s-inicio > * { order: 4 }
#s-inicio > #greet { order: 1; font-size: 15px; font-weight: 600; color: var(--ink-3); margin-bottom: 6px }
#s-inicio > .hero-num { order: 2 }
#s-inicio > #greet-sub { order: 3 }

.hero-num { margin: 0 0 4px }
.hero-num__go { display: block; width: 100%; text-align: left; padding: 0 }
.hero-num__val {
  display: block;
  font-size: clamp(52px, 15vw, 76px);
  font-weight: 700;
  letter-spacing: -.045em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  /* el degradado de marca sobre el número, no detrás: es el único sitio de la
     pantalla donde el color de Surfia aparece a este tamaño */
  background: linear-gradient(120deg, var(--ink) 12%, var(--aqua) 130%);
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
}
.hero-num__meta { display: flex; align-items: center; gap: 10px; margin-top: 10px; flex-wrap: wrap }
.hero-num__lbl { font-size: 14px; color: var(--ink-2) }
.hero-num__meta .trend { font-size: 11.5px; font-weight: 700; font-family: var(--mono); padding: 3px 9px; border-radius: var(--r-pill) }
/* la letra pequeña bajo el número grande: lo que NO está en él ("$X cotizado · 2 por confirmar") */
.hero-num__desglose { display: block; margin-top: 5px; font-size: 12.5px; color: var(--ink-3); font-variant-numeric: tabular-nums }
/* la letra pequeña de «Cotizado»: "2 confirmadas · 3 por confirmar" */
.kpi .kpi-sub { font-size: 12px; color: var(--ink-3); margin: -4px 0 8px; font-variant-numeric: tabular-nums }
.hero-num__meta .trend.up { color: var(--ok); background: var(--ok-soft) }
.hero-num__meta .trend.dn { color: var(--bad); background: var(--bad-soft) }

/* ---------- alertas ---------- */
.alerts { display: flex; flex-direction: column; gap: 8px; margin-bottom: 20px }
/* Barra de color a la izquierda en vez de caja pastel: sobre fondo oscuro los
   rellenos suaves se convierten en manchas y todas las alertas se parecen. */
.alert {
  display: flex; align-items: center; gap: 10px;
  padding: 13px 14px 13px 12px;
  border-radius: var(--r-sm);
  font-size: 13.5px; font-weight: 500;
  border: 1px solid var(--line);
  border-left: 3px solid var(--ink-3);
  background: var(--card);
}
.alert.warning  { border-color: var(--line); border-left-color: var(--warn); background: var(--card); color: var(--ink) }
.alert.critical { border-color: rgba(214, 69, 69, .4); border-left-color: var(--bad); background: var(--card); color: var(--ink) }
.alert.ok { border-left-color: var(--ok) }
.alert .ico { font-size: 15px }
.alert .go { margin-left: auto; font-size: 12.5px; font-weight: 700; color: var(--brand); white-space: nowrap }
/* La barra entera es el botón: en el teléfono, apuntarle al «Ver →» es un
   ejercicio de puntería. El reset global de `button` (arriba) ya quitó fondo y
   borde propios, así que solo hay que devolverle el ancho y la alineación que
   un div traía de fábrica. */
button.alert { width: 100%; text-align: left }
button.alert:hover { border-color: var(--brand); background: var(--card-2) }
button.alert:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px }
/* Un solo foco para toda la hoja: 2px de marca, separado 2px. Las variantes
   con halo extra se quitaron abajo — competían con el color de estado. */

/* ---------- KPIs ----------
   Segundo plano a propósito: la cifra que manda ya está arriba, y estas son el
   detalle para quien quiera bajar a mirarlo. */
.kpis { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px }
.kpi {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r); padding: 15px 16px 13px;
  box-shadow: var(--shadow); transition: transform .18s, box-shadow .18s; position: relative; overflow: hidden; min-width: 0;
}
.kpi:hover { transform: translateY(-2px); box-shadow: var(--shadow-lift) }
.kpi .lbl { font-size: 12px; font-weight: 600; color: var(--ink-3); padding-right: 56px }
.kpi .val { font-size: 26px; font-weight: 700; letter-spacing: -.03em; margin: 5px 0 8px; font-variant-numeric: tabular-nums }
.kpi .val small { font-size: 14px; color: var(--ink-3); font-weight: 600 }
.kpi .split { display: flex; flex-wrap: wrap; gap: 6px 10px; font-size: 12px; color: var(--ink-3) }
.kpi .split span { display: flex; align-items: center; gap: 5px }
.kpi .split i { width: 8px; height: 8px; border-radius: 3px; flex: none }
.kpi .split svg { width: 12px; height: 12px; flex: none }
.kpi .split .whatsapp i { background: var(--wa) }
.kpi .split .instagram i { background: var(--ig-grad) }
.kpi .trend { position: absolute; top: 14px; right: 14px; font-size: 11px; font-weight: 700; font-family: var(--mono); padding: 3px 9px; border-radius: var(--r-pill) }
.kpi .trend.up { color: var(--ok); background: var(--ok-soft) }
.kpi .trend.dn { color: var(--bad); background: var(--bad-soft) }

/* La tarjeta de ventas ya NO se pinta aquí: pasó a ser el número que preside
   la pantalla (.hero-num). La regla se conserva por si el héroe elegido es
   otro y `sales_total` vuelve a la rejilla — ahí sigue siendo la que el dueño
   busca primero (mockup de Luis). */
.kpi.hero { background: var(--brand-grad); border: none; color: #fff }
.kpi.hero .lbl, .kpi.hero .split, .kpi.hero .kpi-sub { color: rgba(255, 255, 255, .82) }
.kpi.hero .trend { background: rgba(255, 255, 255, .2); color: #fff }

/* ---------- gráfico ---------- */
.card { background: var(--card); border: 1px solid var(--line); border-radius: var(--r); padding: 18px; box-shadow: var(--shadow) }
.chart { display: flex; align-items: flex-end; gap: 10px; height: 130px; margin-top: 14px }
.chart .col { flex: 1; display: flex; flex-direction: column; justify-content: flex-end; gap: 3px; height: 100%; min-width: 0 }
.chart .b { border-radius: 6px 6px 3px 3px; min-height: 3px; transition: height .5s cubic-bezier(.2, .8, .2, 1) }
.chart .b.whatsapp { background: var(--wa); opacity: .9 }
.chart .b.instagram { background: var(--ig-grad); opacity: .85; border-radius: 3px }
.chart .d { font-family: var(--mono); font-size: 10px; color: var(--ink-3); text-align: center; margin-top: 7px }
.legend { display: flex; gap: 16px; font-size: 12px; color: var(--ink-2); margin-top: 4px; flex-wrap: wrap }
.legend span { display: flex; align-items: center; gap: 6px }
.legend i { width: 9px; height: 9px; border-radius: 3px }
.legend .whatsapp i { background: var(--wa) }
.legend .instagram i { background: var(--ig-grad) }

/* ---------- feed ---------- */
.feed { display: flex; flex-direction: column }
.ev { display: flex; gap: 12px; padding: 13px 4px; border-bottom: 1px solid var(--line-2); align-items: flex-start }
.ev:last-child { border: none }
/* Las líneas del feed que tienen conversación detrás son botones: llevan al
   chat donde pasó. Se comportan como fila, no como botón (sin fondo propio),
   pero avisan al pasar por encima y con el teclado. */
button.ev { width: 100%; text-align: left; background: none; border-radius: 10px; transition: background .15s }
button.ev.ev-go:hover { background: var(--aqua-soft) }
button.ev.ev-go:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px }
.ev .ch { width: 32px; height: 32px; border-radius: 10px; display: grid; place-items: center; flex: none }
.ev .ch.whatsapp { background: var(--wa-soft) }
.ev .ch.instagram { background: var(--ig-soft) }
.ev .ch svg { width: 16px; height: 16px }
.ev .tx { font-size: 13.5px; color: var(--ink-2); flex: 1; min-width: 0 }
.ev .tag { font-size: 11.5px; font-weight: 600; padding: 3px 10px; border-radius: var(--r-pill); margin-left: 6px; white-space: nowrap }
.tag.cita { background: var(--aqua-soft); color: var(--brand) }
.tag.venta { background: var(--ok-soft); color: var(--ok) }
.tag.esc { background: var(--warn-soft); color: var(--warn) }
.ev .t { font-family: var(--mono); font-size: 10.5px; color: var(--ink-3); white-space: nowrap; padding-top: 2px }

/* ---------- conversaciones ---------- */
.convs { display: flex; flex-direction: column; gap: 9px }
.conv {
  display: flex; gap: 12px; align-items: center; background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-sm); padding: 13px 15px; box-shadow: var(--shadow); cursor: pointer;
  transition: all .15s; text-align: left; width: 100%;
}
.conv:hover { transform: translateY(-1px); box-shadow: var(--shadow-lift); border-color: var(--brand) }
.conv .av { width: 38px; height: 38px; border-radius: 50%; display: grid; place-items: center; font-weight: 700; font-size: 14px; color: #fff; flex: none; position: relative }
.conv .av .mini { position: absolute; bottom: -3px; right: -3px; width: 17px; height: 17px; border-radius: 6px; background: var(--card); display: grid; place-items: center; border: 1px solid var(--line) }
.conv .av .mini svg { width: 10px; height: 10px }
.conv .bd { flex: 1; min-width: 0 }
.conv .nm { font-weight: 600; font-size: 14px; display: flex; align-items: center; gap: 6px; min-width: 0 }
/* El titular son dos piezas: quién es y de dónde (#404). En 375 px no caben las
   dos enteras y hay que elegir cuál se rompe: la persona es a quien el dueño
   saluda, así que se corta la EMPRESA.
   La empresa CRECE desde cero (`flex: 1 1 0`) en vez de encogerse desde su
   texto. No es lo mismo: repartiendo el encogimiento —aunque sea 999 a 1— a la
   persona le tocaba una fracción de píxel, y una caja 0,05 px más corta que su
   texto ya dispara `text-overflow`. Medido: «Ramon Silva» ocupaba 84,40 px en
   una caja de 84,35 y salía «Ramon Sil…» teniendo sitio de sobra. Con base 0 no
   hay nada que repartir: la persona conserva su ancho natural y la empresa se
   queda con lo que sobre. Si la persona sola no cabe, entonces sí encoge ella,
   que es el único caso en que debe.
   Sin `min-width: 0` la elipsis no llega a actuar y la fila se parte en cuatro
   renglones — que es lo que hacía el nombre de SUILLA antes de esto. */
.conv .nm .qn { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
.conv .nm .qs { flex: none; color: var(--ink-3); font-weight: 400 }
.conv .nm .qd { flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; color: var(--ink-2) }
.conv .sn { font-size: 12.5px; color: var(--ink-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-top: 1px }
/* Cuando un cliente te espera, POR QUÉ te espera importa más que releer lo
   último que escribió: el motivo ocupa el lugar del snippet y se distingue por
   color, no por tamaño (la fila tiene que seguir midiendo lo mismo). */
.conv .sn.motivo { color: var(--warn); font-weight: 600 }
/* El motivo es la razón de ser de esta fila: dejarlo en una línea con puntos
   suspensivos («Lleva 28 min · Pide un d…») lo vuelve inútil justo en el
   teléfono, que es donde el dueño lo va a leer. Dos líneas y hasta ahí. */
.conv .sn.motivo { white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; line-height: 1.35 }
/* La columna derecha manda la altura de la fila: con día + hora + estado son
   TRES renglones. `min-height` iguala TODAS las filas — una lista donde las de
   hoy son más bajas que las de ayer se ve dentada al desplazar. */
.conv .mt { display: flex; flex-direction: column; align-items: flex-end; justify-content: space-between; gap: 3px; flex: none; min-height: 52px }
.conv .tm { font-family: var(--mono); font-size: 10.5px; color: var(--ink-3); line-height: 1.2 }
/* El día va encima de la hora y pesa un punto más: es lo que ORDENA la lista.
   Solo aparece cuando NO es de hoy (ver etiquetaDia en ui.js). */
.conv .dy { font-family: var(--mono); font-size: 10.5px; font-weight: 600; color: var(--ink-2); line-height: 1.2; white-space: nowrap }

/* No leídos (#135): el punto con número, como cualquier app de mensajes. Sin
   contador (demo o servidor viejo) el punto queda solo y sigue diciendo lo
   importante: aquí hay algo que no has visto. */
.conv.unread .nm { font-weight: 800 }
.conv.unread .sn { color: var(--ink-2); font-weight: 600 }
.unread-n { min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px; background: var(--brand); color: #fff; font-size: 11px; font-weight: 700; font-family: var(--mono); display: grid; place-items: center; line-height: 1 }

.st { font-size: 11.5px; font-weight: 600; padding: 3px 10px; border-radius: var(--r-pill); white-space: nowrap }
.st.resolved { background: var(--ok-soft); color: var(--ok) }
.st.waiting_owner { background: var(--warn-soft); color: var(--warn) }
.st.booked { background: var(--aqua-soft); color: var(--brand) }
/* Sin responder es lo más grave que puede pasarle a un chat: hay un cliente
   esperando y nadie lo sabe. Va en rojo, no en ámbar como "te espera" — esa
   al menos la escaló el agente a propósito. */
.st.unanswered { background: var(--bad-soft); color: var(--bad) }
/* El dueño tomó el volante en este chat: Surfia está callada ahí. Se lee en
   la lista, no solo dentro del hilo — era fácil olvidar dónde había pausado. */
.st.paused { background: var(--aqua-soft); color: var(--brand); border: 1px dashed currentColor }

.btn { padding: 12px 18px; border-radius: var(--r-sm); font-size: 13.5px; font-weight: 700; transition: all var(--t-fast) }
.btn.primary { background: var(--brand-grad); color: #fff; box-shadow: 0 8px 20px -12px rgba(2, 132, 199, .55) }
.btn.primary:hover { transform: translateY(-1px) }
.btn.ghost { background: var(--aqua-soft); color: var(--brand) }
.btn[disabled] { opacity: .5; cursor: not-allowed; transform: none }

/* ---------- ventas ---------- */
.totals { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr) minmax(0, 1fr); gap: 12px; margin-bottom: 16px }
.tot { background: var(--card); border: 1px solid var(--line); border-radius: var(--r); padding: 15px 16px; box-shadow: var(--shadow); min-width: 0 }
.tot .lbl { font-size: 12px; font-weight: 600; color: var(--ink-3); display: flex; align-items: center; gap: 6px }
.tot .lbl svg { width: 13px; height: 13px }
.tot .val { font-size: 24px; font-weight: 700; letter-spacing: -.03em; margin-top: 5px; font-variant-numeric: tabular-nums }
.tot.hero { background: var(--brand-grad); border: none; color: #fff }
.tot.hero .lbl { color: rgba(255, 255, 255, .8) }
.rows { display: flex; flex-direction: column }
.row { display: flex; align-items: center; gap: 12px; padding: 12px 4px; border-bottom: 1px solid var(--line-2); font-size: 13.5px }
.row:last-child { border: none }
.row .ch-i { width: 28px; height: 28px; border-radius: 9px; display: grid; place-items: center; flex: none }
.row .ch-i.whatsapp { background: var(--wa-soft) }
.row .ch-i.instagram { background: var(--ig-soft) }
.row .ch-i svg { width: 14px; height: 14px }
.row .what { flex: 1; min-width: 0 }
.row .what b { font-weight: 600; display: block }
.row .what span { font-size: 12px; color: var(--ink-3) }
.row .by { font-size: 11.5px; font-weight: 600; padding: 3px 10px; border-radius: var(--r-pill); white-space: nowrap }
.row .by.agent { background: var(--aqua-soft); color: var(--brand) }
.row .by.owner { background: var(--card-2); color: var(--ink-3); border: 1px solid var(--line) }
.row .amt { font-family: var(--mono); font-weight: 700; font-size: 14px; white-space: nowrap; font-variant-numeric: tabular-nums }
.row.summary { border-top: 1px solid var(--line); margin-top: 4px }
.row.summary b { font-family: var(--mono); font-size: 12px; color: var(--ink-3); font-weight: 600 }

/* ---------- pedidos ---------- */
.orders { display: flex; flex-direction: column; gap: 9px }
.orders-summary { display: flex; justify-content: space-between; align-items: baseline; margin: 0 0 10px; color: var(--ink-3); font-size: 13px }
.orders-summary b { color: var(--ink); font-size: 18px }
.orders-summary b small { font-size: 12px; font-weight: 500; color: var(--ink-3) }
.orders-note { margin: 0 0 10px; color: var(--ink-3); font-size: 12px }
.order { background: var(--card); border: 1px solid var(--line); border-radius: var(--r-sm); padding: 13px 15px; box-shadow: var(--shadow) }
.order-head, .order-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap }
.order-head b { display: block; font-size: 14px }
.order-head span, .order-foot span { color: var(--ink-3); font-size: 12px }
.order-head .st { color: var(--ink); font-size: 11px }
.order-attention { display: grid; gap: 4px; margin-top: 10px; padding: 10px 12px; border-left: 3px solid var(--warn); background: var(--card-2); color: var(--ink-2); font-size: 12px }
.order-attention b { color: var(--ink) }
.order ul { margin: 11px 0; padding-left: 18px; color: var(--ink-2); font-size: 13px }
.order li { padding: 2px 0 }
.order li span { float: right; color: var(--ink); font-weight: 600 }
.order li em { color: var(--ink-3); font-size: 11px; font-style: normal }
.order-foot strong { color: var(--brand); font-size: 16px }
.order-foot > span { display: flex; align-items: center; gap: 4px }
.order-foot svg { width: 12px; height: 12px }
.order-open { border: 0; background: transparent; color: var(--brand); cursor: pointer; font-size: 12px; padding: 4px 8px }
.order-open:hover { text-decoration: underline }
.st.confirmed { background: var(--ok-soft); color: var(--ok) }
.st.reminded { background: var(--aqua-soft); color: var(--brand) }
.st.new { background: var(--warn-soft); color: var(--warn) }

/* ---------- inventario ---------- */
.invs { display: flex; flex-direction: column; gap: 9px }
.inv { background: var(--card); border: 1px solid var(--line); border-radius: var(--r-sm); padding: 13px 15px; box-shadow: var(--shadow) }
.inv .r1 { display: flex; align-items: center; gap: 10px; flex-wrap: wrap }
.inv .r1 b { font-weight: 600; font-size: 14px; flex: 1; min-width: 120px }
/* El nombre es un botón que abre la edición; el lápiz es el aviso de que se
   puede. Hereda el estilo del <b> para que la fila se vea igual que siempre. */
.inv .inv-name { display: flex; align-items: center; gap: 6px; flex: 1; min-width: 120px; text-align: left; color: inherit; padding: 0 }
.inv .inv-name b { flex: initial; min-width: 0 }
.inv .inv-name .pen { width: 13px; height: 13px; color: var(--ink-3); flex: none }
.inv .inv-name:hover b, .inv .inv-name:hover .pen { color: var(--brand) }
.inv .r1 .qty { font-family: var(--mono); font-size: 12.5px; font-weight: 700 }
.inv .bar { height: 6px; border-radius: 3px; background: var(--line-2); margin-top: 10px; overflow: hidden }
.inv .bar i { display: block; height: 100%; border-radius: 3px; transition: width .6s ease }
.inv .r2 { display: flex; gap: 8px; margin-top: 8px; font-size: 11px; color: var(--ink-3); align-items: center }
.pill { font-size: 11.5px; font-weight: 600; padding: 3px 10px; border-radius: var(--r-pill); white-space: nowrap }
.pill.critical { background: var(--bad-soft); color: var(--bad) }
.pill.warning { background: var(--warn-soft); color: var(--warn) }
.pill.hot { background: var(--aqua-soft); color: var(--brand) }

/* ---------- canales ---------- */
.duel { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 12px }
.side-card { background: var(--card); border: 1px solid var(--line); border-radius: var(--r); padding: 17px; box-shadow: var(--shadow); min-width: 0 }
.side-card .hd { display: flex; align-items: center; gap: 9px; font-weight: 700; font-size: 15px; margin-bottom: 14px }
.side-card .hd .ch { width: 30px; height: 30px; border-radius: 9px; display: grid; place-items: center }
.side-card .hd .ch.whatsapp { background: var(--wa-soft) }
.side-card .hd .ch.instagram { background: var(--ig-soft) }
.side-card .hd .ch svg { width: 15px; height: 15px }
.mrow { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--line-2); font-size: 13px; color: var(--ink-2) }
.mrow:last-child { border: none }
.mrow b { font-family: var(--mono); font-size: 14px; color: var(--ink); font-weight: 700; font-variant-numeric: tabular-nums }
.vs-bars { margin-top: 12px }
.vs { margin-bottom: 14px }
.vs .lbl { display: flex; justify-content: space-between; gap: 10px; font-size: 12px; color: var(--ink-2); margin-bottom: 6px }
.vs .lbl b { font-family: var(--mono) }
.vs .track { display: flex; height: 10px; border-radius: 5px; overflow: hidden; background: var(--line-2) }
.vs .track .whatsapp { background: var(--wa) }
.vs .track .instagram { background: linear-gradient(90deg, #F58529, #DD2A7B) }
.insight { margin-top: 16px; padding: 14px 16px; border-radius: var(--r-sm); background: var(--aqua-soft); border: 1px solid rgba(34, 211, 238, .3); font-size: 13.5px; color: var(--ink-2) }
.insight .k { font-size: 12px; font-weight: 600; color: var(--brand); display: block; margin-bottom: 4px }

/* ---------- barra de instalación (PWA) ---------- */
/* Arranca DESPUÉS de la barra lateral (232px): a todo lo ancho tapaba el pie de
   la lateral, y con él el botón "Salir" — quien tuviera el aviso de instalar no
   podía cerrar sesión. Lo encontró una prueba automatizada al no poder hacer
   clic en Salir. */
.install-bar {
  position: fixed; left: calc(232px + 12px); right: 12px;
  bottom: calc(12px + env(safe-area-inset-bottom)); z-index: 60;
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 12px 14px; border-radius: var(--r); background: var(--card);
  border: 1px solid var(--line); box-shadow: var(--shadow-lift); font-size: 13.5px;
  animation: in .3s ease;
}
.install-bar[hidden] { display: none }
.install-bar > span { flex: 1 1 200px }
.install-bar .btn { padding: 9px 16px; font-size: 13px }
.install-x { font-size: 15px; color: var(--ink-3); padding: 4px 8px; border-radius: 8px }
.install-x:hover { background: var(--card-2); color: var(--ink) }
/* En móvil no hay barra lateral: vuelve a todo lo ancho, pero por encima de la
   navegación inferior para no tapar los íconos. */
@media (max-width: 820px) {
  .install-bar { left: 12px; bottom: calc(72px + env(safe-area-inset-bottom)) }
}

/* La guía acompaña los menús del teléfono con los mismos colores del panel. */
#installation-guide { max-width: calc(100vw - 24px); max-height: calc(100dvh - 32px) }
#installation-guide .installation-guide-sheet {
  width: min(440px, calc(100vw - 24px));
  max-height: calc(100dvh - 32px);
  overflow-y: auto;
  padding: 24px;
  color: var(--ink);
}
.installation-guide-head { display: flex; align-items: flex-start; gap: 12px; justify-content: space-between }
.installation-guide-head > div { min-width: 0 }
#installation-guide .installation-guide-kicker {
  color: var(--ink-3); font-size: 11px; letter-spacing: .04em; margin: 0 0 10px;
}
#installation-guide h2 { font-size: 23px; line-height: 1.25; margin: 0 0 24px; text-wrap: balance }
#installation-guide .installation-guide-device { display: block; margin: 0 0 7px; color: var(--ink-3); font-size: 12px }
#installation-guide select {
  width: 100%; min-height: 44px; padding: 10px 12px; font: inherit; font-size: 14px;
  color: var(--ink); background: var(--card-2); border: 1px solid var(--line); border-radius: var(--r-sm);
}
#installation-guide .installation-guide-order { color: var(--ink-3); font-size: 12px; margin: 24px 0 8px }
#installation-guide-step { color: var(--ink); font-size: 16px; line-height: 1.65; margin-bottom: 12px }
#installation-guide .installation-guide-help-button { padding: 10px 0; text-align: left; font-size: 13px; min-height: 44px }
#installation-guide .installation-guide-help-text {
  background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: 14px; margin: 8px 0 0; font-size: 14px; line-height: 1.6;
}
#installation-guide .installation-guide-actions { display: flex; gap: 10px; margin-top: 24px }
#installation-guide .installation-guide-actions .btn { min-height: 46px }
#installation-guide .installation-guide-actions .primary { flex: 1 }
#installation-guide .btn:focus-visible, #installation-guide select:focus-visible {
  outline: 2px solid var(--ink); outline-offset: 3px;
}
#member-links { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 18px }

/* ---------- bienvenida ----------
   La primera pantalla. Cubre TODO —incluida la navegación inferior— porque
   quien todavía no entró no tiene nada que navegar; antes se veía el panel de
   un negocio ficticio por detrás del formulario, y eso confunde a cualquiera.
   Va por encima del diálogo (z 90 contra el 100 del <dialog>) para que la hoja
   de entrada suba SOBRE las ondas y no las tape. */
.welcome {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: grid;
  background: var(--marino);
  overflow: hidden;
}
.welcome__waves,
.welcome__veil { position: absolute; inset: 0; width: 100%; height: 100% }
/* El velo apaga las ondas justo donde hay texto, arriba y abajo, para que el
   titular y los botones se lean sin bajarle la vida al fondo. */
.welcome__veil {
  background:
    linear-gradient(180deg, rgba(5, 13, 24, .92) 0%, rgba(5, 13, 24, .35) 34%, rgba(5, 13, 24, .55) 68%, rgba(5, 13, 24, .95) 100%);
  pointer-events: none;
}
.welcome__inner {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 24px;
  padding: clamp(48px, 9vh, 88px) 24px calc(34px + env(safe-area-inset-bottom));
  width: min(460px, 100%);
  margin: 0 auto;
  text-align: center;
}
.welcome__brand { display: flex; align-items: center; justify-content: center; gap: 12px }
.welcome__mark { width: 46px; height: 40px }
.welcome__word { font-size: 30px; font-weight: 700; letter-spacing: -.04em; color: #fff }

.welcome__claim {
  font-size: clamp(26px, 7.5vw, 34px);
  font-weight: 700;
  line-height: 1.18;
  letter-spacing: -.03em;
  color: #fff;
  margin: auto 0;
}
.welcome__claim span { color: var(--aqua) }
.welcome__aviso { margin: 14px 0 0; font-size: 14.5px; color: var(--aqua); text-wrap: balance }

.welcome__actions { display: grid; gap: 10px }
.wbtn {
  width: 100%;
  padding: 17px 20px;
  border-radius: var(--r-pill);
  font-size: 16px;
  font-weight: 600;
  transition: transform .15s ease, opacity .15s ease;
}
.wbtn:active { transform: scale(.985) }
.wbtn--solid { background: #fff; color: #071322 }
/* Vidrio sobre las ondas: se ve el fondo moverse por debajo del botón. */
.wbtn--ghost {
  background: rgba(255, 255, 255, .10);
  border: 1px solid rgba(255, 255, 255, .22);
  color: #fff;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
.welcome__minor { display: flex; align-items: center; justify-content: center; gap: 10px; margin-top: 6px; color: rgba(255, 255, 255, .38) }
.wlink { font-size: 13.5px; font-weight: 600; color: rgba(255, 255, 255, .72); padding: 6px 2px }
.wlink:hover { color: #fff }
.wbtn[hidden], .wlink[hidden], .welcome__minor [hidden] { display: none }

/* ---------- diálogo de conexión ---------- */
/* `margin: auto` lo trae el navegador para todo <dialog> abierto con
   showModal() — es lo que lo centra en la pantalla. Nuestro reset
   `* { margin: 0 }` se lo llevaba por delante, y las siete hojas del panel
   salían pegadas a la esquina de arriba a la izquierda con el resto de la
   pantalla vacío. Se devuelve aquí, en el elemento, para que valga en todas;
   la de bienvenida y la de ajustes en el teléfono lo vuelven a pisar más
   abajo con `auto auto 0` porque esas suben desde el borde de abajo. */
dialog { border: none; padding: 0; background: transparent; margin: auto }
dialog::backdrop { background: rgba(10, 22, 40, .55); backdrop-filter: blur(2px) }
/* Sobre la bienvenida el diálogo no lleva fondo propio: taparía las ondas, que
   son justamente lo que tiene que seguir viéndose detrás de la hoja. */
.welcome-on dialog::backdrop { background: rgba(5, 13, 24, .45); backdrop-filter: blur(6px) }
/* Y la hoja sube desde abajo, pegada al borde, como en una app — no aparece
   flotando en el centro de la pantalla. */
.welcome-on #connect { margin: auto auto 0; max-width: 100%; width: 100% }
.welcome-on #auth-sheet {
  width: min(460px, 100%);
  margin: 0 auto;
  border-radius: 24px 24px 0 0;
  border-bottom: none;
  padding-bottom: calc(22px + env(safe-area-inset-bottom));
  animation: sheet-up .28s cubic-bezier(.2, .8, .3, 1);
}
@keyframes sheet-up { from { transform: translateY(16px); opacity: 0 } to { transform: none; opacity: 1 } }
/* En la hoja, la acción principal es una barra a todo lo ancho y las otras dos
   bajan a texto. Tres botones del mismo tamaño apretados en una esquina —como
   estaban— obligan a leerlos para saber cuál es el que uno vino a pulsar. */
.welcome-on .sheet .actions { display: grid; grid-template-columns: 1fr 1fr; gap: 2px; justify-content: stretch }
.welcome-on .sheet .actions .btn.primary { order: 1; grid-column: 1 / -1; width: 100%; padding: 15px; border-radius: var(--r-pill); font-size: 15px }
.welcome-on .sheet .actions .btn.ghost {
  order: 2;
  background: none;
  border: none;
  box-shadow: none;
  color: var(--ink-3);
  font-size: 13px;
  padding: 8px;
}
.welcome-on .sheet .actions .btn.ghost:hover { color: var(--ink) }
.welcome-on .sheet #switch-code { display: block; width: 100%; text-align: center; margin-top: 2px; color: var(--ink-3) }
.welcome-on .auth-head { justify-content: center; margin-bottom: 2px }
.welcome-on .auth-head h3 { font-size: 19px }
/* La barra de arrastre de una hoja de app: dice "esto sube y baja" sin texto. */
.welcome-on #auth-sheet::before {
  content: "";
  display: block;
  width: 38px;
  height: 4px;
  border-radius: var(--r-pill);
  background: var(--line);
  margin: -6px auto 16px;
}
.sheet { background: var(--card); color: var(--ink); border: 1px solid var(--line); border-radius: var(--r); padding: 22px; width: min(440px, calc(100vw - 32px)); box-shadow: var(--shadow-lift) }
.sheet h3 { font-size: 17px; margin-bottom: 6px }
.sheet p { font-size: 13px; color: var(--ink-3); margin-bottom: 16px }
.field { margin-bottom: 12px }
.field label { display: block; font-size: 12px; font-weight: 600; color: var(--ink-3); margin-bottom: 5px }
.field input { width: 100%; padding: 10px 12px; border-radius: var(--r-sm); border: 1px solid var(--line); background: var(--card-2); color: var(--ink); font-size: 13.5px; font-family: var(--mono) }
.field input:focus { outline: 2px solid var(--brand); outline-offset: 1px; border-color: var(--brand) }
/* El desplegable hereda el chrome del navegador (blanco) si nadie lo viste, y
   en el panel oscuro se lee como un error. Mismo traje que los inputs. */
.field select { width: 100%; padding: 10px 12px; border-radius: var(--r-sm); border: 1px solid var(--line); background: var(--card-2); color: var(--ink); font-size: 13.5px; font-family: var(--mono); appearance: none; background-image: linear-gradient(45deg, transparent 50%, var(--ink-3) 50%), linear-gradient(135deg, var(--ink-3) 50%, transparent 50%); background-position: right 16px center, right 11px center; background-size: 5px 5px, 5px 5px; background-repeat: no-repeat }
.field select:focus { outline: 2px solid var(--brand); outline-offset: 1px; border-color: var(--brand) }
.sheet .msg { font-size: 12.5px; margin-bottom: 12px; min-height: 18px }
.sheet .msg.ok { color: var(--ok) }
.sheet .msg.err { color: var(--bad) }
.sheet .actions { display: flex; gap: 10px; justify-content: flex-end; flex-wrap: wrap }

/* ---------- entrar / crear cuenta ---------- */
.auth-head { display: flex; align-items: center; gap: 10px; margin-bottom: 4px }
.auth-head .mark { width: 30px; height: 26px; display: grid; place-items: center; flex: none }
.auth-head .mark svg { width: 28px; height: 24px }
.auth-head h3 { margin: 0 }

.auth-tabs { display: flex; gap: 6px; background: var(--card-2); border: 1px solid var(--line); border-radius: 11px; padding: 3px; margin: 14px 0 16px }
.auth-tabs button { flex: 1; padding: 8px 10px; border-radius: 8px; font-size: 12.5px; font-weight: 600; color: var(--ink-3); transition: all .15s }
.auth-tabs button.on { background: var(--card); color: var(--brand); box-shadow: var(--shadow) }

.auth-view { display: none }
.auth-view.on { display: block }

/* Un formulario SIN botón de envío dentro no se envía al pulsar Enter: el
   navegador simplemente no hace nada. Como el botón visible ("Entrar") vive
   fuera de los formularios —es compartido por las tres vías— cada uno lleva su
   propio submit fuera de pantalla. Sin esto, escribir la contraseña y pulsar
   Enter no entra, que es lo que hace todo el mundo. */
.submit-oculto {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px; border: 0;
  overflow: hidden; clip-path: inset(50%);
  white-space: nowrap;
}
.auth-note { font-size: 12.5px; color: var(--ink-3); margin-bottom: 14px }
.field .hint { text-transform: none; letter-spacing: 0; font-weight: 500; color: var(--ink-3) }

.linkish { font-size: 12.5px; font-weight: 600; color: var(--brand); padding: 2px 0 }
.linkish:hover { text-decoration: underline }
.linkish.alt { display: block; width: 100%; text-align: center; margin-top: 14px; font-size: 12px; color: var(--ink-3) }

#turnstile-slot:empty { display: none }

.google-btn {
  display: flex; align-items: center; justify-content: center; gap: 10px; width: 100%;
  padding: 11px 16px; border: 1px solid var(--line, #dadce0); border-radius: var(--r-sm);
  background: #fff; color: #1f1f1f; font-size: 13.5px; font-weight: 600; transition: background var(--t-fast)
}
.google-btn:hover { background: #f7f8f8 }
.google-btn[disabled] { opacity: .6; cursor: progress }
.google-btn svg { width: 18px; height: 18px; flex: none }
.apple-btn {
  /* Guía de Apple (Sign in with Apple, botón propio): negro con logo blanco; mínimo 140 × 30 pt; el título mide el 43 %
     del alto del botón (44 px → 19 px, fuente del sistema) y deja al menos el 8 % del ancho a cada lado. */
  box-sizing: border-box; display: flex; align-items: center; justify-content: center; gap: 0; width: 100%; min-width: 140px; min-height: 44px; padding: 0 8%;
  border: 1px solid #000; border-radius: var(--r-sm); background: #000; color: #fff;
  font: 500 19px/1 -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui, sans-serif; transition: opacity var(--t-fast)
}
.apple-btn:active { opacity: .85 }
.apple-btn[disabled] { opacity: .6; cursor: progress }
/* El arte oficial es un lienzo de 56 px con el cuadro negro de 44 px: con margen -6 px el cuadro mide justo el alto del botón y el
   glifo (19 px) queda al 43 % del alto, como pide la guía. */
.apple-btn .apple-logo { width: 56px; height: 56px; flex: none; margin: -6px }
.auth-or { display: flex; align-items: center; gap: 10px; margin: 14px 0; font-size: 12px; color: var(--ink-3) }
.auth-or::before, .auth-or::after { content: ''; flex: 1; height: 1px; background: var(--line, #e5e7eb) }

.pending-banner {
  display: flex; align-items: center; gap: 10px; padding: 12px 14px; margin-bottom: 20px;
  border-radius: var(--r-sm); background: var(--warn-soft); border: 1px solid rgba(201, 138, 43, .3);
  font-size: 13.5px; color: var(--ink);
}
.pending-banner .ico { font-size: 16px }

/* =====================================================
   Ronda de mejoras de Luis (29-jul): encabezado vivo, KPIs que
   entran a su data, gráfico con glow, ventas→conversación,
   inventario editable, demanda perdida y horas pico.
   Lenguaje: "bioluminiscencia" — el brillo aqua de la marca
   emergiendo del marino profundo. IA de vanguardia, sin ruido.
   ============================================================ */

/* ---------- encabezado del negocio ---------- */
/* El anillo giraba sin parar y por debajo llevaba una copia desenfocada
   haciendo de halo. Con el punto de «IA activa» respirando al lado y el punto
   del gráfico latiendo, eran tres cosas en movimiento perpetuo compitiendo con
   la cifra que preside la pantalla. Queda el degradado, quieto: sigue marcando
   el avatar del negocio sin pedir la mirada. El único latido permanente del
   panel es el punto de abajo, que sí significa algo: tu agente está despierto. */
.top .biz .av-ring {
  padding: 2.5px; border-radius: 14px; position: relative;
  background: linear-gradient(135deg, var(--aqua), var(--brand-deep));
}
/* Con logo, el cuadrito cambia de degradado a plato: 3px de aire para que el
   logo no muerda el anillo, y radio 12−3 para que las esquinas cuadren sin
   necesidad de recortar. `contain` y no `cover`: un wordmark recortado son
   letras sueltas sin sentido. */
.top .biz .av[data-logo] { background: var(--logo-plate); padding: 3px }
.top .biz .av > img { width: 100%; height: 100%; object-fit: contain; border-radius: 9px; display: block }
.top .biz .nm { font-size: 17px; font-weight: 800; letter-spacing: -.02em }
.biz-live { display: flex; align-items: center; gap: 6px }
.ia-dot {
  width: 7px; height: 7px; border-radius: 50%; background: var(--aqua); flex: none;
  animation: ia-breathe 2.4s ease-in-out infinite;
}
@keyframes ia-breathe {
  0%, 100% { opacity: 1 }
  50% { opacity: .45 }
}

/* ---------- KPIs clicables ---------- */
button.kpi { display: block; width: 100%; text-align: left; cursor: pointer; font: inherit }
.kpi .peek {
  position: absolute; right: 14px; bottom: 11px; font-size: 11px; font-weight: 700;
  font-family: var(--mono); color: var(--brand); opacity: 0; transform: translateX(-6px);
  transition: opacity .18s, transform .18s; white-space: nowrap;
}
.kpi.hero .peek { color: #fff }
.kpi:hover .peek, .kpi:focus-visible .peek { opacity: 1; transform: none }
.kpi:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px }
.kpi:active { transform: translateY(0) scale(.99) }

/* ---------- gráfico (SVG con glow) ---------- */
.chartwrap { position: relative; margin-top: 14px }
.chart { height: 150px; display: block; margin: 0 }
.chart svg { width: 100%; height: 150px; display: block; overflow: visible }
.chart .grid { stroke: var(--line); stroke-width: 1; stroke-dasharray: 2 7; vector-effect: non-scaling-stroke }
.chart .stroke { vector-effect: non-scaling-stroke; stroke-dasharray: 1; stroke-dashoffset: 1; animation: draw 1.1s cubic-bezier(.4, 0, .2, 1) forwards }
@keyframes draw { to { stroke-dashoffset: 0 } }
.chart .area { opacity: 0; animation: fadein .9s ease .25s forwards }
@keyframes fadein { to { opacity: 1 } }
.chart .dot-last { vector-effect: non-scaling-stroke }

.chart-labels { display: flex; justify-content: space-between; margin-top: 8px }
.chart-labels span { font-family: var(--mono); font-size: 10px; color: var(--ink-3); flex: 1; text-align: center }
.chart-labels span:first-child { text-align: left }
.chart-labels span:last-child { text-align: right }
.chart-tip {
  position: absolute; top: -6px; z-index: 5; pointer-events: none;
  background: var(--marino); color: var(--sobre-marino); border: 1px solid rgba(34, 211, 238, .35);
  border-radius: 10px; padding: 8px 11px; font-size: 11.5px; line-height: 1.6;
  box-shadow: var(--shadow-pop);
  display: flex; flex-direction: column; min-width: 118px;
}
.chart-tip b { font-family: var(--mono) }
.chart-tip span { display: flex; align-items: center; gap: 6px }
.chart-tip span i { width: 8px; height: 8px; border-radius: 3px; flex: none }

/* ---------- ventas → conversación ---------- */
button.row.link { width: 100%; text-align: left; cursor: pointer; font: inherit; border-radius: 10px; transition: background .15s }
button.row.link:hover { background: var(--aqua-soft) }
button.row.link:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px }
.row .chev { font-size: 18px; color: var(--ink-3); font-weight: 700; padding-left: 2px }
button.row.link:hover .chev { color: var(--brand) }

/* ---------- inventario editable ---------- */
.inv-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; flex-wrap: wrap }
.inv-head .btn { flex: none; white-space: nowrap }
.stepper { display: flex; align-items: center; gap: 2px; margin-left: auto }
.stp {
  width: 30px; height: 30px; border-radius: var(--r-sm); display: grid; place-items: center;
  font-family: var(--mono); font-size: 15px; font-weight: 700; color: var(--brand);
  background: var(--aqua-soft); border: 1px solid rgba(34, 211, 238, .3); transition: all .12s;
}
.stp:hover:not([disabled]) { background: var(--brand); color: #fff }
.stp[disabled] { opacity: .35; cursor: not-allowed }
.stepper .qty { min-width: 52px; text-align: center; font-family: var(--mono); font-size: 14px; font-weight: 700 }
.stepper .qty small { font-size: 9.5px; margin-left: 3px; opacity: .7; font-weight: 600 }
.inv .r2 { justify-content: space-between; flex-wrap: wrap }
.avail { display: flex; align-items: center; gap: 7px; font-size: 12.5px; font-weight: 600; color: var(--ink-3); padding: 8px 10px; margin: -8px -10px; min-height: 32px; border-radius: var(--r-sm) }
.avail i { width: 26px; height: 15px; border-radius: var(--r-pill); background: var(--line); position: relative; transition: background .18s; flex: none }
.avail i::after { content: ""; position: absolute; top: 2px; left: 2px; width: 11px; height: 11px; border-radius: 50%; background: #fff; transition: transform .18s; box-shadow: 0 1px 3px rgba(0, 0, 0, .25) }
.avail.on { color: var(--brand) }
.avail.on i { background: var(--brand) }
.avail.on i::after { transform: translateX(11px) }
.inv.off { opacity: .6 }
.pill.mute { background: var(--card-2); color: var(--ink-3); border: 1px solid var(--line) }
/* «Solo bajo pedido» (26-sep): una decisión del dueño, no un problema de
   existencia — verde calmo, lejos del rojo y del ámbar. La tinta se mezcla con
   --ink: en claro se oscurece (el --ok puro da ~3:1 sobre --ok-soft) y en
   oscuro se aclara, porque --ink cambia con el tema. */
.pill.mto { background: var(--ok-soft); color: color-mix(in srgb, var(--ok) 70%, var(--ink)) }
/* Los dos interruptores de la fila («Visible» y «Solo bajo pedido») van juntos
   y bajan de línea en el teléfono. .avail tiene −10 px a cada lado y −8 px
   arriba y abajo (área de toque): con estos huecos las áreas se tocan sin
   encimarse y entre las etiquetas quedan 20 px. */
.inv-switches { display: flex; align-items: center; flex-wrap: wrap; gap: 16px 20px }
.inv-mto-opt { margin-bottom: 12px }

/* ---------- lo más pedido + demanda perdida ---------- */
.demand .dr { display: grid; grid-template-columns: minmax(120px, 200px) minmax(0, 1fr) 34px; gap: 12px; align-items: center; padding: 7px 0; animation: in .4s ease both }
.demand .dl { font-size: 13px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis }
.demand .db { height: 10px; border-radius: 5px; background: var(--line-2); overflow: hidden }
.demand .db i { display: block; height: 100%; border-radius: 5px; background: var(--brand-grad); transition: width .7s var(--ease) }
.demand .dc { font-family: var(--mono); font-size: 13px; font-weight: 700; text-align: right; font-variant-numeric: tabular-nums }
.unmet { margin-top: 14px; border: 1px solid rgba(201, 138, 43, .3); background: var(--warn-soft); border-radius: var(--r-sm); padding: 12px 14px }
.unmet .uh { font-size: 13px; font-weight: 600; color: var(--warn-ink); margin-bottom: 8px; display: flex; align-items: center; gap: 7px }
.unmet .ur { display: flex; justify-content: space-between; gap: 10px; font-size: 13px; padding: 5px 0; border-bottom: 1px dashed rgba(201, 138, 43, .25) }
.unmet .ur:last-of-type { border: none }
.unmet .ur b { font-size: 12px; color: var(--warn-ink); font-weight: 700; white-space: nowrap }
.unmet .un { font-size: 11.5px; color: var(--ink-2); margin-top: 8px }

/* ---------- horas pico ---------- */
.hours { overflow-x: auto }
.hm { display: grid; grid-template-columns: 38px repeat(var(--cols, 7), minmax(28px, 1fr)); gap: 4px; align-items: center; min-width: 300px }
.hm .hh { font-family: var(--mono); font-size: 9.5px; color: var(--ink-3); text-align: center }
.hm .hd { font-family: var(--mono); font-size: 10px; color: var(--ink-2); font-weight: 600 }
.hm .hc {
  display: block; height: 26px; border-radius: 7px;
  background: var(--line-2); /* fallback: Safari iOS < 16.2 no trae color-mix */
  background: color-mix(in srgb, var(--aqua) calc(var(--t) * 82%), var(--line-2));
  transition: transform .12s;
}
.hm .hc:hover { transform: scale(1.12) }
.hm .hc.hot { background: var(--brand-grad) }
.hlegend { display: flex; align-items: center; gap: 5px; margin-top: 12px; font-size: 10.5px; font-family: var(--mono); color: var(--ink-3) }
.hlegend .sw { width: 18px; height: 10px; border-radius: 4px; background: var(--line-2); background: color-mix(in srgb, var(--aqua) calc(var(--t) * 82%), var(--line-2)) }
.hlegend .sw.hot { background: var(--brand-grad) }
.hinsight { display: flex; align-items: center; gap: 9px; margin-top: 12px; padding: 11px 14px; border-radius: var(--r-sm); background: var(--aqua-soft); border: 1px solid var(--aqua-25); font-size: 13px; color: var(--ink-2) }
.hinsight b { color: var(--hl-ink) }

/* ---------- toast ---------- */
.toast {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: calc(20px + env(safe-area-inset-bottom)); z-index: 90;
  background: var(--marino); color: var(--sobre-marino); border: 1px solid rgba(34, 211, 238, .35);
  padding: 11px 18px; border-radius: var(--r-pill); font-size: 13px; font-weight: 600;
  box-shadow: 0 12px 32px -8px rgba(10, 22, 40, .55), 0 0 14px rgba(34, 211, 238, .2);
  animation: toast-in .25s cubic-bezier(.2, .9, .3, 1.2); max-width: min(92vw, 480px); text-align: center;
}
/* Dentro del hilo abierto, el toast deja de anclarse al fondo de la pantalla
   (`bottom`) y pasa a anclarse a lo que el teclado de iOS deja VISIBLE
   (`top`). Con el teclado arriba, el layout viewport (al que se ancla
   `bottom`) sigue midiendo la pantalla entera — su "fondo" queda tapado por
   el teclado, y el aviso se pintaba ahí sin que nadie lo viera: la causa real
   de "le doy al botón y no pasa nada". `--vvtop`/`--vvh` los publica
   thread-viewport.js desde `visualViewport` (sobre `document.documentElement`,
   por eso llegan hasta aquí aunque .toast sea hijo directo de <body>).
   Se limita a `body.hilo-abierto` a propósito: fuera del hilo esas variables
   no se publican y el toast de siempre no cambia en nada. */
body.hilo-abierto .toast {
  top: calc(var(--vvtop, 0px) + var(--vvh, 100dvh) - 64px);
  bottom: auto;
}
.toast.err { border-color: rgba(214, 69, 69, .55) }
.toast.ok { border-color: rgba(34, 197, 94, .55) }
.confirmar-btns { display: flex; gap: 8px; justify-content: flex-end; margin-top: 6px }
.confirmar-hoja p { margin-bottom: 12px; white-space: pre-line }
@keyframes toast-in { from { opacity: 0; transform: translate(-50%, 10px) } to { opacity: 1; transform: translate(-50%, 0) } }

/* ---------- modal de producto ---------- */
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px }

/* ---------- movimiento reducido ---------- */
/* Quien pide menos movimiento no recibe ninguno. Antes esta lista era a mano y
   se escapaban cuatro: el punto del sidebar, la entrada de las pantallas, la
   hoja que sube y el aviso flotante. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important; animation-iteration-count: 1 !important;
    transition-duration: .01ms !important; scroll-behavior: auto !important;
  }
  .chart .stroke { stroke-dashoffset: 0 }
  .chart .area { opacity: 1 }
}

/* ---------- móvil ---------- */
.bnav { display: none }
.mob-logo { display: none }
@media (max-width: 820px) {
  .app { grid-template-columns: minmax(0, 1fr) }
  .side { display: none }
  /* safe-area: con viewport-fit=cover el contenido llega hasta los bordes
     físicos; estos términos lo despegan del reloj arriba y de la barra de
     navegación (más el indicador de inicio) abajo. */
  .main { padding: calc(16px + env(safe-area-inset-top)) 14px calc(96px + env(safe-area-inset-bottom)) }
  .kpis { grid-template-columns: repeat(2, minmax(0, 1fr)) }
  .totals { grid-template-columns: repeat(2, minmax(0, 1fr)) }
  .tot.hero { grid-column: 1 / -1 }
  .duel { grid-template-columns: minmax(0, 1fr) }
  .mob-logo { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 10px }
  /* En el teléfono, todo lo que va ANTES del número compite con él por el
     primer vistazo: la cabecera se aprieta para que la cifra entre en pantalla
     sin tener que desplazar. Lo mismo hace un banco con el saldo. */
  .top { gap: 10px; margin-bottom: 12px }
  /* Con "Última hora" son 4 pastillas: si no caben, la fila se desliza en vez
     de partirse en dos líneas o empujar la pantalla. */
  .seg { max-width: 100%; overflow-x: auto; scrollbar-width: none }
  .seg::-webkit-scrollbar { display: none }
  .seg button { white-space: nowrap; flex: none }
  /* Las filas de chips SIN TOPE — estados de conversación (#chips-st) y
     categorías del catálogo (#inv-cats, tantas como tenga el negocio) — se
     deslizan: sangran hasta el borde real de la pantalla (contrarrestando el
     padding de .main) y se desvanecen a la derecha, que es el aviso de "hay
     más". El padding derecho extra deja que el último chip se vea completo al
     llegar al final, fuera de la zona del degradé.
     La fila de CANALES es el caso contrario y va justo debajo. */
  .chips {
    margin-bottom: 14px; margin-inline: -14px; padding-inline: 14px 36px;
    scroll-snap-type: x proximity;
    -webkit-mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 28px), transparent);
    mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 28px), transparent);
  }
  /* Los canales son un conjunto ACOTADO: un negocio tiene dos o seis, no
     veinte. Por eso esta fila se muestra ENTERA y baja a una segunda línea en
     vez de deslizarse. Es el filtro principal del panel, y un canal que no se
     ve es un canal que no se filtra: el degradé de la derecha, que en las otras
     filas dice "desliza", aquí se leía como "se cortó". Hay que anular una por
     una las propiedades de arriba, porque comparten la clase .chips. */
  #chips-ch {
    flex-wrap: wrap; gap: 6px;
    margin-inline: 0; padding-inline: 0;
    overflow-x: visible; scroll-snap-type: none;
    -webkit-mask-image: none; mask-image: none;
  }
  /* Estos ~30px no son cosmética: son los que deciden si los tres chips de hoy
     caben en una línea en un iPhone SE (375pt) o si se parten en dos. */
  #chips-ch .chip { padding: 6px 11px; gap: 6px; font-size: 12.5px }
  /* Donde "Todos los canales" se vuelve "Todos". El texto largo solo cabe —y
     solo hace falta— cuando hay pantalla de sobra. */
  #chips-ch .lbl-long { display: none }
  .hero-num__val { font-size: clamp(46px, 14vw, 62px) }
  /* en móvil el botón baja a su propia línea en vez de estrujar el texto */
  .databar { flex-wrap: wrap; font-size: 12px; padding: 10px 12px; row-gap: 6px }
  .databar > span:nth-child(2) { flex: 1 1 200px }
  .bnav {
    display: flex; position: fixed; bottom: 0; left: 0; right: 0; z-index: 50;
    background: var(--card); border-top: 1px solid var(--line);
    padding: 7px 4px calc(7px + env(safe-area-inset-bottom));
    box-shadow: var(--shadow-up);
  }
  /* min-width:0 — sin él, un flex item no baja de su contenido y las 7
     pestañas se empujan fuera de la pantalla en un iPhone de 375pt. */
  .bnav button { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 3px; font-size: 10px; font-weight: 600; color: var(--ink-3); padding: 5px 1px; border-radius: var(--r-sm); position: relative; transition: background var(--t-fast), color var(--t-fast) }
  .bnav button .lbl { max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis }
  .bnav button svg { width: 20px; height: 20px }
  .bnav button[data-screen="probar"] svg { width: 20px; height: 18px }
  .bnav button.on { color: var(--brand); background: var(--aqua-soft) }
  .bnav .badge { position: absolute; top: 0; right: 22%; background: var(--bad); color: var(--bad-ink); font-size: 9px; font-weight: 700; min-width: 15px; height: 15px; border-radius: 8px; display: grid; place-items: center; padding: 0 4px }
  .field-row { grid-template-columns: minmax(0, 1fr) }
  .toast { bottom: calc(76px + env(safe-area-inset-bottom)) }
  /* En táctil no hay hover: la pista «Ver →» se ve siempre, y en su propia línea:
     encima de la esquina tapaba el desglose por canal (medido en un teléfono). */
  .kpi .peek { position: static; display: block; margin-top: 8px; font-family: inherit; opacity: 1; transform: none }

  .demand .dr { grid-template-columns: minmax(90px, 130px) minmax(0, 1fr) 30px; gap: 8px }
  .stp { width: 36px; height: 36px }

  /* PEDIDOS, el pie de la tarjeta en el teléfono (21-09, medido a 360px).
     «Cotizar» (54×25), «Compartir PDF» (96×25) y «Abrir conversación» (115×25)
     iban PEGADOS —CERO px entre ellos— y «Cliente desistió», que CANCELA el
     pedido, caía 1px debajo de «Cotizar». Un pulgar que apunta a cotizar podía
     cancelarle un pedido real al dueño. Aquí no cambia ninguna conducta: los
     mismos botones, con el alto que pide un dedo (44px), 8px de aire entre
     vecinos y el botón que destruye en su propio renglón, separado.
     Solo teléfono: en escritorio hay ratón y el pie sigue igual. */
  .order-foot > div { display: flex; flex-wrap: wrap; gap: 8px; width: 100% }
  .order-foot .order-open {
    min-height: 44px; display: inline-flex; align-items: center; justify-content: center;
    font-size: 13px; padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--r-sm);
  }
  /* `flex: 1 0 100%` le da renglón propio (nada más puede compartirlo) y el
     margen de arriba es el aire que impide que un dedo que erra lo alcance. */
  .order-foot .cancel-apt {
    flex: 1 0 100%; min-height: 44px; margin-top: 10px;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 12px; padding: 10px 12px;
  }
}

/* ===== catálogo B2B (nicho inventory, Issue #30 + primer tenant real) ===== */
/* Barra de herramientas del catálogo: solo aparece con >12 productos. */
/* Cabecera del catálogo de Shopify (#491): de dónde viene y hace cuánto. */
#inv-origen { margin-bottom: 12px }
#inv-origen:empty { display: none }
.inv-shopify { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap }
.inv-shopify .ml-txt { margin: 4px 0 0 }
.inv-tools { display: flex; flex-direction: column; gap: 10px; margin-bottom: 12px }
.inv-tools:empty { display: none }
.inv-tools input[type="search"] {
  width: 100%; padding: 10px 14px; border-radius: var(--r-sm); border: 1px solid var(--line);
  background: var(--card); color: var(--ink-2); font: inherit; font-size: 13.5px;
}
.inv-tools input[type="search"]:focus { outline: 2px solid var(--brand); outline-offset: 1px }
.inv .r1 .sku { font-family: var(--mono); font-size: 10.5px; color: var(--ink-3); letter-spacing: .02em }
.inv .r1 .price { font-family: var(--mono); font-size: 12.5px; font-weight: 700; color: var(--brand) }
#inv-more { width: 100%; margin-top: 10px }
/* "Cliente desistió" / "Cancelar cita": acción secundaria, no debe gritar. */
.cancel-apt {
  font-size: 11px; padding: 4px 10px; border-radius: var(--r-sm); cursor: pointer;
  border: 1px solid var(--line); background: transparent; color: var(--ink-3);
}
.cancel-apt:hover { color: var(--bad); border-color: var(--bad) }

/* ---------- Mi Surfia (#52) ----------
   El dueño le escribe a su propio agente antes de exponerlo a un cliente. */

/* El título lleva la marca al lado: es la pantalla donde el dueño moldea a su
   Surfia, y el logo lo dice antes que el texto. 26×23 respeta la proporción
   52:46 del viewBox y le queda a la altura óptica del h1 de 22px. */
.h1-marca { display: flex; align-items: center; gap: 9px }
.h1-marca__mark { width: 26px; height: 23px; flex: none }

.probar-chat { display: flex; flex-direction: column; gap: 14px; margin-top: 14px }
.probar-chat .bubbles { min-height: 60vh; max-height: 72vh; overflow-y: auto }
/* Luis, 15-sep-2026 (sesión con Chez Toto): «hacer la ventana del agente más
   grande». En el escritorio el chat ocupa casi toda la altura; en el teléfono se
   deja sitio a la barra de abajo y a la caja de escribir, que no debe salirse. */
@media (max-width: 820px) { .probar-chat .bubbles { min-height: 48vh; max-height: 58vh } }
/* El chat de prueba no tiene "otro lado": el dueño escribe a la izquierda como
   lo haría el cliente, y su agente responde a la derecha. Reusa .bub tal cual. */
.probar-chat .reply { max-width: none }

.policy-h {
  font-size: 11px; font-family: var(--mono); letter-spacing: .06em;
  color: var(--ink-3); text-transform: uppercase; margin-bottom: 6px;
}
.policy-d { font-size: 13px; color: var(--ink-2); line-height: 1.5 }
/* El icono chico junto al nombre de un canal (la tarjeta Shopify de Mi Surfia, #734).
   La regla salió con la vista vieja de Clientes (#791); sin ella el SVG se pinta a todo lo ancho. */
.ch-mini { display: inline-flex; width: 15px; height: 15px; vertical-align: -2px }
.ch-mini svg { width: 15px; height: 15px }

/* ===== «Cómo responde tu agente» (#50): la tarjeta que manda =====
   Es el único sitio del panel donde el dueño cambia el comportamiento de su
   agente, y era la segunda de trece tarjetas idénticas y pegadas entre sí, con
   el botón más pequeño de la pantalla. Ahora va primera y lleva el degradado de
   marca en un riel de 3px: el mismo recurso de .kpi.hero y del número de
   Inicio, y en Mi Surfia no aparece en ningún otro sitio, así que con verlo ya
   se sabe cuál es. NO se rellena de degradado como .kpi.hero: esta tarjeta
   carga hasta seis renglones a 13px, y el texto claro sobre degradado es el
   problema de contraste que ya obligó a subir --brand en el tema oscuro. Basta
   un baño de --aqua-soft que se apaga a los 140px y deja la lista sobre --card
   limpio. El margen es suyo porque .card no declara ninguno: sin él la tarjeta
   va pegada a la siguiente, y despegarla es la mitad de «destaca». */
.responde {
  position: relative;
  overflow: hidden;
  margin: 4px 0 18px;
  border-color: var(--aqua-35);
  background: linear-gradient(180deg, var(--aqua-soft), transparent 140px), var(--card);
  box-shadow: var(--shadow-lift);
}
/* El `overflow: hidden` de arriba es para que el riel siga la curva de --r. */
.responde::before { content: ""; position: absolute; inset: 0 0 auto; height: 3px; background: var(--brand-grad) }
.responde .source-kicker { margin-bottom: 7px }
.responde-t { display: block; font-size: 21px; font-weight: 700; letter-spacing: -.01em; line-height: 1.25; color: var(--ink) }
.responde-d { font-size: 13.5px; color: var(--ink-2); line-height: 1.5; margin-top: 5px }

/* Un renglón por ajuste: el dueño no lee un párrafo, cuenta reglas. El punto va
   en un ::before y no en list-style para que el aqua no se lleve también el
   color del texto. */
.responde-lista { list-style: none; margin: 13px 0 0; padding: 0; display: grid; gap: 7px }
.responde-lista li { position: relative; padding-left: 17px; font-size: 13px; color: var(--ink-2); line-height: 1.45 }
.responde-lista li::before { content: ""; position: absolute; left: 2px; top: 7px; width: 6px; height: 6px; border-radius: 50%; background: var(--aqua) }
.responde-lista b { color: var(--ink); font-weight: 600 }
.responde-pie { font-size: 12.5px; color: var(--ink-3); line-height: 1.45; margin-top: 14px }

/* La llamada a la acción deja de ser el botón más callado de la pantalla: un
   `ghost mini` decía «detalle», y aquí hay que decir «esto se toca». */
.responde-cta { display: inline-flex; align-items: center; gap: 8px; margin-top: 11px }

@media (max-width: 820px) {
  .responde { margin-bottom: 16px }
  .responde-t { font-size: 19px }
  .responde-cta { width: 100%; justify-content: center; padding: 14px 18px; border-radius: var(--r-pill) }
}

/* ===== Ajustes del agente (#50) =====
   El formulario es más alto que el de inventario (cinco grupos), así que la
   hoja crece y hace scroll interno en vez de empujar el modal fuera de la
   pantalla del teléfono, que es donde el dueño lo va a abrir. */
/* `max-width: 100%`: el <dialog> modal solo deja `100% - 6px - 2em` (la hoja del
   navegador) y `100vw - 32px` lo pasaba por 6 px: en el teléfono se cortaba el
   borde derecho. En el escritorio la hoja sigue en 520 px. */
.sheet-wide { width: min(520px, calc(100vw - 32px)); max-width: 100%; max-height: calc(100dvh - 48px); display: flex; flex-direction: column }
/* El que scrollea es el FORM, que es el hijo flexible — no el div de adentro.
   `min-height: 0` es obligatorio: sin él un ítem flex no baja de su contenido,
   el formulario crece hasta 1055px y "Guardar" queda fuera de una pantalla de
   720. Verificado en navegador: así se rompía. */
.sheet-wide #form-pol { position: relative; flex: 1; min-height: 0; overflow-y: auto; margin: 0 -4px; padding: 0 4px }
/* Mismo bug, mismo arreglo: la hoja de «¿Cómo quieres recibir los avisos?»
   (avisos-equipo-cuestionario.js) es .sheet-wide sin esta regla para SU form
   — sin `min-height: 0` el formulario crecía a ~3.400px y «Enviar» quedaba
   fuera de la tarjeta, pintado sobre el fondo semitransparente del diálogo.
   Verificado en el teléfono (390×844): así se rompía. `position: relative`: su
   submit oculto estiraba el <dialog> igual que en #onb-modal (abajo) y #pol-modal. */
.sheet-wide #form-avq { position: relative; flex: 1; min-height: 0; overflow-y: auto; margin: 0 -4px; padding: 0 4px }
/* Y el tercero, el del cuestionario de alta (#onb-modal): con los cuatro planes
   lo que se desplazaba era TODO el diálogo, y Conecta y los botones quedaban
   fuera de la tarjeta, sobre el fondo gris (capturas del 22-oct-2026, escritorio
   y teléfono). `position: relative` encierra el .submit-oculto (absoluto): sin
   eso su caja era el <dialog> y, al pie del formulario, le dejaba al diálogo
   ~370 px de más para arrastrar en el teléfono (medido a 375×812). */
.sheet-wide #form-onb { position: relative; flex: 1; min-height: 0; overflow-y: auto; margin: 0 -4px; padding: 0 4px }

/* La hoja crece por #id y NO ensanchando .sheet-wide, que también viste el
   cuestionario de alta —nueve preguntas de tres palabras, que en 760 flotarían—
   y el Magazine. Es el patrón que ya usa .magazine-hoja: cada hoja declara su
   propia caja y comparte de .sheet-wide solo la columna y el scroll de arriba. */
#pol-modal .sheet { width: min(760px, calc(100vw - 40px)); max-height: min(880px, calc(100dvh - 40px)); padding: 24px 26px }
#pol-modal .sheet h3 { font-size: 21px; margin-bottom: 4px }
#pol-modal .sheet > p { font-size: 13px; margin-bottom: 18px; max-width: 64ch }
#pol-modal .polset { margin-bottom: 22px }
#pol-modal .polset legend { font-size: 13px; color: var(--ink); margin-bottom: 10px }
/* Con la hoja grande hay que ver dónde acaba el formulario y empieza la decisión. */
#pol-modal .actions { padding-top: 14px; border-top: 1px solid var(--line-2) }

/* En el teléfono deja de flotar con márgenes y ocupa la pantalla, subiendo
   desde abajo como una app — el mismo recurso de la hoja de entrar. */
@media (max-width: 820px) {
  /* El <dialog> trae del navegador `max-height: calc(100% - 12px)`: sin
     anularlo queda una franja de fondo bajo la hoja a pantalla completa. */
  #pol-modal { margin: auto auto 0; width: 100%; max-width: 100%; max-height: 100% }
  #pol-modal .sheet {
    width: 100%; max-width: 560px; margin: 0 auto;
    /* Alto FIJO, no máximo: al cambiar la opción de precios aparece o
       desaparece la lista de preguntas, y la hoja saltaba bajo el pulgar.
       Y en unidad de PANTALLA, nunca un %: el <dialog> no declara alto, así que
       un porcentaje no resuelve, la hoja se va a la altura de su contenido
       (1.432px en una pantalla de 812) y «Guardar cambios» queda 600px por
       debajo del borde. Verificado en el navegador: así se rompía. */
    height: 94dvh;
    max-height: none;
    border-radius: 24px 24px 0 0;
    border-bottom: none;
    padding: 18px 16px calc(16px + env(safe-area-inset-bottom));
    animation: sheet-up .28s cubic-bezier(.2, .8, .3, 1);
  }
  /* La barra de arrastre dice «esto sube y baja» sin texto. `flex: none` porque
     .sheet-wide es un flex column y el ::before es un ítem más: sin él se
     estira y le come alto al formulario. */
  #pol-modal .sheet::before {
    content: ""; display: block; flex: none;
    width: 38px; height: 4px; border-radius: var(--r-pill);
    background: var(--line); margin: 0 auto 14px;
  }
  /* Mismo criterio que la hoja de entrar: la acción principal a todo lo ancho y
     la otra baja a texto. Dos botones iguales en una esquina obligan a leerlos. */
  #pol-modal .actions { display: grid; gap: 6px }
  #pol-modal .actions .btn.primary { order: 1; width: 100%; padding: 15px; border-radius: var(--r-pill); font-size: 15px }
  #pol-modal .actions .btn.ghost { order: 2; background: none; border: none; box-shadow: none; color: var(--ink-3); padding: 10px }
}
/* La hoja nunca se desplaza entera: el que se desplaza es #form-pol. El <dialog> trae del
   navegador `overflow: auto`, y el submit oculto (absoluto) lo estiraba hasta el pie del
   formulario: la rueda sobre el título corría la hoja fuera de la pantalla (medido en
   Chrome, 1440×900: 1.324 px de alto para arrastrar contra 860 visibles). `position:
   relative` en #form-pol encierra al submit; esto cierra el resto, en el escritorio y en
   el teléfono, y no cambia lo que se ve: `auto` ya recortaba igual. */
#pol-modal { overflow: hidden }

.polset { border: none; padding: 0; margin: 0 0 18px }
.polset legend { font-size: 12px; font-weight: 600; color: var(--ink-3); margin-bottom: 8px; padding: 0 }
.polhelp { font-size: 12px; color: var(--ink-3); line-height: 1.45; margin: 6px 0 8px }

/* Opción de precios: la tarjeta entera es clicable, no solo el radio de 16px —
   en móvil apuntarle al círculo es la diferencia entre usarlo y no usarlo. */
.opts { display: grid; gap: 8px }
.opt { display: flex; gap: 10px; align-items: flex-start; padding: 11px 12px; border: 1px solid var(--line); border-radius: 10px; background: var(--card-2); cursor: pointer }
.opt.on { border-color: var(--brand); background: var(--aqua-soft) }
.opt input { margin-top: 2px; accent-color: var(--brand); flex-shrink: 0 }
.opt span { display: block }
.opt b { display: block; font-size: 13.5px; font-weight: 600; margin-bottom: 2px }
.opt em { display: block; font-style: normal; font-size: 12px; color: var(--ink-3); line-height: 1.45 }

.chks { display: flex; flex-wrap: wrap; gap: 8px }
.chk { display: flex; gap: 7px; align-items: center; padding: 7px 11px; border: 1px solid var(--line); border-radius: var(--r-pill); background: var(--card-2); font-size: 13px; cursor: pointer }
.chk input { accent-color: var(--brand) }
.chk:has(input:checked) { border-color: var(--brand); background: var(--aqua-soft) }

/* Motivos de aviso (#136): cada uno lleva título y explicación, así que se
   apilan a lo ancho en vez de ir en pills — el dueño decide leyendo el porqué,
   no el nombre. */
.avisos-motivos { display: grid; gap: 8px }
.avisos-motivos .chk { align-items: flex-start; border-radius: 10px; padding: 11px 12px }
.avisos-motivos .chk input { margin-top: 2px; flex-shrink: 0 }
.avisos-motivos .chk b { display: block; font-size: 13.5px; font-weight: 600; margin-bottom: 2px }
.avisos-motivos .chk em { display: block; font-style: normal; font-size: 12px; color: var(--ink-3); line-height: 1.45 }
.avisos-acciones { display: flex; flex-wrap: wrap; gap: 8px; align-items: center }

.preguntas { display: grid; gap: 8px; margin-bottom: 8px }
.preg { display: flex; gap: 8px; align-items: center }
/* Un solo aspecto para los campos de la hoja «Cómo responde»: las preguntas, los
   renglones de texto de instrucciones y novedades (politica-extras.js) y la fecha «Hasta». */
.preg input, .pol-texto, .pol-hasta input { border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--card-2); color: var(--ink) }
.preg input { flex: 1; min-width: 0; padding: 9px 11px; font-size: 13px }
.preg input:focus, .pol-texto:focus, .pol-hasta input:focus { outline: 2px solid var(--aqua-soft); border-color: var(--brand) }
.btn.mini { padding: 6px 11px; font-size: 12px }

/* «Tus instrucciones» y «Novedades y promociones» (politica-extras.js): renglones de
   texto con el aspecto de .preg, pero en <textarea> (Enter no guarda la hoja) y con
   la tipografía de .fup-texto. En el teléfono el 16px de los campos ya lo pone la
   regla de dispositivo de arriba. */
.pol-fila { align-items: flex-start }
.pol-texto { flex: 1; min-width: 0; width: 100%; padding: 9px 11px; resize: vertical; font: inherit; font-size: 13px; line-height: 1.45 }
.pol-novedad { display: grid; gap: 6px }
.pol-novedad-pie { display: flex; flex-wrap: wrap; align-items: center; gap: 8px }
.pol-hasta { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--ink-3) }
.pol-hasta input { padding: 6px 9px; font: inherit; font-size: 13px }
.pol-vencida { padding: 2px 8px; border-radius: var(--r-pill); font-size: 11.5px; font-weight: 700; background: var(--warn-soft); color: var(--warn-ink) }
.pol-aviso { margin: 0; color: var(--warn-ink) }
.pol-ideas { display: flex; flex-wrap: wrap; gap: 6px }
@media (max-width: 820px) {
  /* Las ideas se tocan con el pulgar: el mismo alto que los atajos de «Tu agente». */
  .pol-ideas .btn { min-height: 36px }
  /* A 375 px «Hasta (opcional)», la fecha (a 16px) y «Quitar» no caben en fila y
     «Quitar» caía solo a otro renglón: el rótulo sube encima de la fecha y «Quitar»
     queda al lado, alineado con el campo. */
  .pol-novedad-pie { align-items: flex-end }
  .pol-hasta { flex-direction: column; align-items: flex-start; gap: 2px }
}

/* ---------- activacion guiada de canales ---------- */
.channel-setup { margin: 18px 0 20px; padding: 18px 0 4px; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line) }
.setup-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 12px }
.setup-head h2 { margin: 2px 0 0; font-size: 18px }
.setup-kicker { color: var(--brand); font-size: 12px; font-weight: 600 }
.setup-status { border: 1px solid var(--line); border-radius: var(--r-pill); color: var(--ink-2); font-size: 11.5px; font-weight: 600; padding: 5px 11px; white-space: nowrap }
.setup-status.connected { border-color: var(--ok); color: var(--ok) }
.setup-status.waiting { border-color: var(--warn); color: var(--warn) }
/* Conectado, la insignia es el interruptor de «que Surfia conteste aquí». Como
   <button> hereda la tipografía del navegador: se le repite la del <span> para
   que apagar no cambie el aspecto de la insignia. */
button.setup-status { background: none; cursor: pointer; font-family: inherit; line-height: normal }
button.setup-status:hover { border-color: var(--ink-3); color: var(--ink) }
button.setup-status:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px }
/* Apagado por el dueño: ni verde (no está contestando) ni rojo (no está roto). */
.setup-status.muted, button.setup-status.connected.muted { border-color: var(--ink-3); color: var(--ink-2) }
button.setup-status.connected.muted:hover { border-color: var(--ok); color: var(--ok) }
.setup-tabs { display: flex; gap: 4px; margin-bottom: 14px }
.setup-tabs button { border-bottom: 2px solid transparent; color: var(--ink-3); font-size: 13px; padding: 7px 10px }
.setup-tabs button.on { border-color: var(--brand); color: var(--ink); font-weight: 700 }
.setup-grid { display: grid; grid-template-columns: minmax(170px, .7fr) minmax(0, 1.3fr); gap: 18px; align-items: start }
.setup-checklist { display: grid; gap: 8px; padding-top: 5px }
.setup-step { color: var(--ink-2); font-size: 12px; line-height: 1.35 }
.setup-step span { color: var(--ink-3); display: inline-block; font-family: var(--mono); margin-right: 7px; width: 13px }
.setup-step.done { color: var(--ok); text-decoration: line-through; text-decoration-color: color-mix(in srgb, var(--ok) 45%, transparent) }
.setup-step.done span { color: var(--ok) }
.setup-chat { min-width: 0 }
.setup-bubbles { background: var(--card-2); border: 1px solid var(--line); border-radius: var(--r-sm); display: grid; gap: 8px; max-height: 230px; min-height: 106px; overflow-y: auto; padding: 11px }
.setup-bubble { border-radius: 10px; font-size: 12.5px; line-height: 1.45; max-width: 88%; padding: 8px 10px; white-space: pre-wrap }
.setup-bubble.assistant { background: var(--card); border: 1px solid var(--line); justify-self: start }
.setup-bubble.owner { background: var(--brand); color: #fff; justify-self: end }
.setup-reply { display: flex; gap: 8px; margin-top: 9px }
.setup-reply input { background: var(--card); border: 1px solid var(--line); border-radius: var(--r-sm); color: var(--ink); flex: 1; min-width: 0; padding: 9px 11px }
.setup-reply input:focus { border-color: var(--brand); outline: 2px solid var(--aqua-soft) }
.setup-reply .btn { flex: none; padding: 9px 14px }
.setup-note { color: var(--ink-3); font-size: 11px; line-height: 1.4; margin: 8px 0 0 }
@media (max-width: 620px) {
  .setup-grid { grid-template-columns: minmax(0, 1fr) }
  .setup-checklist { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 7px 10px }
}

/* ═══════════ Clientes, buscador y cierre del día (auditoría UX 17-ago) ═══════════ */

/* Un cambio de VISTA dentro de una pantalla (Cobros: Cartera ↔ Banco). Va
   pegado al título: los chips de abajo filtran dentro de la vista. */
.seg-view { width: fit-content; margin: 4px 0 12px }

.buscador { margin: 0 0 12px }
.buscador input {
  width: 100%; max-width: 420px; padding: 11px 14px; border-radius: 11px;
  border: 1px solid var(--line); background: var(--card); color: var(--ink);
  font-size: 14px; font-family: inherit;
}
.buscador input::placeholder { color: var(--ink-3) }
.buscador input:focus { outline: 2px solid var(--brand); outline-offset: -1px; border-color: transparent }

/* ═══════════ Clientes (épico #761): la lista y la ficha 360 ═══════════
   Solo tokens existentes: el tema oscuro los redefine y esto lo hereda. */
.cli-totals { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)) }
.tot .tot-sub { font-size: 11.5px; color: var(--ink-3); margin-top: 3px }
.tot.hero .tot-sub { color: rgba(255, 255, 255, .85) }
.cli-orden { width: fit-content; max-width: 100%; overflow-x: auto; margin: 0 0 12px }
.cli-buscador input { max-width: 560px }
.cli-aviso {
  margin: 0 0 12px; padding: 11px 14px; border-radius: var(--r-sm); font-size: 13px;
  background: var(--warn-soft); color: var(--warn-ink); border: 1px solid var(--line);
}
/* La lista: columnas en el escritorio (Cliente | Estado | Última compra |
   Compras | Comprado | Pidió | Te escribió). Sin compras en el negocio se
   esconden las tres de compra y la rejilla se encoge con ellas. */
.cli-lista {
  --cli-cols: minmax(0, 2fr) minmax(0, 1.9fr) minmax(0, 1.3fr) minmax(0, .6fr) minmax(0, 1fr) minmax(0, 1fr) minmax(0, .9fr);
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r); box-shadow: var(--shadow); overflow: hidden;
}
.cli-lista.sin-compras { --cli-cols: minmax(0, 2.4fr) minmax(0, 1.8fr) minmax(0, 1fr) minmax(0, .9fr) }
.cli-lista:has(> .card) { background: none; border: none; box-shadow: none }
.cli-head, .cli-row { display: grid; grid-template-columns: var(--cli-cols); gap: 10px; align-items: center; padding: 11px 14px }
.cli-head { font-size: 11.5px; font-weight: 600; color: var(--ink-3); border-bottom: 1px solid var(--line) }
.cli-row { width: 100%; text-align: left; border-bottom: 1px solid var(--line-2); font-size: 13px; color: var(--ink); transition: background var(--t-fast) }
.cli-row:last-child { border-bottom: none }
.cli-row:hover { background: var(--card-2) }
.cli-row > span { min-width: 0; overflow: hidden; text-overflow: ellipsis }
.cli-row b { font-weight: 600; display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
/* Las notas de las columnas («compra cada 14 días, más o menos», «1 compra con
   renglones sin precio») bajan de línea: cortadas en «…» a 1280 no se leían.
   Solo la de debajo del nombre (empresa · RIF) va en una línea. */
.cli-row small { display: block; font-size: 11.5px; line-height: 1.3; color: var(--ink-3); white-space: normal; overflow-wrap: anywhere }
.cli-row .c-cli small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
.cli-row .c-num, .cli-head .c-num { text-align: right; font-variant-numeric: tabular-nums }
.cli-row .c-estado { display: flex; flex-wrap: wrap; gap: 4px }
.cli-row .c-movil { display: none }
.cli-pill { max-width: 100%; overflow: hidden; text-overflow: ellipsis; font-size: 11px; font-weight: 600; padding: 2px 9px; border-radius: var(--r-pill); white-space: nowrap; background: var(--card-2); color: var(--ink-2); border: 1px solid var(--line) }
.cli-pill.tipo-repeat { background: var(--ok-soft); color: var(--ok); border-color: transparent }
.cli-pill.tipo-once { background: var(--aqua-soft); color: var(--brand); border-color: transparent }
.cli-pill.atrasado, .cli-pill.espera { background: var(--warn-soft); color: var(--warn-ink); border-color: transparent }
.cli-pill.prueba { border-style: dashed; color: var(--ink-3) }
/* «Proveedor» (24-oct-2026): el violeta de los compromisos de la Agenda, que no se usa en ninguna otra pastilla. */
.cli-pill.proveedor { background: var(--comp-bg); color: var(--comp-ink); border-color: transparent }
/* «Pidió» va en ámbar y SIN dinero: todavía no es una compra. */
.cli-pend { color: var(--warn-ink); font-weight: 600 }
.cli-mas { margin: 12px 0 0 }

/* La ficha 360. */
.cli-volver { margin: 0 0 12px }
.cli-f-cab { margin: 0 0 12px }
.cli-f-titulo { display: flex; align-items: center; flex-wrap: wrap; gap: 8px }
.cli-f-titulo h2 { margin: 0; font-size: 20px; letter-spacing: -.02em }
.cli-f-datos { margin: 8px 0 0; font-size: 13px; color: var(--ink-2); display: flex; flex-wrap: wrap; align-items: center; gap: 2px }
.cli-copiar { margin-left: 4px; font-size: 11.5px; font-weight: 600; color: var(--brand); padding: 1px 7px; border-radius: var(--r-pill); background: var(--aqua-soft) }
.cli-origen { color: var(--ink-3) }
.cli-f-prox { margin: 8px 0 0; font-size: 13px; color: var(--ink-2) }
.cli-f-acciones { display: flex; flex-wrap: wrap; gap: 8px; margin: 12px 0 0 }
.cli-f-cab .ficha-form { margin-top: 12px }
.cli-f-cab .ficha-prueba { display: block; margin-top: 12px; font-size: 12.5px; color: var(--ink-3) }
.cli-f-cab .ficha-tipo { margin-top: 12px; font-size: 12.5px }
.cli-f-frase { font-size: 14.5px; color: var(--ink); margin: 0 0 12px; max-width: 70ch }
.cli-h { font-size: 15px; margin: 18px 0 8px }
.cli-hist-chips { margin-bottom: 10px }
.cli-pedido.requested .order-foot span { color: var(--warn-ink) }

/* ═══════════ «Por recuperar» (épico #761, PR-D): la bandeja y el seguimiento de la ficha ═══════════
   Solo tokens existentes: el tema oscuro los redefine y esto lo hereda. */
.cli-tabs { margin: 0 0 14px }
.fup-grupo { margin: 0 0 14px }
.fup-grupo-cab { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap }
.fup-grupo .cli-h { margin: 16px 0 8px }
.fup-grupo .cli-h .n { font-size: 12px; font-weight: 600; color: var(--ink-3) }
.fup { margin: 0 0 10px }
.fup-cab { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; flex-wrap: wrap }
.fup-quien { min-width: 0 }
.fup-quien b { display: block; font-size: 15px; overflow-wrap: anywhere }
.fup-quien small { display: block; font-size: 12px; color: var(--ink-3); overflow-wrap: anywhere }
.fup-motivo { margin: 8px 0 0; font-size: 13.5px; color: var(--ink) }
.fup-escribio { margin: 6px 0 0; font-size: 13px; font-weight: 600; color: var(--warn-ink) }
.fup-compra { margin: 6px 0 0; font-size: 12.5px; color: var(--ink-2) }
.fup-falla { margin: 8px 0 0; padding: 8px 11px; border-radius: var(--r-sm); font-size: 12.5px; background: var(--bad-soft); color: var(--bad) }
.fup-texto {
  display: block; width: 100%; margin: 10px 0 0; padding: 10px 12px; min-height: 84px; resize: vertical;
  border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--card-2); color: var(--ink);
  font: inherit; font-size: 13.5px; line-height: 1.45;
}
.fup-texto:focus { outline: 2px solid var(--brand); outline-offset: -1px; border-color: transparent }
.fup-nota { margin: 8px 0 0; font-size: 12.5px; line-height: 1.4; color: var(--ink-3) }
.fup-acciones { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 12px 0 0 }
.fup-acciones a.btn { display: inline-block; text-decoration: none }
.fup-menu { position: relative }
.fup-menu summary { list-style: none; cursor: pointer }
.fup-menu summary::-webkit-details-marker { display: none }
.fup-menu summary::after { content: " ▾" }
.fup-menu[open] summary::after { content: " ▴" }
.fup-menu-lista {
  position: absolute; z-index: 5; top: calc(100% + 4px); left: 0; display: flex; flex-direction: column; gap: 6px;
  min-width: 210px; max-width: calc(100vw - 48px); padding: 10px; border: 1px solid var(--line);
  border-radius: var(--r-sm); background: var(--card); box-shadow: var(--shadow-lift);
}
.fup-fecha { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--ink-3) }
.fup-fecha input, .fup-recordar input, .fup-ajuste input[type="number"] {
  padding: 8px 10px; border: 1px solid var(--line); border-radius: 8px; background: var(--card-2); color: var(--ink); font: inherit; font-size: 14px;
}
.fup-compacta .fup-motivo { margin-top: 6px }
.fup-aviso {
  display: flex; align-items: center; justify-content: space-between; gap: 10px; margin: 0 0 12px; padding: 10px 14px;
  border-radius: var(--r-sm); font-size: 13px; background: var(--ok-soft); color: var(--ok); border: 1px solid var(--line);
}
.fup-ajuste { margin: 18px 0 0 }
.fup-ajuste summary { cursor: pointer; font-weight: 600; font-size: 13.5px }
.fup-ajuste input[type="number"] { width: 76px }
.fup-chk { display: flex; align-items: center; gap: 8px; margin: 10px 0; font-size: 13px }
.fup-recordar { margin: 12px 0 0; display: flex; flex-direction: column; gap: 10px }
.fup-recordar label { display: flex; flex-direction: column; gap: 4px; font-size: 12.5px; color: var(--ink-3) }
@media (max-width: 820px) {
  .fup-acciones .btn.primary { flex: 1 1 100% }
  .fup-menu-lista { position: static; margin-top: 6px }
}

/* ═══════════ «Cotizaciones» (épico #761, PR-H2): la pestaña y su tarjeta ═══════════
   La tarjeta es la de la bandeja (.fup); aquí solo lo que suma: el elector del mensaje, los pedidos que se
   deben (cada uno con su «Ya se la mandé») y la caja de solo lectura del mensaje aprobado. Solo tokens. */
.cot-variantes { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin: 10px 0 0 }
.cot-var-cab { font-size: 12.5px; color: var(--ink-3) }
.cot-variantes .seg { width: fit-content; max-width: 100% }
.cot-pedidos { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-direction: column; gap: 6px }
.cot-pedido {
  display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 8px 10px;
  border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--card-2);
}
.cot-ped { min-width: 0 }
.cot-ped b { display: block; font-size: 13.5px; overflow-wrap: anywhere }
.cot-ped small { display: block; font-size: 12px; color: var(--ink-3) }
.cot-pedido-mas { font-size: 12.5px; color: var(--ink-3); padding: 0 2px }
.fup-texto[readonly] { resize: none; color: var(--ink-2); cursor: default }
@media (max-width: 820px) {
  .cli-tabs button { padding: 6px 10px }
  .cot-variantes .seg { flex-wrap: wrap; overflow: visible; width: 100% }
  .cot-variantes .seg button { flex: 1 1 auto; white-space: normal }
  .cot-pedido { flex-direction: column; align-items: stretch }
  .cot-pedido .btn { width: 100% }
}

/* El cierre del día. Cada línea entra a su pantalla, así que se comporta como
   las alertas de arriba: la fila ENTERA es el botón, no una flechita. */
.cierre { margin: 18px 0 6px }
.cierre-h { margin: 0 0 10px }
.cierre-lista { display: flex; flex-direction: column; gap: 8px }
.cierre-l {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  padding: 13px 15px; border-radius: 12px; border: 1px solid var(--line);
  background: var(--card); font-size: 14px; color: var(--ink); transition: all .15s;
}
.cierre-l:hover { transform: translateX(2px) }
.cierre-tx { flex: 1; min-width: 0 }
.cierre-l .go { color: var(--ink-3); font-weight: 700; flex: none }
/* Lo que te toca hacer se distingue de lo que salió bien SIN gritar: el panel
   entero ya usa el ámbar para "esto te espera" y el verde para "esto se logró". */
.cierre-l.urgente { border-color: rgba(217, 119, 6, .35); background: var(--warn-soft) }
.cierre-l.urgente .cierre-tx { font-weight: 600; color: var(--warn) }
.cierre-l.ok .cierre-tx { color: var(--ok) }

/* MercadoLibre en Canales */
.ml-card { margin-bottom: 14px }
.ml-card .hd { display: flex; align-items: center; gap: 9px; font-weight: 700; font-size: 15px; margin-bottom: 8px }
.ml-card .hd .ch { width: 26px; height: 26px; display: grid; place-items: center }
.ml-card .hd .ch svg { width: 20px; height: 20px }
.wa-signup-actions { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0 }
.wa-signup-actions .btn { flex: 1 1 100%; text-align: left; min-height: 44px }
/* «Conecta tu Instagram» (#742). El glifo es el OFICIAL de Meta (multicolor),
   sin tocar, y sigue sus pautas: nunca menos de 29×29 px, y libre alrededor la
   mitad de su tamaño respecto a textos y otros logos. Va a 30 px con 15 px hasta
   el texto, en la cabecera y en el botón. En el botón va sobre blanco en los dos
   temas, tal como lo entrega Meta, sin ponerlo encima del degradado de Surfia. */
#ig-connect-card .hd { gap: 15px }
#ig-connect-card .hd .ch { width: 30px; height: 30px }
#ig-connect-card .hd .ch img { width: 30px; height: 30px; display: block }
.ig-connect-account { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 12px; margin: 0 0 10px; font-size: 15px }
.ig-connect-account b { color: var(--ink); font-weight: 700; overflow-wrap: anywhere }
.ig-connect-account span { font-size: 12.5px; color: var(--ink-2) }
.ig-connect-account code { font-family: var(--mono); font-size: 12.5px; color: var(--ink); overflow-wrap: anywhere }
.ig-switch { display: flex; align-items: center; gap: 10px; min-height: 44px; margin: 0 0 6px; font-size: 13.5px; color: var(--ink-2); text-align: left }
.ig-switch b { color: var(--ink) }
.ig-switch i { width: 34px; height: 20px; border-radius: var(--r-pill); background: var(--line-2); position: relative; transition: background .18s; flex: none }
.ig-switch i::after { content: ""; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%; background: #fff; transition: transform .18s; box-shadow: 0 1px 3px rgba(0, 0, 0, .25) }
.ig-switch.on i { background: var(--brand) }
.ig-switch.on i::after { transform: translateX(14px) }
.ig-switch.on b { color: var(--brand) }
.ig-connect-warn { font-size: 13px; line-height: 1.45; color: var(--warn-ink); background: var(--warn-soft); border-radius: var(--r-sm); padding: 9px 11px; margin: 0 0 10px; max-width: 60ch }
.ig-connect-notice { color: var(--ink) }
.ig-connect-status { font-size: 13px; margin: 0; max-width: 60ch }
.ig-connect-status.err { color: var(--bad); margin: 0 0 6px }
.ig-connect-actions { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0 }
.btn.ig-login { display: inline-flex; align-items: center; gap: 15px; padding-top: 7px; padding-bottom: 7px; background: #fff; color: #111; border: 1px solid #dbdbdb; box-shadow: none }
.btn.ig-login img { width: 30px; height: 30px; flex: none }
.btn.ghost.ig-danger { background: var(--bad-soft); color: var(--bad) }
@media (prefers-reduced-motion: reduce) { .ig-switch i, .ig-switch i::after { transition: none } }
@media (max-width: 620px) {
  .ig-connect-actions .btn { flex: 1 1 100%; justify-content: center; text-align: center }
}
.ml-txt { font-size: 13.5px; color: var(--ink-2); margin: 0 0 14px; max-width: 60ch }

@media (max-width: 820px) {
  /* En el teléfono, cada fila de controles es contenido que el dueño no ve sin
     bajar. Esta pantalla ya arrastra la banda de datos, la cabecera, el período
     y los canales; añadirle vista + buscador + orden en filas propias dejaba la
     primera conversación fuera de la pantalla. Se juntan y se recorta lo que el
     título ya dice. */
  #s-convs .sub-h { display: none }
  .conv-tools { display: flex; align-items: center; gap: 8px; margin: 4px 0 12px }
  .conv-tools .buscador { margin: 0; flex: 1; min-width: 0 }
  .conv-tools .buscador input { max-width: none }
  /* Clientes en el teléfono: una tarjeta de dos líneas por cliente —quién es
     (con su empresa o RIF) y sus pastillas, y debajo cuándo escribió, lo que
     pidió y lo que compró. Arriba solo el número grande: los conteos de las
     otras tarjetas ya van en los chips, y con las cinco la primera fila
     quedaba fuera de la pantalla a 375. El orden baja de línea en vez de
     esconder «Nombre» fuera de la pantalla. */
  .cli-orden { flex-wrap: wrap; overflow: visible }
  .cli-orden button { padding: 6px 10px; font-size: 12px }
  .cli-totals { gap: 8px }
  .cli-totals .tot { padding: 10px 13px }
  .cli-totals .tot:not(.hero) { display: none }
  .cli-totals .tot .val { font-size: 20px }
  .cli-buscador input { max-width: none }
  .cli-head { display: none }
  .cli-row { display: flex; flex-wrap: wrap; gap: 4px 8px; padding: 11px 12px }
  .cli-row > span:not(.c-cli):not(.c-estado):not(.c-movil) { display: none }
  .cli-row .c-cli { flex: 1 1 60%; min-width: 0 }
  .cli-row .c-estado { flex: 0 1 auto; justify-content: flex-end }
  .cli-row .c-movil { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; flex-basis: 100%; font-size: 12px; line-height: 1.35; color: var(--ink-3); white-space: normal; overflow: hidden }
}


/* ---------- iconos de interfaz ----------
   El sprite sustituyó a los emojis del panel (alertas, insights, barra de
   datos, botones). Un emoji no hereda el color: el rojo de «te esperan» y el
   ámbar de «casi agotado» tenían que ir en el propio glifo, y cada teléfono
   dibujaba el suyo. Estos toman `currentColor` del sitio donde caen. */
svg.ico { width: 17px; height: 17px; flex: none; display: block }
.alert svg.ico { align-self: flex-start; margin-top: 1px }
.alert.critical svg.ico { color: var(--bad) }
.alert.warning svg.ico { color: var(--warn-ink) }
.alert.ok svg.ico { color: var(--ok) }
.databar svg.ico { width: 15px; height: 15px }
.databar.demo svg.ico { color: var(--aqua) }
.databar.live svg.ico { color: var(--ok) }
.databar.err svg.ico { color: var(--bad) }
.unmet .uh svg.ico { width: 15px; height: 15px; color: var(--warn-ink) }
.hinsight svg.ico { width: 15px; height: 15px; color: var(--aqua); flex: none }
.sn.motivo svg.ico, .th-motivo svg.ico { width: 13px; height: 13px; display: inline-block; vertical-align: -2px; margin-right: 4px }
.install-bar svg.ico, .update-bar svg.ico { width: 15px; height: 15px; display: inline-block; vertical-align: -3px; margin-right: 6px }
.btn-icon svg.ico { width: 15px; height: 15px; display: inline-block; vertical-align: -3px }
.pending-banner svg.ico { color: var(--warn-ink) }

/* La nota que antes se repetía en cada fila del catálogo, dicha una sola vez. */
.inv-nota { font-size: 12.5px; color: var(--ink-3); padding: 12px 4px 0; text-align: center }

/* ---------- siluetas de carga ----------
   El panel arrancaba en blanco entre uno y tres segundos mientras resolvían
   las llamadas al servidor. Estas formas ocupan el sitio de lo que viene, sin
   brillo ni parpadeo: el arranque deja de parecer una pantalla rota. */
.sk { display: block; border-radius: 7px; background: var(--card-2); border: 1px solid var(--line-2) }
.sk + .sk { margin-top: 10px }
.sk-hero { padding: 4px 0 2px }
.sk-fila { padding: 15px 14px; border-radius: var(--r-sm); border: 1px solid var(--line); background: var(--card) }
.sk-kpi { padding: 15px 16px 17px; border-radius: var(--r); border: 1px solid var(--line); background: var(--card) }

/* ---- Cuestionario de alta (#166) ---- */
.onb-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px }
.onb-progress { font-size: 12px; color: var(--ink-3); white-space: nowrap }
.onb-chips { display: flex; flex-wrap: wrap; gap: 8px }
.onb-chip { padding: 7px 12px; border: 1px solid var(--line); border-radius: 999px; background: var(--card-2); cursor: pointer; font-size: 13px; text-align: left; color: inherit }
.onb-chip.on { border-color: var(--brand); font-weight: 600; box-shadow: 0 0 0 1px var(--brand) inset }
.onb-candado { opacity: .72 }
.onb-resumen { margin: 0; padding-left: 18px }
.onb-resumen li { margin: 0 0 7px }
.onb-plans { display: grid; gap: 10px }
.onb-plan { text-align: left; border: 1px solid var(--line); border-radius: 12px; padding: 12px 14px; background: var(--card-2); cursor: pointer; color: inherit; display: grid; gap: 3px }
.onb-plan.on { border-color: var(--brand); box-shadow: 0 0 0 1px var(--brand) inset }
.onb-plan .precio { font-size: 19px; font-weight: 700 }
.onb-plan em { color: var(--ink-3); font-style: normal; font-size: 12px }
/* Planes v3, el mes gratis y el cierre del alta (alta-planes.js, alta-cierre.js; 22-oct-2026). */
.onb-falta { font-size: 13px; line-height: 1.45; color: var(--warn-ink); background: var(--warn-soft); border-radius: var(--r-sm); padding: 9px 11px; margin: 0 0 12px }
.onb-promo { font-size: 13.5px; font-weight: 600; color: var(--ok); background: var(--ok-soft); border-radius: var(--r-sm); padding: 8px 11px; margin: 0 0 12px }
.sheet .onb-plan-incluye { font-size: 13px; line-height: 1.45; color: var(--ink-2); border-left: 3px solid var(--brand); padding: 2px 0 2px 10px; margin: 0 0 12px }
.onb-plan-canales { font-size: 13px; color: var(--ink-2) }
.onb-plan-lista { display: grid; gap: 2px; margin-top: 4px; font-size: 12.5px; color: var(--ink-2) }
.onb-plan-lista span::before { content: "· " }
.onb-plan-linea { font-size: 12.5px; color: var(--ink-2); margin: 12px 0 0 }
.onb-plan-actual { border: 1px solid var(--brand); border-radius: 12px; padding: 12px 14px; background: var(--card-2) }
/* Esencial = UN canal que el dueño elige (27-oct-2026): pegado debajo de su tarjeta marcada, con su mismo borde. */
.onb-plan.on:has(+ .onb-plan-canal) { border-bottom-left-radius: 0; border-bottom-right-radius: 0 }
.onb-plan-canal { margin-top: -10px; border: 2px solid var(--brand); border-top: 0; border-radius: 0 0 12px 12px; padding: 12px 14px 6px; background: var(--card-2); display: grid; gap: 10px }
.onb-plan-canal .onb-plan-canal-t { margin: 0; font-size: 13px; font-weight: 600; color: var(--ink) }
.onb-plan-canal .onb-chip { min-height: 40px }
.onb-plan-canal .onb-plan-canal-mas { margin: 0; font-size: 12.5px; color: var(--ink-2) }
.onb-plan-subir { display: block; background: none; border: 0; padding: 0; min-height: 44px; color: var(--brand); font-size: 13px; font-weight: 600; text-decoration: underline; cursor: pointer; text-align: left }
.onb-despues, .wa-gs-link { background: none; border: 0; padding: 10px 0; min-height: 44px; color: var(--ink-2); font-size: 13px; text-decoration: underline; cursor: pointer; text-align: left }
.wa-gs-link.on { color: var(--brand); font-weight: 600 }
/* «Tu marca y tus materiales» (alta-materiales.js): una fila por material; todo el botón «Subir» es el input de archivo. */
.onb-mats { display: grid; gap: 10px; margin-top: 4px }
.onb-mat { display: flex; align-items: center; justify-content: space-between; gap: 12px; border: 1px solid var(--line); border-radius: 12px; padding: 10px 12px; background: var(--card-2) }
.onb-mat-txt { display: grid; gap: 2px; min-width: 0 }
.onb-mat-txt em { font-style: normal; font-size: 12px; color: var(--ink-3) }
.onb-mat-det { font-size: 12px; font-weight: 400; color: var(--ink-2) }
.onb-mat-estado { font-size: 12.5px; color: var(--ink-2); overflow-wrap: anywhere }
.onb-mat-estado.ok { color: var(--ok) }
.onb-mat-estado.err { color: var(--bad) }
/* Con algo ya subido (✓ en verde), el archivo rechazado se dice en su propia línea, en rojo. */
.onb-mat-error { display: block; color: var(--bad) }
.onb-mat-subir { position: relative; flex: none; min-height: 44px; display: inline-flex; align-items: center; cursor: pointer }
.onb-mat-subir input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer }
.onb-mat-subir:focus-within { outline: 2px solid var(--brand); outline-offset: 2px }
.onb-fin { margin: 0; padding-left: 18px }
.onb-fin li { margin: 0 0 8px; line-height: 1.45 }
.wa-gs-abrir { display: flex; align-items: center; justify-content: center; min-height: 48px; margin: 4px 0 12px; font-size: 15px; text-decoration: none }
.wa-gs-mano-t { font-size: 13px; font-weight: 600; margin: 12px 0 4px }
.wa-gs-mano { margin: 0 0 10px; padding-left: 18px; font-size: 13px; color: var(--ink-2) }
.wa-gs-mano li { margin: 0 0 3px }
.wa-gs-aviso { color: var(--ink) }
.wa-gs-status { font-size: 13px; margin: 0; max-width: 60ch }
.wa-gs-status.err { color: var(--bad); margin: 0 0 6px }
.wa-gs-modo { margin-top: 12px }
#wa-gupshup-card .setup-note a { color: inherit }
/* La línea discreta encima de la tarjeta de Meta mientras el equipo pasa ese WhatsApp a Gupshup (wa-canales.js). */
.wa-migrando { color: var(--ink-3); font-size: 12.5px; line-height: 1.4; margin: 0 0 8px; max-width: 70ch }
/* «¿Tu número ya trabaja con otro proveedor…?» es el tercer radio del grupo con aspecto de enlace: el radio queda fuera de la vista pero con foco de teclado. */
.wa-gs-otro { position: relative; display: inline-flex; align-items: center }
.wa-gs-otro input { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0 }
.wa-gs-otro:focus-within { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 4px }

/* ---- Surfia aprendió esto de tus clientes (#167) ---- */
.aprendizajes { display: grid; gap: 10px; margin: 4px 0 14px }
.apr-card { border: 1px solid var(--line); border-radius: 12px; background: var(--card-2); padding: 12px 14px }
.apr-card p { margin: 4px 0 10px; color: var(--ink-3); font-size: 13px }
.apr-card textarea { width: 100%; resize: vertical }
.apr-veces { font-size: 11px; color: var(--ink-3); margin-left: 6px }
.apr-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px }

/* ── Cobros (épico ERP F1) ─────────────────────────────────────────────── */
.cob-chips { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0 4px }
.cob-form { display: flex; flex-wrap: wrap; gap: 12px; padding: 14px; align-items: flex-end }
.cob-form label { display: flex; flex-direction: column; gap: 4px; font-size: 13px }
.cob-form input, .cob-form select { padding: 6px 8px; font: inherit }
#cob-f-tasa-wrap { display: flex; gap: 12px }
#cob-f-tasa-wrap[hidden] { display: none }
.cob-draft { display: block; white-space: normal; color: var(--ink-3); font-size: 12.5px; margin-top: 4px }

/* ── Bloques de la Torre de Control ────────────────────────────────────── */
.bloque-row { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-top: 1px solid var(--line) }
.bloque-row:first-of-type { border-top: 0 }
.bloque-row .what { flex: 1; min-width: 0 }
.bloque-row .what b { display: block; font-size: 14px }
.bloque-row .what span { color: var(--ink-3); font-size: 12.5px }

/* La hoja «Más» solo existe en el teléfono: en escritorio la barra lateral ya lo enseña todo. */
.mas { display: none }
/* En el demo no hay papelera (el dataset no tiene chats borrados): el chip no promete nada. */
html.demo [data-convstatus="trash"] { display: none }

/* ── Torre de Control (asistente del dueño) ────────────────────────────── */
.torre-fab {
  position: fixed; right: 18px; bottom: 18px; z-index: 60;
  display: flex; align-items: center; gap: 7px;
  padding: 11px 16px; border: 0; border-radius: 999px; cursor: pointer;
  background: var(--brand-grad); color: #fff; font: inherit; font-weight: 600; font-size: 14px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, .28);
}
.torre-fab svg { width: 18px; height: 18px; fill: currentColor }
.torre-fab:hover { filter: brightness(1.08) }
/* La disposición vive en torre-layout.css; solo la Torre conserva saltos. */
.torre .bub { white-space: pre-wrap; overflow-wrap: anywhere }
.torre .sugerencia { color: var(--ink-3); font-size: 12px; line-height: 1.6; padding: 10px 0 }
.torre .sugerencia svg { width: 15px; height: 15px; color: var(--brand); margin-right: 6px }
.propuesta {
  border: 1px solid var(--brand); border-radius: 12px; padding: 11px 13px; margin: 8px 0;
  background: color-mix(in srgb, var(--brand) 8%, transparent);
}
.propuesta .what b { display: block; font-size: 13px }
.propuesta .what span { display: block; color: var(--ink-3); font-size: 12.5px; margin-top: 2px }
.propuesta-btns { display: flex; gap: 8px; margin-top: 9px }
/* El descuento de un pedido dictado: los atajos del negocio en fila, y el
   formulario de «Otro %» sólo cuando se pide. Los botones envuelven en el
   teléfono, que es donde Verónica carga los pedidos. */
.torre-pedido-descuento { margin-top: 10px }
.torre-pedido-descuento .propuesta-btns { flex-wrap: wrap }
.torre-pedido-descuento-titulo { font-size: 12px; opacity: .75 }
.torre-pedido-descuento-motivo { margin: 6px 0 0; font-size: 12.5px; opacity: .8 }
.torre-pedido-descuento-otro { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 9px }
.torre-pedido-descuento-otro label { font-size: 12px; opacity: .75 }
.torre-pedido-descuento-otro input[type="number"] { width: 5.5em }
.torre-pedido-descuento-otro input[type="text"] { flex: 1 1 12em; min-width: 9em }
.torre .guia-tarjeta {
  display: flex; align-items: center; justify-content: space-between; gap: 10px; margin: 2px 0 8px; padding: 10px 12px;
  border-radius: 14px; font-size: 12.5px;
  background: color-mix(in srgb, var(--brand) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--brand) 28%, transparent);
}
.torre .guia-tarjeta .btn { flex: none }
.torre .torre-chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 2px 0 6px }

/* ── Guía paso a paso (guia-panel.js) ─────────────────────────────────────
   El manual que enseña Agente Surfia, encima del panel. La capa no bloquea
   nada (pointer-events: none): el dueño sigue pulsando lo que se le señala.
   z 80: sobre la barra del teléfono (50) y el botón flotante (60), bajo el
   toast (90). Una hoja modal (capa superior) siempre queda encima: por eso la
   guía termina en cuanto se abre una. */
.guia { position: fixed; inset: 0; z-index: 80; pointer-events: none }
.guia-foco {
  position: fixed; border-radius: var(--r); pointer-events: none;
  box-shadow: 0 0 0 9999px rgba(10, 22, 40, .55), 0 0 0 2px var(--aqua);
  transition: top var(--t-fast) var(--ease), left var(--t-fast) var(--ease), width var(--t-fast) var(--ease), height var(--t-fast) var(--ease);
}
.guia-burbuja {
  position: fixed; pointer-events: auto; width: min(340px, calc(100vw - 24px));
  background: var(--marino); color: var(--sobre-marino); border: 1px solid var(--aqua-35);
  border-radius: var(--r); padding: 14px 16px; font-size: 13.5px; line-height: 1.5; box-shadow: var(--shadow-pop);
}
.guia-burbuja.centro { left: 50%; top: 50%; transform: translate(-50%, -50%) }
.guia-burbuja .guia-paso { font-family: var(--mono); font-size: 11px; letter-spacing: .06em; text-transform: uppercase; color: var(--aqua); margin-bottom: 6px }
.guia-burbuja p { margin: 0 0 12px }
.guia-btns { display: flex; gap: 8px; justify-content: flex-end }
.guia-btns .btn:not(.primary) { background: transparent; color: var(--sobre-marino); border: 1px solid var(--aqua-35) }
@media (prefers-reduced-motion: reduce) { .guia-foco, .guia-burbuja { transition: none; animation: none } }
@media (max-width: 820px) {
  /* En el teléfono la burbuja se pega al borde de abajo (encima de la barra)
     o al de arriba cuando lo señalado está en la mitad de abajo. */
  .guia-burbuja.dock { left: 12px; right: 12px; width: auto; bottom: calc(74px + env(safe-area-inset-bottom)) }
  .guia-burbuja.dock-arriba { left: 12px; right: 12px; width: auto; top: calc(12px + env(safe-area-inset-top)) }
}
@media (max-width: 820px) {
  .torre-fab { bottom: calc(64px + env(safe-area-inset-bottom)) }
  /* Con un hilo abierto el botón se va. En el teléfono el hilo es una pantalla
     de foco y su caja de respuesta vive pegada al fondo: el botón flotante caía
     justo encima de "Enviar" y del borde derecho del textarea, y contestarle a
     un cliente — lo único que se hace en esa pantalla — se volvía puntería.
     La Torre no se pierde: al volver a la lista el botón está otra vez ahí. */
  body.hilo-abierto .torre-fab { display: none }
  body.torre-abierta .bnav { display: none }
  /* Con la hoja «Más» abierta el FAB (z 60) flotaba sobre la cuadrícula, y
     encima sobra: la Torre ya está ahí dentro como un icono más. */
  body.mas-abierta .torre-fab { display: none }
  body.torre-abierta { overflow: hidden }
  /* La entrada a la Torre vuelve a decir con palabras lo que es.
     Era un círculo de 42 px con un cerebro y nada más: el rótulo se había
     quitado porque tapaba las tarjetas y la caja del chat. Las dos cosas que
     tapaba ya están resueltas por separado — con un hilo abierto o con la hoja
     «Más» arriba, la entrada se esconde (las reglas de aquí arriba) — así que
     lo único que quedaba en pie era el miedo, no el problema. Un cerebro mudo
     no le dice a un dueño de finca que AHÍ se le habla a Surfia, que es lo
     único que él hace desde el teléfono.
     El rótulo del teléfono sale de `data-movil` y no del `<span>`: el `<span>`
     es el de escritorio y no se toca ni una letra. 48 px de alto es el mínimo
     de un dedo. */
  .torre-fab { min-height: 48px; padding: 12px 18px; gap: 8px; font-size: 14.5px }
  .torre-fab svg { width: 20px; height: 20px }
  .torre-fab span { display: none }
  .torre-fab::after { content: attr(data-movil) }
  /* Con el rótulo la entrada es más alta, así que la lista termina más arriba:
     estos píxeles son los que evitan que el último botón de la última tarjeta
     quede debajo de ella cuando el dueño llega al final. */
  .main { padding-bottom: calc(118px + env(safe-area-inset-bottom)) }
  /* La hoja «Más» (épico #404): a pantalla completa bajo la barra (z 49 < 50),
     así la barra sigue a mano para saltar a una fija o cerrar con el mismo botón. */
  .mas:not([hidden]) { display: block }
  .mas {
    position: fixed; inset: 0; z-index: 49; background: var(--bg); overflow-y: auto;
    -webkit-overflow-scrolling: touch; padding: 0 16px calc(84px + env(safe-area-inset-bottom));
  }
  /* El respiro de arriba lo pone el encabezado, no la hoja: es él quien tiene
     que despejar la barra de estado —igual que `.main`— y quien se queda
     pegado arriba al bajar, para que «Cerrar» esté siempre a mano por larga
     que sea la lista. Los márgenes negativos llevan su fondo hasta los bordes:
     sin ellos el contenido se vería pasar por los 16px de los lados. */
  .mas-head {
    position: sticky; top: 0; z-index: 1; background: var(--bg);
    display: flex; align-items: center; gap: 8px;
    margin: 0 -16px 0; padding: calc(16px + env(safe-area-inset-top)) 16px 10px;
    border-bottom: 1px solid var(--line);
  }
  .mas-head h2 { flex: 1; min-width: 0; margin: 0; font-size: 20px }
  .mas-guia { padding-top: 12px }
  .mas-guia .sub-h { margin: 0 0 10px; font-size: 13px }
  .mas-head .btn, .mas-guia .btn { flex: none; padding: 7px 10px; font-size: 12.5px; display: inline-flex; align-items: center; gap: 5px }
  .mas-guia .btn svg { width: 14px; height: 14px; fill: none; stroke: currentColor }
  .mas-seccion h3 { font-size: 12px; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-3); margin: 18px 0 10px; font-weight: 600 }
  /* Tres columnas, no cuatro: las secciones traen tres iconos y la cuarta
     columna quedaba vacía, con la fila recostada a la izquierda. Con tres, las
     celdas son anchas, el icono crece y los nombres largos («Personaliza
     Surfia», «Torre de Control») dejan de cortarse. */
  .mas-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px 8px }
  /* «Tu cuenta» al pie de la hoja: quién eres y «Salir» (hallazgo de la prueba de humo, 22-oct). Con borde: sin él
     el `.btn` del tema oscuro se lee como texto suelto. */
  .mas-cuenta { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 16px }
  .mas-cuenta .polhelp { margin: 2px 0 0 }
  .mas-salir { flex: none; min-height: 44px; padding: 0 18px; border: 1px solid var(--line); border-radius: 12px; font-weight: 600 }
  /* `width: 100%` como todo botón que hace de bloque en esta hoja de estilos
     (.kpi, .alert, .ev, .row.link): WebKit no estira los controles de
     formulario como ítems de grid, se quedan en su contenido y se pegan a la
     izquierda de su celda, cada uno con un ancho distinto según su etiqueta. */
  .mas-item { width: 100%; display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 0; font-size: 11.5px; font-weight: 500; color: var(--ink-2); text-align: center }
  .mas-item .ico { width: 62px; height: 62px; border-radius: 18px; background: var(--card-2); border: 1px solid var(--line); display: grid; place-items: center; transition: background var(--t-fast), border-color var(--t-fast) }
  .mas-item .ico svg { width: 24px; height: 24px }
  /* El cerebro de «Agente Surfia» lleva las tres corrientes del logo, pero solo
     donde el fondo las deja. Aquí el fondo es --card-2 y los azules lucen — es
     el mismo sitio donde #i-logo ya pinta el logo tricolor, en «Mi Surfia». En
     el botón flotante el fondo ES el degradado de marca: un azul sobre azul
     desaparece, así que allí no se define nada y las tres caen en el
     `currentColor` blanco. */
  .mas-item .ico svg { --cerebro-1: var(--logo-1); --cerebro-2: var(--logo-2); --cerebro-3: var(--logo-3) }
  /* Dos líneas en vez de «…»: el dueño puede renombrar sus pestañas y un
     nombre largo volvería a cortarse por mucho que quepan los de hoy. */
  .mas-item .lbl { max-width: 100%; overflow: hidden; white-space: normal; overflow-wrap: anywhere; line-height: 1.25; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical }
  .mas-item.fav .ico { border-color: var(--brand); background: var(--aqua-soft) }
  .mas-item.fav { color: var(--brand); font-weight: 600 }
  .mas-item:active .ico { background: var(--aqua-soft) }
  body.mas-abierta { overflow: hidden }
}

/* Precio de proveedor con demasiado tiempo encima: en Venezuela eso importa. */
.precio-viejo { color: var(--warn); font-weight: 600 }

/* «Las palabras de tu negocio» (vocabulario, fase Torre te recibe) */
.vocab-h { margin-top: 18px; }
.vocab-row { display: flex; align-items: center; gap: 10px; margin: 8px 0; }
.vocab-row label { flex: 1; color: var(--ink-2); font-size: 14px; }
.vocab-row input { width: 150px; }
#vocab-guardar { margin-top: 10px; }
.onb-trae { border: 1px solid var(--line); border-radius: 10px; padding: 12px 14px; margin: 12px 0; background: var(--card-2); }
.onb-trae p { margin: 6px 0 0; color: var(--ink-2); font-size: 14px; }

/* El alta viva (la Torre te recibe) */
.alta-vista { border: 1px solid var(--line); border-radius: 12px; padding: 10px 12px; margin-bottom: 10px; background: var(--card-2); }
.alta-mini { display: flex; flex-wrap: wrap; gap: 6px; }
.alta-tab { border: 1px solid var(--line); border-radius: 999px; padding: 3px 10px; font-size: 12.5px; background: var(--bg); transition: transform .35s ease, opacity .35s ease; }
.alta-tab.alta-on { animation: alta-pop .45s ease; border-color: var(--brand); }
@keyframes alta-pop { from { transform: scale(.6); opacity: 0; } to { transform: scale(1); opacity: 1; } }
.alta-hint { margin: 8px 0 0; font-size: 12.5px; color: var(--ink-2); }
.alta-chat { max-height: 46vh; min-height: 180px; overflow-y: auto; display: flex; flex-direction: column; gap: 8px; padding: 4px 2px; }
#alta-form { display: flex; gap: 8px; margin-top: 10px; }
#alta-form input { flex: 1; }
.alta-pie { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; justify-content: flex-end; }
@media (max-width: 480px) {
  .alta-chat { max-height: 38vh; }
  .alta-mini { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 2px; }
}
.pill-reco { background: color-mix(in srgb, var(--brand) 14%, transparent); color: var(--brand); border-radius: 999px; padding: 1px 8px; font-size: 11px; font-weight: 600; }

/* La release que está corriendo (#276). Discreta a propósito: se busca cuando
 * algo salió raro después de publicar, no se lee todos los días. */
.version-pie { font-size: 11.5px; color: var(--ink-3); text-align: center; margin: 18px 0 4px }

/* ---------- el editor de la cotización (Issue #399, PR B) ---------- */
.doc-editor { display: flex; flex-direction: column; gap: 12px }
.doc-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; flex-wrap: wrap }
.doc-head b { display: block; font-size: 15px }
.doc-head span { color: var(--ink-3); font-size: 12px }
.doc-acciones { display: flex; gap: 8px; flex-wrap: wrap; align-items: center }
.doc-lineas { width: 100%; border-collapse: collapse; font-size: 13px }
.doc-lineas th { text-align: left; font-size: 11px; color: var(--ink-3); font-weight: 600; padding: 6px 6px; border-bottom: 1px solid var(--line) }
.doc-lineas td { padding: 5px 6px; border-bottom: 1px solid var(--line-2); vertical-align: top }
.doc-lineas td small { display: block; color: var(--ink-3); font-size: 11px }
.doc-lineas input { width: 100%; min-width: 60px; padding: 7px 8px; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--card-2); color: var(--ink); font-size: 13px }
.doc-lineas td:nth-child(2) input, .doc-lineas td:nth-child(3) input { font-family: var(--mono); text-align: right }
/* La descripción es lo que se lee: se lleva el ancho que necesita, no el que le sobra a los montos. */
.doc-lineas th:first-child, .doc-lineas td:first-child { width: 36% }
/* La unidad va debajo de la cantidad, en la misma celda: es texto del cliente («mts», «cajas»), no un número. */
.doc-lineas td input[data-campo="unit"] { margin-top: 4px; font-family: inherit; text-align: left; font-size: 12px }
.doc-cabecera { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px 14px }
.doc-cabecera label { display: flex; flex-direction: column; gap: 4px; font-size: 11.5px; color: var(--ink-3) }
.doc-cabecera label.ancho { grid-column: 1 / -1 }
.doc-cabecera input, .doc-cabecera textarea { width: 100%; padding: 8px 10px; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--card-2); color: var(--ink); font-size: 13px }
/* Un <textarea> nace con letra de máquina: las condiciones y el motivo se leen con la del panel. */
.doc-cabecera textarea { font-family: inherit; line-height: 1.45 }
.doc-totales { display: flex; gap: 18px; flex-wrap: wrap; justify-content: flex-end; font-size: 12.5px; color: var(--ink-3) }
.doc-totales b { color: var(--ink); font-family: var(--mono); margin-left: 4px }
.doc-totales .total b { color: var(--brand); font-size: 15px }
.doc-estado { margin: 0; font-size: 12px; color: var(--ink-3) }
.doc-estado.ok { color: var(--ok) }
.doc-estado.error { color: var(--bad); font-weight: 600 }
.doc-lineas input[aria-invalid="true"] { border-color: var(--bad); background: var(--bad-soft) }
.doc-terms { color: var(--ink-2); font-size: 12.5px; white-space: pre-wrap }
/* Pistas de precio bajo la descripción (#831) y «Buscar en el catálogo» (#834): el costo, el sugerido con «Usar», los parecidos con «Enlazar». */
.doc-pista { display: flex; flex-direction: column; gap: 2px; margin-top: 4px; font-size: 11px; color: var(--ink-3) }
.doc-pista:empty { display: none }
.doc-pista b { color: var(--ink) }
.doc-pista .mini { padding: 2px 8px; font-size: 11px; margin-left: 4px }
.doc-pista-pidio { font-style: italic }
.doc-pista-baja { color: var(--warn-ink); font-weight: 600 }
.doc-pista-mala { color: var(--bad); font-weight: 600 }
.doc-candidatos { display: flex; flex-direction: column; gap: 4px; margin-top: 4px; font-size: 11px; color: var(--ink-3) }
.doc-candidatos:empty { display: none }
.doc-candidato { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 4px 8px; border: 1px solid var(--line-2); border-radius: var(--r-sm); background: var(--card-2) }
.doc-candidato-datos { display: flex; flex-direction: column; gap: 1px; min-width: 0 }
.doc-candidato-datos b { color: var(--ink) }
.doc-candidatos-vacio { font-style: italic }
/* Como los demás inputs del renglón (.doc-lineas input); con .doc-lineas delante para ganarle en especificidad. */
.doc-lineas .doc-candidatos-q { box-sizing: border-box; padding: 4px 8px; font-size: 12px }
.doc-lineas td > .mini[data-doc-buscar] { margin-top: 4px; padding: 2px 8px; font-size: 11px }
@media (max-width: 720px) { .doc-cabecera { grid-template-columns: 1fr 1fr } .doc-lineas th:nth-child(4), .doc-lineas td:nth-child(4) { display: none } }

/* ---- Documentos por módulos (plan del 22-sep-2026): pestañas por tipo,
 * filtros, búsqueda, enlaces entre documentos, forma de pago de la factura y
 * la hoja «Nuevo documento». Todo con los tokens de la paleta. ---- */
.docs-barra { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin: 4px 0 10px }
.docs-barra .seg-view { margin: 0; max-width: 100%; overflow-x: auto; scrollbar-width: none }
.docs-barra .seg-view::-webkit-scrollbar { display: none }
.docs-barra .seg-view button { white-space: nowrap }
.docs-barra > .btn { margin-left: auto }
.docs-filtros { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 12px }
.docs-estados { display: flex; gap: 6px; overflow-x: auto; scrollbar-width: none; padding-bottom: 2px }
.docs-estados::-webkit-scrollbar { display: none }
.docs-estados .chip { padding: 5px 12px; font-size: 12.5px; box-shadow: none }
.docs-buscar { flex: 1 1 220px; min-width: 0; padding: 8px 14px; border: 1px solid var(--line); border-radius: var(--r-pill); background: var(--card); color: var(--ink); font-size: 13px }
.docs-buscar:focus { outline: 2px solid var(--brand); outline-offset: 1px; border-color: var(--brand) }
.docs-mas { display: block; margin: 10px auto 0 }
.doc-fila .what > span { display: block }
.doc-fila .pill { padding: 1px 8px; font-size: 11px }
.doc-fila.anulada .what b { color: var(--ink-3); text-decoration: line-through }
.doc-fila.anulada .amt { color: var(--ink-3) }
.doc-enlaces { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 6px }
.doc-enlaces .pill { font-size: 11px; padding: 2px 9px }
.doc-enlace { font-size: 11.5px; font-weight: 600; padding: 2px 10px; border-radius: var(--r-pill); border: 1px solid var(--line); background: var(--card-2); color: var(--brand); cursor: pointer }
.doc-enlace:hover { border-color: var(--brand) }
.doc-enlace.borrador { color: var(--ink-3); border-style: dashed }
/* Las acciones del ciclo son el siguiente paso del documento: se leen como
 * botón, con el borde de la marca, no como texto suelto. */
.doc-acciones .btn[data-doc-ciclo] { border: 1px solid var(--brand); color: var(--brand); padding: 10px 16px }
.doc-acciones .btn[data-doc-ciclo]:hover { background: var(--aqua-soft) }
.doc-cabecera small { font-size: 11px; color: var(--ink-3) }
.doc-pago { border: 1px solid var(--line); border-radius: var(--r-sm); padding: 12px 14px; margin: 0; display: flex; flex-direction: column; gap: 10px; min-width: 0 }
.doc-pago legend { font-size: 12px; font-weight: 600; color: var(--ink-2); padding: 0 4px }
.doc-formas { display: flex; gap: 8px; flex-wrap: wrap }
.doc-forma { display: inline-flex; align-items: center; gap: 6px; padding: 7px 14px; border: 1px solid var(--line); border-radius: var(--r-pill); background: var(--card); font-size: 13px; font-weight: 600; color: var(--ink-2); cursor: pointer }
.doc-forma input { accent-color: var(--brand); margin: 0 }
.doc-forma:has(input:checked) { border-color: var(--brand); color: var(--brand); background: var(--aqua-soft) }
/* La tasa solo existe si paga en bolívares; el resto del tiempo ni se ve. */
.doc-pago:not([data-forma="bs"]) .doc-tasa { display: none }
.doc-dato { font-size: 12.5px; color: var(--ink-2); margin: 0 }
/* La nota de entrega no lleva precios: su 3.ª columna es la nota, no un monto. */
.doc-lineas.sin-precios td:nth-child(2) { width: 110px; vertical-align: middle }
.doc-lineas.sin-precios td:nth-child(3) input { font-family: inherit; text-align: left }
/* La numeración de tus documentos: una fila por tipo, con la vista previa. */
.source-data-card.numeracion { grid-column: 1 / -1; min-height: 0; align-items: stretch }
.numeracion .serie-fila { display: grid; grid-template-columns: 120px repeat(3, minmax(0, 1fr)) auto auto; gap: 10px; align-items: end; padding: 10px 0; border-top: 1px solid var(--line-2) }
.numeracion .serie-fila > b { align-self: center; font-size: 13.5px }
.numeracion .serie-fila label { display: flex; flex-direction: column; gap: 4px; font-size: 11.5px; color: var(--ink-3) }
.numeracion .serie-fila input { width: 100%; padding: 7px 9px; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--card-2); color: var(--ink); font-size: 13px; font-family: var(--mono) }
.numeracion .serie-previa { align-self: center; font-size: 12px; color: var(--ink-3); white-space: nowrap }
.numeracion .serie-previa b { color: var(--brand); font-family: var(--mono) }
.numeracion .serie-fila .btn.mini { align-self: center; border: 1px solid var(--brand); color: var(--brand) }
@media (max-width: 720px) {
  .numeracion .serie-fila { grid-template-columns: repeat(3, minmax(0, 1fr)) }
  .numeracion .serie-fila > b, .numeracion .serie-previa { grid-column: 1 / -1 }
}
/* Ventas: debajo de cada venta, sus documentos y «Facturar». */
.venta-docs { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; padding: 0 4px 12px 44px; border-bottom: 1px solid var(--line-2) }
.venta-docs .btn.mini { padding: 4px 11px; border: 1px solid var(--brand); color: var(--brand) }
.doc-nuevo-hoja { width: min(520px, calc(100vw - 32px)); max-height: calc(100dvh - 48px); overflow-y: auto }
.doc-nuevo-modos { width: fit-content; margin: 4px 0 14px }
.doc-nuevo-lista { max-height: 320px; overflow-y: auto; margin-bottom: 12px; padding: 0 10px }
.doc-nuevo-lista .row { padding: 10px 2px }
.doc-nuevo-clientes { display: flex; flex-direction: column; gap: 6px; max-height: 220px; overflow-y: auto; margin-bottom: 12px }
.doc-nuevo-cliente { display: flex; flex-direction: column; align-items: flex-start; gap: 1px; text-align: left; padding: 8px 12px; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--card-2); color: var(--ink); font-size: 13px }
.doc-nuevo-cliente span { font-size: 11.5px; color: var(--ink-3) }
.doc-nuevo-cliente.on { border-color: var(--brand); background: var(--aqua-soft) }
.doc-nuevo-hoja .field-row { grid-template-columns: 2fr 1fr 1fr }
@media (max-width: 720px) {
  .docs-barra > .btn { margin-left: 0; width: 100% }
  /* En el teléfono la fila se lee en dos pisos: qué documento es (con sus
   * enlaces) arriba a lo ancho, y el monto con su botón debajo, a la derecha. */
  .doc-fila { flex-wrap: wrap; row-gap: 6px }
  .doc-fila .what { flex: 1 1 100% }
  .doc-fila .amt, .doc-fila .by { margin-left: auto }
  /* En el teléfono cada renglón es una ficha de dos o tres pisos: la
   * descripción a lo ancho (es lo que se lee), y debajo cantidad, precio y la
   * nota. Una tabla de cinco columnas en 375 px cortaba la descripción en
   * «Botas de». El IVA del renglón se sigue escondiendo (regla de arriba). */
  .doc-lineas thead { display: none }
  .doc-lineas tbody tr { display: grid; grid-template-columns: 1fr 1fr auto; gap: 6px 8px; padding: 10px 0; border-bottom: 1px solid var(--line-2) }
  .doc-lineas tbody td { display: block; padding: 0; border: 0; width: auto }
  .doc-lineas th:first-child, .doc-lineas td:first-child { width: auto }
  .doc-lineas tbody td:first-child { grid-column: 1 / -1 }
  /* Sin cabecera, cada campo dice qué es. */
  .doc-lineas tbody td[data-etiqueta]::before { content: attr(data-etiqueta); display: block; font-size: 10.5px; font-weight: 600; color: var(--ink-3); margin-bottom: 3px }
  .doc-lineas:not(.sin-precios) tbody tr[data-doc-linea] td:nth-child(5) { grid-column: 1 / 3 }
  .doc-lineas:not(.sin-precios) tbody tr[data-doc-linea] td:nth-child(6) { grid-column: 3; grid-row: 2 }
  /* Emitido: el 4.º es el total del renglón, no el IVA — ese sí se ve. */
  .doc-lineas.emitida tbody td:nth-child(4) { display: block; text-align: right }
  /* La nota de entrega: su 4.ª columna es «quitar renglón». */
  .doc-lineas.sin-precios tbody td:nth-child(4) { display: block }
  /* Los botones de las pistas y del buscador, con zona táctil de dedo; la casilla «Buscar otro…» a 16 px para que iOS no haga zoom. */
  .doc-pista .mini, .doc-candidato .mini, .doc-lineas td > .mini[data-doc-buscar] { padding: 6px 12px }
  .doc-lineas .doc-candidatos-q { padding: 8px 10px; font-size: 16px }
  .doc-nuevo-hoja .field-row { grid-template-columns: 1fr 1fr }
  .doc-nuevo-hoja .field-row .field:first-child { grid-column: 1 / -1 }
}
/* Pestaña «Banco» de Cobros (#404, punto 29): el resumen, los movimientos por
   estado y la subida del estado de cuenta. Las entradas en verde, las salidas
   apagadas: lo que se cuadra es lo que entra. */
#cob-tabs { margin-bottom: 12px }
.banco-mov .amt.in { color: var(--ok) }
.banco-mov .amt.out { color: var(--ink-3) }
.banco-subir input[type="file"] { font-size: 13px; max-width: 100% }
.banco-subir .thread-note { flex-basis: 100% }
.banco-resultado { flex-basis: 100%; margin: 0; padding-left: 18px; font-size: 13px; color: var(--ink-2) }
.banco-resultado li + li { margin-top: 4px }

/* Cuadrar un depósito (#404, punto 29, mitad 2): cada hipótesis con su
   confianza en palabras; la tasa y el método antes de confirmar. */
.banco-hip .what span { white-space: normal }
.banco-hip .conf { font-size: 11.5px; font-weight: 700; padding: 3px 9px; border-radius: 999px; white-space: nowrap }
.conf.alta { background: var(--aqua-soft); color: var(--brand) }
.conf.media { background: var(--card-2); color: var(--ink) }
.conf.baja { background: var(--card-2); color: var(--ink-3) }
.banco-tasa .thread-note { flex-basis: 100% }
.banco-metodo { display: inline-flex; flex-direction: column; gap: 4px; font-size: 13px; margin: 10px 0 }
.banco-metodo select { padding: 6px 8px; font: inherit }
.banco-acciones { display: flex; gap: 8px; margin: 12px 0 }
/* Datos de ejemplo (#404, punto 42): mientras el Inicio es de muestra, cada
   KPI lo dice en su etiqueta y el sello va arriba; el resto se atenúa un poco
   para que no compita con el sello. */
html.muestra .kpi .lbl::after { content: ' · ejemplo'; font-weight: 400; color: var(--ink-3) }
html.muestra #feed, html.muestra #demand-block, html.muestra #hours-block, html.muestra #avisos, html.muestra #alerts { opacity: .9 }
.muestra-sello b { font-weight: 700 }
/* Avisos agrupados (#404, punto 14): una familia con tres o más avisos se
   pliega en un grupo, y pasado el tope el resto queda tras «ver N avisos más».
   El resumen del grupo se ve como una barra de aviso pero no navega: despliega.
   Sin la flecha nativa del navegador: el «Ver ▾» ya dice qué hace. */
.aviso-grupo, .aviso-mas { width: 100% }
.aviso-grupo > summary, .aviso-mas > summary { cursor: pointer; list-style: none }
.aviso-grupo > summary::-webkit-details-marker { display: none }
.aviso-mas > summary::-webkit-details-marker { display: none }
.aviso-grupo > summary .go::before { content: 'Ver ▾' }
.aviso-grupo[open] > summary .go::before { content: 'Cerrar ▴' }
.aviso-grupo[open] > summary.alert { border-color: var(--brand) }
.aviso-grupo-lista { display: flex; flex-direction: column; gap: 8px; margin: 8px 0 0 10px; padding-left: 10px; border-left: 2px solid var(--line) }
.aviso-mas > summary { padding: 6px 12px; font-size: 13px; font-weight: 700; color: var(--brand) }
.aviso-mas > summary:hover { text-decoration: underline }
.aviso-mas > summary:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 6px }

/* Pedidos honestos (#404, PR 14a): el cliente que ya viene (empresa · RIF ·
   teléfono), la promesa de cotización y el buscador. */
.pedidos-q { width: 100%; max-width: 520px; margin: 0 0 12px; padding: 9px 12px; font: inherit; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--card); color: var(--ink) }
.pedidos-q[hidden] { display: none }
.order-head .order-cliente { display: block; font-size: 12.5px; color: var(--ink-2) }
/* El número del pedido: se lee de un golpe y no compite con el nombre. */
.order-head .order-num { display: block; font-size: 12px; font-weight: 600; color: var(--ink-2); letter-spacing: .02em }
.chip-cotizacion { display: inline-block; margin-top: 4px; padding: 2px 8px; border-radius: 999px; font-size: 11.5px; font-weight: 700 }
.chip-cotizacion.prometida { background: var(--aqua-soft); color: var(--brand) }
.chip-cotizacion.vencida { background: var(--warn-soft); color: var(--warn-ink) }
/* Lo que pasó con el pedido en Shopify (#676): dónde está, el pago y la preparación. */
.order-shopify { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px }
.chip-pedido { display: inline-block; padding: 2px 8px; border-radius: 999px; font-size: 11.5px; font-weight: 700 }
.chip-pedido.ok { background: var(--ok-soft); color: var(--ok) }
.chip-pedido.wait { background: var(--aqua-soft); color: var(--brand) }
.chip-pedido.warn { background: var(--warn-soft); color: var(--warn-ink) }
.chip-pedido.muted { background: var(--line); color: var(--ink-2) }

/* «Cliente de prueba» (#404, punto 5b): un interruptor pequeño bajo la ficha
   del hilo. Marcado, la persona deja de contar en las cifras. */
.ficha-prueba { display: inline-flex; align-items: center; gap: 6px; margin-left: 8px; font-size: 12px; color: var(--ink-3); cursor: pointer; white-space: nowrap }
.ficha-prueba input { margin: 0 }

/* «Cliente | Proveedor» (24-oct-2026, rediseño del Magazine): dos opciones en un
   solo grupo, la pulsada con el mismo aqua de los demás selectores. Solo tokens:
   el modo oscuro sale del tema. En el hilo va en su propia línea, bajo los datos
   de la ficha; el aviso de Surfia baja de línea cuando no cabe. */
.ficha-tipo { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; margin-top: 6px; font-size: 11.5px; line-height: 1.35 }
.ficha-tipo-ops { display: inline-flex; gap: 2px; padding: 2px; background: var(--card); border: 1px solid var(--line); border-radius: var(--r-pill) }
.ficha-tipo-op { padding: 3px 12px; border-radius: var(--r-pill); font-size: 12px; font-weight: 600; color: var(--ink-3); transition: background .15s, color .15s }
.ficha-tipo-op:hover { color: var(--ink-2) }
.ficha-tipo-op[aria-pressed="true"] { background: var(--aqua-soft); color: var(--brand) }
/* Inerte solo cuando no hay nada que confirmar: con el aviso de Surfia puesto, el pulsado ES el botón de confirmar. */
.ficha-tipo:not(.ficha-tipo-sospecha) .ficha-tipo-op[aria-pressed="true"] { cursor: default }
.ficha-tipo-op:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px }
.ficha-tipo-nota { padding: 3px 10px; border-radius: var(--r-sm); background: var(--warn-soft); color: var(--warn-ink); font-weight: 600 }
.ficha-tipo[aria-busy="true"] { opacity: .6; pointer-events: none }
.ficha-tipo[hidden] { display: none }
/* En el teléfono el dedo necesita más que 20 px de alto. */
@media (max-width: 820px) {
  .ficha-tipo-op { padding: 6px 14px }
}

/* ═══════════ Agenda: el calendario (29-sep-2026) ═══════════
 * Día, semana, mes y lista (agenda-calendario*.js). Cada bloque trae su
 * posición como variables (--ini, --dur, --carril, --carriles; --r0 es el
 * primer minuto de la rejilla) y aquí se hace la cuenta con --hora, el alto de
 * una hora: en el teléfono baja y nada del JS cambia.
 * Colores: cita = aqua de marca, compromiso (llamada, visita, retiro) =
 * violeta, nueva por confirmar = borde punteado ámbar, pasada = atenuada.
 * Los tres bloques de variables son gemelos: tema claro, oscuro por sistema y
 * oscuro fijado (misma regla que los de arriba). */
:root {
  --cita-borde: #0284C7;
  --cita-bg: rgba(2, 132, 199, .09);
  --cita-line: rgba(2, 132, 199, .22);
  --cita-ink: #0369A1;
  --comp-borde: #7C3AED;
  --comp-bg: rgba(124, 58, 237, .08);
  --comp-line: rgba(124, 58, 237, .22);
  --comp-ink: #6D28D9;
  --ahora: #E11D48;
  --nueva-raya: rgba(201, 138, 43, .12);
  --cal-hoy: rgba(2, 132, 199, .035);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --cita-borde: #22D3EE;
    --cita-bg: rgba(34, 211, 238, .12);
    --cita-line: rgba(34, 211, 238, .28);
    --cita-ink: #67E8F9;
    --comp-borde: #A78BFA;
    --comp-bg: rgba(167, 139, 250, .14);
    --comp-line: rgba(167, 139, 250, .30);
    --comp-ink: #C4B5FD;
    --ahora: #FB7185;
    --nueva-raya: rgba(223, 175, 99, .12);
    --cal-hoy: rgba(34, 211, 238, .04);
  }
}
:root[data-theme="dark"] {
  --cita-borde: #22D3EE;
  --cita-bg: rgba(34, 211, 238, .12);
  --cita-line: rgba(34, 211, 238, .28);
  --cita-ink: #67E8F9;
  --comp-borde: #A78BFA;
  --comp-bg: rgba(167, 139, 250, .14);
  --comp-line: rgba(167, 139, 250, .30);
  --comp-ink: #C4B5FD;
  --ahora: #FB7185;
  --nueva-raya: rgba(223, 175, 99, .12);
  --cal-hoy: rgba(34, 211, 238, .04);
}

.cal {
  --hora: 56px;
  --gutter: 58px;
  display: grid; gap: 12px;
}
.cal .ico { width: 16px; height: 16px; flex: none }
.cal.cargando .cal-cols, .cal.cargando .cal-mgrid, .cal.cargando .cal-lista { opacity: .55; transition: opacity var(--t-fast) }

/* la barra: ‹ Hoy › y las cuatro vistas */
.cal-barra { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px }
.cal-nav { display: flex; align-items: center; gap: 6px; min-width: 0 }
.cal-flecha { width: 34px; height: 34px; display: grid; place-items: center; border-radius: 10px; border: 1px solid var(--line); background: var(--card); color: var(--ink-2); box-shadow: var(--shadow) }
.cal-flecha:hover { color: var(--brand); border-color: var(--cita-line) }
.cal-flecha svg { width: 18px; height: 18px }
.cal-flecha.sig svg { transform: scaleX(-1) }
.cal-titulo { margin: 0 0 0 6px; font-size: 17px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-transform: none }
.cal-vistas { width: fit-content }

/* la franja de arriba: hoy, la próxima, las nuevas y Google */
.cal-resumen { display: flex; flex-wrap: wrap; gap: 8px }
.cal-dato { display: inline-flex; align-items: center; gap: 8px; padding: 8px 12px; border-radius: var(--r-sm); background: var(--card); border: 1px solid var(--line); box-shadow: var(--shadow); font-size: 13px; color: var(--ink-2); text-align: left }
.cal-dato b { color: var(--ink) }
.cal-dato > b:first-child { font-family: var(--mono); font-size: 18px; line-height: 1 }
.cal-dato em { font-style: normal; color: var(--cita-ink); font-weight: 600 }
button.cal-dato:hover { border-color: var(--cita-line) }
.cal-dato.proxima, .cal-dato.ahora { background: var(--cita-bg); border-color: var(--cita-line) }
.cal-dato.proxima .ico, .cal-dato.ahora .ico { color: var(--cita-borde) }
.cal-dato.ahora { box-shadow: 0 0 0 2px var(--cita-line), var(--shadow) }
.cal-dato.nuevas { background: var(--warn-soft); border-color: transparent; color: var(--warn-ink) }
.cal-dato.nuevas b { color: var(--warn-ink) }
.cal-dato.google.ok { color: var(--ok) }
.cal-dato.google:not(.ok) { color: var(--brand) }
.cal-resumen.cargando .cal-dato { color: var(--ink-3) }

/* Día y Semana: la rejilla por horas */
/* `clip` y no `hidden`: recorta las esquinas sin volverse contenedor de
   scroll, y así la fila de los días se queda pegada arriba al bajar. */
.cal-rejilla { position: relative; background: var(--card); border: 1px solid var(--line); border-radius: var(--r); box-shadow: var(--shadow); overflow: clip }
.cal-cab { position: sticky; top: 0; z-index: 5; display: grid; grid-template-columns: var(--gutter) repeat(var(--dias), minmax(0, 1fr)); border-bottom: 1px solid var(--line); background: var(--card); border-radius: var(--r) var(--r) 0 0 }
.cal-cabdia { position: relative; display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 8px 4px; border-left: 1px solid var(--line-2); color: var(--ink-3); font-size: 11.5px; text-transform: capitalize }
.cal-cabdia:hover .cd-num { background: var(--aqua-soft) }
.cal-cabdia .cd-num { width: 32px; height: 32px; display: grid; place-items: center; border-radius: 50%; font-size: 17px; font-weight: 700; color: var(--ink) }
.cal-cabdia.pasado .cd-num { color: var(--ink-3) }
.cal-cabdia.hoy .cd-sem { color: var(--brand); font-weight: 700 }
.cal-cabdia.hoy .cd-num, .cal-cabdia.hoy:hover .cd-num { background: var(--brand-grad); color: #fff }
.cal-cabdia .cd-n { position: absolute; top: 6px; right: 6px; min-width: 18px; padding: 1px 5px; border-radius: var(--r-pill); background: var(--cita-bg); color: var(--cita-ink); font-size: 10.5px; font-weight: 700; font-family: var(--mono) }
.cal-rejilla.v-dia .cal-cab { display: none } /* la tira de la semana ya dice qué día es */
.cal-cuerpo { position: relative; display: grid; grid-template-columns: var(--gutter) minmax(0, 1fr) }
.cal-hora { position: relative; height: var(--hora) }
.cal-hora span { position: absolute; top: -7px; right: 8px; font-family: var(--mono); font-size: 10.5px; color: var(--ink-3); white-space: nowrap }
.cal-hora:first-child span { top: 3px }
.cal-cols {
  position: relative; display: grid; grid-template-columns: repeat(var(--dias), minmax(0, 1fr)); height: calc(var(--horas) * var(--hora));
  background:
    repeating-linear-gradient(to bottom, var(--line) 0 1px, transparent 1px var(--hora)),
    repeating-linear-gradient(to bottom, transparent 0 calc(var(--hora) / 2), var(--line-2) calc(var(--hora) / 2) calc(var(--hora) / 2 + 1px), transparent calc(var(--hora) / 2 + 1px) var(--hora));
}
.cal-col { position: relative; border-left: 1px solid var(--line-2) }
.cal-col.finde { background: color-mix(in srgb, var(--card-2) 70%, transparent) }
.cal-col.hoy { background: var(--cal-hoy) }

/* cada cita: un bloque del alto de su duración */
.cal .cev {
  position: absolute; z-index: 1; overflow: hidden;
  top: calc((var(--ini) - var(--r0)) * var(--hora) / 60 + 1px);
  height: calc(var(--dur) * var(--hora) / 60 - 3px);
  left: calc(var(--carril) * (100% - 6px) / var(--carriles) + 3px);
  width: calc((100% - 6px) / var(--carriles) - 3px);
  display: flex; flex-direction: column; gap: 1px; padding: 5px 22px 5px 8px; text-align: left;
  background: var(--card); background-image: linear-gradient(var(--cita-bg), var(--cita-bg));
  border: 1px solid var(--cita-line); border-left: 3px solid var(--cita-borde); border-radius: 9px;
  color: var(--ink); font-size: 11.5px; line-height: 1.25; box-shadow: var(--shadow);
  transition: transform var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
.cal .cev:hover { z-index: 2; transform: translateY(-1px); box-shadow: var(--shadow-lift) }
.cal .cev:focus-visible { z-index: 2; outline: 2px solid var(--brand); outline-offset: 1px }
.cal .cev.t-compromiso { background-image: linear-gradient(var(--comp-bg), var(--comp-bg)); border-color: var(--comp-line); border-left-color: var(--comp-borde) }
.cal .cev.e-nueva { border-style: dashed; border-left-style: solid; background-image: repeating-linear-gradient(-45deg, transparent 0 7px, var(--nueva-raya) 7px 10px), linear-gradient(var(--cita-bg), var(--cita-bg)) }
.cal .cev.t-compromiso.e-nueva { background-image: repeating-linear-gradient(-45deg, transparent 0 7px, var(--nueva-raya) 7px 10px), linear-gradient(var(--comp-bg), var(--comp-bg)) }
.cal .cev.pasada { opacity: .5; filter: saturate(.5) }
.cal .cev.encurso { box-shadow: 0 0 0 2px var(--cita-borde), var(--shadow-lift) }
.cal .cev.corto { flex-direction: row; align-items: center; gap: 6px; padding-top: 1px; padding-bottom: 1px }
.ev-hora { display: flex; align-items: center; gap: 4px; font-family: var(--mono); font-size: 10.5px; font-weight: 600; color: var(--cita-ink); white-space: nowrap }
.cal .t-compromiso .ev-hora { color: var(--comp-ink) }
.cal .ev-hora .ico { width: 12px; height: 12px }
.ev-quien { font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0 }
.ev-que { color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis }
.ev-marcas { position: absolute; top: 4px; right: 4px; display: flex; flex-direction: column; gap: 2px }
.cal .ev-marcas .ico { width: 13px; height: 13px }
.cal .corto .ev-marcas { top: 50%; transform: translateY(-50%); flex-direction: row }
.m-nueva { color: var(--warn) }
.m-rec { color: var(--cita-borde) }
.m-sync-ok { color: var(--ok) }
.m-sync-wait { color: var(--ink-3) }

/* la línea roja de «ahora» */
.cal-ahora { position: absolute; left: 0; right: 0; z-index: 3; height: 2px; top: calc((var(--ini) - var(--r0)) * var(--hora) / 60); background: var(--ahora); pointer-events: none }
.cal-ahora::before { content: ''; position: absolute; left: -5px; top: -4px; width: 10px; height: 10px; border-radius: 50%; background: var(--ahora) }
.cal-ahora span { position: absolute; right: 3px; top: -9px; white-space: nowrap; padding: 1px 6px; border-radius: var(--r-pill); background: var(--ahora); color: #fff; font-family: var(--mono); font-size: 10px; font-weight: 700 }

.cal-vacio { position: absolute; inset: 0 0 0 var(--gutter); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; padding: 24px; text-align: center; color: var(--ink-3); font-size: 13px; pointer-events: none }
.cal-vacio b { color: var(--ink); font-size: 15px }
.cal .cal-vacio .ico { width: 34px; height: 34px; color: var(--brand); opacity: .7 }
.cal-vacio.suelto { position: static; background: var(--card); border: 1px solid var(--line); border-radius: var(--r); padding: 40px 20px }

/* la tira de la semana encima del Día */
.cal-tira { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; padding: 6px; background: var(--card); border: 1px solid var(--line); border-radius: var(--r); box-shadow: var(--shadow) }
.cal-tira button { display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 6px 0; border-radius: 10px; color: var(--ink-3); font-size: 11px; text-transform: capitalize }
.cal-tira b { font-size: 16px; color: var(--ink) }
.cal-tira em { display: flex; gap: 2px; height: 5px }
.cal-tira em i { width: 5px; height: 5px; border-radius: 50%; background: var(--cita-borde) }
.cal-tira button.hoy span { color: var(--brand); font-weight: 700 }
.cal-tira button.on { background: var(--aqua-soft) }
.cal-tira button.on b { color: var(--brand) }

/* Mes */
.cal-mes { background: var(--card); border: 1px solid var(--line); border-radius: var(--r); box-shadow: var(--shadow); overflow: hidden }
.cal-msem, .cal-mgrid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)) }
.cal-msem { border-bottom: 1px solid var(--line) }
.cal-msem div { padding: 8px 4px; text-align: center; font-size: 11.5px; color: var(--ink-3); text-transform: capitalize }
.cal-mgrid { grid-auto-rows: minmax(108px, auto) }
.cal-mdia { display: flex; flex-direction: column; gap: 3px; min-width: 0; padding: 4px; border-right: 1px solid var(--line-2); border-bottom: 1px solid var(--line-2) }
.cal-mdia:nth-child(7n) { border-right: none }
.cal-mdia.finde { background: color-mix(in srgb, var(--card-2) 70%, transparent) }
.cal-mdia.fuera { background: var(--card-2) }
.cal-mdia.fuera .cal-mnum { opacity: .45 }
.cal-mnum { align-self: flex-start; width: 26px; height: 26px; border-radius: 50%; font-size: 12.5px; font-weight: 700; color: var(--ink-2) }
.cal-mnum:hover { background: var(--aqua-soft) }
.cal-mdia.hoy .cal-mnum { background: var(--brand-grad); color: #fff }
.chip-ev { display: block; width: 100%; padding: 2px 6px; border-radius: 6px; border-left: 3px solid var(--cita-borde); background: var(--cita-bg); color: var(--ink); font-size: 11px; text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis }
.chip-ev b { font-family: var(--mono); font-weight: 600; color: var(--cita-ink) }
.chip-ev.t-compromiso { border-left-color: var(--comp-borde); background: var(--comp-bg) }
.chip-ev.t-compromiso b { color: var(--comp-ink) }
.chip-ev.e-nueva { outline: 1px dashed var(--warn); outline-offset: -1px }
.chip-ev.pasada { opacity: .5 }
.chip-mas { padding: 0 6px; text-align: left; font-size: 11px; font-weight: 600; color: var(--brand) }

/* Lista */
.cal-lista { display: grid; gap: 16px }
.cal-ldia h3 { margin: 0 0 8px; font-size: 12.5px; font-weight: 700; color: var(--ink-3); letter-spacing: .02em }
.cal-ldia.hoy h3 { color: var(--brand) }
.cal-litem { display: grid; grid-template-columns: 76px minmax(0, 1fr) auto; gap: 12px; align-items: center; width: 100%; margin-bottom: 8px; padding: 12px 14px; text-align: left; background: var(--card); border: 1px solid var(--line); border-left: 4px solid var(--cita-borde); border-radius: var(--r-sm); box-shadow: var(--shadow) }
.cal-litem:hover { border-color: var(--cita-line); border-left-color: var(--cita-borde) }
.cal-litem.t-compromiso, .cal-litem.t-compromiso:hover { border-left-color: var(--comp-borde) }
.cal-litem.e-nueva { border-style: dashed; border-left-style: solid }
.cal-litem.pasada { opacity: .55 }
.li-hora b { display: block; font-family: var(--mono); font-size: 14px; color: var(--cita-ink) }
.t-compromiso .li-hora b { color: var(--comp-ink) }
.li-hora small { font-size: 11px; color: var(--ink-3) }
.li-cuerpo { min-width: 0 }
.li-cuerpo b { display: block; font-size: 14px }
.li-cuerpo span { display: block; font-size: 12.5px; color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis }
.li-marcas { display: flex; flex-direction: column; align-items: flex-end; gap: 4px }
.pill-estado { padding: 3px 8px; border-radius: var(--r-pill); background: var(--ok-soft); color: var(--ok); font-size: 11px; font-weight: 600; white-space: nowrap }
.e-nueva .pill-estado, .pill-estado.e-nueva { background: var(--warn-soft); color: var(--warn-ink) }
.e-recordada .pill-estado, .pill-estado.e-recordada { background: var(--aqua-soft); color: var(--brand) }
.pill-sync { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; color: var(--ink-3); white-space: nowrap }
.pill-sync.sync-ok { color: var(--ok) }
.pill-sync .ico { width: 12px; height: 12px }

/* la leyenda */
.cal-leyenda { padding: 10px 14px; background: var(--card); border: 1px solid var(--line); border-radius: var(--r-sm); font-size: 12.5px; color: var(--ink-2) }
.cal-leyenda summary { cursor: pointer; list-style: none; font-weight: 600 }
.cal-leyenda summary::-webkit-details-marker { display: none }
.cal-leyenda summary::before { content: '▸'; display: inline-block; width: 14px; color: var(--ink-3) }
.cal-leyenda[open] summary::before { content: '▾' }
.cal-leyenda ul { display: flex; flex-wrap: wrap; gap: 10px 18px; margin: 10px 0 0; padding: 0; list-style: none }
.cal-leyenda li { display: flex; align-items: center; gap: 8px }
.cal-muestra { width: 28px; height: 20px; display: grid; place-items: center; border-radius: 6px; background: var(--cita-bg); border: 1px solid var(--cita-line); border-left: 3px solid var(--cita-borde); color: var(--cita-ink) }
.cal .cal-muestra .ico { width: 12px; height: 12px }
.cal-muestra.t-compromiso { background: var(--comp-bg); border-color: var(--comp-line); border-left-color: var(--comp-borde); color: var(--comp-ink) }
.cal-muestra.e-nueva { border-style: dashed; border-left-style: solid; background-image: repeating-linear-gradient(-45deg, transparent 0 5px, var(--nueva-raya) 5px 8px); color: var(--warn) }
.cal-muestra.e-recordada { color: var(--brand) }
.cal-muestra.pasada { opacity: .5 }
.cal-muestra.sync-ok { background: var(--ok-soft); border-color: transparent; color: var(--ok) }
.cal-muestra.sync-wait { background: var(--card-2); border-color: var(--line); color: var(--ink-3) }

/* la ficha de una cita */
.cita-ficha { width: min(440px, calc(100vw - 32px)) }
.cficha { padding: 18px 20px 20px; background: var(--card); border: 1px solid var(--line); border-top: 4px solid var(--cita-borde); border-radius: var(--r); box-shadow: var(--shadow-pop); color: var(--ink) }
.cficha.t-compromiso { border-top-color: var(--comp-borde) }
.cficha .ico { width: 16px; height: 16px; flex: none }
.cficha header { display: flex; align-items: center; justify-content: space-between }
.fi-tipo { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: var(--r-pill); background: var(--cita-bg); color: var(--cita-ink); font-size: 11.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase }
.t-compromiso .fi-tipo { background: var(--comp-bg); color: var(--comp-ink) }
.fi-cerrar { width: 34px; height: 34px; display: grid; place-items: center; border-radius: 10px; color: var(--ink-3) }
.fi-cerrar:hover { background: var(--card-2); color: var(--ink) }
.cficha h2 { margin: 12px 0 2px; font-size: 20px }
.fi-que { margin: 0 0 14px; color: var(--ink-2) }
.fi-filas { display: grid; gap: 10px; padding-top: 14px; border-top: 1px solid var(--line-2) }
.fi-fila { display: grid; grid-template-columns: 18px 70px minmax(0, 1fr); gap: 10px; align-items: center; font-size: 13.5px }
.fi-fila > .ico { color: var(--ink-3) }
.fi-k { font-size: 12px; color: var(--ink-3) }
.fi-v small { color: var(--ink-3) }
.cficha footer { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; margin-top: 18px }
.btn.peligro { background: var(--bad-soft); color: var(--bad) }

@media (max-width: 820px) {
  .cal { --hora: 52px; --gutter: 46px }
  .cal-barra { flex-direction: column; align-items: stretch; gap: 8px }
  .cal-nav { flex-wrap: wrap }
  .cal-titulo { order: -1; flex: 1 0 100%; margin: 0 0 2px; font-size: 16px }
  /* los datos de arriba en una fila que se desliza, no cuatro renglones */
  .cal-resumen { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; margin: 0 -14px; padding: 2px 14px 4px }
  .cal-resumen::-webkit-scrollbar { display: none }
  .cal-dato { flex: none; padding: 7px 11px; font-size: 12.5px; box-shadow: none }
  .cal-vistas { width: 100% }
  .cal-vistas button { flex: 1 }
  .cal-hora span { right: 5px; font-size: 9.5px }
  /* la semana en 375 pt: columnas de ~44 px — el bloque dice quién y el
     toque abre la ficha con todo lo demás */
  .v-semana .ev-que, .v-semana .ev-hora, .v-semana .ev-marcas, .v-semana .cd-n, .v-semana .cal-ahora span { display: none }
  .v-semana .cev { padding: 3px 2px 3px 4px; font-size: 10px }
  .v-semana .ev-quien { white-space: normal; overflow-wrap: anywhere; line-height: 1.15 }
  .v-semana .cal-cabdia .cd-num { width: 28px; height: 28px; font-size: 15px }
  .cal-mgrid { grid-auto-rows: minmax(62px, auto) }
  .chip-ev { height: 6px; padding: 0; border-left: none; border-radius: 3px; font-size: 0; background: var(--cita-borde) }
  .chip-ev.t-compromiso { background: var(--comp-borde) }
  .chip-ev.e-nueva { outline: none; background: var(--warn) }
  .chip-ev b { display: none }
  .chip-mas { font-size: 10px; padding: 0 2px }
  .cal-litem { grid-template-columns: 58px minmax(0, 1fr) }
  .li-marcas { grid-column: 2; flex-direction: row; flex-wrap: wrap; align-items: center }
  .cal-leyenda ul { flex-direction: column; gap: 8px }
}
@media (max-width: 620px) {
  .cita-ficha { width: 100vw; max-width: 100vw; margin: auto auto 0 }
  .cficha { border-radius: 20px 20px 0 0; padding-bottom: calc(20px + env(safe-area-inset-bottom)) }
  .cficha footer .btn { flex: 1 }
}
@media (prefers-reduced-motion: reduce) {
  .cal .cev, .cal .cev:hover { transition: none; transform: none }
}

/* ===== EQUIPO SURFIA (cuenta master): la franja y la cartera de negocios =====
   Todo con tokens que ya existen, para que el tema oscuro los siga sin un
   bloque gemelo que haya que recordar actualizar (el aviso del :root de arriba).
   El semáforo usa los tres pares semánticos de la paleta —ok / warn / bad— y no
   colores nuevos: «crítico» aquí es lo mismo que «crítico» en cualquier otra
   pantalla del panel, y eso se aprende una sola vez. */
.master-banner {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  background: var(--aqua-soft); border: 1px solid var(--aqua-35); border-radius: var(--r-sm);
  padding: 9px 13px; margin-bottom: 10px; font-size: 13px; color: var(--ink-2);
}
.master-banner b { color: var(--ink) }
.master-banner svg.ico { width: 18px; height: 14px; color: var(--brand); flex: none }
.master-banner select {
  font: inherit; padding: 5px 8px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--card); color: var(--ink); max-width: 210px;
}
.master-banner [data-negocio-volver] { margin-left: auto }
.master-tools { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 16px }
.master-tools .resumen { font-size: 12.5px; color: var(--ink-3) }

.negocios { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px }
.negocio {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r);
  padding: 16px; box-shadow: var(--shadow); display: flex; flex-direction: column; gap: 11px;
}
.negocio.atencion { border-color: var(--warn) }
.negocio.critico { border-color: var(--bad) }
.negocio header { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px }
.negocio header b { font-size: 15px; color: var(--ink) }
.negocio-rubro { display: block; font-size: 12px; color: var(--ink-3); margin-top: 2px }
.salud { font-size: 11.5px; font-weight: 700; padding: 3px 10px; border-radius: var(--r-pill); white-space: nowrap; flex: none }
.salud.ok { background: var(--ok-soft); color: var(--ok) }
.salud.atencion { background: var(--warn-soft); color: var(--warn-ink) }
.salud.critico { background: var(--bad-soft); color: var(--bad) }
.negocio .motivos, .negocio .canales { display: flex; gap: 6px; flex-wrap: wrap }
.negocio .cifras {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px;
  font-variant-numeric: tabular-nums;
}
.negocio .cifras .lbl { display: block; font-size: 11px; color: var(--ink-3) }
.negocio .cifras b { font-size: 15px; color: var(--ink) }
.negocio .pie { font-size: 12px; color: var(--ink-3); margin: 0 }
.negocio .btn { align-self: flex-start }
.casos { display: flex; flex-direction: column; gap: 12px }

@media (max-width: 820px) {
  .negocios { grid-template-columns: minmax(0, 1fr) }
  .master-banner [data-negocio-volver] { margin-left: 0 }
}

/* ===== CASOS (cuenta master, F3): la libreta con la que el equipo corrige al
   agente. Mismos tres pares semánticos de la paleta que el semáforo de un
   negocio —ok / warn / bad— y ni un color nuevo: «mal respondido» se lee igual
   que «crítico» en cualquier otra pantalla, y eso se aprende una sola vez.
   La tinta de «mal» es var(--bad) y NO var(--bad-ink): esa última es la tinta
   para ENCIMA del rojo lleno (blanco en claro, marino en oscuro) y sobre
   --bad-soft no se leería. Es el mismo par que .salud.critico. */
.caso {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r);
  padding: 14px 16px; display: flex; flex-direction: column; gap: 9px;
}
.caso.mal { border-color: var(--bad) }
.caso.revisar { border-color: var(--warn) }
.caso .hd { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px }
.caso .hd b { font-size: 14.5px; color: var(--ink) }
.caso .tx { font-size: 13px; color: var(--ink-2); display: flex; flex-direction: column; gap: 5px }
.caso .tx b { color: var(--ink) }
.caso .tx small { font-size: 11.5px; color: var(--ink-3) }
.caso .nota { margin: 0; color: var(--ink-2) }
.caso .acciones { display: flex; gap: 8px; flex-wrap: wrap }
.veredicto { font-size: 11.5px; font-weight: 700; padding: 3px 10px; border-radius: var(--r-pill); white-space: nowrap; flex: none }
.veredicto.bien { background: var(--ok-soft); color: var(--ok) }
.veredicto.mal { background: var(--bad-soft); color: var(--bad) }
.veredicto.revisar { background: var(--warn-soft); color: var(--warn-ink) }
/* La hoja de marcar: cada veredicto en su propia línea, que es como se lee una
   pregunta de tres opciones en un teléfono. El mensaje de error reusa `.sheet
   .msg.err`, que ya existe. `.caso-hoja .caso-op` y no `.caso-op` a secas: la
   regla `.field label` de arriba es más específica y le ganaría. */
.caso-lbl { display: block; font-size: 12px; font-weight: 600; color: var(--ink-3); margin-bottom: 5px }
.caso-hoja .caso-op { display: flex; align-items: center; gap: 8px; padding: 5px 0; margin: 0; font-size: 13.5px; font-weight: 400; color: var(--ink) }
/* `.field input` (arriba) estira todo input al 100 %: un radio también, y quedaba
   lejos de su etiqueta. Y el textarea de la nota no tenía regla propia. */
.caso-hoja .caso-op input { width: auto; flex: none; margin: 0; padding: 0 }
.caso-hoja textarea { width: 100%; box-sizing: border-box; padding: 10px 12px; border-radius: var(--r-sm); border: 1px solid var(--line); background: var(--card-2); color: var(--ink); font: inherit; font-size: 13.5px; resize: vertical }
/* «Reportar esta respuesta» (issue 792, Google Play): un enlace discreto bajo cada respuesta de
   la IA, en «Probar tu agente» y en Agente Surfia. La hoja que abre reusa
   `.caso-hoja` de arriba. */
.bub .reportar-btn { display: block; margin-top: 6px; padding: 0; border: 0; background: none; font: inherit; font-size: 11.5px; color: var(--ink-3); text-decoration: underline; cursor: pointer; white-space: normal }
.bub .reportar-btn:disabled { text-decoration: none; cursor: default }

/* Voz privada del agente: controles visibles mientras usa el micrófono. */
.torre-voz { padding: 8px 14px; border-top: 1px solid var(--line); flex-shrink: 0; }
.torre-voz[hidden] { display: none; }
.torre-voz-actions { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.torre-voz-status { font-size: 12px; color: var(--ink-3); margin-top: 5px; }
/* Los botones de voz y el clip llevan icono también en escritorio. Su tamaño se
   fija AQUÍ y no se hereda de `.chip svg`: un `<svg>` sin medida propia mide
   300×150 px, y el día que esa regla compartida cambie reventaría esta fila. */
.torre-voz .chip svg, .torre-archivos-actions .chip svg { width: 16px; height: 16px; flex-shrink: 0 }
.torre-voz-player audio { width: 100%; height: 36px; margin-top: 6px; }
.torre .bub [data-voz-audio] { display: block; margin-top: 8px; }
.torre-archivos { padding: 8px 14px; border-top: 1px solid var(--line); flex-shrink: 0; max-height: 40vh; overflow-y: auto; }
.torre-archivos[hidden] { display: none; }
.torre-archivos-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.torre-archivos-actions > span, .torre-archivos-status { font-size: 12px; color: var(--ink-3); }
.torre-archivos-status:not(:empty) { margin-top: 6px; }
.torre-archivos-lista { display: grid; gap: 6px; }
.torre-archivo { display: flex; align-items: center; gap: 8px; margin-top: 6px; min-width: 0; }
.torre-archivo img { width: 42px; height: 42px; object-fit: cover; border-radius: 6px; }
.torre-archivo-icono { width: 42px; text-align: center; font-size: 24px; }
.torre-archivo-nombre { flex: 1; min-width: 0; overflow-wrap: anywhere; font-size: 12px; }
.torre-archivo-nombre small { display: block; color: var(--ink-3); }
.torre .bub .torre-archivo-enviado { display: block; margin-top: 8px; max-width: 100%; white-space: normal; overflow-wrap: anywhere; }
.torre-archivos-vista img { display: block; max-width: 100%; max-height: 180px; object-fit: contain; margin: 8px 0; }
.torre-archivos-vista .chip { display: inline-block; margin: 6px 6px 0 0; max-width: 100%; overflow-wrap: anywhere; }
/* Este bloque va DESPUÉS de las reglas de `.torre-archivos`, no antes: una
   media query no suma especificidad, así que una regla igual escrita más
   abajo le gana. Escrito arriba, `.torre-archivos { padding: 10px 14px }`
   era CSS muerto. */
@media (max-width: 820px) {
  /* En el teléfono el micrófono deja de ser un chip de 35 px al lado de otro.
     El dueño le habla a Surfia por nota de voz: «Nota de voz» pasa a ocupar su
     propio renglón, con el color de la marca y 48 px de alto, y lo que lo
     acompaña («Hablar con Surfia», «Descartar», «Terminar y enviar») se
     reparte el renglón de abajo con el mismo alto. No cambia lo que hace
     ningún botón: es el mismo `data-voz` que pinta torre-voz.js.
     Se anclan a `.torre-voz` a propósito: `.chip` es una clase compartida con
     los filtros de canal y con la cabecera del hilo, y esos no se tocan. */
  .torre-voz { padding: 8px 14px }
  .torre-voz-actions { gap: 12px; align-items: stretch }
  /* 13,5 px y no 14,5: con el icono al lado, «Terminar y enviar» —el botón que
     manda la nota— partía en dos renglones en un teléfono de 360 px. */
  .torre-voz .chip, .torre-archivos-actions .chip {
    flex: 1 1 130px; justify-content: center; min-height: 48px;
    padding: 12px 8px; gap: 5px; font-size: 13.5px; white-space: normal;
    /* En vivo Y grabando conviven tres botones con palabra; a 360 px quedan
       ~64 px de texto y «conversación» no cabe entera: que parta, no que se salga. */
    overflow-wrap: anywhere; min-width: 0;
  }
  .torre-voz .chip svg, .torre-archivos-actions .chip svg { width: 18px; height: 18px; flex-shrink: 0 }
  /* Los TRES controles de reposo pasan a ser iconos: el micrófono (nota de
     voz), el auricular (conversación en vivo) y el clip (adjuntar). En 360 px
     la palabra era lo único que los hacía anchos, y anchos empujaban la
     conversación fuera de la pantalla; el dedo necesita 48 px, no la palabra.
     Solo estos tres: los botones de los momentos delicados («Terminar y
     enviar», «Descartar», «Enviar nota», «Terminar conversación») conservan su
     palabra al lado del icono, porque ahí un toque de más borra una nota.
     La palabra no se pierde para nadie: `aria-label` y `title` la dicen, y el
     `<span>` que se apaga es el mismo que se lee entero en escritorio. */
  .torre-voz .chip[data-voz="record"], .torre-voz .chip[data-voz="call"],
  .torre-archivos-actions .chip[data-archivos="elegir"] {
    flex: 0 0 48px; width: 48px; padding: 0;
  }
  .torre-voz .chip[data-voz="record"] > span, .torre-voz .chip[data-voz="call"] > span,
  .torre-archivos-actions .chip[data-archivos="elegir"] > span { display: none }
  .torre-voz .chip[data-voz="record"] svg, .torre-voz .chip[data-voz="call"] svg,
  .torre-archivos-actions .chip[data-archivos="elegir"] svg { width: 22px; height: 22px }
  /* El renglón de la voz medía 5 px de más por el margen de un aviso vacío. */
  .torre-voz-status:empty { margin-top: 0 }
  /* El micrófono manda: es la forma en que el dueño le habla a Surfia. Lleva el
     color de la marca; lo que lo acompaña queda en segundo plano, con el mismo
     alto. No se estira a todo el ancho a propósito: cada renglón de más aquí
     abajo es un renglón menos de conversación cuando sube el teclado. */
  /* `white` y no un hex: de aquí hasta el final del archivo las pruebas de Casos
     y de la cuenta master exigen cero hex sueltos, porque un hex no sigue al
     tema oscuro. Este blanco NO debe seguirlo: va sobre el degradado de la
     marca, que es igual en los dos temas (lo mismo que `.btn.primary`). */
  .torre-voz .chip[data-voz="record"] {
    background: var(--brand-grad); border-color: transparent; color: white;
  }
  .torre-voz .chip:disabled, .torre-archivos-actions .chip:disabled { opacity: .5 }
  /* Adjuntar una foto —la factura, la nevera, el cuaderno— es la otra forma de
     contarle algo a Surfia sin escribir. Con el clip hecho icono de 48 px, la
     aclaración («Hasta 3 archivos · 10 MB en total») vuelve a caber A SU LADO:
     ese renglón que ya no baja solo es el que le devolvemos a la conversación,
     y el límite se sigue leyendo sin tocar nada. */
  .torre-archivos { padding: 8px 14px }
  .torre-archivos-actions { gap: 12px }
  .torre-archivos-actions > span { flex: 1 1 auto; min-width: 0 }
  /* El teclado sube y la barra de gestos ocupa abajo: sin este respiro,
     «Preguntar» —el botón que manda la pregunta— queda debajo del borde. */
  .torre-caja .btn { min-height: 48px }
}
.torre-shopify { display: block; }
.torre-shopify table { width: 100%; margin: 8px 0; font-size: 12px; border-collapse: collapse; }
.torre-shopify caption { text-align: left; color: var(--ink-3); margin-bottom: 5px; }
.torre-shopify th, .torre-shopify td { padding: 5px; text-align: left; border-bottom: 1px solid var(--line); overflow-wrap: anywhere; }
.torre-shopify td small { display: block; color: var(--ink-3); }
.torre-shopify p { margin: 8px 0; font-size: 12px; }
/* Una propuesta de Shopify ya CERRADA (#: «cuadros atravesados») se pliega:
 * una línea, sin el peso visual de --brand de una pendiente de verdad. */
.torre-shopify-cerrada { border-color: var(--line); background: transparent; padding: 8px 13px; }
.torre-shopify-cerrada > summary { cursor: pointer; list-style: none; color: var(--ink-3); font-size: 12.5px; }
.torre-shopify-cerrada > summary::-webkit-details-marker { display: none; }
.torre-shopify-cerrada > summary::before { content: '▸ '; }
.torre-shopify-cerrada[open] > summary::before { content: '▾ '; }
.torre-shopify-cerrada[open] > summary { margin-bottom: 8px; }
.torre-shopify-cerrada table { margin-top: 0; }
/* El aviso corto al fondo del chat (#: «cuadros atravesados») reemplaza las
 * tablas completas que antes se apilaban ahí: solo salta a la tarjeta, que
 * ya vive dentro de su turno. */
.torre-shopify-aviso { display: block; width: 100%; text-align: center; margin: 4px 0; }
/* La tarjeta «Cambios del catálogo» (23-oct-2026) hereda la tabla de .torre-shopify. El aviso de un
 * renglón (empieza a llevar existencia, precio que salta…) va en la tinta de advertencia. */
/* `anywhere` (heredado) deja que las columnas se encojan hasta partir «Existencia» por la mitad en el
 * teléfono; `break-word` solo parte una palabra que de verdad no cabe. */
.torre-catalogo th, .torre-catalogo td { overflow-wrap: break-word; }
.torre-catalogo td { vertical-align: top; }
.torre-catalogo-aviso td { color: var(--warn-ink); background: var(--warn-soft); font-size: 11.5px; }
.torre-catalogo ul { margin: 4px 0 8px; padding-left: 18px; font-size: 12px; }
.torre-mensaje-texto {
  width: 100%; min-height: 76px; margin: 8px 0; padding: 8px 10px; resize: vertical;
  border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--card-2); color: var(--ink); font: inherit;
}
.torre-mensaje-texto:focus { outline: 2px solid var(--brand); outline-offset: 1px; }
.torre-mensaje-texto-fija { margin: 8px 0; font-size: 13px; white-space: pre-wrap }
.torre-mensaje-motivo { margin: 8px 0 4px; color: var(--warn-ink); }

/* La tarjeta «Registrar pago» (encargo D): la vista previa congelada
 * (§5, órdenes/fichas duplicadas del cliente) y la lista de evidencias de
 * un pago ya confirmado (§6, referencia enmascarada). */
.torre-pago-previa { margin: 6px 0; font-size: 12px; color: var(--ink-3); }
.torre-pago-evidencias { margin: 8px 0; padding: 0; list-style: none; font-size: 12px; }
.torre-pago-evidencias li { padding: 3px 0; border-bottom: 1px solid var(--line); overflow-wrap: anywhere; }
/* El aviso plegable «Pagos por resolver» (§3): calcado de
 * .torre-shopify-cerrada — una línea por defecto, nunca la lista abierta. */
.torre-pago-pendientes { border-color: var(--line); background: transparent; padding: 8px 13px; margin-bottom: 8px; }
.torre-pago-pendientes > summary { cursor: pointer; list-style: none; color: var(--ink-3); font-size: 12.5px; }
.torre-pago-pendientes > summary::-webkit-details-marker { display: none; }
.torre-pago-pendientes > summary::before { content: '▸ '; }
.torre-pago-pendientes[open] > summary::before { content: '▾ '; }
.torre-pago-pendientes[open] > summary { margin-bottom: 8px; }
.torre-pago-pendientes ul { margin: 0; padding: 0; list-style: none; }
.torre-pago-pendiente-fila { padding: 8px 0; border-top: 1px solid var(--line); font-size: 12.5px; }
.torre-pago-pendiente-fila:first-child { border-top: none; }

/* Bienvenida individual: los mismos controles del panel, en una sola columna. */
#member-welcome .sheet { max-height: calc(100dvh - 40px); overflow-y: auto; }
#member-welcome textarea { width: 100%; resize: vertical; padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--card-2); color: var(--ink); font: inherit; }
#member-welcome textarea:focus { outline: 2px solid var(--brand); outline-offset: 1px; }
#member-welcome small { color: var(--ink-3); }

/* Qué atiende Surfia en Instagram (Mi Surfia; tramo 8 del épico de Instagram). Los cupos van en
   una rejilla que se apila sola en el teléfono; el estado de cada cuenta y la lista de
   preguntas de inicio, en texto chico debajo de su casilla. */
#ig-interacciones-card .ig-cupos { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px }
#ig-interacciones-card .ig-cupos input { width: 100% }
#ig-interacciones-card .ig-estado { margin: 8px 0 0; font-size: 13px; color: var(--ink-2); overflow-wrap: anywhere }
#ig-interacciones-card .ig-estado .btn { margin-left: 6px; padding: 4px 10px; font-size: 12px }
#ig-interacciones-card .ig-preguntas { margin: 6px 0 0 18px; padding: 0; font-size: 13px; color: var(--ink-2) }
#ig-interacciones-card .ig-observation-group { margin-top: 16px; overflow-wrap: anywhere }
#ig-interacciones-card .ig-observation-evidence { padding: 12px 0; border-top: 1px solid var(--line); font-size: 14px }
#ig-interacciones-card .ig-observation-evidence ul { padding-left: 20px }


/* Mi Surfia por secciones (frontend/mi-surfia.js, maquetas aprobadas el 27-oct-2026).
   Un índice con una fila por sección y, al tocarla, la sección sola. Primero el teléfono:
   el índice es UNA lista que cabe en la pantalla y dentro de una sección hay una pastilla
   «Mi Surfia» para volver. En el escritorio el índice es una rejilla de 2 columnas y la
   sección trae la miga y un menú lateral para saltar de una a otra. Solo tokens del
   panel: sigue al tema claro y al oscuro. */
#s-probar[data-ms-vista="seccion"] .ms-indice,
#s-probar:not([data-ms-vista="seccion"]) .ms-cabeza,
#s-probar:not([data-ms-vista="seccion"]) .ms-layout { display: none }
.ms-seccion[hidden], .ms-sec[hidden], .ms-menu button[hidden], .agente-mini[hidden] { display: none }

/* «Ver la guía otra vez» (mi-surfia-guia.js): un enlace discreto bajo el subtítulo, con el área
   táctil de un botón. */
.ms-guia-link {
  display: inline-flex; align-items: center; min-height: 44px; margin: -14px 0 4px; padding: 0;
  background: none; border: 0; color: var(--brand); font: inherit; font-size: 14px; font-weight: 600; text-decoration: underline; text-underline-offset: 3px; cursor: pointer;
}

/* La franja de «Tu agente» con «Probar» (identidad-agente.js). */
.agente-mini {
  position: relative; overflow: hidden; display: flex; align-items: center; gap: 12px;
  padding: 14px 14px 14px 16px; margin-bottom: 14px; border-color: var(--aqua-35);
  background: linear-gradient(180deg, var(--aqua-soft), transparent 90px), var(--card); box-shadow: var(--shadow-lift);
}
.agente-mini::before { content: ""; position: absolute; inset: 0 0 auto; height: 3px; background: var(--brand-grad) }
.agente-mini .agente-avatar { width: 42px; height: 42px; font-size: 18px }
.agente-mini .agente-nombre { font-size: 18px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis }
.agente-linea { display: block; margin-top: 1px; font-size: 12.5px; color: var(--ink-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis }
.agente-mini .btn { flex: none; display: inline-flex; align-items: center; gap: 6px; padding: 10px 16px; border-radius: var(--r-pill) }

/* Las filas del índice. */
.ms-secciones { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px }
.ms-sec {
  display: flex; align-items: flex-start; gap: 14px; width: 100%; padding: 16px; text-align: left;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r); box-shadow: var(--shadow); color: var(--ink);
  transition: border-color var(--t-fast);
}
.ms-sec:hover { border-color: var(--aqua-35) }
.ms-sec:focus-visible, .ms-menu button:focus-visible, .ms-volver:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px }
.ms-sec-ico {
  flex: none; display: grid; place-items: center; width: 40px; height: 40px; border-radius: 12px;
  background: var(--aqua-soft); border: 1px solid var(--aqua-25); color: var(--brand);
}
.ms-sec-ico svg { width: 20px; height: 20px }
.ms-sec-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px }
.ms-sec-t { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 15.5px; font-weight: 700; line-height: 1.3 }
.ms-sec-t .pill, .ms-menu .pill { padding: 2px 8px; font-size: 10.5px }
.ms-sec-que { font-size: 13px; line-height: 1.45; color: var(--ink-2) }
.ms-sec-estado { font-size: 12.5px; line-height: 1.4; color: var(--ink-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis }
.ms-sec-estado:empty { display: none }
.ms-sec-chev { flex: none; align-self: center; width: 18px; height: 18px; color: var(--ink-3) }
.ms-sec-solo-equipo { border-style: dashed }

/* Dentro de una sección: la miga (escritorio) o la pastilla «Mi Surfia» (teléfono). */
.ms-cabeza { display: flex; align-items: center; gap: 6px; margin: 0 0 12px; font-size: 13px; color: var(--ink-3) }
.ms-volver { display: inline-flex; align-items: center; gap: 4px; padding: 4px 0; font-size: 13px; color: var(--ink-3) }
.ms-volver:hover { color: var(--brand) }
.ms-volver svg { display: none; width: 16px; height: 16px }
.ms-miga-sep { width: 14px; height: 14px }
.ms-miga-actual { color: var(--brand); font-weight: 600 }
.ms-layout { display: grid; grid-template-columns: 250px minmax(0, 1fr); gap: 22px; align-items: start }
.ms-menu { position: sticky; top: 20px; display: grid; gap: 2px; padding: 8px }
.ms-menu button {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 9px 10px; border-radius: 10px;
  font-size: 13.5px; font-weight: 500; color: var(--ink-2); text-align: left;
}
.ms-menu button svg { flex: none; width: 17px; height: 17px; opacity: .8 }
.ms-menu button:hover { background: var(--card-2) }
.ms-menu button.on { background: var(--aqua-soft); color: var(--brand); font-weight: 700 }
.ms-menu .pill { margin-left: auto }

/* La sección: su título y, debajo, sus tarjetas separadas por el hueco. */
.ms-seccion { display: grid; gap: 12px; min-width: 0 }
.ms-seccion > h1 { margin: 0 }
.ms-seccion > .sub-h { margin: -8px 0 4px }
/* Las tarjetas traían márgenes para despegarse unas de otras: aquí los pone el hueco. */
.ms-seccion > .responde, .ms-seccion > .agente-hero { margin: 0 }
.ms-seccion > .probar-chat { margin-top: 0 }
.ms-seccion > .source-entry { margin-bottom: 0 }
.ms-seccion > #install-help { justify-self: start }
/* Una sola cabecera de tarjeta: la kicker + negrita, el h3 de Bloques, el .tema-titulo y
   el .policy-h se leían como cuatro cosas distintas. */
.ms-seccion .source-kicker + b, .ms-seccion .card > h3, .ms-seccion .tema-titulo,
.ms-seccion .policy-h, .ms-card-t {
  display: block; margin: 3px 0 0; font-family: inherit; font-size: 15px; font-weight: 700; line-height: 1.3;
  letter-spacing: normal; text-transform: none; color: var(--ink);
}
.ms-seccion .card > h3.vocab-h { margin-top: 18px }
/* …salvo el nombre del agente, que es el titular de «Tu agente». */
.ms-seccion .agente-hero .agente-nombre { margin: 0; font-size: 22px }

@media (max-width: 820px) {
  /* El índice en el teléfono: UNA lista, filas de ≥ 60 px, sin la frase larga. */
  .ms-secciones {
    grid-template-columns: minmax(0, 1fr); gap: 0; padding: 2px 0; overflow: hidden;
    background: var(--card); border: 1px solid var(--line); border-radius: var(--r); box-shadow: var(--shadow);
  }
  .ms-sec { align-items: center; min-height: 60px; padding: 11px 14px; border: 0; border-radius: 0; background: none; box-shadow: none }
  .ms-sec:not([hidden]) ~ .ms-sec { border-top: 1px solid var(--line) }
  .ms-sec-ico { width: 36px; height: 36px; border-radius: 11px }
  .ms-sec-ico svg { width: 19px; height: 19px }
  .ms-sec-txt { gap: 1px }
  .ms-sec-t { flex-wrap: nowrap; font-size: 15px }
  .ms-sec-que { display: none }
  /* Dentro: sin menú ni miga; la pastilla «Mi Surfia» para volver, con área táctil ≥ 36 px. */
  .ms-layout { grid-template-columns: minmax(0, 1fr); gap: 0 }
  .ms-menu, .ms-miga-sep, .ms-miga-actual { display: none }
  .ms-volver {
    min-height: 36px; padding: 6px 12px 6px 8px; border-radius: var(--r-pill);
    background: var(--aqua-soft); color: var(--brand); font-weight: 700;
  }
  .ms-volver svg { display: block }
}

/* «Lo que Surfia sabe de tu negocio» (cuestionario-acceso.js + lo-que-sabe.js): seis datos
   en palabras del dueño, lo que falta en ámbar y «Editar respuestas». En el escritorio los
   datos van en dos columnas; en el teléfono, una lista. Solo tokens del panel. */
.sabe {
  position: relative; overflow: hidden; border-color: var(--aqua-35);
  background: linear-gradient(180deg, var(--aqua-soft), transparent 140px), var(--card); box-shadow: var(--shadow-lift);
}
.sabe::before { content: ""; position: absolute; inset: 0 0 auto; height: 3px; background: var(--brand-grad) }
.ms-seccion .sabe .sabe-t { margin-top: 6px; font-size: 20px; letter-spacing: -.01em; line-height: 1.25 }
.sabe-d { margin: 3px 0 0; font-size: 13px; color: var(--ink-2) }
.sabe-borrador { margin: 10px 0 0; font-size: 12.5px; color: var(--warn-ink) }
.datos { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin: 16px 0 0 }
.dato { display: flex; gap: 12px; align-items: flex-start; padding: 12px; border-radius: var(--r-sm); background: var(--card-2); border: 1px solid var(--line-2) }
.dato-ico { flex: none; display: grid; place-items: center; width: 32px; height: 32px; border-radius: 10px; background: var(--aqua-soft); color: var(--brand) }
.dato-ico svg { width: 17px; height: 17px }
.dato-txt { flex: 1; min-width: 0 }
.dato dt { font-size: 12px; font-weight: 600; letter-spacing: .01em; color: var(--ink-3) }
.dato dd { margin: 2px 0 0; font-size: 14px; line-height: 1.42; color: var(--ink); overflow-wrap: anywhere }
.dato.falta .dato-ico { background: var(--warn-soft); color: var(--warn-ink) }
/* Sin valor, la fila entera dice «Falta un dato»; con valor (el horario sin sus horas), solo la nota. */
.dato.falta:not(:has(.dato-falta)) dd, .dato-falta { color: var(--warn-ink) }
.dato-falta { margin: 4px 0 0; font-size: 12.5px }
.sabe .lnk { padding: 0; font-size: 13px; font-weight: 700; color: var(--warn-ink); text-decoration: underline; text-underline-offset: 2px }
.falta-aparte {
  display: flex; align-items: center; gap: 12px; margin-top: 12px; padding: 12px; border-radius: var(--r-sm);
  background: var(--warn-soft); border: 1px solid color-mix(in srgb, var(--warn) 35%, transparent);
}
.falta-aparte > svg { flex: none; width: 20px; height: 20px; color: var(--warn-ink) }
.falta-aparte p { flex: 1; margin: 0; font-size: 13px; line-height: 1.45; color: var(--ink-2) }
.falta-aparte p b { color: var(--ink); font-weight: 600 }
.falta-aparte .lnk { flex: none; text-decoration: none }
.sabe-acciones { display: flex; align-items: center; flex-wrap: wrap; gap: 14px; margin-top: 16px }
.sabe-acciones .btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px }
.sabe-pie { margin: 0; font-size: 12.5px; line-height: 1.45; color: var(--ink-3) }
@media (max-width: 820px) {
  .datos { grid-template-columns: minmax(0, 1fr); gap: 0; margin-top: 10px; background: var(--card-2); border: 1px solid var(--line-2); border-radius: var(--r-sm) }
  .dato { padding: 12px 10px; border: 0; border-radius: 0; background: none }
  .dato + .dato { border-top: 1px solid var(--line-2) }
  .sabe-acciones .btn { width: 100%; min-height: 48px; border-radius: var(--r-pill); font-size: 15px }
  .sabe-pie { width: 100%; text-align: center }
}

/* «Tu agente»: la primera tarjeta de «Cómo responde Surfia» y su hoja (identidad-agente.js).
   Sin nombre es una invitación («Ponle nombre a tu agente»); con nombre, quién da la
   cara, cómo se presenta y el saludo exacto. El riel de marca de .responde se repite
   aquí a propósito: es lo primero que se ve en la sección. Solo tokens del panel (claro y
   oscuro). */
.agente-hero {
  position: relative; overflow: hidden; margin: 4px 0 14px;
  border-color: var(--aqua-35);
  background: linear-gradient(180deg, var(--aqua-soft), transparent 120px), var(--card);
  box-shadow: var(--shadow-lift);
}
.agente-hero::before { content: ""; position: absolute; inset: 0 0 auto; height: 3px; background: var(--brand-grad) }
.agente-fila { display: flex; align-items: center; gap: 12px; flex-wrap: wrap }
.agente-id { flex: 1; min-width: 0 }
.agente-id .source-kicker { margin-bottom: 2px }
.agente-avatar {
  flex: none; display: grid; place-items: center; width: 46px; height: 46px; border-radius: 50%;
  background: var(--aqua-soft); border: 1px solid var(--aqua-35); color: var(--brand); font-size: 20px; font-weight: 700;
}
.agente-nombre { display: block; font-size: 22px; font-weight: 700; letter-spacing: -.01em; line-height: 1.2; color: var(--ink); overflow-wrap: anywhere }
.agente-pastilla {
  flex: none; padding: 4px 11px; border-radius: var(--r-pill); border: 1px solid var(--line);
  background: var(--card-2); color: var(--ink-2); font-size: 12px; font-weight: 600;
}
.agente-saludo { margin: 10px 0 0; font-size: 13.5px; line-height: 1.5; color: var(--ink-2); overflow-wrap: anywhere }
.agente-acciones { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 14px }
.agente-acciones .btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px }
.agente-hero .agente-nombre + .agente-saludo { margin-top: 6px }
.identidad-etq { display: block; margin: 4px 0 6px; font-size: 13px; font-weight: 600; color: var(--ink) }
#identidad-nombre {
  width: 100%; padding: 10px 12px; border-radius: var(--r-sm); border: 1px solid var(--line);
  background: var(--card-2); color: var(--ink); font-size: 14px;
}
#identidad-nombre:focus { outline: 2px solid var(--brand); outline-offset: 1px; border-color: var(--brand) }
.identidad-atajos { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px }
.identidad-saludo { overflow-wrap: anywhere }
.identidad-bot { margin-top: 14px }
@media (max-width: 820px) {
  .agente-acciones .btn { flex: 1 1 100%; min-height: 44px; justify-content: center }
  .identidad-atajos .btn { min-height: 36px }
}

/* «Costo de envío» (envio-tarifa.js): la tarifa vigente en una línea y el error del
   servidor, que fuera de una hoja no traía color propio. */
.envio-vigente { margin: 8px 0 10px; font-size: 14px; font-weight: 600; color: var(--ink) }
#envio-card .msg.err { margin: 6px 0 10px; font-size: 12.5px; color: var(--bad) }

/* Copias del correo de avisos (avisos-correo-copias.js): cada copia en su fila, con su «Quitar». */
.correo-copia { display: flex; gap: 8px; align-items: center; margin-bottom: 8px }
.correo-copia input { flex: 1; min-width: 0; padding: 10px 12px; border-radius: var(--r-sm); border: 1px solid var(--line); background: var(--card-2); color: var(--ink); font-size: 13.5px }
.correo-copia input:focus { outline: 2px solid var(--brand); outline-offset: 1px; border-color: var(--brand) }

/* Las filas de «Tu negocio» (mi-surfia-filas.js): texto a la izquierda, botón a la derecha. */
.ms-fila { display: flex; align-items: center; justify-content: space-between; gap: 18px }
.ms-fila b { display: block; margin-top: 3px }
.ms-fila p { margin: 5px 0 0; color: var(--ink-3); font-size: 12.5px; line-height: 1.5 }
.ms-fila .btn { flex: none }
@media (max-width: 820px) {
  .ms-fila { align-items: stretch; flex-direction: column }
  .ms-fila .btn { width: 100%; min-height: 44px }
}

/* Bloques: «Activo / Apagado» se lee como un interruptor (role="switch", aria-checked).
   Antes era un botón relleno o un texto suelto según el estado y no parecía el mismo control. */
.bloque-sw {
  position: relative; display: inline-flex; align-items: center; min-height: 36px;
  padding: 7px 14px 7px 52px; border-radius: var(--r-pill); border: 1px solid var(--line);
  background: var(--card-2); color: var(--ink-3); font-size: 13px; font-weight: 600;
}
.bloque-sw::before {
  content: ""; position: absolute; left: 10px; top: 50%; width: 30px; height: 18px; margin-top: -9px;
  border-radius: var(--r-pill); background: var(--line); transition: background var(--t-fast);
}
.bloque-sw::after {
  content: ""; position: absolute; left: 12px; top: 50%; width: 14px; height: 14px; margin-top: -7px;
  border-radius: 50%; background: var(--card); box-shadow: var(--shadow); transition: transform var(--t-fast) var(--ease);
}
.bloque-sw[aria-checked="true"] { color: var(--brand); border-color: var(--brand); background: var(--aqua-soft) }
.bloque-sw[aria-checked="true"]::before { background: var(--brand) }
.bloque-sw[aria-checked="true"]::after { transform: translateX(12px) }
.bloque-sw:disabled { opacity: .6; cursor: default }
@media (max-width: 820px) { .bloque-sw { min-height: 44px } }

/* «Tu equipo» (Mi Surfia): quién recibe los avisos de Surfia y cómo le van llegando. */
.equipo-lista { list-style: none; padding: 0; margin: 8px 0 0 }
.equipo-lista > li { padding: 12px 0; border-top: 1px solid var(--line); overflow-wrap: anywhere }
.equipo-lista > li:first-child { border-top: 0; padding-top: 4px }
.equipo-lista .polhelp { margin: 2px 0 }
.equipo-estado { font-size: 12.5px; line-height: 1.45; margin: 4px 0 8px; color: var(--ink-2) }
.equipo-estado.ok { color: var(--ok) }
.equipo-estado.warn { color: var(--warn-ink) }
.equipo-avisos { margin: 8px 0 }
.equipo-avisos > summary { cursor: pointer; font-size: 13px; font-weight: 700; color: var(--brand); padding: 6px 0 }
.equipo-avisos > summary:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 6px }
.equipo-avisos ol { list-style: none; padding: 0; margin: 4px 0 0 }
.equipo-aviso { font-size: 12.5px; line-height: 1.45; color: var(--ink-2); padding: 6px 0; border-top: 1px solid var(--line) }
.equipo-aviso.warn { color: var(--warn-ink) }
