/* ══════════════════════════════════════════════════════════════════
   SABBIA · sabbia.css — BASE UNIVERSAL (design system de toda la app)
   ══════════════════════════════════════════════════════════════════
   Regla de oro: este archivo define TODA la app. Aquí viven los tokens
   y TODAS las primitivas reutilizables (tipografía, botones, campos,
   tarjetas, KPIs, estados, tablas, cintas, avisos, layout). Cada
   pantalla enlaza este archivo con una sola línea y solo añade la
   MAQUETACIÓN de su contenido, componiéndola con estas primitivas.
   Ninguna pantalla redefine color, botón, campo, peso ni tamaño.

       <link rel="stylesheet" href="../assets/sabbia.css">

   ► Cambiar cualquier cosa del aspecto (un color, un botón, un KPI) se
     hace SOLO aquí y toda la app lo adopta.
   Estilo: minimalista/tenue — negritas con menos peso, colores suaves,
   botones limpios (píldora, sin relleno), pocos fondos, sin sobresaltos.
   ══════════════════════════════════════════════════════════════════ */

/* La paleta vive aparte (tokens.css) para que las páginas sueltas
   puedan usarla sin arrastrar todo el armazón. Ver docs/ESTANDAR_UI.md. */
@import url('tokens.css');
/* Tipografía de marca (Inter). Debe ir la primera del archivo (@import). */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');



/* ── Reset ligero ─────────────────────────────────────────────── */
*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}
body{
  font-family:'Inter',system-ui,-apple-system,'Segoe UI',Roboto,sans-serif;
  background:var(--fondo);
  color:var(--grafito);
  line-height:1.55;
  -webkit-font-smoothing:antialiased;
  font-size:15px;                     /* nombres / importes / texto base */
}

/* ── Tipografía ───────────────────────────────────────────────────
   Escala del look tenue: título 21 · KPI 24 · texto 15 · subtítulo 13,5
   · etiqueta 11 · badge 13. Negritas aligeradas.                    */
h1{font-size:21px;font-weight:var(--peso-fuerte);letter-spacing:-.01em;color:var(--grafito)}
h2{font-size:16px;font-weight:var(--peso-fuerte);color:var(--grafito)}
h3{font-size:14px;font-weight:var(--peso-medio);color:var(--grafito)}
strong,b{font-weight:var(--peso-fuerte)}
a{color:var(--agua-hondo);text-decoration:none;transition:var(--trans)}
a:hover{color:var(--grafito)}

/* Utilidades de texto (roles de la escala) */
.sub{font-size:13.5px;color:var(--gris)}                 /* subtítulo */
.etq{font-size:11px;font-weight:var(--peso-etq);color:var(--gris);letter-spacing:.04em;text-transform:uppercase}  /* etiqueta */
.muted{color:var(--gris)}
.num{font-variant-numeric:tabular-nums}                   /* cifras alineadas */

/* ── Layout ───────────────────────────────────────────────────── */
.wrap{max-width:1100px;margin:0 auto;padding:28px 22px 64px}
.top{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;margin-bottom:18px}
.top .sub{margin-top:3px}
.grid{display:grid;gap:14px 18px}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:14px 18px}
.grid3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:14px 18px}
.full{grid-column:1 / -1}
@media (max-width:720px){
  .grid2,.grid3{grid-template-columns:1fr}
}

/* ── Tarjetas / contenedores ──────────────────────────────────────
   Úsalas solo cuando algo necesita de verdad un contenedor. El estilo
   tenue prefiere separar con líneas antes que con cajas.             */
.card{background:var(--blanco);border:1px solid var(--linea);border-radius:var(--radio);padding:22px}
.panel{background:var(--papel);border:1px solid var(--linea);border-radius:var(--radio);padding:18px}

/* Separador fino (secciones separadas por línea, sin caja) */
.hr{border:0;border-top:1px solid var(--linea);margin:22px 0}
.seccion{padding:20px 0;border-top:1px solid var(--linea)}
.seccion:first-child{border-top:0}

