/* ============================================================
   Savia · Finanzas del Vivero — hoja de estilos
   ============================================================ */
:root{
  /* Los tokens de la demo aprobada (docs/demo/rediseno-movil.html). En claro, cinco valores
     se corrigen para que las pastillas y los íconos pasen AA: la guarda de contraste de
     `pruebas/verificar.mjs` mide estos pares en los dos temas. */
  --page:#e2e8de; --bg:#edf1ea; --surface:#ffffff; --surface-2:#f4f7f1; --ink:#13211c; --ink-2:#5a6b63; --ink-3:#7a8981; --line:#dde5d9;
  --primary:#0b3d2e; --primary-ink:#ffffff; --accent:#0e7a55; --accent-soft:#e6f4ea; --lime:#d4f25a; --lime-ink:#0b3d2e;
  --ok:#0e7a55; --ok-soft:#e6f4ea; --warn:#8f5b00; --warn-soft:#fbedcf; --danger:#b23a25; --danger-soft:#fbe2dc; --danger-ink:#ffffff;
  --scrim:rgba(9,28,21,.42); --tabbar:rgba(255,255,255,.92); --shadow:0 22px 50px -26px rgba(11,61,46,.45);
  --banner:#0b3d2e; --banner-ink:#ffffff; --toast-ic:#d4f25a;
  /* La tercera serie de los gráficos: el primario en claro; en oscuro el primario es el mismo
     verde que el acento (gs-0), así que ahí pasa a la lima. */
  --serie-2:var(--primary);
  --fd:'Bricolage Grotesque',ui-sans-serif,system-ui,sans-serif; --fb:'Instrument Sans',ui-sans-serif,system-ui,-apple-system,'Segoe UI',sans-serif;
  /* estructura */
  --r-sm:6px; --r:10px; --r-lg:14px; --r-pill:999px;
  --sh-1:0 1px 2px rgba(14,28,22,.06);
}
/* El oscuro: igual al de la demo. Dos veces, con los mismos valores —la guarda lo exige—: por
   preferencia del sistema (salvo que el usuario haya elegido «Claro») y por elección explícita. */
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){
  --page:#070e0b; --bg:#0e1613; --surface:#151f1b; --surface-2:#1b2722; --ink:#e5ede7; --ink-2:#98aaa0; --ink-3:#6b7e74; --line:#25342e;
  --primary:#46d394; --primary-ink:#06251a; --accent:#46d394; --accent-soft:#173a2a; --lime:#d4f25a; --lime-ink:#0b3d2e;
  --ok:#46d394; --ok-soft:#173a2a; --warn:#f0b54a; --warn-soft:#382b11; --danger:#ff7c64; --danger-soft:#3b1d17; --danger-ink:#2a0d07;
  --scrim:rgba(0,0,0,.58); --tabbar:rgba(17,26,22,.92); --shadow:0 22px 50px -26px rgba(0,0,0,.8);
  --banner:#173a2a; --banner-ink:#e5ede7; --toast-ic:#0e7a55; --serie-2:var(--lime); color-scheme:dark}}
:root[data-theme="dark"]{
  --page:#070e0b; --bg:#0e1613; --surface:#151f1b; --surface-2:#1b2722; --ink:#e5ede7; --ink-2:#98aaa0; --ink-3:#6b7e74; --line:#25342e;
  --primary:#46d394; --primary-ink:#06251a; --accent:#46d394; --accent-soft:#173a2a; --lime:#d4f25a; --lime-ink:#0b3d2e;
  --ok:#46d394; --ok-soft:#173a2a; --warn:#f0b54a; --warn-soft:#382b11; --danger:#ff7c64; --danger-soft:#3b1d17; --danger-ink:#2a0d07;
  --scrim:rgba(0,0,0,.58); --tabbar:rgba(17,26,22,.92); --shadow:0 22px 50px -26px rgba(0,0,0,.8);
  --banner:#173a2a; --banner-ink:#e5ede7; --toast-ic:#0e7a55; --serie-2:var(--lime); color-scheme:dark}

*,*::before,*::after{box-sizing:border-box}
html,body{height:100%}
/* La barra de scroll reserva su lugar siempre. Sin esto, apagar el scroll del fondo para
   abrir un modal le saca la barra a la página y todo el contenido salta unos 15px a la
   derecha — y vuelve a saltar al cerrarlo. Es una línea de CSS en vez de medir el ancho de
   la barra desde JavaScript, que además no se puede hacer desde el DOM de las pruebas. */
html{scrollbar-gutter:stable}
body.con-overlay{overflow:hidden}
body{margin:0;background:var(--bg);color:var(--ink);font:400 15px/1.45 var(--fb);-webkit-font-smoothing:antialiased}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
@media (prefers-reduced-motion:reduce){*,*::before,*::after{animation:none!important;transition:none!important;scroll-behavior:auto!important}}
h1,h2,h3,h4{margin:0;font-family:var(--fd);font-weight:600;letter-spacing:-.01em}
p{margin:0}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit}
:where(input,select,textarea){font:inherit;color:inherit}
::selection{background:var(--accent-soft)}
.icon{width:18px;height:18px;stroke:currentColor;fill:none;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;flex:none}
.icon-sm{width:15px;height:15px}
.icon-lg{width:22px;height:22px}
.mono{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12.5px;letter-spacing:-.02em}
.num{font-variant-numeric:tabular-nums;white-space:nowrap}
.neg{color:var(--danger)}
.muted{color:var(--ink-2)}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}

/* ---------- armazón (mobile-first, como la demo) ----------
   La base es el celular: barra inferior fija y el contenido con aire abajo para que la barra no
   lo tape. Desde 720 px el riel de la izquierda; desde 1100 px la barra lateral de 264 px (los
   dos bloques de más abajo). Las barras van en la capa 20–25: el `.overlay` (85) y los avisos
   (90) quedan siempre encima. */
.app{min-height:100vh}
.main{min-width:0;padding-bottom:calc(104px + env(safe-area-inset-bottom,0px))}
.wrap{max-width:1240px;margin:0 auto;padding-left:max(16px, env(safe-area-inset-left,0px));padding-right:max(16px, env(safe-area-inset-right,0px))}
.side,.rail{display:none}
.view{padding-top:12px;padding-bottom:24px}
#view:focus{outline:none}
.view-card{animation:rise .28s ease both}
@keyframes rise{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}

/* el encabezado pegajoso: una fila que no se parte y no se sale */
.top{position:sticky;top:env(safe-area-inset-top,0px);z-index:20;background:var(--bg);border-bottom:1px solid transparent;transition:border-color .2s}
.top.scrolled{border-bottom-color:var(--line)}
.top-in{display:flex;align-items:center;gap:8px;min-height:62px;padding-top:8px;padding-bottom:8px}
.top-t{flex:1;min-width:0}
.eyebrow{margin:0;font:600 11.5px var(--fb);letter-spacing:.08em;text-transform:uppercase;color:var(--ink-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.top-t h1{margin:0;font:700 clamp(19px,5.6vw,23px)/1.1 var(--fd);letter-spacing:-.02em;text-wrap:balance;overflow-wrap:anywhere}
.top-t #page-sub{margin:2px 0 0;font-size:13px;color:var(--ink-2)}
.top-acts{display:flex;align-items:center;gap:6px;flex:none}
.brandmark{width:38px;height:38px;border-radius:13px;background:var(--primary);color:var(--lime);display:grid;place-items:center;flex:none}
.brandmark .icon{width:19px;height:19px}
.me{width:44px;height:44px;border-radius:14px;border:0;padding:0;cursor:pointer;background:var(--primary);color:var(--primary-ink);font:700 15px var(--fd);display:grid;place-items:center;flex:none}
.datechip{display:inline-flex;align-items:center;gap:6px;padding:7px 11px;border-radius:999px;background:var(--surface);border:1px solid var(--line);font-weight:600;font-size:13px;color:var(--ink-2);white-space:nowrap}
.datechip .icon{width:15px;height:15px;color:var(--accent)}
.gsearch{position:relative;display:none;flex:0 1 360px;min-width:0}
.gsearch>.icon{position:absolute;left:13px;top:22px;transform:translateY(-50%);color:var(--ink-3);pointer-events:none}
.gsearch input{padding-left:40px;min-height:44px}
/* La lista de resultados cae debajo del campo: por encima de la vista y debajo de las hojas (85). */
.gres{position:absolute;left:0;right:0;top:calc(100% + 6px);background:var(--surface);border:1px solid var(--line);border-radius:16px;box-shadow:var(--shadow);max-height:420px;overflow:auto;overscroll-behavior:contain;z-index:30;padding-bottom:8px}
.gres .bres-sec{margin:12px 14px 4px;min-height:0}
.gres .bres-group{margin:0 8px}
.busqueda-movil{margin-bottom:6px}
.busqueda-res .bres-sec{margin:16px 2px 6px;min-height:0}
.bres-group button.row:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}

/* la barra inferior del celular */
.tabbar{position:fixed;left:0;right:0;bottom:0;z-index:25;display:grid;grid-template-columns:repeat(5,minmax(0,1fr));align-items:center;padding:6px max(6px, env(safe-area-inset-right,0px)) calc(8px + env(safe-area-inset-bottom,0px)) max(6px, env(safe-area-inset-left,0px));background:var(--tabbar);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);border-top:1px solid var(--line)}
.tab{display:grid;justify-items:center;gap:3px;padding:6px 0;min-height:52px;min-width:0;border:0;background:none;cursor:pointer;color:var(--ink-2);font:600 11px var(--fb)}
.tab span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.tab .icon{width:23px;height:23px}
.tab[aria-current="page"]{color:var(--ink)}
.tab[aria-current="page"] .icon{color:var(--accent)}
.tab-new{justify-self:center;width:56px;height:56px;border-radius:18px;border:0;padding:0;cursor:pointer;background:var(--lime);color:var(--lime-ink);display:grid;place-items:center;box-shadow:var(--shadow)}
.tab-new .icon{width:27px;height:27px;stroke-width:2.3}

