:root{
  --ink:#33312A; --ink-2:#665F52; --ink-3:#6A6659;
  --yellow:#FBD10D; --yellow-ink:#1B1A17;
  --bg:#E9E6DC; --surface:#F2EFE6; --panel:#DFDBCE;
  --hairline:rgba(51,49,42,.13); --hairline-2:rgba(51,49,42,.08);
  --ok:#1A7A4C; --info:#2361C4; --live:#1FAE5C;
  --r-sm:6px; --r-md:12px;
  --s-1:4px; --s-2:8px; --s-3:16px; --s-4:24px; --s-5:32px; --s-6:40px; --s-7:48px; --s-8:64px;
  --font:-apple-system,BlinkMacSystemFont,"Inter","Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  --sidebar-w: 232px; --sidebar-w-collapsed: 64px;
  --t-theme: .45s cubic-bezier(.4,0,.2,1);
  color-scheme: light;
}
html[data-theme="dark"]{
  --ink:#EDEBE4; --ink-2:#ABA89E; --ink-3:#867F70;
  --bg:#151412; --surface:#1D1C19; --panel:#201F1B;
  --hairline:rgba(255,255,255,.10); --hairline-2:rgba(255,255,255,.06);
  color-scheme: dark;
}
*,*::before,*::after{ box-sizing:border-box; }
*,*::before,*::after{ transition: background-color var(--t-theme), border-color var(--t-theme), color var(--t-theme), box-shadow var(--t-theme); }
body{ margin:0; font-family:var(--font); color:var(--ink); background:var(--bg); font-size:14px; line-height:1.5;
  font-weight:400; letter-spacing:-.006em; -webkit-font-smoothing:antialiased; }
a{ color:inherit; text-decoration:none; }
h1,h2,h3{ margin:0; font-weight:650; letter-spacing:-.015em; }
.ic{ display:inline-flex; align-items:center; gap:7px; }
.btn{ display:inline-flex; align-items:center; gap:7px; font-weight:600; font-size:13px; padding:7px 14px; border-radius:var(--r-sm);
  border:1px solid transparent; cursor:pointer; transition:background .12s ease, border-color .12s ease, transform .12s ease; }