/* ── BOTONES ──────────────────────────────────────────────────────
   Todos píldora, fondo transparente (nunca relleno sólido), y PESO
   FIJO 500 en todos los estados: el peso NO cambia en hover (si la
   negrita apareciera al pasar el ratón, el texto se ensancharía y el
   botón se movería). El énfasis va por MARCO y COLOR, jamás por peso.  */
.btn,.btn-primario,.btn-vf,.btn-quiet,.btn-peligro{
  display:inline-flex;align-items:center;justify-content:center;
  border-radius:var(--pill);
  background:transparent;
  padding:9px 18px;
  font-family:inherit;
  font-size:13.5px;
  font-weight:var(--peso-medio);   /* 500 — fijo en todos los estados */
  line-height:1;
  cursor:pointer;
  white-space:nowrap;
  border:1px solid transparent;
  transition:var(--trans);
}
.btn[disabled],.btn-primario[disabled],.btn-vf[disabled]{opacity:.5;cursor:not-allowed}

/* ── Variantes (21/22-09-2026) ──────────────────────────────────────
   Nacen de contar lo que la app YA hacía por su cuenta. Si mañana hace
   falta otra, se añade aquí: una variante que no está en la base es una
   variante que cada pantalla va a dibujar distinta. */

/* PEQUEÑO — para barras de herramientas y acciones de fila. Medida de en
   medio de las cuatro que había sueltas por ahí. Se acepta también
   `.btn.mini`: cuatro módulos ya lo escribían así y no merece la pena
   tocarles el marcado por un guion. La forma canónica es `.btn-mini`. */
.btn-mini,.btn.mini,.btn-primario.mini,.btn-quiet.mini{padding:4px 11px;font-size:12px}

/* PELIGRO — lo que no tiene vuelta atrás: borrar, revocar, desconectar.
   Va en --err-hondo (el rojo), NO en --err (la teja de los avisos): un
   vencimiento y un borrado para siempre no pueden pintarse igual. */
.btn-peligro{border-color:var(--linea);color:var(--err-hondo)}
.btn-peligro:hover{border-color:var(--err-hondo);
  background:color-mix(in srgb, var(--err-hondo) 7%, transparent)}

/* Secundario — el botón base */
.btn{border-color:var(--linea);color:var(--gris)}
.btn:hover{border-color:var(--gris);color:var(--grafito);background:rgba(74,72,66,.03)}

/* Primario — perfil un poco más marcado de base. Bebe de los tokens del
   despacho: sin color elegido, es exactamente el de siempre. */
.btn-primario{border:1.5px solid var(--boton-borde);color:var(--boton-texto)}
.btn-primario:hover{border-color:var(--boton-texto);background:color-mix(in srgb, var(--boton-texto) 7%, transparent)}

/* Verifactu — igual, en tierra */
.btn-vf{border:1.5px solid var(--tierra);color:var(--tierra)}
.btn-vf:hover{background:rgba(184,155,130,.06)}

/* Terciario / discreto — solo texto, sin marco ni relleno (acciones secundarias) */
.btn-quiet{border-color:transparent;color:var(--gris)}
.btn-quiet:hover{color:var(--grafito);background:rgba(74,72,66,.03)}

/* ── CAMPOS DE FORMULARIO ─────────────────────────────────────── */
.campo{display:flex;flex-direction:column;gap:6px}
.campo > label{font-size:12.5px;color:var(--gris);font-weight:var(--peso-etq)}
.campo input,.campo select,.campo textarea,
input.campo,select.campo,textarea.campo{
  width:100%;
  border:1px solid var(--linea);
  border-radius:8px;
  padding:9px 11px;
  font-family:inherit;
  font-size:14px;
  color:var(--grafito);
  background:var(--blanco);
  transition:var(--trans);
}
.campo textarea{resize:vertical;min-height:80px}
.campo input:focus,.campo select:focus,.campo textarea:focus,
input.campo:focus,select.campo:focus,textarea.campo:focus{
  outline:none;
  border-color:var(--agua);
  box-shadow:0 0 0 3px rgba(127,184,175,.15);
}
.campo input::placeholder,.campo textarea::placeholder{color:var(--gris-claro)}

/* ── KPIs ─────────────────────────────────────────────────────────
   Sin caja de fondo: solo cifra + etiqueta, separadas por línea fina. */