/* el riel (tablet) y la barra lateral (PC) */
.rail{position:fixed;top:0;bottom:0;left:0;z-index:25;width:calc(92px + env(safe-area-inset-left,0px));padding:calc(14px + env(safe-area-inset-top,0px)) 8px 14px calc(8px + env(safe-area-inset-left,0px));background:var(--surface);border-right:1px solid var(--line);flex-direction:column;align-items:center;gap:6px}
.rail .brandmark{margin-bottom:8px}
.rail .tab-new{width:52px;height:52px;margin-bottom:10px}
.rail-i{display:grid;justify-items:center;gap:4px;width:76px;padding:9px 2px;border:0;border-radius:16px;background:none;cursor:pointer;color:var(--ink-2);font:600 11.5px var(--fb);text-align:center}
.rail-i .icon{width:23px;height:23px}
.rail-i:hover{background:var(--surface-2)}
.rail-i[aria-current="page"]{background:var(--accent-soft);color:var(--ink)}
.rail-i[aria-current="page"] .icon{color:var(--accent)}
.side{position:fixed;top:0;bottom:0;left:0;z-index:25;width:264px;padding:18px 14px 14px;background:var(--surface);border-right:1px solid var(--line);flex-direction:column;overflow-y:auto}
.side-brand{display:flex;align-items:center;gap:10px;padding:2px 6px 16px}
.side-brand b{display:block;font:700 19px/1.1 var(--fd)}
.side-brand small{color:var(--ink-2);font-size:12.5px}
.side nav{display:grid;gap:2px}
.side h2{margin:16px 10px 6px;font:700 11px var(--fb);letter-spacing:.09em;text-transform:uppercase;color:var(--ink-2)}
.side-i{display:flex;align-items:center;gap:10px;min-height:44px;padding:0 10px;border:0;border-radius:12px;background:none;cursor:pointer;color:var(--ink-2);font:600 14px var(--fb);text-align:left;width:100%}
.side-i .icon{width:19px;height:19px}
.side-i:hover{background:var(--surface-2);color:var(--ink)}
.side-i[aria-current="page"]{background:var(--accent-soft);color:var(--ink)}
.side-i[aria-current="page"] .icon{color:var(--accent)}
.side-i em{margin-left:auto;font-style:normal;font-size:12px;font-weight:700;color:var(--warn);background:var(--warn-soft);padding:2px 7px;border-radius:99px}
.side-foot{margin-top:auto;padding-top:16px;display:grid;gap:10px}
.profile{display:flex;align-items:center;gap:10px;padding:10px;border-radius:14px;background:var(--surface-2);border:1px solid var(--line);text-align:left;width:100%;cursor:pointer;color:var(--ink);font:inherit}
.profile .row-main b{font-size:14px}

/* la subnavegación (segmentado con scroll) y el selector de tema */
.seg{display:flex;gap:2px;background:var(--surface-2);border:1px solid var(--line);border-radius:14px;padding:3px;overflow-x:auto;scrollbar-width:none}
.seg::-webkit-scrollbar{display:none}
.seg button,.seg label{flex:1 0 auto;min-height:44px;padding:8px 13px;border:0;border-radius:11px;background:none;font:600 13.5px var(--fb);color:var(--ink-2);white-space:nowrap;display:grid;place-items:center;cursor:pointer}
.seg button:hover{color:var(--ink)}
.seg button[aria-current="page"],.seg button.on,.seg label:has(input:checked){background:var(--surface);color:var(--ink);box-shadow:0 0 0 1px var(--line)}
.seg input{position:absolute;opacity:0;width:1px;height:1px}
.seg label:has(input:focus-visible){outline:2px solid var(--accent);outline-offset:1px}
.subnav{margin:4px 0 14px}