.btn:active{ transform:scale(.97); }
.btn-primary{ background:var(--yellow); color:var(--yellow-ink); }
.btn-primary:hover{ background:#EFC300; box-shadow:0 4px 14px rgba(251,209,13,.28); }
.btn-line{ background:var(--surface); border-color:var(--hairline); color:var(--ink-2); }
.btn-line:hover{ border-color:rgba(128,128,128,.4); color:var(--ink); }
.btn-text{ display:inline-flex; align-items:center; gap:7px; color:var(--ink-2); font-weight:550; font-size:13px; padding:4px 2px; transition:color .12s ease; }
.btn-text:hover{ color:var(--ink); }
.topbar-group{ display:flex; align-items:center; gap:10px; background:var(--panel); border:1px solid var(--hairline); border-radius:999px; padding:4px; }
.topbar-group .divider{ width:1px; height:18px; background:var(--hairline); }
.live-pill{ display:inline-flex; align-items:center; gap:6px; font-size:11.5px; font-weight:600; color:var(--ink-2); padding:0 4px 0 8px; }
.live-dot{ width:7px; height:7px; border-radius:50%; background:var(--live); position:relative; flex-shrink:0; }
.live-dot::after{ content:''; position:absolute; inset:-4px; border-radius:50%; background:var(--live); opacity:.45; animation:live-ping 1.8s cubic-bezier(0,0,.2,1) infinite; }
@keyframes live-ping{ 0%{transform:scale(.6);opacity:.5;} 70%{transform:scale(1.9);opacity:0;} 100%{opacity:0;} }
.clock{ font-size:12.5px; font-weight:600; color:var(--ink-2); font-variant-numeric:tabular-nums; display:flex; align-items:center; gap:6px; white-space:nowrap; }
.clock i{ font-size:12px; color:var(--ink-3); }
.icon-btn{ position:relative; width:32px; height:32px; border-radius:50%; display:flex; align-items:center; justify-content:center;
  background:transparent; border:none; color:var(--ink-2); cursor:pointer; font-size:14px; flex-shrink:0; }
.icon-btn:hover{ color:var(--ink); background:var(--hairline-2); }
.icon-btn .badge{ position:absolute; top:-3px; right:-3px; min-width:15px; height:15px; padding:0 3px; border-radius:999px;
  background:#C0392B; color:#fff; font-size:9px; font-weight:700; display:flex; align-items:center; justify-content:center; line-height:1; border:1.5px solid var(--bg); }
.theme-toggle{ display:flex; align-items:center; gap:2px; }
.theme-toggle button{ border:none; background:transparent; width:24px; height:24px; border-radius:999px; display:flex; align-items:center;
  justify-content:center; color:var(--ink-3); cursor:pointer; font-size:12.5px; transition:background .15s ease, color .15s ease; }
.theme-toggle button.active{ background:var(--ink); color:var(--bg); }
.app-shell{ display:flex; min-height:100vh; }
.app-sidebar{ width:var(--sidebar-w); flex-shrink:0; background:var(--surface); border-right:1px solid var(--hairline);
  padding:var(--s-3) 0 0; display:flex; flex-direction:column; position:sticky; top:0; height:100vh;
  overflow-x:hidden; overflow-y:auto; transition: width .18s ease, background-color var(--t-theme), border-color var(--t-theme); }
.app-sidebar.collapsed{ width:var(--sidebar-w-collapsed); }
.app-sidebar-top{ display:flex; align-items:center; justify-content:space-between; padding:0 var(--s-3) var(--s-3); gap:8px; }
.app-sidebar-brand{ display:flex; align-items:center; gap:8px; overflow:hidden; white-space:nowrap; }
/* El clip de CLIPBOOK. Era un cuadrado amarillo de relleno: la marca existía
   en /LOGOS y la aplicación no la usaba en ninguna parte. */
.app-sidebar-brand .mark{ width:19px; height:19px; flex-shrink:0; display:block; }
.app-sidebar-brand .name{ font-weight:650; font-size:13.5px; letter-spacing:-.01em; }
.app-sidebar.collapsed .app-sidebar-top{ justify-content:center; padding:0 0 var(--s-3); }
.app-sidebar.collapsed .app-sidebar-brand .name, .app-sidebar.collapsed .sidebar-collapse-btn, .app-sidebar.collapsed .apps-btn{ display:none; }
.sidebar-collapse-btn{ display:flex; align-items:center; justify-content:center; width:26px; height:26px; border-radius:var(--r-sm);
  border:none; background:transparent; color:var(--ink-3); cursor:pointer; flex-shrink:0; }
.sidebar-collapse-btn:hover{ background:var(--hairline-2); color:var(--ink); }
.apps-btn{ display:flex; align-items:center; justify-content:center; width:26px; height:26px; border-radius:var(--r-sm);
  border:none; background:transparent; color:var(--ink-2); cursor:pointer; flex-shrink:0; font-size:13px; }
.apps-btn:hover{ background:var(--hairline-2); color:var(--ink); }
.app-sidebar-expand-btn{ display:none; width:26px; height:26px; align-items:center; justify-content:center; border-radius:var(--r-sm);
  border:none; background:transparent; color:var(--ink-3); cursor:pointer; margin:0 auto var(--s-2); }
.app-sidebar.collapsed .app-sidebar-expand-btn{ display:flex; }
.app-sidebar-expand-btn:hover{ background:var(--hairline-2); color:var(--ink); }
.app-sidebar-link{ display:flex; align-items:center; gap:9px; padding:6px var(--s-3); margin:1px 8px; border-radius:var(--r-sm);
  font-size:13px; color:var(--ink-2); font-weight:500; white-space:nowrap; transition:background-color .12s ease, color .12s ease; }
.app-sidebar-link i{ font-size:14px; width:16px; text-align:center; opacity:.75; flex-shrink:0; }
.app-sidebar-link:hover{ background:var(--hairline-2); color:var(--ink); }
.app-sidebar-link.active{ background:rgba(251,209,13,.16); color:var(--ink); font-weight:600; }
.app-sidebar-link.active i{ opacity:1; }
.app-sidebar.collapsed .app-sidebar-link{ justify-content:center; margin:1px 6px; padding:8px; }
.app-sidebar.collapsed .app-sidebar-link .lbl{ display:none; }
/* El padding superior separa una sección de la anterior. Estaba en 24px, que
   se veía bien con rótulos de una línea pero desproporcionado apenas uno
   envuelve a dos. 16px separa igual de claro y no deja el hueco. */
.sec-toggle{ width:100%; display:flex; align-items:center; justify-content:space-between; gap:6px; background:none; border:none;
  cursor:pointer; padding:var(--s-3) var(--s-3) 6px; text-align:left; }
/* El primero de cada bloque no necesita separarse de nada: arriba tiene el
   borde del módulo o su cabecera, no otra sección. Dos casos: el bloque que
   parte directo con la sección (Configuración) y el que parte con la cabecera
   del módulo (Mailing, Comercial). */
.module-block > .sec-toggle:first-child,
.module-context + .sec-toggle{ padding-top:var(--s-2); }
.sec-toggle .chev{ font-size:9px; color:var(--ink-3); transition:transform .18s ease; }
.sec-toggle.closed .chev{ transform:rotate(-90deg); }
.sec-body{ display:grid; grid-template-rows:1fr; transition:grid-template-rows .2s ease; }
.sec-body.closed{ grid-template-rows:0fr; }
.sec-inner{ overflow:hidden; }
.app-sidebar.collapsed .sec-toggle{ height:1px; padding:0; margin:var(--s-3) 10px; background:var(--hairline); overflow:hidden; }
.app-sidebar.collapsed .sec-toggle .section-label, .app-sidebar.collapsed .sec-toggle .chev{ display:none; }
.app-sidebar.collapsed .sec-body.closed{ grid-template-rows:1fr; }
/* line-height ajustado: el 1.5 heredado abría demasiado los rótulos de dos
   líneas ("Configuración del negocio"). En mayúsculas y a 11px no hace falta
   tanto aire entre líneas. */
.section-label{ font-size:11px; font-weight:650; color:var(--ink-3); text-transform:uppercase; letter-spacing:.05em;
  line-height:1.35; }
/* Cada módulo tiene su propio color de acento. El color se declara UNA vez
   por bloque en --m-accent (como componentes RGB, para poder modular la
   opacidad) y todo lo de adentro lo hereda. Así agregar un módulo nuevo es
   una línea de CSS y no repetir el color en seis reglas. */
.module-block{ position:relative; margin-left:16px; padding-left:12px;
  --m-accent:251,209,13; --m-ink:#8A6A00;
  border-left:2px solid rgba(var(--m-accent),.55); }
.module-block .app-sidebar-link, .module-block .sec-toggle{ margin-left:0; padding-left:8px; }
.app-sidebar.collapsed .module-block{ margin-left:0; padding-left:0; border-left:none; }
.app-sidebar.collapsed .module-block .app-sidebar-link{ padding-left:8px; }
/* La cabecera del módulo ES el interruptor: al hacerle clic se pliega el
   módulo completo con todas sus secciones. Antes había que cerrar Mailing y
   Contactos por separado para dejar de ver el módulo. */
/* El ancho sale de los márgenes, no de un 100% pelado: se extiende 14px a la
   izquierda (para tapar el sangrado del bloque y quedar pegada a la barra de
   color) y respira 10px a la derecha. Sin ese aire derecho la caja moría contra
   el borde del sidebar y las esquinas redondeadas no se veían — el radius
   estaba ahí, pero no se apreciaba. */
.module-context{ margin:0 10px var(--s-2) -14px; padding:6px 9px; border-radius:var(--r-sm); background:rgba(var(--m-accent),.14);
  display:flex; align-items:center; gap:9px; overflow:hidden; width:calc(100% + 4px);
  border:none; font:inherit; text-align:left; cursor:pointer; transition:background .12s ease, margin-bottom .2s ease; }
.module-context:hover{ background:rgba(var(--m-accent),.22); }
/* min-width:0 en el texto: sin esto un nombre largo ("Configuración del
   negocio") estira su columna, empuja la flecha fuera de la caja y el
   overflow la corta. Con esto el texto cede y la flecha se queda en su sitio. */
.module-context > div{ flex:1; min-width:0; }
.module-context .name{ white-space:normal; line-height:1.25; }
/* Plegado: no hay nada abajo de qué separarse. Mantener el margen dejaba la
   barra de color estirada bajo una cabecera que ya no tenía contenido. */
.module-context.closed{ margin-bottom:0; }
.module-context .mod-chev{ margin-left:auto; font-size:9px; color:var(--m-ink); transition:transform .18s ease;
  flex-shrink:0; align-self:center; }
.module-context.closed .mod-chev{ transform:rotate(-90deg); }
/* Separación entre módulos. 8px basta: el borde de color ya los separa, no
   hace falta además un hueco grande. */
.module-block + .module-block{ margin-top:var(--s-2); }
/* Mismo truco de grid que las secciones: anima el plegado sin tener que
   medir alturas a mano. */
.module-body{ display:grid; grid-template-rows:1fr; transition:grid-template-rows .2s ease; }
.module-body.closed{ grid-template-rows:0fr; }
.module-body > .module-body-inner{ overflow:hidden; min-height:0; }
/* Con el sidebar achicado no hay cabecera que tocar, así que el módulo no
   puede quedar plegado y sin forma de abrirlo. */
.app-sidebar.collapsed .module-body.closed{ grid-template-rows:1fr; }
.app-sidebar.collapsed .module-context{ cursor:default; }
.app-sidebar.collapsed .module-context .mod-chev{ display:none; }
.module-context i{ width:16px; text-align:center; color:var(--m-ink); flex-shrink:0; font-size:15px; }
/* line-height ceñido en ambos: el 1.5 que heredaban del body sumaba ~9px de
   aire por cabecera que no separaba nada, solo estiraba la barra de color. */
.module-context .name{ font-size:12.5px; font-weight:700; color:var(--ink); line-height:1.25; }
.module-context .tag2{ font-size:9.5px; font-weight:700; color:var(--m-ink); text-transform:uppercase; letter-spacing:.05em; display:block; line-height:1.3; }

/* Un color por módulo. El amarillo queda reservado para Mailing (es el color
   de marca y fue el primer módulo). Los demás usan tonos que se distinguen
   entre sí pero que no arrastran significado de estado: verde puro diría
   "éxito" y rojo diría "error" en una interfaz que ya usa ambos para eso.

   Para agregar un módulo nuevo basta una línea acá con su --m-accent en RGB;
   todo lo de adentro (borde, cabecera, íconos) lo hereda solo. */

/* Mi negocio: gris azulado. Deliberadamente el más apagado — son ajustes que
   se tocan una vez, no el trabajo del día. Que se distinga sin pedir atención. */
.module-block.mod-negocio{ --m-accent:92,104,134; --m-ink:#4A5570; }
[data-theme="dark"] .module-block.mod-negocio{ --m-ink:#A8B4D6; }

/* Contactos: ciruela. Color propio porque es un módulo propio — es la base de
   personas que usan todos, no una función de Marketing. */
.module-block.mod-contactos{ --m-accent:126,86,140; --m-ink:#6A4778; }
[data-theme="dark"] .module-block.mod-contactos{ --m-ink:#C9A5D6; }

/* Comercial: verde azulado. */
.module-block.mod-comercial{ --m-accent:14,124,107; --m-ink:#0A5A4E; }
[data-theme="dark"] .module-block.mod-comercial{ --m-ink:#4FD1BB; }
.app-sidebar.collapsed .module-context{ justify-content:center; padding:8px; margin-left:0; width:auto; }
.app-sidebar.collapsed .module-context .name, .app-sidebar.collapsed .module-context .tag2{ display:none; }
.back-link{ display:flex; align-items:center; gap:8px; padding:6px var(--s-3); margin:0 8px var(--s-3); font-size:12px;
  color:var(--ink-3); border-radius:var(--r-sm); white-space:nowrap; }
.back-link:hover{ color:var(--ink); background:var(--hairline-2); }
.app-sidebar.collapsed .back-link{ justify-content:center; margin:0 6px var(--s-3); }
.app-sidebar.collapsed .back-link .lbl{ display:none; }
.app-sidebar-org{ margin:0 8px var(--s-2); padding:5px 8px; border-radius:var(--r-sm); background:transparent;
  display:flex; align-items:center; gap:8px; white-space:nowrap; overflow:hidden; cursor:pointer; border:none; width:calc(100% - 16px); text-align:left; font:inherit; color:inherit; }
.app-sidebar-org:hover{ background:var(--hairline-2); }
.app-sidebar-org i{ font-size:12.5px; color:var(--ink-3); flex-shrink:0; }
.app-sidebar-org .org-meta{ min-width:0; overflow:hidden; line-height:1.28; }
.app-sidebar-org .org-label{ display:block; font-size:9px; font-weight:700; color:var(--ink-3); text-transform:uppercase; letter-spacing:.05em; }
.app-sidebar-org .org-name{ display:block; font-size:12px; font-weight:600; color:var(--ink-2); overflow:hidden; text-overflow:ellipsis; }
.app-sidebar-org .chev-sm{ margin-left:auto; font-size:9px; color:var(--ink-3); flex-shrink:0; }
.app-sidebar.collapsed .app-sidebar-org{ display:none; }
.app-sidebar-footer{ margin-top:auto; padding:var(--s-3); border-top:1px solid var(--hairline); }
.profile-row{ display:flex; align-items:center; gap:9px; border-radius:var(--r-sm); padding:5px; margin:-5px; transition:background-color .12s ease; }
.profile-row:hover{ background:var(--hairline-2); }
.avatar-img{ width:30px; height:30px; border-radius:50%; object-fit:cover; flex-shrink:0; border:1px solid var(--hairline); }
.profile-meta{ min-width:0; overflow:hidden; white-space:nowrap; }
.profile-meta .pname{ font-size:12.5px; font-weight:650; color:var(--ink); overflow:hidden; text-overflow:ellipsis; }
.profile-meta .prole{ font-size:11px; color:var(--ink-3); overflow:hidden; text-overflow:ellipsis; }
.app-sidebar.collapsed .app-sidebar-footer{ padding:var(--s-3) 0; }
.app-sidebar.collapsed .profile-row{ justify-content:center; margin:0; padding:0; }
.app-sidebar.collapsed .profile-meta{ display:none; }
.app-main{ flex:1; min-width:0; }
.app-topbar{ padding:26px var(--s-7) var(--s-4); display:flex; align-items:center; justify-content:space-between; gap:16px; }
.app-topbar h1{ font-size:18px; }
.app-content{ padding:0 var(--s-7) var(--s-7); max-width:1080px; }
.insight{ display:flex; align-items:flex-start; gap:10px; background:rgba(251,209,13,.12); border:1px solid rgba(251,209,13,.4);
  border-radius:var(--r-md); padding:12px 16px; margin-bottom:var(--s-5); font-size:13px; }
.insight i{ color:#8A6A00; margin-top:1px; }
.insight b{ font-weight:650; }
.insight .go{ margin-left:auto; white-space:nowrap; }
.search-input{ display:flex; align-items:center; gap:8px; background:var(--surface); border:1px solid var(--hairline);
  border-radius:var(--r-sm); padding:7px 12px; flex:1; max-width:320px; }
.search-input i{ color:var(--ink-3); font-size:13px; flex-shrink:0; }
.search-input input{ border:none; background:none; outline:none; font:inherit; color:var(--ink); width:100%; }
.search-input input::placeholder{ color:var(--ink-3); }
.toolbar-row{ display:flex; align-items:center; gap:10px; margin-bottom:var(--s-4); flex-wrap:wrap; }
.toolbar-row .spacer{ flex:1; }
.panel{ background:var(--surface); border:1px solid var(--hairline); border-radius:var(--r-md); overflow:hidden; }
.panel-body{ padding:6px 20px 10px; }
.data-table{ width:100%; border-collapse:collapse; font-size:13.5px; }
.data-table thead th{ text-align:left; font-size:11px; font-weight:650; color:var(--ink-3); text-transform:uppercase;
  letter-spacing:.04em; padding:16px 14px 12px; border-bottom:1px solid var(--hairline); white-space:nowrap; }
.data-table tbody td{ padding:15px 14px; border-bottom:1px solid var(--hairline-2); vertical-align:middle; }
.data-table tbody tr:last-child td{ border-bottom:none; }
.data-table tbody tr:hover{ background:var(--hairline-2); }
.data-table .cname{ font-weight:600; color:var(--ink); font-size:13.5px; }
.data-table .cemail{ color:var(--ink-3); font-size:12.5px; margin-top:2px; }
.tag{ display:inline-flex; align-items:center; gap:5px; font-size:12px; font-weight:550; color:var(--ink-2); flex-shrink:0; }
.tag .dot{ width:5px; height:5px; border-radius:50%; background:var(--ink-3); }
.tag.done .dot{ background:var(--ok); } .tag.warn .dot{ background:#8A6A00; } .tag.info .dot{ background:var(--info); }
.pagination{ display:flex; align-items:center; justify-content:space-between; padding-top:var(--s-4); font-size:12.5px; color:var(--ink-3); }
/* La paginación se usa de dos formas en las vistas: envuelta en .pagination o
   suelta en .pg-btns. Los estilos aplican a AMBAS para que nunca salgan los
   números pelados. */
.pagination .pg-btns, .pg-btns{ display:flex; align-items:center; gap:6px; flex-wrap:wrap; }
.pagination a, .pagination span.pg-current, .pagination span.pg-disabled,
.pg-btns a, .pg-btns span.pg-current, .pg-btns span.pg-disabled{
  min-width:30px; height:30px; padding:0 9px; border-radius:var(--r-sm); border:1px solid var(--hairline);
  background:var(--surface); color:var(--ink-2); cursor:pointer; display:flex; align-items:center;
  justify-content:center; font-size:12.5px; font-variant-numeric:tabular-nums; text-decoration:none;
  transition:border-color .12s ease, background .12s ease, color .12s ease; }
.pagination a:hover, .pg-btns a:hover{ border-color:rgba(128,128,128,.45); color:var(--ink); background:var(--hairline-2); }
.pagination span.pg-current, .pg-btns span.pg-current{ background:var(--ink); color:var(--bg); border-color:var(--ink); font-weight:650; }
.pagination span.pg-disabled, .pg-btns span.pg-disabled{ color:var(--ink-3); opacity:.4; cursor:default; }
.pagination span.pg-dots, .pg-btns span.pg-dots{ padding:0 4px; color:var(--ink-3); display:flex; align-items:center; }

/* Fix: quita el estilo nativo del navegador en botones de acción tipo icono (editar/eliminar) */
button.btn-text{
  border:none;
  background:none;
  -webkit-appearance:none;
  appearance:none;
  cursor:pointer;
  font:inherit;
  border-radius:var(--r-sm);
}
button.btn-text:hover{
  background:var(--hairline-2);
}

/* Fix: centrar el contenido principal en vez de dejarlo pegado al sidebar */
.app-content{
  margin: 0 auto;
}

/* Acciones de página: fila alineada a la derecha, arriba del contenido.
   Reemplaza a los botones que antes vivían en el topbar; el topbar quedó
   solo para lo global (reloj, tema, avisos, cuenta). */
.page-actions{ display:flex; justify-content:flex-end; align-items:center;
  gap:10px; flex-wrap:wrap; margin:14px 0 20px; }
.page-actions form{ margin:0; }
@media (max-width:640px){
  .page-actions{ justify-content:stretch; }
  .page-actions > *{ flex:1; }
  .page-actions .btn{ width:100%; justify-content:center; }
}

/* Estado vacío de listas. Vivía copiado en el <style> de cada vista, así que
   unas lo tenían y otras no: la misma app mostraba una lista vacía con un
   bloque explicativo y otra con nada. Acá es global y todas se ven igual. */
.empty-state{ display:flex; flex-direction:column; align-items:center; text-align:center; padding:56px 24px; }
.empty-state .es-icon{ width:64px; height:64px; border-radius:16px; display:flex; align-items:center;
  justify-content:center; background:var(--hairline-2); color:var(--ink-3); font-size:28px; margin-bottom:18px; }
.empty-state.filtered .es-icon{ background:transparent; }
.empty-state h2{ font-size:16px; font-weight:700; color:var(--ink); margin:0 0 6px; }
.empty-state p{ font-size:13px; color:var(--ink-3); max-width:400px; line-height:1.6; margin:0 0 22px; }

/* ─────────────────────────────────────────────────────────────
   RESPONSIVE

   Hasta acá el layout era de escritorio y nada más: el sidebar es un bloque
   fijo de 232px dentro de un flex, así que en un teléfono de 390px se comía
   más de la mitad del ancho y el contenido quedaba en una columna inservible.

   En móvil el sidebar pasa a ser un CAJÓN: sale de la pantalla y se muestra
   encima al tocar el botón de menú, con un fondo oscuro detrás para cerrarlo.
   Así el contenido usa el ancho completo, que es lo único que importa en un
   teléfono.
   ───────────────────────────────────────────────────────────── */
.cb-mobile-menu{ display:none; }
.cb-sidebar-backdrop{ display:none; }

@media (max-width:900px){
  /* El sidebar sale del flujo y se convierte en cajón deslizante. */
  .app-sidebar{
    position:fixed; top:0; left:0; bottom:0; z-index:500;
    width:min(280px, 84vw); max-width:none;
    transform:translateX(-100%);
    transition:transform .22s ease;
    box-shadow:0 0 40px rgba(0,0,0,.45);
  }
  .app-sidebar.mobile-open{ transform:translateX(0); }
  /* En móvil no aplica el modo "achicado" de escritorio. */
  .app-sidebar.collapsed{ width:min(280px, 84vw); }

  .cb-sidebar-backdrop{
    display:block; position:fixed; inset:0; z-index:450;
    background:rgba(0,0,0,.5); opacity:0; pointer-events:none;
    transition:opacity .22s ease;
  }
  .cb-sidebar-backdrop.on{ opacity:1; pointer-events:auto; }

  /* Botón de menú: fijo arriba a la izquierda, a la altura del título. */
  .cb-mobile-menu{
    display:flex; align-items:center; justify-content:center;
    position:fixed; top:18px; left:12px; z-index:520;
    width:38px; height:38px; border-radius:10px;
    background:var(--surface); border:1px solid var(--hairline);
    color:var(--ink); font-size:18px; cursor:pointer;
  }
  /* El título se corre para no chocar con el botón. */
  .app-topbar{ padding-left:62px; flex-wrap:wrap; row-gap:10px; }
  .app-topbar h1{ font-size:16px; }
  .app-content{ padding-left:14px; padding-right:14px; }

  /* El reloj ocupa espacio y no aporta en un teléfono. */
  .clock{ display:none; }

  /* Las tablas anchas se desplazan de lado en vez de romper el layout.
     Se cubren los dos casos que existen en el proyecto: la tabla dentro de
     .panel-body (11 vistas) y la tabla colgando directo de .panel (23 vistas,
     sobre todo el módulo Comercial). Una regla en vez de 23 ediciones: si
     mañana aparece una tabla nueva, ya queda cubierta sola. */
  .panel-body,
  .panel{ overflow-x:auto; }
  .data-table{ min-width:560px; }

  /* El desplazamiento lateral necesita anunciarse: sin esto el usuario no
     sabe que hay más columnas a la derecha y cree que faltan datos. */
  .panel > .data-table,
  .panel-body > .data-table{
    -webkit-overflow-scrolling:touch;
  }

  /* Los filtros se apilan a ancho completo. */
  .filters{ flex-direction:column; align-items:stretch; }
  .filters > *{ width:100%; }
}

@media (max-width:520px){
  .app-topbar h1{ font-size:15px; }
  .topbar-group{ gap:6px; }
  .live-pill{ display:none; }   /* "En vivo" es decorativo; el espacio no lo es */
}

/* ── Afinado móvil ─────────────────────────────────────────────
   Detalles que separan "se ve" de "se usa bien" en un teléfono. */
@media (max-width:900px){
  /* El buscador tenía max-width:320px pensado para escritorio: en móvil
     quedaba angosto al lado de selects a ancho completo. */
  .search-input{ max-width:none; }

  /* Objetivos táctiles: 44px es el mínimo cómodo para un dedo. Los botones
     estaban dimensionados para el clic preciso de un mouse. */
  .btn, .icon-btn, .filters select, .search-input{ min-height:44px; }
  .btn{ padding:11px 18px; }
  select, input, textarea{ font-size:16px; }  /* <16px hace que iOS haga zoom al enfocar */

  /* Aire lateral consistente y respeto por el notch/barra inferior. */
  .app-content{ padding-bottom:calc(24px + env(safe-area-inset-bottom)); }
  .app-topbar{ padding-top:calc(18px + env(safe-area-inset-top)); }
  .cb-mobile-menu{ top:calc(14px + env(safe-area-inset-top)); }

  /* Las tarjetas de indicadores en una sola columna: dos no caben legibles. */
  .hero, .kpi-grid{ grid-template-columns:1fr !important; }

  /* Menús desplegables no se salen de la pantalla. */
  .cb-notif-menu, .cb-acct-menu{ width:min(320px, calc(100vw - 24px)) !important; }
}

/* El cajón se anima solo si la persona no pidió menos movimiento. */
@media (prefers-reduced-motion:reduce){
  .app-sidebar, .cb-sidebar-backdrop, .btn, .cta{ transition:none !important; }
}

/* ─────────────────────────────────────────────────────────────
   Filtros plegables (móvil)

   El botón y el plegado solo existen bajo 900px. En escritorio los filtros
   caben en una fila y esconderlos sería un clic de más sin ninguna ganancia,
   así que ahí el botón simplemente no se muestra y el formulario se ve
   completo como siempre.
   ───────────────────────────────────────────────────────────── */
.cb-filtros-toggle{ display:none; }

@media (max-width: 900px){
  .cb-filtros-toggle{
    display:flex; align-items:center; justify-content:space-between;
    width:100%; gap:10px; margin-bottom:12px;
    padding:12px 14px; min-height:44px;
    border:1px solid var(--hairline); border-radius:var(--r-sm);
    background:var(--surface); color:var(--ink);
    font:inherit; font-size:13.5px; font-weight:600;
    cursor:pointer; text-align:left;
  }
  .cb-filtros-toggle .bi-chevron-down{ transition:transform .18s ease; font-size:12px; color:var(--ink-3); }
  .cb-filtros-toggle.abierto .bi-chevron-down{ transform:rotate(180deg); }

  /* El contador de filtros activos: la señal de que la lista que estás
     viendo está recortada. Sin esto, una lista filtrada parece una lista
     vacía y la gente cree que perdió datos. */
  .cb-filtros-n{
    display:inline-block; margin-left:6px; padding:1px 7px;
    border-radius:999px; background:var(--yellow,#FBD10D); color:#1B1A17;
    font-size:11px; font-weight:800; font-variant-numeric:tabular-nums;
  }

  .cb-filtros-plegable.cerrado{ display:none; }
}

@media (max-width: 900px){
  /* El min-width de 560px existe para que las columnas no se aplasten. Pero
     cuando la tabla no tiene datos y solo muestra el estado vacío, ese ancho
     mínimo empuja el mensaje fuera de la pantalla y el botón de "crear el
     primero" queda cortado. Justo el momento en que más importa que se vea.
     Si la tabla contiene un estado vacío, no hay columnas que proteger. */
  .data-table.sin-datos{ min-width:0; }
  /* Sin datos, los encabezados de columna no informan nada: son seis palabras
     que juntas no caben en 390px y empujan el mensaje fuera de la pantalla.
     Se ocultan y el estado vacío queda centrado, que es lo único que importa
     en ese momento. */
  .data-table.sin-datos thead{ display:none; }
  .empty-state{ padding-left:18px; padding-right:18px; }
  .empty-state .btn{ width:100%; justify-content:center; }
  .empty-state > .btn + .btn,
  .empty-state a.btn + a.btn{ margin-top:10px; }

  /* Los botones de acción de la pantalla: en fila no caben tres y el texto se
     parte en dos líneas. Apilados a ancho completo se leen enteros y además
     dan un blanco cómodo para el pulgar. */
  .page-actions{ flex-direction:column; align-items:stretch; gap:8px; }
  .page-actions .btn,
  .page-actions form,
  .page-actions form .btn{ width:100%; justify-content:center; }
}

@media (max-width: 900px){


}


/* ── Título del topbar en teléfono ──
   En 390px el título compite con el botón de menú (62px), el selector de tema,
   la campana y el avatar: quedan ~160px, y "Precios de proveedores" se recorta
   a "Precios d…". Recortar el nombre de la pantalla para ahorrar 40px
   verticales es mal negocio: la persona necesita saber dónde está.

   Así que bajo 600px el título se lleva su propia línea, siempre. "Siempre" es
   la parte importante: antes el salto dependía del largo del texto, y una
   interfaz que a veces salta y a veces no se siente descuidada aunque cada
   caso por separado se vea bien.

   Sobre 600px (tablets) no hace falta: el título y los controles conviven en
   una fila con espacio de sobra. */
@media (max-width: 600px){
  .app-topbar h1{ flex:1 0 100%; }
}

/* ── Topbar en teléfono: dos filas ordenadas ──
   El título arriba con el botón de menú, los controles debajo alineados a la
   derecha. Antes los controles heredaban la sangría de 62px del botón de menú
   y quedaban flotando a media izquierda, sin alinearse con nada — se veía
   accidental más que diseñado.

   La corona del super administrador sobresale del círculo por diseño, así que
   la fila necesita aire arriba para no cortarla. */
@media (max-width: 600px){
  /* El padding lateral del topbar venía de escritorio (48px) mientras el
     contenido de abajo usa 14px: los controles quedaban flotando lejos del
     borde y desalineados con todo lo demás de la pantalla. Se igualan. */
  .app-topbar{
    padding-top:14px; padding-bottom:12px; padding-right:14px;
    align-items:flex-start;
  }

  /* Todo lo que no sea el título (el grupo de controles) se va a la derecha y
     recupera el margen que le comía la sangría del botón de menú. */
  .app-topbar > *:not(h1){
    margin-left:auto; margin-right:0;
    padding-top:10px;   /* aire para la corona */
  }

  /* En una pantalla de 390px el avatar de 40px + su corona pesan demasiado
     para un elemento que no es la tarea. Se achica sin perder legibilidad. */
  /* flex-shrink:0 es lo que evita el óvalo. Sin eso, cuando la fila de
     controles no alcanza, el navegador le roba ancho al avatar pero respeta
     su alto: 34 de alto por 28 de ancho = huevo. Un círculo tiene que estar
     protegido de encogerse en una sola dirección. */
  .app-topbar #acctBtn{
    width:34px; height:34px; min-width:34px; min-height:34px;
    flex-shrink:0; aspect-ratio:1; font-size:12px;
  }
  .app-topbar .cb-crown{ width:16px; height:13px; top:-8px; }

  /* El selector de tema: sin achicarlo. Lo había reducido a 26px para ganar
     espacio en el topbar, y después me contradije agrandándolo a 36 por
     ergonomía. Gana la ergonomía — 26px no se acierta con el pulgar, y el
     espacio ya lo resolvimos poniendo el título en su propia línea. */
  .app-topbar .topbar-group{ padding:4px 6px; }
}

/* ── Áreas de toque y legibilidad en teléfono ──
   La auditoría a 390px encontró controles de 21 a 32px de alto. Con un mouse
   son cómodos; con el pulgar se fallan. La referencia de Apple y Google es
   44px, y bajo 36px el error de toque se dispara.

   La técnica: se agranda el área sensible sin agrandar el dibujo. Un ícono de
   14px sigue viéndose de 14px, pero el rectángulo que responde al dedo mide
   40. Así no se engorda la interfaz para arreglar la ergonomía. */
@media (max-width: 600px){

  /* Editar / eliminar en las listas: eran 28px y van uno al lado del otro,
     que es la peor combinación — chico y con un vecino que también es clic. */
  .btn-text{ min-height:40px; min-width:40px; padding:0 10px; justify-content:center; }
  td .btn-text{ display:inline-flex; }


  /* Selectores de filtro. */
  select, .filters select{ min-height:40px; }

  /* Botones de sugerencia del asistente de campañas: 21px. */
  .suggest-btn{ min-height:36px; padding:0 10px; }

  /* Selector de tema: tres botones de 26px pegados entre sí. Se agrandan y se
     separan, que importa tanto como el tamaño cuando están juntos. */
  .theme-toggle{ gap:4px; }
  .theme-toggle button{ width:36px; height:36px; }
  .topbar-group{ padding:4px 6px; }

  /* Los encabezados de tabla a 10,5px y en mayúsculas son difíciles de leer en
     una pantalla chica sostenida a distancia de brazo. 11,5 no cambia el
     diseño y sí la legibilidad. */
  .app-content .data-table thead th,
  .app-content table.mv th,   /* movimientos de Inventario */
  .app-content table.ct th{ font-size:11.5px; }   /* carro del punto de venta */

  /* Las etiquetas de tipo de cliente (Retail, Mayorista) a 10px.
     Va con .app-content adelante por especificidad: el bloque <style> de cada
     vista carga después de esta hoja, así que a igualdad de peso gana la
     vista. Con un selector más específico, no. */
  .app-content .tier{ font-size:11px; }
}

@media (max-width: 600px){
  /* El nombre en cada fila de una lista es el enlace principal — el que la
     persona toca para entrar a la ficha. Medía 20px de alto: solo el texto
     respondía, y errarle por dos píxeles no hacía nada.

     El truco es padding + margen negativo del mismo valor: el área sensible
     crece hasta cubrir la celda completa, pero el diseño no se mueve ni un
     píxel porque el margen negativo devuelve el espacio que el padding tomó. */
  .data-table td > a{
    display:block;
    padding:11px 0;
    margin:-11px 0;
  }
}

/* ─────────────────────────────────────────────────────────────────────────
   Barra de filtros
   ─────────────────────────────────────────────────────────────────────────
   Estaba copiada a mano en 9 vistas del módulo Comercial y en NINGUNA otra.
   Por eso las pantallas nuevas (Gastos, Activos) mostraban los <select> con
   la apariencia nativa del sistema operativo mientras el buscador de al lado
   sí estaba vestido: el mismo bloque, dos estéticas.

   Es el mismo problema que tuvo el topbar: un bloque copiado en N vistas se
   desincroniza siempre, y peor, falta en las que se escriben después. Vive
   acá, una vez. Las copias locales de Comercial son idénticas y se quedan sin
   hacer daño; el día que alguien las borre, esto ya las cubre.
   ───────────────────────────────────────────────────────────────────────── */
.filters{ display:flex; gap:8px; flex-wrap:wrap; align-items:center; margin-bottom:16px; }
.filters select,
.filters input[type=date],
.filters input[type=text]:not(.search-input input){
  padding:8px 10px; border-radius:var(--r-sm); border:1px solid var(--hairline);
  background:var(--surface); color:var(--ink); font:inherit; font-size:12.5px;
}
.filters select{ cursor:pointer; }

/* Un encabezado de tabla flotando sobre un estado vacío nombra columnas que
   no tienen ni una fila debajo: promete datos que no existen. Se ocultaba
   solo en móvil; el problema es igual de real en escritorio. */
.data-table.sin-datos thead{ display:none; }

/* ─────────────────────────────────────────────────────────────────────────
   Timbre de PAGADO
   ─────────────────────────────────────────────────────────────────────────
   Un check verde chico se pierde entre los demás iconos de la pantalla. El
   timbre inclinado se lee de reojo, sin buscarlo, y es la metáfora que ya
   conocen: en una oficina un documento pagado lleva un timbre encima.

   Va rotado y con opacidad alta pero no total, como tinta sobre papel. La
   rotación es de −8° y no de −45°: a 45° se convierte en decoración y tapa
   texto; a −8° se lee de corrido y aun así se nota que es un sello.
   ───────────────────────────────────────────────────────────────────────── */
.timbre{
  display:inline-flex; align-items:center; gap:7px;
  padding:6px 14px; border:2px solid rgb(14,124,107); border-radius:7px;
  color:rgb(14,124,107); background:rgba(14,124,107,.07);
  font-size:13px; font-weight:800; text-transform:uppercase; letter-spacing:.09em;
  transform:rotate(-8deg); white-space:nowrap; flex-shrink:0;
}
.timbre i{ font-size:15px; }
.timbre.grande{ font-size:16px; padding:9px 20px; border-width:2.5px; }
[data-theme="dark"] .timbre{ color:#4FD1BB; border-color:#4FD1BB; background:rgba(79,209,187,.09); }

/* El check verde de una fila pagada, para las tablas de historial. Acá el
   timbre completo sería demasiado: la fila ya está en una tabla que se llama
   "historial de pagos", así que basta con confirmar. */
.check-pagado{
  display:inline-flex; align-items:center; gap:5px;
  color:rgb(14,124,107); font-size:12px; font-weight:680;
}
[data-theme="dark"] .check-pagado{ color:#4FD1BB; }

/* La aparición del timbre después de registrar un pago. Un sello se posa: baja
   y se asienta, no aparece de la nada. Dura poco — 420ms — porque una
   confirmación que se hace esperar deja de confirmar y empieza a estorbar. */
@keyframes cb-timbrar{
  0%   { opacity:0; transform:rotate(-8deg) scale(1.6); }
  60%  { opacity:1; transform:rotate(-8deg) scale(.94); }
  100% { opacity:1; transform:rotate(-8deg) scale(1); }
}
.timbre.recien{ animation:cb-timbrar .42s cubic-bezier(.2,.8,.3,1) both; }

@media (prefers-reduced-motion: reduce){
  .timbre.recien{ animation:none; }
}