.kpis{display:flex;flex-wrap:wrap;border-top:1px solid var(--linea);border-bottom:1px solid var(--linea);margin:22px 0}
.kpi{flex:1 1 140px;padding:14px 18px;border-left:1px solid var(--linea)}
.kpi:first-child{border-left:0}
.kpi .num{display:block;font-size:24px;font-weight:var(--peso-fuerte);color:var(--grafito);line-height:1.1}
.kpi label,.kpi .etq{display:block;font-size:11px;font-weight:var(--peso-etq);color:var(--gris);letter-spacing:.04em;text-transform:uppercase;margin-top:4px}

/* ── ESTADOS / BADGES ─────────────────────────────────────────────
   Solo texto de color, sin borde ni pastilla (menos fondos).         */
.estado{font-size:13px;font-weight:var(--peso-etq)}
.estado.pend,.estado.pendiente{color:var(--tierra)}
.estado.cobrado,.estado.ok{color:var(--agua-hondo)}
.estado.vencido,.estado.err{color:var(--err)}

/* Etiqueta discreta (chip sin fondo) */
.tag{font-size:12.5px;color:var(--gris)}

/* ── CINTAS / TIRAS INFORMATIVAS ──────────────────────────────────
   Solo texto (menos fondos). La cinta del obligado tributario indica
   siempre de qué emisor son los datos (multi-inquilino).             */
.obligado,.tira{display:inline-flex;align-items:center;gap:8px;font-size:12.5px;color:var(--gris)}
.obligado b{font-weight:var(--peso-fuerte);color:var(--grafito)}
.obligado .cif{color:var(--gris)}

/* ── TABLAS / LISTAS ──────────────────────────────────────────────
   Sin caja: filas separadas por línea fina.                          */
.tabla{width:100%;border-collapse:collapse}
.tabla th{
  text-align:left;font-size:11px;font-weight:var(--peso-etq);color:var(--gris);
  letter-spacing:.04em;text-transform:uppercase;
  padding:8px 10px;border-bottom:1px solid var(--linea);
}
.tabla td{padding:10px;border-bottom:1px solid var(--linea);font-size:14px}
.tabla tr:hover td{background:rgba(74,72,66,.02)}
/* Segunda línea de una celda (el NIF bajo el cliente, el vencimiento bajo
   la fecha): el dato que acompaña, en pequeño y gris, sin otra columna. */
.tabla td .bajo{display:block;font-size:12px;color:var(--gris);overflow:hidden;text-overflow:ellipsis}
/* La fila de totales al pie: lo que se ve, sumado. Cifras alineadas con
   sus columnas, línea más firme arriba y ninguna abajo; sin hover, que
   no es una fila que se abra. */
.tabla tfoot td{border-top:2px solid var(--grafito);border-bottom:0;font-variant-numeric:tabular-nums;background:transparent}
.tabla tfoot tr:hover td{background:transparent}
.tabla tfoot td.pie-rotulo{font-weight:var(--peso-fuerte);color:var(--grafito)}
.tabla tfoot td.pie-rotulo .bajo{font-weight:400}

/* Fila genérica de lista (cabecera + filas con divisor) */
.fila{display:flex;align-items:center;gap:12px;padding:10px 0;border-bottom:1px solid var(--linea)}
.fila.cab{font-size:11px;font-weight:var(--peso-etq);color:var(--gris);letter-spacing:.04em;text-transform:uppercase}

/* ── AVISOS / FEEDBACK ────────────────────────────────────────── */
.msg-err{color:var(--err);font-size:13px}
.msg-ok{color:var(--agua-hondo);font-size:13px}
.aviso{font-size:13px;color:var(--gris)}

/* Toast (confirmaciones flotantes) */
.toast{
  position:fixed;left:50%;bottom:26px;transform:translateX(-50%) translateY(16px);
  background:var(--grafito);color:#fff;padding:11px 18px;border-radius:var(--radio);
  font-size:14px;opacity:0;pointer-events:none;transition:var(--trans);z-index:50;
  box-shadow:var(--sombra);
}
.toast.show{opacity:1;transform:translateX(-50%) translateY(0)}
.toast.ok{background:var(--agua-hondo)}
.toast.err{background:var(--err)}