/* listas agrupadas, títulos de sección, pastillas (los de la demo: «Más» y las listas) */
.sec{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:24px 2px 9px;min-height:28px}
.sec h2,.sec h3{margin:0;font:700 12px var(--fb);letter-spacing:.08em;text-transform:uppercase;color:var(--ink-2)}
.link{color:var(--accent);font-weight:600;font-size:13.5px;white-space:nowrap;flex:none;min-height:44px;display:inline-flex;align-items:center;gap:4px;background:none;border:0;cursor:pointer;font-family:inherit}
.link .icon{width:16px;height:16px}
.group{background:var(--surface);border:1px solid var(--line);border-radius:18px;overflow:hidden}
.row{display:flex;align-items:center;gap:12px;padding:12px 14px;width:100%;text-align:left;min-height:60px;border:0;background:none;color:inherit;font:inherit}
button.row{cursor:pointer}
.group>.row+.row,.group>*+.row{border-top:1px solid var(--line)}
button.row:hover{background:var(--surface-2)}
.row-main{flex:1;min-width:0}
.row-main b{display:block;font-weight:600;font-size:15px;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.row-main small{display:block;color:var(--ink-2);font-size:13px;margin-top:1px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.row-end{text-align:right;flex:none;display:grid;justify-items:end;gap:4px;max-width:52%}
.row-end b{display:block;font:700 15px var(--fd);white-space:nowrap;font-variant-numeric:tabular-nums}
.row-end small{color:var(--ink-2);font-size:12px;white-space:nowrap}
.pos{color:var(--ok)}
.neg{color:var(--danger)}
.row-end b.muted{color:var(--ink-2);font:600 13.5px var(--fb)}
.chev{color:var(--ink-3)}
.ri{width:40px;height:40px;border-radius:13px;display:grid;place-items:center;flex:none;background:var(--accent-soft);color:var(--accent)}
.ri.warn{background:var(--warn-soft);color:var(--warn)}
.ri.danger{background:var(--danger-soft);color:var(--danger)}
.ri.n{background:var(--surface-2);color:var(--ink-2)}
.ri .icon{width:19px;height:19px}
.ava{width:40px;height:40px;border-radius:14px;display:grid;place-items:center;flex:none;font:700 15px var(--fd);background:var(--accent-soft);color:var(--accent)}
.ava.lg{width:56px;height:56px;border-radius:18px;font-size:20px}
/* La pastilla de la demo. `.badge` —la de las pantallas que todavía la emiten con `badge()`— es
   un alias: misma forma y los mismos tokens, así que se lee en claro y en oscuro (antes llevaba
   bordes con literales claros que en el oscuro quedaban como un recuadro brillante). */
.pill,.badge{display:inline-flex;align-items:center;gap:4px;font:600 11.5px/1 var(--fb);padding:5px 8px;border-radius:999px;background:var(--surface-2);color:var(--ink-2);white-space:nowrap;border:1px solid var(--line)}
.pill.ok,.badge.ok{background:var(--ok-soft);color:var(--ok);border-color:transparent}
/* `info` (cliente, recibida) se distingue de `ok` (ambos, conciliada): fondo de superficie, texto
   pleno y borde de acento —pares ya medidos por la guarda: `--ink` sobre `--surface`—. */
.badge.info{background:var(--surface);color:var(--ink);border-color:var(--accent)}
.pill.warn,.badge.warn{background:var(--warn-soft);color:var(--warn);border-color:transparent}
.pill.danger,.badge.danger{background:var(--danger-soft);color:var(--danger);border-color:transparent}
.pill.lime{background:var(--lime);color:var(--lime-ink);border-color:transparent}
.mas-perfil{margin-top:4px}
.mas-salir{margin-top:22px}

/* la hoja «Cargar…» */
.create-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
.create{display:flex;align-items:center;gap:11px;padding:13px;min-height:64px;border-radius:16px;background:var(--surface-2);border:1px solid var(--line);text-align:left;min-width:0;cursor:pointer;color:var(--ink);font:inherit}
.create:hover{border-color:var(--accent)}
.create .ri{width:38px;height:38px}
.create span{min-width:0}
.create b{display:block;font-size:14.5px}
.create small{display:block;color:var(--ink-2);font-size:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* la Ayuda (`assets/ayuda.js`): el índice con su buscador y el artículo. Los moldes son los de
   «Más» (`.sec`, `.group`, `button.row`) y de las listas (`.search`); acá sólo lo propio. */
.ayuda-perdido{margin-bottom:4px}
.ayuda-estado{margin:10px 2px 0;color:var(--ink-2);font-size:13px}
.ayuda-indice .sec:first-child{margin-top:12px}
/* El título y el resumen de un artículo se leen enteros: en la Ayuda no se cortan con «…». */
.ayuda .group .row-main b,.ayuda .group .row-main small{white-space:normal;overflow-wrap:anywhere}
.ayuda-art .eyebrow{margin-top:6px}
.ayuda-titulo{font-size:22px;line-height:1.25;margin-top:4px;overflow-wrap:anywhere}
.ayuda-resumen{color:var(--ink-2);font-size:15px;margin-top:6px}
.ayuda-cuerpo{margin-top:16px;display:grid;gap:12px;font-size:15px;line-height:1.55;overflow-wrap:anywhere}
.ayuda-cuerpo h3{font-size:16px;margin-top:8px}
.ayuda-cuerpo ol,.ayuda-cuerpo ul{margin:0;padding-left:22px;display:grid;gap:6px}
.ayuda-cuerpo .notice{margin-top:0}
/* Un enlace a otro artículo, adentro de una oración: va en línea, como un enlace de texto (la
   excepción de los objetivos táctiles para lo que vive dentro de un párrafo). */
.ayuda-cuerpo .link{display:inline;min-height:0;padding:0;white-space:normal;font-size:inherit;text-decoration:underline;text-underline-offset:2px}
.ayuda-acciones{display:flex;flex-wrap:wrap;gap:8px;margin-top:18px}
.ayuda-acciones .btn{max-width:100%}
.ayuda-rol{margin-top:14px}

/* ---------- listas: barra, chips, conteo, tabla de la PC ---------- */
.toolbar{display:flex;gap:8px;align-items:center;margin-top:14px}
.search{position:relative;flex:1;min-width:0}
.search .icon{position:absolute;left:13px;top:50%;transform:translateY(-50%);color:var(--ink-3);pointer-events:none}
.search input{padding-left:40px}
/* En el celular los chips deslizan de borde a borde: el margen negativo es el del `.wrap` (16 px;
   24 en la tablet), así que la tira llega al borde de la pantalla sin desbordar la página. */
.chips{display:flex;gap:8px;overflow-x:auto;scrollbar-width:none;margin-left:-16px;margin-right:-16px;padding:12px 16px 2px}
.chips::-webkit-scrollbar{display:none}
.chip{display:inline-flex;align-items:center;gap:6px;flex:none;min-height:44px;padding:8px 14px;border-radius:999px;border:1px solid var(--line);background:var(--surface);font:600 13px var(--fb);color:var(--ink-2);white-space:nowrap;cursor:pointer}
.chip[aria-pressed="true"]{background:var(--primary);border-color:var(--primary);color:var(--primary-ink)}
.chip b{font-weight:700;margin-left:4px;opacity:.75}
.lista-cuenta{margin:12px 2px 8px;font-size:12.5px;color:var(--ink-2)}
.lista-vacia{margin-top:14px}
.tbl-wrap{overflow-x:auto;border:1px solid var(--line);border-radius:18px;background:var(--surface)}
.tbl-wrap table.tbl{font-size:14px}
.tbl-wrap table.tbl th{font:700 11.5px var(--fb);letter-spacing:.07em;padding:12px 14px;position:sticky;top:0}
.tbl-wrap table.tbl td{white-space:nowrap}
.tbl-wrap table.tbl td.envuelve{white-space:normal;min-width:140px}
/* Cheques tiene nueve columnas (las de la demo), y Movimientos, Transferencias y Gastos siete u
   ocho: con celdas un poco más angostas, y el concepto que envuelve, entran a 1280 sin desplazar
   la tabla. */
#lista-cheques .tbl-wrap table.tbl td.envuelve,#lista-movimientos_tesoreria .tbl-wrap table.tbl td.envuelve,
#lista-transferencias .tbl-wrap table.tbl td.envuelve,#lista-gastos_varios .tbl-wrap table.tbl td.envuelve{min-width:100px}
#lista-cheques .tbl-wrap table.tbl th,#lista-cheques .tbl-wrap table.tbl td,
#lista-movimientos_tesoreria .tbl-wrap table.tbl th,#lista-movimientos_tesoreria .tbl-wrap table.tbl td,
#lista-transferencias .tbl-wrap table.tbl th,#lista-transferencias .tbl-wrap table.tbl td,
#lista-gastos_varios .tbl-wrap table.tbl th,#lista-gastos_varios .tbl-wrap table.tbl td{padding-left:10px;padding-right:10px}
table.tbl td.r,table.tbl th.r{text-align:right}
table.tbl tbody tr[data-accion],table.tbl tbody tr[data-usuario]{cursor:pointer}
table.tbl tbody tr[data-accion]:focus-visible,table.tbl tbody tr[data-usuario]:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
/* Lo que el buscador esconde: `.row` (flex), `.empty` (grid) y los envoltorios declaran su
   `display`, que le gana al del atributo `hidden`. */
.row[hidden],tr[hidden],.empty[hidden],.lista-vacia[hidden],[data-pieles][hidden]{display:none}

/* ---------- botones ----------
   Los de la demo: 48 px de alto en todos lados (44 el chico), con las variantes como clases
   sueltas —`btn primary`, `btn ghost`, `btn danger`, `btn lime`, `btn sm`, `btn block`—. Quedan
   dos clases viejas como alias (`btn-ghost`, `btn-sm`) porque queda una pantalla que las emite
   (la de error, con «Ir al Panel»); `btn-primary` y `btn-danger` ya no las usa nadie. */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:48px;padding:0 18px;
  border:1px solid transparent;border-radius:14px;font-weight:600;font-size:15px;cursor:pointer;
  background:var(--surface);color:var(--ink);text-decoration:none;white-space:nowrap;
  transition:background .14s,border-color .14s,transform .05s
}
.btn:active{transform:translateY(1px)}
.btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.btn .icon{width:18px;height:18px}
.btn.primary{background:var(--primary);color:var(--primary-ink)}
.btn.ghost,.btn-ghost{background:var(--surface-2);color:var(--ink);border-color:var(--line)}
.btn.ghost:hover,.btn-ghost:hover{border-color:var(--ink-3)}
.btn.danger{background:var(--danger);color:var(--danger-ink)}
.btn.lime{background:var(--lime);color:var(--lime-ink)}
.btn.sm,.btn-sm{min-height:44px;padding:0 14px;font-size:14px;border-radius:12px}
.btn.block{width:100%}
.btn[disabled]{opacity:.5;cursor:not-allowed}
/* `.btn{display:inline-flex}` le gana al `display:none` que trae el atributo `hidden`,
   así que un botón con `hidden` se seguía viendo. */
.btn[hidden]{display:none}
.icon-btn{
  width:44px;height:44px;display:inline-grid;place-items:center;flex:none;border:1px solid transparent;background:transparent;
  border-radius:13px;color:var(--ink-2);cursor:pointer;transition:background .14s,color .14s
}
.icon-btn:hover{background:var(--surface-2);color:var(--ink)}
.icon-btn.danger:hover{background:var(--danger-soft);color:var(--danger)}

/* ---------- tarjetas ---------- */
.card{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--sh-1)}
.grid{display:grid;gap:16px}
.g-4{grid-template-columns:repeat(4,minmax(0,1fr))}

/* ---------- KPI ----------
   `.stats` de `.stat` es el de la demo (dos columnas en el celular, cuatro desde la tablet). `kpi()`
   emite un `.stat` suelto, que vive en las grillas `.g-4` de siempre. Los cuatro informes también
   lo usan (el `.kpi` viejo se fue con la Task 11). */
.stats{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;margin-top:14px}
.stat{background:var(--surface);border:1px solid var(--line);border-radius:16px;padding:12px 13px;min-width:0}
.stat span{display:block;font-size:12.5px;color:var(--ink-2);font-weight:600}
.stat b{display:block;font:700 18px/1.15 var(--fd);margin-top:4px;overflow-wrap:anywhere;letter-spacing:-.01em;font-variant-numeric:tabular-nums}
.stat small{display:block;font-size:12px;color:var(--ink-2);margin-top:3px}
.stat.hl{border-color:var(--accent)}
/* Los tonos de `kpi()`: una franja a la izquierda, como la tarjeta vieja —acento para el normal,
   aviso y peligro para las alertas—, con los tokens de los dos temas. */
.stat.k{box-shadow:inset 3px 0 0 var(--accent)}
.stat.k-amber{box-shadow:inset 3px 0 0 var(--warn);border-color:var(--warn)}
.delta{font-weight:600}
.delta.up{color:var(--ok)}
.delta.down{color:var(--danger)}

/* ---------- tablas ---------- */
table.tbl{width:100%;border-collapse:separate;border-spacing:0;font-size:13px}
table.tbl th{
  text-align:left;font-size:11px;letter-spacing:.07em;text-transform:uppercase;color:var(--ink-2);
  font-weight:600;padding:11px 14px;background:var(--surface-2);border-bottom:1px solid var(--line);white-space:nowrap
}
table.tbl td{padding:11px 14px;border-bottom:1px solid var(--line);vertical-align:middle}
table.tbl tbody tr{transition:background .12s}
table.tbl tbody tr:hover{background:var(--surface-2)}
table.tbl tbody tr:last-child td{border-bottom:0}
table.tbl td.right,table.tbl th.right{text-align:right}
table.tbl .main-cell{font-weight:600}
table.tbl .subline{font-size:11.5px;color:var(--ink-2);font-weight:400}

/* ---------- toolbar / filtros del legado ----------
   La barra de las cuatro pantallas que todavía viven dentro de una tarjeta (comprobantes, remitos,
   cobros y pagos, cheques; Tasks 6–8): con su relleno y su borde, y el buscador acotado. */
.card>.toolbar{flex-wrap:wrap;gap:10px;margin-top:0;padding:14px 18px;border-bottom:1px solid var(--line)}
.card>.toolbar .search{min-width:210px;max-width:340px}
/* Los campos de la demo: 48 px de alto y 16 px de letra en todos los anchos —con menos de 16 el
   iOS amplía la página al enfocar—. Van envueltos en `:where()` para no sumar especificidad: así
   los retoques de cada contexto (`.search input`, `.it-f input`) siguen ganando
   con una sola clase, como antes. */
:where(input:not([type=checkbox]):not([type=radio]):not([type=file]),select,textarea){
  width:100%;min-width:0;min-height:48px;font:500 16px var(--fb);padding:11px 14px;border-radius:13px;
  border:1px solid var(--line);background-color:var(--surface-2);color:var(--ink);-webkit-appearance:none;appearance:none
}
:where(select){background-image:linear-gradient(45deg,transparent 50%,var(--ink-3) 50%),linear-gradient(135deg,var(--ink-3) 50%,transparent 50%);background-position:calc(100% - 18px) 52%,calc(100% - 13px) 52%;background-size:5px 5px;background-repeat:no-repeat;padding-right:34px}
:where(textarea){resize:vertical;min-height:84px}
:where(input[readonly]){color:var(--ink-2)}
select:focus,input:focus,textarea:focus{outline:none;border-color:var(--accent);background-color:var(--surface)}
select:focus-visible,input:focus-visible,textarea:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
input[aria-invalid="true"],select[aria-invalid="true"],textarea[aria-invalid="true"]{border-color:var(--danger)}
.count-pill{font-size:12px;color:var(--ink-2);background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-pill);padding:4px 11px}

/* ---------- formularios ---------- */
.form-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px}
.field{display:flex;flex-direction:column;gap:6px;min-width:0}
.field.w2{grid-column:span 2}
.field.w3{grid-column:span 3}
.field label{font-size:13px;font-weight:600;color:var(--ink-2)}
.field label .req{color:var(--danger)}
.field .hint{font-size:12.5px;color:var(--ink-2)}
/* La grilla de los formularios de la demo: 2 columnas en el celular, 4 en la tablet y 6 en la
   hoja `form` de la PC. Un campo ocupa 2 (todo el ancho en el celular); `w-half`, 1; `w2`, todo
   el ancho hasta la PC y 4 de 6 ahí; `w3`, siempre todo. */
.fgrid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px 10px}
.fgrid>.field{grid-column:span 2}
.fgrid>.field.w-half{grid-column:span 1}
.fgrid>.field.w2{grid-column:span 2}
.fgrid>.field.w3{grid-column:1/-1}
.field .lbl{font-size:13px;font-weight:600;color:var(--ink-2)}
/* El segmentado dentro de un campo: radios con su etiqueta al lado (no envuelta), así cada
   opción tiene su `for`. */
.field .seg label{font:600 13.5px var(--fb);color:var(--ink-2)}
.seg input:checked+label{background:var(--surface);color:var(--ink);box-shadow:0 0 0 1px var(--line)}
.seg input:focus-visible+label{outline:2px solid var(--accent);outline-offset:1px}
.check{display:flex;align-items:center;gap:8px;padding-top:22px}
.check input{width:16px;height:16px;accent-color:var(--accent)}
.err{border-color:var(--danger)!important;box-shadow:0 0 0 3px var(--danger-soft)!important}

/* ---------- hojas: modal, submodal y cajón ----------
   Mobile-first, como la demo (`docs/demo/rediseno-movil.html`, `.sheet`): en el celular y la
   tablet todo lo que se abre encima es una HOJA que sube desde abajo —con su asa `.grab`,
   redondeada sólo arriba—; desde 1100 px (el bloque de la PC, más abajo) los formularios, los
   menús y las confirmaciones son un diálogo centrado y la ficha (`.drawer`) un panel a la derecha.

   El armazón es una columna de tres bloques: encabezado, cuerpo y pie. El único que scrollea es
   el cuerpo —`flex:1;min-height:0;overflow:auto`—, y por eso el encabezado y las acciones quedan
   a la vista siempre. El tope se mide en `dvh`, que sí se encoge cuando sube el teclado del
   celular (el `vh` de la línea de antes es el respaldo para el navegador que no lo entienda), y
   descuenta el notch del iPhone (`safe-area-inset-top`); el pie suma la barra gestual.

   `z-index:85` no es arbitrario: las barras viven entre 20 y 25 (el menú lateral del celular en
   80) y los avisos en 90. La hoja tapa todo lo de atrás y queda debajo de los avisos, que son lo
   que dice si la escritura salió bien. El modal y el cajón comparten la capa: el modal queda
   encima porque `#modal-root` va después de `#drawer-root` en el documento. */
.overlay{position:fixed;inset:0;z-index:85;background:var(--scrim);animation:fade .22s ease both}
@keyframes fade{from{opacity:0}to{opacity:1}}
.modal{position:absolute;left:0;right:0;bottom:0;margin:0 auto;width:100%;max-width:760px;display:flex;flex-direction:column;max-height:calc(100vh - 24px);max-height:calc(100dvh - 24px - env(safe-area-inset-top,0px));background:var(--surface);color:var(--ink);border-radius:26px 26px 0 0;box-shadow:var(--shadow);outline:none;animation:hoja .26s cubic-bezier(.2,.8,.2,1) both}
/* El formulario ocupa todo el alto disponible: no salta de tamaño cuando agrega un ítem. */
.hoja-form{height:calc(100vh - 24px);height:calc(100dvh - 24px - env(safe-area-inset-top,0px))}
@keyframes pop{from{opacity:0;transform:translateY(10px) scale(.99)}to{opacity:1;transform:none}}
/* La hoja entra subiendo desde el borde de abajo, que es de donde viene: 260 ms con la curva de
   la demo. Con `prefers-reduced-motion` la regla de arriba de todo apaga la animación. */
@keyframes hoja{from{transform:translateY(100%)}to{transform:none}}
@keyframes dialogo{from{opacity:0;transform:translate(-50%,-46%)}to{opacity:1;transform:translate(-50%,-50%)}}
@keyframes panel{from{transform:translateX(100%)}to{transform:none}}
.grab{width:40px;height:5px;border-radius:9px;background:var(--line);margin:8px auto 2px;flex:none}
.modal-hd{display:flex;gap:12px;align-items:flex-start;justify-content:space-between;margin:0 18px;padding:8px 0 12px;border-bottom:1px solid var(--line);flex:none}
.modal-tt{min-width:0}
.modal-hd h2{margin:0;font:700 21px/1.15 var(--fd);letter-spacing:-.01em;overflow-wrap:anywhere}
.modal-hd p{margin:3px 0 0;color:var(--ink-2);font-size:13.5px}
.modal-hd .icon-btn{margin-left:auto;margin-top:-6px;margin-right:-8px}
.modal-bd{flex:1;min-height:0;overflow:auto;overscroll-behavior:contain;padding:14px 18px 22px}
.modal-ft{flex:none;display:flex;flex-wrap:wrap;gap:10px;align-items:center;padding:12px 18px;padding-bottom:calc(12px + env(safe-area-inset-bottom,0px));border-top:1px solid var(--line);background:var(--surface)}
.modal-ft .note{flex:1 1 100%;font-size:12.5px;color:var(--ink-2)}
.modal-ft .note:empty{display:none}
.modal-ft .btn{flex:1}
.modal-ft .btn.ghost{flex:0 1 auto}
/* Sin pie, el cuerpo es el que respeta la barra gestual. */
.modal-bd:last-child{padding-bottom:calc(22px + env(safe-area-inset-bottom,0px))}
.confirm-ic{width:52px;height:52px;border-radius:16px;display:grid;place-items:center;background:var(--danger-soft);color:var(--danger);margin-bottom:12px}
.confirm-ic .icon{width:24px;height:24px}
.confirm-msg{margin:0 0 6px;font-weight:600;overflow-wrap:anywhere}
/* «No se puede borrar»: la lista de lo que depende del registro. */
.deps{margin:0 0 10px;padding-left:20px;color:var(--ink)}
.deps li{margin:2px 0;overflow-wrap:anywhere}
.modal-bd .muted+.deps{margin-top:6px}

/* ---------- cajón (la ficha de un registro) ----------
   La misma hoja, de alto completo, con una barra de acciones fija opcional (`.drawer-ft`). */
.drawer{position:absolute;left:0;right:0;bottom:0;margin:0 auto;width:100%;max-width:760px;display:flex;flex-direction:column;height:calc(100vh - 24px);height:calc(100dvh - 24px - env(safe-area-inset-top,0px));background:var(--surface);color:var(--ink);border-radius:26px 26px 0 0;box-shadow:var(--shadow);outline:none;animation:hoja .26s cubic-bezier(.2,.8,.2,1) both}
.drawer-hd{display:flex;gap:12px;align-items:flex-start;margin:0 18px;padding:8px 0 12px;border-bottom:1px solid var(--line);flex:none}
.drawer-tt{min-width:0;flex:1}
.drawer-hd .icon-btn{margin-left:auto;margin-top:-6px;margin-right:-8px}
.drawer-bd{flex:1;min-height:0;overflow:auto;overscroll-behavior:contain;padding:14px 18px 22px}
.drawer-bd:last-child{padding-bottom:calc(22px + env(safe-area-inset-bottom,0px))}
.drawer-ft{flex:none;display:flex;flex-wrap:wrap;gap:10px;padding:12px 18px;padding-bottom:calc(12px + env(safe-area-inset-bottom,0px));border-top:1px solid var(--line);background:var(--surface)}
.drawer-ft .btn{flex:1}
/* La ficha de la demo: el héroe, la grilla de acciones y los datos en pares. */
.ficha-tt{margin:0;font:700 21px/1.15 var(--fd);letter-spacing:-.01em;overflow-wrap:anywhere}
.fhero{display:grid;gap:10px;padding:16px;background:var(--surface-2);border:1px solid var(--line);border-radius:20px}
.fhero-h{display:flex;gap:12px;align-items:center;min-width:0}
.fhero small.k{display:block;font-size:12px;color:var(--ink-2);font-weight:700;letter-spacing:.06em;text-transform:uppercase}
.fhero .big{font:700 30px/1.1 var(--fd);letter-spacing:-.01em;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}
.fhero-pills{display:flex;flex-wrap:wrap;gap:6px}
.acts{display:grid;grid-template-columns:repeat(auto-fit,minmax(96px,1fr));gap:8px;margin-top:12px}
.act{display:grid;justify-items:center;align-content:center;gap:6px;padding:12px 6px;min-height:72px;border-radius:16px;background:var(--surface);border:1px solid var(--line);font:600 12.5px var(--fb);color:var(--ink);text-align:center;cursor:pointer}
.act .icon{color:var(--accent)}
.act.dz .icon{color:var(--danger)}
.act:hover{background:var(--surface-2)}
div.kv{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}
div.kv>div{background:var(--surface-2);border-radius:12px;padding:9px 11px;min-width:0}
div.kv small{display:block;font-size:11.5px;color:var(--ink-2);font-weight:600}
div.kv b{display:block;font-weight:600;font-size:14px;overflow-wrap:anywhere}
div.kv .wide{grid-column:1/-1}
.it-line{display:flex;justify-content:space-between;gap:12px;padding:11px 14px;align-items:flex-start}
.it-line+.it-line{border-top:1px solid var(--line)}
.it-line .row-main b,.it-line .row-main small{white-space:normal;overflow-wrap:anywhere}
.it-line .q{color:var(--ink-2);font-weight:600;margin-right:4px}
.it-line .amt{font:700 15px var(--fd);flex:none}
.subtot{display:flex;justify-content:space-between;padding:10px 14px;background:var(--surface-2);border-top:1px solid var(--line);font-size:13.5px;color:var(--ink-2)}
.subtot b{color:var(--ink);font-variant-numeric:tabular-nums}
.subtot.grand{background:var(--primary);color:var(--primary-ink)}
.subtot.grand b{color:var(--primary-ink);font:700 18px var(--fd)}
.memo{margin-top:10px;padding:12px 14px;border-radius:14px;background:var(--surface-2);border:1px dashed var(--line);font-size:13.5px;color:var(--ink-2)}
.tl{list-style:none;margin:0;padding:4px 0 0 4px}
.tl li{position:relative;padding:0 0 16px 26px}
.tl li::before{content:"";position:absolute;left:6px;top:16px;bottom:-2px;width:2px;background:var(--line)}
.tl li:last-child::before{display:none}
.tl li::after{content:"";position:absolute;left:0;top:4px;width:14px;height:14px;border-radius:50%;background:var(--surface);border:3px solid var(--accent)}
.tl li.danger::after{border-color:var(--danger)}
.tl li.last::after{background:var(--accent)}
.tl b{display:block;font-weight:600}
.tl small{display:block;color:var(--ink-2);font-size:13px}
/* Los pares de las fichas que todavía no pasaron a la de la demo (comprobante, pago, cheque,
   usuario): un `<dl>` de dos columnas. */
dl.kv{display:grid;grid-template-columns:150px 1fr;gap:9px 14px;font-size:13px}
dl.kv dt{color:var(--ink-2);font-size:12.5px}
dl.kv dd{margin:0;font-weight:500}

/* ---------- estados vacíos, avisos / carga ---------- */
.empty{display:grid;justify-items:center;gap:6px;text-align:center;padding:30px 18px;color:var(--ink-2);font-size:14px}
.empty .icon{width:30px;height:30px;color:var(--ink-3);stroke-width:1.5}
.empty b{color:var(--ink);font-size:15px}
.empty .btn{margin-top:6px}
/* Los vacíos del legado, con título y párrafo. */
.empty h4{margin:6px 0 0;font-size:16px;color:var(--ink)}
.empty p{font-size:13px;max-width:380px;margin:0 auto 8px}
.notice{display:flex;gap:10px;align-items:flex-start;margin-top:12px;padding:11px 12px;border-radius:14px;background:var(--accent-soft);color:var(--ink);font-size:13.5px}
.notice .icon{color:var(--accent);margin-top:1px;flex:none}
.notice p{margin:0;flex:1;min-width:0}
.notice.warn{background:var(--warn-soft)}
.notice.warn .icon{color:var(--warn)}
.skel{padding:16px 18px;display:flex;flex-direction:column;gap:10px}
.sk{height:14px;border-radius:var(--r-sm);background:linear-gradient(90deg,var(--surface-2) 25%,var(--line) 37%,var(--surface-2) 63%);background-size:400% 100%;animation:shimmer 1.2s infinite}
@keyframes shimmer{from{background-position:100% 0}to{background-position:0 0}}