/* ── UTILIDADES ───────────────────────────────────────────────── */
.oculto{display:none!important}
.spacer{flex:1}
.acciones{display:flex;gap:10px;align-items:center}

/* ══ SHELL DE APLICACIÓN — 3 columnas a pantalla completa ══════════
   Marco transversal: barra superior + menú (izq, fijo) + contenido
   (centro, fluido, el más claro) + widgets (der, fijo). Cada columna
   scrollea por dentro → el marco no se mueve al cambiar de contenido.
   Estructura en cada pantalla:
     <div class="top-app">…marca + acciones de pantalla…</div>
     <div class="shell">
       <nav class="col-izq nav-mod" id="nav-mod" data-modulo="X"></nav>
       <main class="col-centro">…contenido…</main>
       <aside class="col-der">…widgets…</aside>
     </div>
     <script src="../assets/shell.js?v=1"></script>   (rellena el menú)
   ────────────────────────────────────────────────────────────────── */
.top-app{
  height:var(--top-h);position:sticky;top:0;z-index:50;
  display:flex;align-items:center;justify-content:space-between;gap:16px;
  padding:0 20px;background:rgba(255,255,255,.9);backdrop-filter:blur(8px);
  border-bottom:1px solid var(--linea);
}
.top-app .marca{font-weight:var(--peso-fuerte);letter-spacing:-.01em}
.top-app .marca .dot{color:var(--agua)}
.top-app .acciones{display:flex;gap:10px;align-items:center}

.shell{
  display:grid;
  grid-template-columns:var(--col-izq) minmax(0,1fr) var(--col-der);
  height:calc(100vh - var(--top-h));
  overflow:hidden;                       /* el marco no se mueve */
}
.col-izq,.col-centro,.col-der{overflow:auto;min-height:0}   /* scroll por columna */
.col-izq{border-right:1px solid var(--linea);padding:18px 14px;background:var(--papel)}
.col-centro{padding:24px 28px;background:var(--blanco)}      /* el más claro: el contenido resalta */
.col-der{border-left:1px solid var(--linea);padding:18px 16px;background:var(--papel)}

/* Menú de módulos (columna izquierda) */
.nav-mod-tit{font-size:11px;font-weight:var(--peso-medio);color:var(--gris);letter-spacing:.04em;text-transform:uppercase;margin:6px 8px 8px}
.nav-mod a{display:block;padding:9px 12px;border-radius:8px;color:var(--grafito);text-decoration:none;font-size:14px;transition:var(--trans);cursor:pointer}
.nav-mod a:hover{background:var(--arena-clara)}
.nav-mod a.act{background:var(--arena-clara);color:var(--agua-hondo);font-weight:var(--peso-medio)}

/* Responsive: se pliega widgets y luego el menú */
/* OJO: el `.col-der{display:none}` que habia aqui no estaba acotado a
   `.shell`, asi que escondia los widgets de TODA la app desde el bloque
   de un armazon que ya no usa ninguna pantalla. Ahora la regla de los
   widgets vive en un solo sitio, con los cajones, al final del fichero. */
@media (max-width:1600px){.shell{grid-template-columns:var(--col-izq) minmax(0,1fr)}}
/* El menu ya no se esconde: se convierte en cajon (ver mas abajo). */
@media (max-width:720px){.shell{grid-template-columns:1fr}}

/* ══════════════════════════════════════════════════════════════════
   SHELL DE APP — layout transversal de 3 columnas (a pantalla completa)
   Barra superior + [menú fijo · contenido fluido y más claro · widgets fijo].
   Laterales de ancho FIJO; centro FLUIDO. Cada columna scrollea por dentro
   → el marco no se mueve al cambiar de vista, y ocupa toda la pantalla.

   Estructura HTML que usa cada pantalla:
     <div class="top-app"><div class="marca">Sabb<span class="dot">i</span>a</div>…</div>
     <div class="app">
       <nav  class="col col-izq" data-nav>…subnav propio opcional…</nav>
       <main class="col col-centro">… contenido …</main>
       <aside class="col col-der">… widgets …</aside>
     </div>
   y en el <head>:  <script src="../assets/nav.js" defer></script>
   y en su <style> local:  html,body{height:100%;overflow:hidden}
   ══════════════════════════════════════════════════════════════════ */