/* ---------- toasts ---------- */
/* Abajo y al centro, por encima de la barra inferior del celular, como la demo. Con una hoja
   abierta (`body.con-overlay`) suben: abajo taparían el pie con «Guardar» justo cuando la
   escritura falla —los avisos viven en la capa 90 y la hoja en la 85—. */
.toast-root{position:fixed;left:50%;transform:translateX(-50%);bottom:calc(92px + env(safe-area-inset-bottom,0px));z-index:90;display:flex;flex-direction:column;gap:8px;align-items:center;width:max-content;max-width:calc(100% - 32px);pointer-events:none}
body.con-overlay .toast-root{top:calc(12px + env(safe-area-inset-top,0px));bottom:auto}
.toast{background:var(--ink);color:var(--bg);border-radius:14px;padding:12px 16px;font-size:14px;font-weight:600;box-shadow:var(--shadow);display:flex;gap:8px;align-items:center;max-width:100%;pointer-events:auto;animation:pop .18s ease both}
.toast .icon{color:var(--toast-ic)}
.toast.warn{background:var(--warn-soft);color:var(--ink);border:1px solid var(--warn)}
.toast.warn .icon{color:var(--warn)}
.toast.err{background:var(--danger);color:var(--danger-ink)}
.toast.err .icon{color:currentColor}


/* ---------- submodal (alta rápida desde un desplegable) ---------- */
/* Se apila adentro del modal: un velo sobre el formulario de atrás y otra hoja que sube encima.
   En la PC es un diálogo centrado sobre el del formulario. */
.submodal{position:absolute;inset:0;z-index:5;padding:0;background:var(--scrim);border-radius:inherit;animation:fade .2s ease both}
/* El submodal usa las mismas tres clases que el modal —`.modal-hd`, `.modal-bd` y
   `.modal-ft`—, así que hereda el encabezado y el pie fijos y el scroll único que arregló
   el armazón. Lo único que le falta es que SU contenedor sea una columna: antes scrolleaba
   entero (`max-height:92%;overflow:auto`), lo que con el cuerpo del modal detrás daba tres
   scrolls anidados. */
.submodal-bd{position:absolute;left:0;right:0;bottom:0;width:100%;max-width:none;max-height:calc(100% - 24px);display:flex;flex-direction:column;overflow:hidden;background:var(--surface);border-radius:26px 26px 0 0;box-shadow:var(--shadow);outline:none;animation:hoja .26s cubic-bezier(.2,.8,.2,1) both}
.submodal .form-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
.submodal .field.w3{grid-column:span 2}

/* ---------- lista de ítems ----------
   Mobile-first, como la demo (`.it`): en el celular y la tablet cada `.it-row` es una TARJETA —un
   encabezado «Ítem N» con el subtotal y la papelera de 44 px, el producto entero, y cantidad,
   precio e IVA (en el remito: cantidad, unidad y valor) en una fila de tres, que es la `.it-nums`
   de la demo hecha con áreas de grilla—. El detalle se pliega detrás del renglón de abajo: es lo
   que `prodCambio()` ya trajo del producto al elegirlo.

   No hay envoltorios en el marcado: los ocho hijos de la fila son los siete campos y el renglón,
   en el orden de las columnas. Por eso en la PC (el bloque de 1100 px, dentro de la hoja `form`)
   la misma fila es un renglón de la grilla de `--it-cols`, alineado con el encabezado
   `.items-hd`, sin que nadie cuente píxeles a mano. Las columnas se declaran UNA vez, en la clase
   del contenedor, y las comparten el encabezado y cada fila. */
.items{counter-reset:item}
#items-body{display:grid;gap:10px}
.items-comp{--it-cols:26% 1fr 78px 108px 76px 108px 44px}
.items-rem{--it-cols:26% 1fr 78px 92px 108px 108px 44px}
.items-hd{display:none}
.it-row{position:relative;counter-increment:item;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));grid-template-areas:"h sub sub" "prod prod prod" "n1 n2 n3";gap:10px 8px;align-items:end;padding:12px;border:1px solid var(--line);border-radius:16px;background:var(--surface)}
.it-row::before{content:"Ítem " counter(item);grid-area:h;align-self:center;font-size:12px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-2)}
.it-f{display:grid;gap:6px;min-width:0}
.it-l{display:block;font-size:13px;font-weight:600;color:var(--ink-2)}
.it-c-prod{grid-area:prod}
.it-c-desc{grid-column:1/-1}
.it-c-cant{grid-area:n1}
.items-comp .it-c-precio{grid-area:n2}
.items-comp .it-c-iva{grid-area:n3}
.items-rem .it-c-unidad{grid-area:n2}
.items-rem .it-c-precio{grid-area:n3}
.it-c-cant input,.it-c-precio input,.it-c-iva select,.it-c-unidad select{padding-left:10px;padding-right:10px}
.it-c-iva select,.it-c-unidad select{padding-right:28px}
/* El subtotal va en el encabezado de la tarjeta, a la derecha, y deja 48 px libres: ahí está
   la papelera. Su rótulo lo lee el lector de pantalla; a la vista, el número alcanza. */
.it-c-sub{grid-area:sub;justify-self:end;align-self:center;padding-right:48px;font:700 15px var(--fd);font-variant-numeric:tabular-nums;color:var(--ink)}
.it-c-sub .it-l{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
/* La papelera, clavada en la esquina de arriba a la derecha de la tarjeta, en el renglón del
   encabezado: lejos del desplegable de producto, que va en el renglón de abajo. */
.it-c-x{position:absolute;top:6px;right:6px}
.it-row:not(.abierto) .it-c-desc{display:none}
.it-mas{display:flex;grid-column:1/-1;align-items:center;gap:6px;width:100%;min-height:44px;padding:4px 0 0;border:0;border-top:1px dashed var(--line);background:none;font:600 13.5px var(--fb);color:var(--accent);cursor:pointer;text-align:left}
.it-mas-flecha{font-size:11px;color:var(--ink-3)}
.addline{display:inline-flex;align-items:center;gap:6px;min-height:44px;margin-top:6px;padding:0 4px;border:0;background:none;font:600 14px var(--fb);color:var(--accent);cursor:pointer}
/* Los totales de la demo: renglones sobre `--surface-2` y el total en el verde de la marca. */
.totbox{margin-top:14px;border-radius:16px;overflow:hidden;border:1px solid var(--line)}
.totbox>div{display:flex;justify-content:space-between;gap:10px;padding:10px 14px;font-size:14px;color:var(--ink-2);background:var(--surface-2)}
.totbox>div+div{border-top:1px solid var(--line)}
.totbox b{color:var(--ink);font-variant-numeric:tabular-nums}
.totbox .grand{background:var(--primary);color:var(--primary-ink);align-items:baseline}
.totbox .grand b{font:700 21px var(--fd);color:var(--primary-ink)}
.fsec{margin:22px 0 10px;font:700 12px var(--fb);letter-spacing:.08em;text-transform:uppercase;color:var(--ink-2);display:flex;align-items:baseline;justify-content:space-between;gap:10px;flex-wrap:wrap}
.fsec small{font:500 12.5px var(--fb);letter-spacing:0;text-transform:none}
.fact-items{margin-top:2px}

/* ---------- medios de un cobro o pago (las tarjetas `.it` de la demo) ---------- */
.its{display:grid;gap:10px}
.it{border:1px solid var(--line);border-radius:16px;padding:12px;display:grid;gap:10px;background:var(--surface);min-width:0}
.it>.field{grid-column:1/-1}
.it [hidden]{display:none!important}
.it-h{display:flex;justify-content:space-between;align-items:center;font-size:12px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-2)}
.it-nums{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}
.it-nums.two{grid-template-columns:repeat(2,minmax(0,1fr))}
.it-nums .field{grid-column:auto}
.it-nums input,.it-nums select{padding-left:10px;padding-right:10px}
.it-nums select{padding-right:28px}
.money-in{display:flex;align-items:center;border:1px solid var(--line);border-radius:13px;background:var(--surface-2);padding-left:14px;min-width:0}
.money-in:focus-within{border-color:var(--accent);background:var(--surface);outline:2px solid var(--accent);outline-offset:1px}
.money-in span{font-weight:700;color:var(--ink-2)}
.money-in input{border:0!important;background:transparent!important;text-align:right;font-variant-numeric:tabular-nums;min-width:0}
.money-in input:focus-visible{outline:none}
.sumline{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:6px 12px;margin-top:10px;padding:12px 14px;border-radius:14px;background:var(--accent-soft);color:var(--ink);font-size:14px}
.sumline.warn{background:var(--warn-soft)}
.sumline.danger{background:var(--danger-soft)}
.sumline b{font:700 18px var(--fd);font-variant-numeric:tabular-nums}
.sumline .nota{flex-basis:100%;color:var(--ink-2);font-size:13px}

/* ---------- chart ---------- */
/* ---------- panel (demo: héroe, tarjetas, leyendas, dona) ---------- */
.panel-fecha{margin-top:4px}
.panel-top{margin-top:12px}
.panel-top .stats{margin-top:12px}
.panel-grid{margin-top:12px}
.hero{background:var(--banner);color:var(--banner-ink);border-radius:22px;padding:18px;display:grid;gap:10px;min-width:0;position:relative;overflow:hidden}
.hero small{font-size:12px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;opacity:.75}
.hero b{font:700 30px/1.05 var(--fd);letter-spacing:-.02em;overflow-wrap:anywhere}
.hero p{margin:0;font-size:13.5px;opacity:.85}
.hero .pill{justify-self:start;white-space:normal}
.hero-mark{position:absolute;right:-18px;top:-18px;width:110px;height:110px;color:var(--lime);opacity:.18}
.stats.three>.stat:last-child{grid-column:1/-1}
/* La tarjeta suelta de la demo (`.card.llana`): con su propio aire. */
.card.llana{border-radius:18px;padding:14px;min-width:0;box-shadow:none}
.card.llana h3{margin:0 0 2px;font:700 16px var(--fd)}
.card.llana .cap{margin:0 0 10px;font-size:13px;color:var(--ink-2)}
.grid.g2,.grid.g3{gap:12px;grid-template-columns:minmax(0,1fr)}
.grid>*{min-width:0}
.sw{width:10px;height:10px;border-radius:3px;flex:none}
.dlist{list-style:none;margin:10px 0 0;padding:0;display:grid;gap:8px}
.dlist li{display:flex;align-items:center;gap:8px;font-size:13.5px;min-width:0}
.dlist li span.n{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dlist li b{font-weight:600;font-variant-numeric:tabular-nums}
.dlist li em{font-style:normal;color:var(--ink-2);font-size:12px;width:38px;text-align:right;font-variant-numeric:tabular-nums}
.donut-wrap{display:flex;gap:16px;align-items:center;flex-wrap:wrap}
.donut-wrap .chart{flex:none;width:180px;max-width:100%}
.donut-wrap .dlist{flex:1;min-width:180px;margin:0}
.chart{width:100%;min-height:40px}
.chart svg{display:block;overflow:visible}
/* El flujo del Panel no crece con la tarjeta: en la PC el viewBox de 380 llegaba a 400 px de alto. */
.card.llana .graf svg{max-height:260px}
.hbar{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:4px 10px;align-items:center;font-size:13.5px}
.hbar+.hbar{margin-top:10px}
.hbar span{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hbar b{font-weight:600;font-variant-numeric:tabular-nums}
.hbar i{grid-column:1/-1;height:8px;border-radius:99px;background:var(--surface-2);border:1px solid var(--line);overflow:hidden;display:block}
.hbar i em{display:block;height:100%;background:var(--accent);border-radius:99px}
/* La barra de saldo de Cuentas y cajas: va debajo del nombre, adentro de la fila. */
.row-main .saldo-bar{margin-top:8px}
/* La dona: el aro de fondo, los segmentos y los textos con tokens. */
.dona .d-aro{stroke:var(--surface-2)}
.dona .d-sub{fill:var(--ink-2);font-family:var(--fb)}
.dona .d-val{fill:var(--ink);font-family:var(--fd)}
.dona .gs-0{stroke:var(--accent)} .dona .gs-1{stroke:var(--warn)} .dona .gs-2{stroke:var(--serie-2)}
.dona .gs-3{stroke:var(--ink-2)} .dona .gs-4{stroke:var(--danger)} .dona .gs-5{stroke:var(--ink-3)}
.sw.gs-0{background:var(--accent)} .sw.gs-1{background:var(--warn)} .sw.gs-2{background:var(--serie-2)}
.sw.gs-3{background:var(--ink-2)} .sw.gs-4{background:var(--danger)} .sw.gs-5{background:var(--ink-3)}

/* ---------- gráficos de informe ---------- */
.graf{width:100%}
.graf svg{display:block;max-width:100%;height:auto}
.graf-lg{display:flex;flex-wrap:wrap;gap:8px 18px;margin-top:12px;font-size:12px;color:var(--ink-2)}
.graf-lg .lg{display:inline-flex;align-items:center;gap:7px}
.graf-lg .lg i{width:10px;height:10px;border-radius:3px;flex:none}
/* Los gráficos traen sus colores en atributos (los lee el PDF); en pantalla mandan los tokens,
   así que el oscuro también se lee. La leyenda lleva el color en `style` (el PDF lo lee de
   ahí): por eso su regla necesita el `!important`. */
.graf .gs-0{fill:var(--accent)} .graf .gs-1{fill:var(--warn)} .graf .gs-2{fill:var(--serie-2)}
.graf .gs-3{fill:var(--ink-2)} .graf .gs-4{fill:var(--danger)} .graf .gs-5{fill:var(--ink-3)}
.graf polyline.gs-0{fill:none;stroke:var(--accent)} .graf polyline.gs-1{fill:none;stroke:var(--warn)} .graf polyline.gs-2{fill:none;stroke:var(--serie-2)}
.graf polyline.gs-3{fill:none;stroke:var(--ink-2)} .graf polyline.gs-4{fill:none;stroke:var(--danger)} .graf polyline.gs-5{fill:none;stroke:var(--ink-3)}
.graf .g-guia{stroke:var(--line)}
.graf .g-eje,.graf .g-rot{fill:var(--ink-2);font-family:var(--fb)}
.graf .g-val{fill:var(--ink);font-family:var(--fb)}
.graf .g-pos{fill:var(--danger)}
.graf .g-neg{fill:var(--accent)}
.graf .g-cero{fill:var(--ink-3);stroke:var(--ink-3)}
.graf-lg i.gs-0{background:var(--accent)!important} .graf-lg i.gs-1{background:var(--warn)!important} .graf-lg i.gs-2{background:var(--serie-2)!important}
.graf-lg i.gs-3{background:var(--ink-2)!important} .graf-lg i.gs-4{background:var(--danger)!important} .graf-lg i.gs-5{background:var(--ink-3)!important}

/* ---------- misc ---------- */
.split{display:flex;align-items:center;gap:10px}
/* El aviso de las pantallas de error (no cargó, ruta inexistente): el mismo `.notice` de la demo,
   con tokens, así que se lee en claro y en oscuro. */
.hint-box{display:flex;gap:10px;align-items:flex-start;padding:11px 12px;border-radius:14px;background:var(--accent-soft);color:var(--ink);font-size:13.5px}
.hint-box .icon{color:var(--accent);flex:none;margin-top:1px}
/* Modelo de datos: el nombre de una tabla o columna (`.code`) y las columnas de cada tabla como
   pastillas (`.tags`), como la demo. */
.code{font:500 12.5px ui-monospace,SFMono-Regular,Menlo,monospace;background:var(--surface-2);border:1px solid var(--line);border-radius:7px;padding:1px 6px;white-space:nowrap;color:var(--ink)}
.row-main b:has(.code),.row-main small:has(.code),.row-main .code,.notice .code{white-space:normal;overflow-wrap:anywhere}
.tags{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}
.modelo-nombre{display:flex;align-items:center;gap:8px;min-width:0}
.modelo-nombre .icon{color:var(--accent);flex:none;width:18px;height:18px}
.modelo-tabla .pill{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-weight:500}
.modelo-bajada{margin:0 2px 9px;font-size:13px;color:var(--ink-2)}

/* ---------- informes ---------- */
/* El lenguaje de la demo: la tarjeta de filtros con el período (`infFiltros`), los KPIs `.stat`,
   los paneles `.card` con su `h3` y su `.cap`, las tablas `.tbl` y el detalle como `.group`. */
.informe{min-width:0}
.inf-filtros{margin-top:12px}
.inf-filtros .chips{margin:0;padding:0}
.informe-acciones,.field.informe-acciones{display:flex;flex-direction:row;gap:8px;flex-wrap:wrap;align-items:center}
.inf-filtros .informe-acciones{align-self:end;min-height:48px}
.inf-nota{margin-top:12px}
.nota{font-size:12.5px;color:var(--ink-2);line-height:1.55;margin:10px 0 0}
.inf-paneles{display:grid;gap:12px;margin-top:12px;grid-template-columns:minmax(0,1fr)}
.inf-panel .tbl-wrap{margin-top:10px;border-radius:14px}
.inf-panel .graf{margin-top:4px}
table.tbl tfoot td{padding:11px 14px;border-top:1px solid var(--line);background:var(--surface-2);font-size:13px;white-space:nowrap}
/* El detalle plegable: cada remito es una fila del `.group`; abierta, muestra sus líneas. */
.inf-detalles{margin-top:10px}
.inf-detalles>.det+.det{border-top:1px solid var(--line)}
.det>summary{list-style:none;cursor:pointer}
.det>summary::-webkit-details-marker{display:none}
.det>summary .chev{transition:transform .15s;flex:none}
.det[open]>summary .chev{transform:rotate(90deg)}
.det>summary:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
.det>.tbl-wrap{margin:0 12px 12px;border-radius:12px}
.det .row-end{display:flex;align-items:center;gap:8px}


/* ---------- responsive ---------- */
@media (max-width:1180px){
  .g-4{grid-template-columns:repeat(2,minmax(0,1fr))}
  .form-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
  .field.w3{grid-column:span 2}
}
@media (max-width:860px){
  /* El armazón ya no vive acá: la base de la hoja es el celular (ver «armazón», arriba). Este
     bloque queda para las grillas y los formularios viejos (`.form-grid`), hasta que cada pantalla
     pase a la base mobile-first. La lista de ítems y la `.fgrid` ya viven en la base. */
  .g-4{grid-template-columns:1fr}
  .form-grid{grid-template-columns:1fr}
  .field.w2,.field.w3{grid-column:span 1}
  .medio{grid-template-columns:1fr}
  .medio .extra{grid-template-columns:repeat(2,minmax(0,1fr))}

  .submodal .form-grid{grid-template-columns:1fr}
  .submodal .field.w2,.submodal .field.w3{grid-column:span 1}
}

/* ---------- tablet (desde 720 px): el riel reemplaza a la barra inferior ---------- */
@media (min-width:720px){
  .tabbar{display:none}
  .rail{display:flex}
  .main{margin-left:calc(92px + env(safe-area-inset-left,0px));padding-bottom:40px}
  .wrap{padding-left:24px;padding-right:max(24px, env(safe-area-inset-right,0px))}
  .top-t h1{font-size:26px}
  .t-hide{display:none}
  .create-grid{grid-template-columns:repeat(3,minmax(0,1fr))}
  .toast-root{bottom:28px}
  .chips{margin-left:-24px;margin-right:-24px;padding-left:24px;padding-right:24px}
  .stats{grid-template-columns:repeat(4,minmax(0,1fr))}
  .stats.three{grid-template-columns:repeat(3,minmax(0,1fr))}
  .stats.three>.stat:last-child{grid-column:auto}
  .grid.g2{grid-template-columns:repeat(2,minmax(0,1fr))}
  .grid .span2{grid-column:1/-1}
  .stat b{font-size:clamp(16px,1.6vw,19px)}
  div.kv{grid-template-columns:repeat(3,minmax(0,1fr))}
  .fgrid{grid-template-columns:repeat(4,minmax(0,1fr))}
  .fgrid>.field.w2{grid-column:1/-1}
}
/* Lo que es sólo de la PC (`.d-only`), fuera de la PC no se ve. */
@media (max-width:1099px){.d-only{display:none!important}}

/* ---------- PC (desde 1100 px): diálogos centrados y la ficha a la derecha ----------
   La base de arriba es el celular y la tablet: todo es hoja. Acá se pisa lo justo para la PC,
   con los anchos de la demo: formulario hasta 1000 px con su grilla de 6 columnas, menú hasta
   680 y confirmación hasta 460; sin asa. La ficha (`.drawer`) es un panel de alto completo
   pegado a la derecha, de `min(540px,100%)`. */
@media (min-width:1100px){
  /* el armazón: la barra lateral reemplaza al riel */
  .rail{display:none}
  .side{display:flex}
  .main{margin-left:264px}
  .wrap{padding-left:32px;padding-right:32px}
  .gsearch{display:block}
  .m-brand,.m-search{display:none}
  .top-in{min-height:70px}
  .m-only{display:none!important}
  .grid.g3{grid-template-columns:repeat(3,minmax(0,1fr))}
  .grid .span2{grid-column:span 2}
  .panel-top{display:grid;grid-template-columns:1.25fr 3fr;gap:12px;align-items:stretch}
  .panel-top .stats{margin-top:0;grid-template-columns:repeat(3,minmax(0,1fr))}
  .datechip.d-only,.btn.d-only{display:inline-flex}
  .chips{margin-left:0;margin-right:0;padding-left:0;padding-right:0}
  .lbl-short{display:none}
  /* En la ficha (panel de 540 px) los pares vuelven a dos columnas. */
  .drawer div.kv{grid-template-columns:repeat(2,minmax(0,1fr))}
  /* las hojas */
  .drawer{left:auto;right:0;top:0;bottom:0;margin:0;width:min(540px,100%);max-width:none;height:100%;max-height:none;border-radius:24px 0 0 24px;animation-name:panel}
  .drawer .grab{display:none}
  .drawer-hd{padding-top:16px}
  .hoja-form,.hoja-menu,.hoja-confirm{top:50%;bottom:auto;left:50%;right:auto;margin:0;width:min(1000px,calc(100% - 64px));max-width:none;height:auto;max-height:calc(100% - 64px);border-radius:24px;transform:translate(-50%,-50%);animation-name:dialogo}
  .hoja-menu{width:min(680px,calc(100% - 64px))}
  .hoja-confirm{width:min(460px,calc(100% - 64px))}
  .hoja-form>.grab,.hoja-menu>.grab,.hoja-confirm>.grab{display:none}
  .hoja-form>.modal-hd,.hoja-menu>.modal-hd,.hoja-confirm>.modal-hd{padding-top:18px}
  .hoja-form .form-grid{grid-template-columns:repeat(6,minmax(0,1fr))}
  .hoja-form .field{grid-column:span 2}
  .hoja-form .field.w2{grid-column:span 4}
  .hoja-form .field.w3{grid-column:1/-1}
  .hoja-form .fgrid{grid-template-columns:repeat(6,minmax(0,1fr))}
  .hoja-form .fgrid>.field.w-half{grid-column:span 1}
  .hoja-form .fgrid>.field.w2{grid-column:span 4}
  /* Las tarjetas de medios llevan su propia grilla: el `span 2` de la hoja las desarmaba. */
  .hoja-form .it-nums .field{grid-column:auto}
  .hoja-form .it>.field{grid-column:1/-1}
  /* Los ítems en la PC: la tarjeta del celular se vuelve un renglón de la grilla de `--it-cols`,
     alineado con el encabezado de columnas. Los rótulos de cada campo los pone el encabezado, así
     que se esconden a la vista y se dejan para el lector de pantalla. Campos de 40 px: con los de
     48 la lista de ítems quedaba más alta que la tabla que reemplaza. */
  .hoja-form #items-body{gap:0}
  .hoja-form .items-hd{display:grid;grid-template-columns:var(--it-cols);gap:8px;padding:7px 8px;border-bottom:1px solid var(--line);font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--ink-2);font-weight:700}
  .hoja-form .items-hd>span:nth-child(6){text-align:right}
  .hoja-form .it-row{grid-template-columns:var(--it-cols);grid-template-areas:none;gap:8px;align-items:center;padding:6px 8px;border:0;border-bottom:1px solid var(--line);border-radius:0;background:none}
  .hoja-form .it-row::before{content:none;display:none}
  .hoja-form .it-f{grid-area:auto;grid-column:auto}
  .hoja-form .it-row .it-c-desc{display:grid}
  .hoja-form .it-l{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
  .hoja-form .it-f input,.hoja-form .it-f select{min-height:40px;padding:8px 10px;font-size:14px;border-radius:10px}
  .hoja-form .it-c-iva select,.hoja-form .it-c-unidad select{padding-right:28px}
  .hoja-form .it-c-sub{padding-right:0;font:600 14px var(--fb)}
  .hoja-form .it-c-x{position:static;justify-self:end}
  .hoja-form .it-mas{display:none}
  .hoja-form .totbox{margin-left:auto;max-width:360px}
  /* El pie pinta su propio fondo: sin el radio, tapa las esquinas redondeadas de abajo. */
  .modal-ft{justify-content:flex-end;border-radius:0 0 24px 24px}
  .drawer-ft{border-radius:0 0 0 24px}
  .modal-ft .note{flex:1 1 auto;margin-right:auto}
  .modal-ft .btn,.modal-ft .btn.ghost{flex:0 0 auto;min-width:150px}
  .submodal-bd{top:50%;bottom:auto;left:50%;right:auto;width:min(600px,calc(100% - 48px));max-height:calc(100% - 48px);border-radius:24px;transform:translate(-50%,-50%);animation-name:dialogo}
  .submodal-bd>.grab{display:none}
  /* El submodal vive adentro de un `.hoja-form`: sin esto heredaría su grilla de 6 columnas por
     orden de la cascada. Se fija la suya, de dos, con la especificidad que le gana. */
  .hoja-form .submodal .form-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
  .hoja-form .submodal .field{grid-column:span 1}
  .hoja-form .submodal .field.w2,.hoja-form .submodal .field.w3{grid-column:1/-1}
  .submodal-bd>.modal-hd{padding-top:18px}
}

/* ---------- táctil ----------
   Los botones (48 px, 44 el chico) y la cruz de cerrar (44×44) ya miden lo que piden los dedos
   en todos los anchos: es el tamaño de la demo y vive en sus reglas de arriba. Este bloque queda
   para los campos, que en la base ya van a 16 px pero tienen retoques más específicos —la lista
   de ítems— que en el táctil también tienen que llegar a 16.

   Los campos suben a 16px porque iOS Safari amplía la página al enfocar un campo de menos de
   16px, así que cada toque en un campo hace zoom y después hay que volver a alejar. El tamaño
   es el único remedio; `maximum-scale` en el `viewport` lo apagaría pero también le sacaría el
   zoom a quien lo necesita para leer. */
@media (pointer:coarse){
  select,input[type=text],input[type=number],input[type=date],input[type=email],input[type=tel],textarea{font-size:16px}
  /* Las dos líneas que la revisión de la Task 5 exigió, y el porqué de cada una:
     — `input` a secas. `input[type=text]` NO matchea un `<input>` sin atributo `type`: el
       selector mira el atributo, no el tipo por defecto del HTML. Y en esta app los campos
       pelados son mayoría —`Punto de venta`, `Número`, `Adjunto (URL)` del comprobante,
       `assets/app.js:1161`—, así que sin esta línea el iOS seguía haciendo zoom en la
       pantalla insignia del plan.
     — el override de la lista de ítems. `.it-f input,.it-f select` tiene especificidad
       (0,1,1) y le gana a la regla del `input` pelado de este bloque, que es (0,0,1) como
       todo selector de elemento, así que sin esta línea los campos de la lista de ítems se
       quedaban en los 12,5px de la parte general de esta hoja. */
  input,select,textarea{font-size:16px}
  .it-f input,.it-f select{font-size:16px}
  /* Y la lista de ítems de la hoja de PC (≥ 1100 px) también: `.hoja-form .it-f input` (0,2,1) la
     baja a 14px y le gana a la de arriba, así que una tablet táctil apaisada hacía zoom ahí. */
  .hoja-form .it-f input,.hoja-form .it-f select{font-size:16px}
  /* La etiqueta del campo acompaña: 12px al lado de un campo de 16 se lee como un error. */
  .field label{font-size:13px}
}

/* ---------- impresión ---------- */
@media print{
  /* El papel es claro siempre: los tokens vuelven a los del tema claro aunque la pantalla esté
     en oscuro (por sistema o por elección). Mismo peso que los bloques del oscuro y después de
     ellos, así que ganan. */
  :root,:root:not([data-theme="light"]),:root[data-theme="dark"]{
    --page:#e2e8de; --bg:#edf1ea; --surface:#ffffff; --surface-2:#f4f7f1; --ink:#13211c; --ink-2:#5a6b63; --ink-3:#7a8981; --line:#dde5d9;
    --primary:#0b3d2e; --primary-ink:#ffffff; --accent:#0e7a55; --accent-soft:#e6f4ea; --lime:#d4f25a; --lime-ink:#0b3d2e;
    --ok:#0e7a55; --ok-soft:#e6f4ea; --warn:#8f5b00; --warn-soft:#fbedcf; --danger:#b23a25; --danger-soft:#fbe2dc; --danger-ink:#ffffff;
    --banner:#0b3d2e; --banner-ink:#ffffff; --serie-2:var(--primary); color-scheme:light}
  .tabbar,.rail,.side,.top,.toast-root,.informe-acciones,#modal-root,#drawer-root{display:none!important}
  html,body{background:#fff;height:auto}
  .main{margin-left:0;padding-bottom:0}
  .view{padding:0}
  .view-card{background:none;border:0;box-shadow:none;border-radius:0}
  /* Un `<svg>` no se parte entre dos hojas. Un `barrasHorizontales` de diez filas tiene un
     viewBox de 520 × 394 —relación 0,76— y a todo el ancho útil de la hoja pide unos 210 mm de
     alto contra una banda de 190: no entra, así que el navegador lo empujaba a la hoja
     siguiente y dejaba la anterior casi en blanco. Medido, Remitos salía con su hoja 5 al
     0,11 % de tinta y Producción con la 6 al 0,22 %; el control de la Task 7 —600 px, o 158,75
     mm— bajaba Remitos de 20 a 18 hojas y llenaba las hojas 4 y 5.
     Acotado el alto, el `preserveAspectRatio` por defecto del SVG (`xMidYMid meet`) escala el
     contenido para que entre: lo achica y lo centra, no lo deforma. La pantalla no se toca. */
  .graf svg{max-height:158mm}
  /* Medido en Chromium 152: las barras del SVG salen con su `fill` aunque el diálogo no
     imprima los fondos, así que esta regla no es lo que las salva del blanco. Lo que sí
     depende de ella son los fondos de CSS que acompañan al gráfico: sin la regla, la pastilla
     «no suma» del detalle se imprime en blanco (2.296 px de `#e9eee6` contra 0), y los chips
     de color de la leyenda —que son `<i style="background:…">` fuera del SVG— salen seis
     cuadrados blancos en `precio-por-producto`, que es donde el gráfico tiene seis series. */
  .graf svg,.stat,.badge,.pill,.chip,.graf-lg .lg i,.hero,.dona svg,.sw,.stat-btn .share em{-webkit-print-color-adjust:exact;print-color-adjust:exact}
  /* Los paneles fluyen. `break-inside:avoid` sobre una caja más alta que la hoja no quiere
     decir «no cortes este panel» sino «empezá este panel en una hoja nueva», y deja la
     anterior casi en blanco: medido, Remitos salía en 21 hojas con la 5 al 0,47 % de tinta y
     Contabilidad en 13 con la 13 al 0,46 %. Lo que el diseño quiere es que no se corte una
     fila ni un encabezado, y eso se pide sobre las unidades chicas. */
  .card,.stat,.informe,.group{break-inside:auto;page-break-inside:auto;box-shadow:none}
  .informe{break-after:page;page-break-after:always}
  .informe:last-of-type{break-after:auto;page-break-after:auto}
  .grid,.g-4{display:block}
  .grid>.stat,.grid>.card{margin-bottom:10px}
  table.tbl{font-size:11px}
  /* El encabezado de la tabla se repite en cada hoja que la continúa, y ninguna fila se parte
     entre dos hojas. */
  table.tbl thead{display:table-header-group}
  table.tbl tr{break-inside:avoid;page-break-inside:avoid}
  /* El encabezado no se despega de lo que lo sigue: el del panel, la etiqueta de un KPI —que si
     no se queda sin su valor, en la hoja siguiente— y el resumen de un detalle, que si no se
     queda sin su tabla. Medido: sin la etiqueta en esta lista, Producción salía con «Mejor mes»
     al pie de la hoja 1 y su valor al tope de la 2. */
  .sec,.inf-panel>h3,.stat span,.det>summary{break-after:avoid;page-break-after:avoid}
  /* Si quedaran cerrados, el impreso saldría sin las líneas del detalle. */
  details{display:block}
  details>summary{list-style:none;cursor:default}
  details:not([open])>*{display:block}
  .det>summary.row{display:flex}
  /* Medido en Chromium 152: un `details` cerrado no esconde su contenido con `display:none`
     —le deja la caja maquetada y le saltea el pintado—, así que la regla de arriba no lo abre
     ahí: sin ésta, el PDF del navegador sale sin una sola línea del detalle (14 páginas en vez
     de 21, y ningún importe de línea). El navegador esconde con
     `::details-content{content-visibility:hidden}` y ésta es la forma de pisarlo. */
  details::details-content{content-visibility:visible}
  @page{size:A4 landscape;margin:10mm}
}

/* ---------------------------- Pantalla de login ---------------------------
   El de la demo: el logo, «Savia», la bajada, el `seg` de dos pestañas y los dos formularios, sobre
   el fondo de la app y con sus tokens (se ve en claro y en oscuro). Tapa a la app (`fixed`, capa
   100) mientras está a la vista. */
#login{position:fixed;inset:0;z-index:100;overflow-y:auto;background:var(--bg);display:grid;place-items:center;
  padding:calc(24px + env(safe-area-inset-top,0px)) max(16px, env(safe-area-inset-right,0px)) calc(24px + env(safe-area-inset-bottom,0px)) max(16px, env(safe-area-inset-left,0px))}
.login-card{width:100%;max-width:360px;text-align:center;color:var(--ink)}
.login-card .logo{width:64px;height:64px;border-radius:21px;background:var(--primary);color:var(--lime);display:grid;place-items:center;margin:0 auto 14px}
.login-card .logo .icon{width:30px;height:30px}
.login-card h1{margin:0;font:700 34px var(--fd);letter-spacing:-.02em}
.login-sub{margin:4px 0 20px;color:var(--ink-2)}
.login-form{display:grid;gap:14px;text-align:left;margin-top:18px}
.dots{display:flex;justify-content:center;gap:10px;margin-top:2px}
.dots span{width:12px;height:12px;border-radius:50%;border:2px solid var(--ink-3)}
.dots span.on{background:var(--accent);border-color:var(--accent)}
.login-error{margin-top:14px;padding:11px 12px;border-radius:14px;background:var(--danger-soft);color:var(--danger);font-size:13.5px;font-weight:600;text-align:left}
/* `#login`, `.app` y `.login-form` declaran su `display`, y ese `display` de autor le gana al
   `display:none` que trae el atributo `hidden` (el mismo caso que `.btn[hidden]`, más arriba).
   Medido en Chromium: sin estas reglas, `el.hidden = true` no escondía nada — la tarjeta quedaba
   encima del panel después de entrar, el panel se veía detrás del login al salir, y los dos
   formularios salían a la vez porque la pestaña sólo cambiaba el `hidden` del que no
   correspondía. */
#login[hidden]{display:none}
.app[hidden]{display:none}
.login-form[hidden]{display:none}
.login-error[hidden]{display:none}
/* «¿No podés entrar?»: tres renglones fijos, cerrados por defecto. El `summary` mide 44 px de alto
   para el dedo, como cualquier botón. */
.login-ayuda{margin-top:18px;text-align:left;color:var(--ink-2);font-size:14px}
.login-ayuda>summary{min-height:44px;display:flex;align-items:center;justify-content:center;cursor:pointer;font-weight:600;color:var(--ink);border-radius:12px}
.login-ayuda>summary:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.login-ayuda ul{margin:6px 0 0;padding-left:20px;display:grid;gap:6px;line-height:1.45}

/* ---------- informe de terceros ---------- */
/* Sin tokens nuevos: los colores de tipo salen de `CHIP_TIPO` en `app.js` —el mismo criterio que
   la lista de terceros—, así que un tipo se ve igual en el informe y en el padrón. */
.chip .dot,.stat-btn .dot{width:8px;height:8px;border-radius:50%;background:var(--ink-3);flex:none;display:inline-block}
.chip[data-tipo="cliente"] .dot,.stat-btn[data-tipo="cliente"] .dot{background:var(--accent)}
.chip[data-tipo="proveedor"] .dot,.stat-btn[data-tipo="proveedor"] .dot{background:var(--warn)}
.chip[data-tipo="ambos"] .dot,.stat-btn[data-tipo="ambos"] .dot{background:var(--serie-2)}
.chip[aria-pressed="true"] .dot{background:currentColor}
.pos{color:var(--primary)}
.inf-filtros .t-pie{display:flex;flex-direction:row;align-items:center;gap:12px;flex-wrap:wrap;align-self:end;min-height:48px}

/* Las tarjetas del eje: un `.stat` que se aprieta. Dos por fila en el celular y cuatro desde la
   tablet (las de `.stats`); el importe se parte antes que desbordar. */
.stats.tipos{margin-top:0}
/* Lo que va adentro del valor y del pie de un `.stat` (el signo del saldo, la variación) no es
   la etiqueta: no hereda el `display:block` de `.stat span`. */
.stat b i{font-style:normal}
.stat small span{display:inline;font-size:inherit}
.stat-btn{font:inherit;color:inherit;text-align:left;cursor:pointer;display:block;width:100%}
.stat-btn:hover{border-color:var(--accent)}
.stat-btn[aria-pressed="true"]{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent)}
.stat-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.stat-btn span{display:flex;align-items:center;gap:7px}
.stat-btn .share{display:block;height:6px;border-radius:99px;background:var(--surface-2);border:1px solid var(--line);overflow:hidden;margin-top:9px}
.stat-btn .share em{display:block;height:100%;border-radius:99px;background:var(--ink-3)}
.stat-btn[data-tipo="cliente"] .share em{background:var(--accent)}
.stat-btn[data-tipo="proveedor"] .share em{background:var(--warn)}
.stat-btn[data-tipo="ambos"] .share em{background:var(--serie-2)}
.inf-seg{margin-top:16px}

.usuarios{display:grid;grid-template-columns:minmax(0,1fr);gap:12px;margin-top:12px}
.ucard{background:var(--surface);border:1px solid var(--line);border-radius:18px;padding:14px;min-width:0}
.ucard-top{display:flex;gap:12px;align-items:center}
.ucard-parte{margin-left:auto;flex:none}
.uava{width:40px;height:40px;border-radius:13px;display:grid;place-items:center;font-weight:700;font-size:14px;color:var(--accent);flex:none;background:var(--accent-soft)}
.ucard-top h3{font:700 16px var(--fd);margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ucard-top .role{font-size:12.5px;color:var(--ink-2)}
.u-metrics{display:grid;grid-template-columns:minmax(0,.8fr) minmax(0,.8fr) minmax(0,1.4fr);gap:10px;margin-top:12px;padding-top:12px;border-top:1px solid var(--line)}
.u-metrics .lbl{font-size:12px;color:var(--ink-2);font-weight:600}
.u-metrics .val{font:700 15px var(--fd);margin-top:3px;font-variant-numeric:tabular-nums;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ulist{margin-top:10px;display:flex;flex-direction:column;gap:1px}
.ulist button{display:flex;align-items:center;gap:10px;width:100%;min-height:44px;text-align:left;background:none;border:0;padding:6px 8px;border-radius:10px;cursor:pointer;font:inherit;font-size:13.5px;color:inherit}
.ulist button:hover{background:var(--surface-2)}
.ulist .rs{font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ulist .amt{margin-left:auto;font-variant-numeric:tabular-nums;color:var(--ink-2);white-space:nowrap}
.u-foot{margin-top:10px;display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.spark{display:flex;align-items:flex-end;gap:4px;height:38px;margin-top:12px}
.spark i{flex:1;background:var(--accent-soft);border-radius:3px 3px 0 0;min-height:3px}
.spark i.hi{background:var(--accent)}
.spark-lbl{display:flex;gap:4px;margin-top:5px}
.spark-lbl span{flex:1;text-align:center;font-size:11px;color:var(--ink-2)}

/* El encabezado que ordena: el `<th>` dice su orden en `aria-sort` y el botón adentro hereda la
   letra del encabezado. */
.tlink{font:inherit;font-weight:600;color:var(--ink);text-align:left;min-height:44px;display:inline-flex;align-items:center;background:none;border:0;padding:0;cursor:pointer}
.tlink:hover{color:var(--accent);text-decoration:underline}
.tlink:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:4px}
table.tbl th .th-orden{letter-spacing:inherit;text-transform:inherit;color:inherit;font-weight:inherit;min-height:32px}
table.tbl th[aria-sort="ascending"],table.tbl th[aria-sort="descending"]{color:var(--accent)}

.switch{display:inline-flex;align-items:center;gap:9px;font-size:13.5px;color:var(--ink-2);cursor:pointer;user-select:none;min-height:44px}
.switch input{position:absolute;opacity:0;pointer-events:none}
.switch .track{width:36px;height:20px;border-radius:999px;background:var(--line);position:relative;transition:background .18s;flex:none}
.switch .track::after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:var(--surface);box-shadow:0 1px 2px rgba(0,0,0,.25);transition:transform .18s}
.switch input:checked + .track{background:var(--accent)}
.switch input:checked + .track::after{transform:translateX(16px)}
.switch input:focus-visible + .track{outline:2px solid var(--accent);outline-offset:2px}
@media (min-width:720px){
  .usuarios{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (min-width:1100px){
  .usuarios{grid-template-columns:repeat(auto-fill,minmax(320px,1fr))}
}