:root{ --col-izq:240px; --col-der:320px; --top-h:64px; }

.top-app{position:sticky;top:0;z-index:30;height:var(--top-h);display:flex;align-items:center;justify-content:space-between;padding:0 20px;background:rgba(255,255,255,.9);backdrop-filter:blur(8px);border-bottom:1px solid var(--linea)}
.top-app .marca{font-weight:var(--peso-fuerte);letter-spacing:-.01em;color:var(--grafito)}
.top-app .marca .dot{color:var(--agua)}

.app{display:grid;grid-template-columns:var(--col-izq) minmax(0,1fr) var(--col-der);height:calc(100vh - var(--top-h));overflow:hidden}
.col{overflow:auto;min-height:0}
.col-izq{background:var(--papel);border-right:1px solid var(--linea);padding:18px 14px}     /* menú · off-white cálido */
.col-centro{background:var(--blanco);padding:24px 28px}                                      /* contenido · el más claro (resalta) */
.col-der{background:var(--papel);border-left:1px solid var(--linea);padding:18px 16px}      /* widgets · off-white cálido */

/* Menú (columna izquierda) */
.nav-tit{font-size:11px;font-weight:var(--peso-medio);color:var(--gris);letter-spacing:.04em;text-transform:uppercase;margin:6px 8px 8px}
.nav a{display:block;padding:9px 12px;border-radius:8px;color:var(--grafito);text-decoration:none;font-size:14px;transition:var(--trans);cursor:pointer}
.nav a:hover{background:var(--arena-clara);color:var(--grafito)}
.nav a.act{background:var(--arena-clara);color:var(--agua-hondo);font-weight:var(--peso-medio)}

/* Widgets (columna derecha) */
.wtit{font-size:11px;font-weight:var(--peso-medio);color:var(--gris);letter-spacing:.04em;text-transform:uppercase;margin:6px 4px 10px}
.wcard{background:var(--blanco);border:1px solid var(--linea);border-radius:var(--radio);padding:14px;margin-bottom:14px}
.wrow{display:flex;justify-content:space-between;align-items:baseline;font-size:13.5px;padding:5px 0;color:var(--gris)}
.wrow b{color:var(--grafito);font-weight:var(--peso-medio)}

/* Responsive: se pliega la columna de widgets y luego el menú.
   Widgets a 1600 y no a 1100 (Gus, 30-09, tras probar en un MacBook Air:
   «en monitores de menos de 24 pulgadas siempre se oculta la columna
   derecha con un botón para abrirla»). A 1280 px los 560 px fijos de las
   dos columnas dejaban 705 al contenido y las tablas se salían. */
@media (max-width:1600px){ .app{grid-template-columns:var(--col-izq) minmax(0,1fr)} }
/* Idem para la reticula de la app. */
@media (max-width:720px){ .app{grid-template-columns:1fr} }

/* ══ RIEL DE NAVEGACIÓN — la columna izquierda de TODA la app ═══════
   Añadido el 24-07-2026. Suite (el home) ya usaba este riel de iconos
   con etiqueta mientras el resto de pantallas llevaba un menú de texto:
   dos lenguajes para lo mismo, y era lo primero que se movía de sitio al
   saltar de módulo. Gus pidió unificar y eligió el riel.

   Lo pinta assets/nav.js en cada pantalla (contenedor [data-nav]); desde
   el 30-09 también en Suite. Tres bandas: los módulos (.riel-sabbia), las
   secciones del módulo que declara la pantalla (.riel-modulo, con su
   .riel-ceja) y el pie. El aspecto se cambia SÓLO aquí.
   ────────────────────────────────────────────────────────────────── */
.riel{display:flex;flex-direction:column;align-items:stretch;gap:2px;min-height:100%}
.riel-sabbia,.riel-modulo{display:flex;flex-direction:column;align-items:stretch;gap:2px}
.riel .sep{height:1px;background:var(--linea);margin:10px 8px}
.riel .empuje{margin-top:auto}
.riel .riel-quien{font-size:12px;color:var(--gris);padding:0 12px 6px}
.riel-ceja{font-size:10px;font-weight:var(--peso-etq);letter-spacing:.14em;text-transform:uppercase;
  color:var(--gris-claro);padding:0 11px;margin:2px 0 4px}

.rail-item{display:flex;align-items:center;gap:11px;padding:8px 11px;
  border-radius:9px;color:var(--gris);cursor:pointer;text-decoration:none;
  transition:background var(--trans),color var(--trans)}
/* Las secciones que son botones (Mi empresa, RRHH, Usuarios) se ven igual
   que los enlaces: sin el marco ni la letra del navegador. */
button.rail-item{border:0;background:none;font:inherit;width:100%;text-align:left}
.rail-item:focus{outline:none}
.rail-item:focus-visible{outline:2px solid var(--agua-hondo);outline-offset:-2px}
.rail-item:hover{background:var(--arena-clara);color:var(--grafito)}
.rail-item.activo{background:var(--arena-clara);color:var(--agua-hondo)}
.rail-item .ico{width:20px;height:20px;flex:none}
.rail-item .et{font-size:13.5px;font-weight:var(--peso-medio);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* Poca altura (portátil de 13", Gus 30-09): si la pantalla tiene banda 2,
   los módulos se pliegan a una fila de iconos arriba —el nombre queda en
   el `title`— y las secciones del módulo conservan el suyo. Es la misma
   idea que la banda de la bandeja. A 1280×700 el riel de Suite pedía
   746 px en una columna de 636: Salir y las últimas secciones quedaban
   debajo. Por debajo de 720 de ancho el riel es cajón y no se pliega. */
@media (min-width:721px) and (max-height:820px){
  .con-modulo .riel-sabbia{flex-direction:row;flex-wrap:wrap;gap:2px}
  .con-modulo .riel-sabbia .sep,
  .con-modulo .riel > .riel-ceja:first-child{display:none}
  .con-modulo .riel-sabbia .rail-item{padding:8px}
  .con-modulo .riel-sabbia .rail-item .et{display:none}
}

/* ── La marca de la barra, al tamano de la barra nueva ──────────────────
   La barra paso de 56 a 64 px (peticion de Gus, 27-07). El disco y el
   nombre crecen con ella; si no, la cabecera se ve mas alta pero vacia.
   Van aqui y no inyectados desde nav.js: es el pendiente que quedaba
   apuntado —«mover a sabbia.css los estilos de la cabecera co-branded»— y
   se aprovecha para cerrarlo en la parte que toca a la marca de Sabbia. */
:root{--cabeza-marca-tam:34px}
.top-app .marca-sabbia .mk{width:var(--cabeza-marca-tam);height:var(--cabeza-marca-tam)}
.top-app .marca-sabbia .wm{font-size:27px;line-height:1}
@media (max-width:720px){
  :root{--cabeza-marca-tam:28px}
  .top-app .marca-sabbia .wm{font-size:22px}
}

/* ══ CAJONES LATERALES — las columnas de lado cuando no caben ══════
   Capa 2 del responsive (28-07-2026).

   DE DÓNDE VIENE. La capa 1 arregló el fallo gordo —aquí ponía
   `.col-izq{display:none}` y en un móvil te quedabas SIN NAVEGACIÓN—
   convirtiendo el menú en cajón. Pero aquel mecanismo sabía de UNA
   columna, la del armazón común, y las pantallas con retícula propia
   tienen las suyas: la bandeja de tres paneles, el visor con su barra de
   290 px sobre el lienzo. Esto lo generaliza.

   DOS LADOS Y DOS CORTES, porque no son el mismo problema:
     izq · 720  — el MENÚ. Por debajo no caben columna y contenido.
     der · 1600 — los WIDGETS. En Finanzas son los dos donuts que FILTRAN
                  la lista, así que ocultarlos no quitaba información:
                  quitaba una acción. Y sin decirlo. Era 1100 hasta el
                  30-09: en un portátil (MacBook Air, 1280-1470 px) la
                  columna fija dejaba el contenido en 705 px y las tablas
                  se salían; decisión de Gus, por debajo de 24" se pliega.

   EL ASPECTO CUELGA DE UNA CLASE (`.cajon-izq` / `.cajon-der`) y la pone
   assets/cajon.js. A propósito, y es la lección de la capa 1 llevada un
   paso más abajo: aquella versión escondía la columna por ancho y
   confiaba en que el botón llegase, o sea que un JS que no cargara volvía
   a dejarte sin navegación. Ahora el CSS no esconde nada por su cuenta:
   sin cajón, el menú se apila encima del contenido —incómodo, pero
   entero—. El peor caso es fealdad, no una pantalla muerta.

   `position:fixed` y no un panel dentro de la retícula: así el contenido
   no se reajusta al abrir y cerrar —que en un móvil se lee como un
   salto— y el cajón puede tapar sin empujar.

   Dos ajustes por pantalla, en CSS porque son de maquetación:
     --cajon-top    de dónde arranca (por defecto, bajo la barra común)
     --cajon-desde  cuánto se separa de su lado (el visor deja ver su riel)
   ─────────────────────────────────────────────── */
/* La CLASE dice quién es un cajón; el ANCHO dice cuándo lo es. Las dos
   cosas hacen falta, y separarlas fue el tropiezo de la primera versión de
   este bloque: la geometría estaba aquí arriba, sin media query, así que
   `assets/cajon.js` ponía la clase y el menú y los widgets se iban a
   `position:fixed` fuera de pantalla EN UN ORDENADOR. Presupuestos, Mi
   empresa e Importador se quedaron «en modo móvil» en una pantalla de 27
   pulgadas. Lo cazó Gus en dos minutos, mirando.

   Así que la geometría va DENTRO de cada corte, y se escribe dos veces a
   propósito: el cajón de la izquierda no puede ser fijo entre 721 y 1600
   —ahí el menú es una columna normal y sólo se plegan los widgets—, así
   que no son la misma regla con otro lado. Son dos reglas. */

/* El velo. Sólo existe mientras hay un cajón abierto, y un cajón sólo se
   abre desde un botón que por encima de su corte no se puede pulsar: por
   eso éste sí puede vivir fuera de las media queries. */
.velo-cajon { position: fixed; inset: var(--cajon-top, var(--top-h)) 0 0 0; z-index: 59;
              background: rgba(31,30,28,.38); border: 0; padding: 0; }

/* El botón del cajón. Sólo aparece por debajo de su corte; por encima la
   columna está a la vista y un botón para abrirla no significaría nada.
   `sin-nada` lo apaga cuando el panel está vacío —hay secciones sin
   widgets—: un botón que abre un panel en blanco es peor que no estar. */
.btn-cajon {
  display: none; align-items: center; justify-content: center;
  width: 38px; height: 38px; flex: none;
  border: 1px solid var(--linea); border-radius: var(--radio);
  background: var(--blanco); color: var(--grafito); cursor: pointer;
}
.btn-cajon:hover { background: var(--arena-clara); }
.btn-cajon svg { width: 18px; height: 18px; }
.btn-cajon.sin-nada { display: none !important; }

/* ── Por debajo de 1600: los widgets, a cajón ────────────────────
   Sin cajón siguen sin ocupar sitio, y no por pereza: la retícula pasa a
   dos columnas, así que una tercera columna en flujo caería a una segunda
   FILA de un `.app` de alto fijo y aplastaría la primera. */
@media (max-width: 1600px) {
  .col-der { display: none; }
  .cajon-der {
    display: block;
    position: fixed; z-index: 60;
    top: var(--cajon-top, var(--top-h)); bottom: 0;
    right: var(--cajon-desde, 0);
    width: min(82vw, 320px);
    transform: translateX(101%);
    transition: transform .18s ease;
    will-change: transform;
  }
  .cajon-der.abierto { transform: none; box-shadow: 0 0 40px rgba(0,0,0,.22); }
  .btn-cajon-der { display: inline-flex; }
}

/* ── Por debajo de 720: el menú, a cajón ────────────────────── */
@media (max-width: 720px) {
  .cajon-izq {
    display: block;
    position: fixed; z-index: 60;
    top: var(--cajon-top, var(--top-h)); bottom: 0;
    left: var(--cajon-desde, 0);
    width: min(82vw, 320px);
    transform: translateX(-101%);      /* el 1% de más se come la sombra */
    transition: transform .18s ease;
    will-change: transform;
  }
  .cajon-izq.abierto { transform: none; box-shadow: 0 0 40px rgba(0,0,0,.22); }
  .btn-cajon { display: inline-flex; }
  /* Y el contenido, a ancho completo con aire de móvil. */
  .col-centro { padding: 16px 14px; }
}

/* ══ LA CAMPANA — el grano de arena que cae al agua ════════════════
   Las notificaciones de la casa (29-07). La animación es EL GIF del
   diseño de Gus (assets/campana-onda.gif, 32px, transparente): el grano
   cae y la onda se expande. En calma se enseña su fotograma quieto
   (campana-quieta.png): sin pendientes NO se mueve nada — el movimiento
   significa, no decora. El cambio quieto⇄onda lo hace nav.js cambiando
   el src, no un CSS que anime encima del dibujo de otro.

   El número va en AGUA y no en rojo (decisión de Gus): el rojo de la
   casa es el del error, y una mención no es un error. */
/* Sin marco (Gus, 29-07): el dibujo ya ES el boton — un borde alrededor
   de una onda es una pecera. El hover lo dice con un halo suave. */
.campana { position: relative; width: 38px; height: 38px; flex: none;
  border: 0; border-radius: 50%;
  background: none; cursor: pointer; overflow: visible; padding: 0;
  transition: var(--trans); }
.campana:hover { background: var(--arena-clara); }
/* En calma, casi un fantasma (Gus, 29-07): gris y apenas perceptible —
   esta ahi para quien lo busque, no reclama nada. Con noticias, a todo
   color y con su onda. La transicion suaviza el despertar. */
.camp-img { width: 32px; height: 32px; display: block; margin: 2px auto;
  filter: grayscale(1) opacity(.28); transition: filter .4s ease; }
.campana.con-noticias .camp-img { filter: none; }
.campana:hover .camp-img { filter: grayscale(1) opacity(.55); }
.campana.con-noticias:hover .camp-img { filter: none; }
.camp-n { position: absolute; top: -5px; right: -5px; min-width: 15px; height: 15px;
  border-radius: 8px; background: var(--agua-hondo); color: var(--blanco);
  font-size: 9px; font-weight: var(--peso-fuerte); line-height: 15px; padding: 0 4px;
  box-shadow: 0 0 0 2px var(--blanco); }

/* El panel: la misma receta que los demas desplegables de la casa. */
.camp-panel { position: absolute; right: 12px; top: calc(100% + 6px); z-index: 45;
  width: min(340px, 92vw); max-height: 380px; overflow-y: auto;
  background: var(--papel); border: 1px solid var(--linea); border-radius: 10px;
  box-shadow: 0 6px 18px rgba(74,72,66,.12); padding: 8px; display: none; }
.camp-panel.abierto { display: block; }
.camp-panel .tit { font-size: 11px; font-weight: var(--peso-etq); letter-spacing: .04em;
  text-transform: uppercase; color: var(--gris); padding: 6px 8px 4px; }
.camp-fila { display: block; padding: 8px 9px; border-radius: 8px; text-decoration: none;
  color: var(--grafito); font-size: 13px; line-height: 1.35; }
.camp-fila:hover { background: var(--arena-clara); }
.camp-fila .de { font-weight: var(--peso-medio); }
.camp-fila .que { color: var(--gris); font-size: 12px; display: block;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.camp-nada { padding: 14px 9px; font-size: 12.5px; color: var(--gris); }

/* Que nada se salga por el lado. Una tabla ancha o un titulo largo empujan
   el ancho del documento y aparece el desplazamiento lateral, que en un
   movil es de las cosas que peor se sienten. */
@media (max-width: 720px) {
  html, body { max-width: 100%; overflow-x: hidden; }
  table { display: block; overflow-x: auto; }
  h1 { font-size: 19px; }
}
