/* =========================================================================
   niddo · Panel de administracion
   Portado desde la maqueta demos/admin.html
   ========================================================================= */
:root{
  --nd-blue:#7E96C4; --nd-blue-dk:#5D74A0; --nd-blue-soft:#E8EDF7;
  --nd-pink:#F3A8B8; --nd-pink-soft:#FCE6EB;
  --nd-bg:#F4F6FB; --nd-card:#FFFFFF; --nd-border:#E4E9F3;
  --nd-ink:#37405A; --nd-muted:#8791AB;
  --nd-ok:#3FA987; --nd-ok-soft:#E4F4EE;
  --nd-warn:#D89127; --nd-warn-soft:#FBF0DC;
  --nd-danger:#D96461; --nd-danger-soft:#FBE6E5;
  --nd-ml:#FFE600;
  --sidebar-w:252px;
}
*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{background:var(--nd-bg);color:var(--nd-ink);font-family:'Segoe UI',system-ui,-apple-system,Roboto,sans-serif;font-size:14px}
a{color:inherit;text-decoration:none}
form{margin:0}

/* ---------- Estructura ---------- */
.wrapper{display:flex;min-height:100vh}
.sidebar{width:var(--sidebar-w);min-width:var(--sidebar-w);background:#fff;border-right:1px solid var(--nd-border);
  position:fixed;top:0;left:0;bottom:0;display:flex;flex-direction:column;z-index:1000;transition:.25s}
.main{flex-grow:1;margin-left:var(--sidebar-w);padding:26px 32px 60px;min-width:0}

/* ---------- Barra lateral ---------- */
.sb-logo{padding:22px 20px 16px;border-bottom:1px solid var(--nd-border);display:flex;align-items:center;gap:10px}
/* El isotipo. Lo dibuja MarcaExpert como SVG en linea; aca solo se le da
   color y tamanio. Antes era este mismo lugar resuelto con un div, bordes y
   dos ::before, que era un parecido y no el logo.
   Va sin animacion, a diferencia de la tienda: el panel se mira ocho horas
   seguidas y un logo respirando en el rabillo del ojo cansa. */
.logo-mark{height:32px;width:auto;flex-shrink:0;overflow:visible}
.lg-antifaz{fill:var(--nd-blue-soft);stroke:var(--nd-blue)}
.lg-trazo,.lg-cara{stroke:var(--nd-blue)}
.lg-rosa{fill:var(--nd-pink)}
.topbar .logo-mark{height:26px}
.login-brand .logo-mark{height:46px}
.sb-name{font-size:1.35rem;font-weight:800;letter-spacing:-.5px;color:var(--nd-blue-dk)}
.sb-sub{font-size:.6rem;letter-spacing:2.5px;color:var(--nd-muted);text-transform:uppercase;font-weight:700}
.sb-nav{flex-grow:1;overflow-y:auto;padding:14px 0}
.sb-title{padding:12px 22px 6px;font-size:.62rem;font-weight:800;letter-spacing:1.6px;color:#B4BCD0;text-transform:uppercase}
.sb-item{display:flex;align-items:center;justify-content:space-between;padding:9px 22px;color:#6F7994;
  cursor:pointer;font-size:.87rem;border-left:3px solid transparent;transition:.15s}
.sb-item:hover{background:#FAFBFE;color:var(--nd-blue-dk)}
.sb-item i:first-child{margin-right:9px;color:#A9B2C7;width:16px;display:inline-block}
.sb-item.open,.sb-item.active{color:var(--nd-blue-dk);background:var(--nd-blue-soft);border-left-color:var(--nd-blue);font-weight:600}
.sb-item.open i:first-child,.sb-item.active i:first-child{color:var(--nd-blue)}
.sb-arrow{font-size:.62rem;opacity:.55;transition:transform .25s}
.sb-item.open .sb-arrow{transform:rotate(180deg)}
.sb-sub-list{max-height:0;overflow:hidden;transition:max-height .25s ease;list-style:none;margin:0;padding:0;background:#FBFCFE}
.sb-sub-list.open{max-height:400px}
.sb-sub-list a{display:block;padding:8px 22px 8px 50px;color:#8791AB;font-size:.82rem;position:relative}
.sb-sub-list a::before{content:'';position:absolute;left:32px;top:50%;width:7px;height:1px;background:#D5DBE8}
.sb-sub-list a:hover{color:var(--nd-blue-dk);background:var(--nd-blue-soft)}
.sb-sub-list a.on{color:var(--nd-blue-dk);font-weight:700;background:var(--nd-blue-soft)}
.sb-foot{padding:14px 18px;border-top:1px solid var(--nd-border);background:#FBFCFE}
.sb-user{display:flex;align-items:center;gap:10px;margin-bottom:11px}
.sb-avatar{width:34px;height:34px;border-radius:50%;background:var(--nd-pink-soft);border:1px solid var(--nd-pink);
  display:flex;align-items:center;justify-content:center;color:#C9788A;flex-shrink:0}
.sb-role{font-size:.58rem;letter-spacing:1.4px;color:var(--nd-muted);font-weight:800}
.sb-uname{font-weight:700;font-size:.85rem}
.sb-logout{display:block;text-align:center;padding:8px;border:1px solid var(--nd-border);border-radius:7px;
  color:var(--nd-muted);font-size:.78rem;font-weight:600;background:none;width:100%;cursor:pointer;font-family:inherit}
.sb-logout:hover{background:var(--nd-danger-soft);color:var(--nd-danger);border-color:#F0C9C8}

/* ---------- Cabecera de pagina ---------- */
.page-head{display:flex;align-items:flex-start;justify-content:space-between;gap:18px;flex-wrap:wrap;margin-bottom:22px}
.page-title{font-size:1.5rem;font-weight:800;margin:0 0 4px;letter-spacing:-.3px}
.page-sub{font-size:.84rem;color:var(--nd-muted);margin:0;max-width:68ch}
.page-desc{color:var(--nd-muted);font-size:.86rem;margin:0}
.crumb{font-size:.72rem;color:#AEB6C9;margin-bottom:6px;letter-spacing:.4px}
.crumb a:hover{color:var(--nd-blue)}

/* ---------- Tarjetas ---------- */
.card{background:var(--nd-card);border:1px solid var(--nd-border);border-radius:12px;padding:20px}
.card+.card{margin-top:18px}

/* Una columna de tarjetas, una abajo de la otra.
   Hace falta porque ".card + .card" no alcanza: varias tarjetas estan envueltas
   en un <asp:Panel>, que dibuja un div en el medio, y entonces el hermano
   anterior de la tarjeta no es una tarjeta sino ese div. El selector no engancha
   y las dos quedan pegadas. Con el gap no importa que haya envoltorios: la
   separacion la pone la columna y no las tarjetas.
   align-content:start para que las filas no se estiren cuando la otra columna
   es mas alta. */
.pila{display:grid;gap:18px;align-content:start}

/* Adentro de cualquier grilla la separacion ya la pone el gap: el margen de
   arriba se sumaria al gap, y en una grilla de dos columnas ademas desalinearia
   la segunda tarjeta respecto de la primera. */
.grid>.card+.card,
.pila>.card+.card{margin-top:0}
.card-head{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:16px;flex-wrap:wrap}
.card-title{font-size:.95rem;font-weight:800;margin:0}
.card-note{font-size:.76rem;color:var(--nd-muted);margin:3px 0 0}

.grid{display:grid;gap:18px}
/* Un item de grilla no baja de lo que mide su contenido mas angosto salvo que
   se le diga. Sin esto una tabla ancha adentro de una tarjeta estira su
   columna y con ella la pagina, y el scroll propio de .tbl-wrap no sirve. */
.grid>*{min-width:0}
.g4{grid-template-columns:repeat(4,1fr)}
.g3{grid-template-columns:repeat(3,1fr)}
.g2{grid-template-columns:repeat(2,1fr)}
.g-23{grid-template-columns:2fr 1fr}
@media(max-width:1200px){.g4{grid-template-columns:repeat(2,1fr)}.g-23,.g3{grid-template-columns:1fr}}

/* Dos tarjetas lado a lado adentro de una columna. Se comporta como una
   tarjeta mas para la separacion vertical, y la de adentro no suma la suya
   porque de eso ya se encarga el gap. */
.card-fila{display:grid;grid-template-columns:1fr 1fr;gap:18px;align-items:start}
.card-fila>*{min-width:0}
.card-fila>.card+.card{margin-top:0}
.card+.card-fila,.card-fila+.card,.card-fila+.card-fila{margin-top:18px}
@media(max-width:820px){.card-fila{grid-template-columns:1fr}}
@media(max-width:820px){.g4,.g2{grid-template-columns:1fr}}

/* ---------- Botones ---------- */
.btn{display:inline-flex;align-items:center;gap:7px;border:1px solid var(--nd-border);background:#fff;color:var(--nd-ink);
  padding:8px 14px;border-radius:8px;font-size:.82rem;font-weight:600;cursor:pointer;transition:.15s;font-family:inherit;text-decoration:none}
.btn:hover{background:#F7F9FD;border-color:#CFD8E8}
.btn-primary{background:var(--nd-blue);border-color:var(--nd-blue);color:#fff}
.btn-primary:hover{background:var(--nd-blue-dk);border-color:var(--nd-blue-dk);color:#fff}
.btn-pink{background:var(--nd-pink);border-color:var(--nd-pink);color:#7A3947}
/* Secundario: la accion que acompania a la principal sin competirle. */
.btn-sec{background:var(--nd-blue-soft);border-color:#D2DCF0;color:var(--nd-blue-dk)}
.btn-sec:hover{background:#DCE4F3;border-color:#BFCDE8}
.btn-danger{background:#fff;border-color:#F0C9C8;color:var(--nd-danger)}
.btn-danger:hover{background:var(--nd-danger-soft)}
.btn-sm{padding:5px 10px;font-size:.75rem}
.btn-icon{padding:6px 9px}
.btn:disabled{opacity:.5;cursor:not-allowed}

/* ---------- Etiquetas ---------- */
.badge{display:inline-flex;align-items:center;gap:5px;padding:3px 9px;border-radius:20px;font-size:.7rem;font-weight:700;white-space:nowrap}
.b-ok{background:var(--nd-ok-soft);color:var(--nd-ok)}
.b-warn{background:var(--nd-warn-soft);color:var(--nd-warn)}
.b-danger{background:var(--nd-danger-soft);color:var(--nd-danger)}
.b-info{background:var(--nd-blue-soft);color:var(--nd-blue-dk)}
.b-pink{background:var(--nd-pink-soft);color:#C9788A}
.b-mute{background:#F1F3F8;color:var(--nd-muted)}
.b-ml{background:#FFF9C4;color:#8A7500;border:1px solid #F2E27A}

/* ---------- Tablas ---------- */
.tbl{width:100%;border-collapse:collapse;font-size:.83rem}
.tbl th{text-align:left;padding:9px 10px;font-size:.68rem;letter-spacing:1px;text-transform:uppercase;
  color:var(--nd-muted);font-weight:800;border-bottom:1px solid var(--nd-border);white-space:nowrap}
.tbl td{padding:11px 10px;border-bottom:1px solid #F0F3F9;vertical-align:middle}
.tbl tbody tr:hover{background:#FAFBFE}
.tbl .num{text-align:right;font-variant-numeric:tabular-nums}
.tbl-wrap{overflow-x:auto;margin:0 -20px;padding:0 20px;min-width:0}

/* Que la tabla se DESPLACE en vez de aplastarse.
   .tbl-wrap ya tiene overflow-x, pero el navegador prefiere partir el texto
   antes que desbordar: en una tablet, una grilla de diez columnas entra toda
   igual, con "3x2 en pijamas" roto en cuatro renglones y cada fila del alto de
   un parrafo. Medido en un iPad de 1194 px: la celda pasaba de 55 a 87 px.

   La regla es simple: lo corto nunca se parte, y lo largo se parte pero con un
   ancho minimo para que no quede en columna de una palabra por renglon. Asi la
   tabla crece lo que necesita y el sobrante se ve desplazando dentro de su
   caja, sin que la pagina se vaya de lado. */
.tbl th,
.tbl td{white-space:nowrap}

.tbl .prod-cell,
.tbl .prod-name,
.tbl .prod-meta,
.tbl td.envuelve{white-space:normal}

.tbl .prod-name,
.tbl .prod-meta{min-width:180px}
.tbl-vacia{text-align:center;padding:40px 20px;color:var(--nd-muted)}
.tbl-vacia i{font-size:2rem;display:block;margin-bottom:10px;color:#CBD5E9}

/* ---------- Reclamos de Mercado Libre ----------
   El titulito que separa las secciones de la ficha de un reclamo. Estaba
   escrito con estilo en linea, repetido en cada seccion; con una clase, agregar
   una seccion nueva no obliga a copiar nueve propiedades. */
.rec-titulo{
  font-size:.82rem;font-weight:800;letter-spacing:.1em;text-transform:uppercase;
  color:var(--nd-muted);margin:20px 0 10px}

/* Una devolucion en curso. El borde a la izquierda la separa del resto sin
   agregar otra tarjeta adentro de la tarjeta. */
.rec-devolucion{
  border-left:3px solid var(--nd-blue-dk);background:var(--nd-blue-soft);
  border-radius:10px;padding:14px 16px}
.rec-devolucion .reng{display:flex;justify-content:space-between;gap:14px;
  padding:5px 0;font-size:.86rem}
.rec-devolucion .reng span:first-child{color:var(--nd-blue-dk)}
.rec-devolucion .reng span:last-child{font-weight:600;text-align:right}

/* Las resoluciones posibles, una por renglon. */
.rec-resolucion{
  display:flex;align-items:baseline;gap:10px;padding:8px 0;
  border-bottom:1px solid var(--nd-border);font-size:.88rem}
.rec-resolucion:last-child{border-bottom:0}
.rec-resolucion .clave{font-family:ui-monospace,Consolas,monospace;font-size:.78rem;
  color:var(--nd-muted);white-space:nowrap}

/* Quien pide la resolucion. No va con .clave, que es monoespaciada porque ahi
   iba un codigo de Mercado Libre; aca va el nombre de una persona. */
.rec-resolucion .quien{font-weight:700;white-space:nowrap;min-width:110px}

/* Un titulo de tercer nivel adentro de la ficha del reclamo: "Vuelve por",
   "Que vuelve". Mas chico que .rec-titulo, que encabeza la seccion. */
.rec-subtitulo{
  font-size:.8rem;font-weight:700;color:var(--nd-ink);margin:16px 0 8px}

/* Los botones de la devolucion. Envuelven en telefono en vez de desbordar: es
   la fila que mas botones puede llegar a tener de la pantalla. */
.rec-acciones{display:flex;flex-wrap:wrap;gap:10px;margin-top:14px}
.rec-acciones .btn{flex:0 1 auto}

@media (max-width:560px){
  /* De a uno y a lo ancho: con cuatro botones, dos por fila quedan de 90px y
     el texto se parte a la mitad de una palabra. */
  .rec-acciones{flex-direction:column}
  .rec-acciones .btn{width:100%}
}

/* El informe de que la devolucion llego mal. Enmarcado porque es un formulario
   que manda algo irreversible, no un bloque mas de la ficha. */
.rec-llegomal{
  border:1px solid var(--nd-border);border-radius:10px;padding:16px;margin-top:14px;
  background:var(--nd-bg)}
.rec-llegomal .field{margin-bottom:12px}

/* Un estado que no es ni bueno ni malo: "hay que hacerlo a mano". */
.b-mut{background:var(--nd-border);color:var(--nd-muted)}

/* Dos interruptores en la misma celda del filtro. En telefono uno abajo del
   otro: de a dos no entran con la etiqueta al lado. */
.sw-fila{display:flex;flex-wrap:wrap;gap:14px;align-items:center;padding-top:6px}

@media (max-width:560px){ .sw-fila{flex-direction:column;align-items:flex-start;gap:8px} }

/* ---------- Precios por articulo ---------- */

/* La grilla de precios es ancha por naturaleza: dos columnas por canal mas
   costo. Las de numeros se aprietan para que entre el nombre del producto. */
.tbl-precios th.num,.tbl-precios td.num{white-space:nowrap}
.tbl-precios .prod-name{font-weight:600}
.tbl-precios .prod-meta{font-family:ui-monospace,Consolas,monospace;font-size:.74rem;color:var(--nd-muted)}

/* El precio se escribe en la celda. Angosto y alineado a la derecha: es un
   numero en una columna de numeros, no un campo de formulario. */
.celda-precio{padding:4px 8px}
.inp-precio{
  width:104px;min-width:84px;text-align:right;padding:5px 8px;font-size:.82rem;
  font-variant-numeric:tabular-nums;background:transparent;border-color:transparent}
.inp-precio:hover{border-color:var(--nd-border);background:#fff}
.inp-precio:focus{border-color:var(--nd-blue);background:#fff}

.paginador{display:flex;align-items:center;justify-content:center;gap:14px;
  padding:14px 0 4px;font-size:.84rem}

@media (max-width:720px){
  /* En telefono el campo ocupa la celda: con 104px fijos la tabla se va de
     ancho y el numero queda cortado contra el borde. */
  .inp-precio{width:100%;min-width:72px}
  .paginador{gap:10px}
}

/* ---------- Aviso de version nueva ---------- */

/* Arranca a la derecha del menu lateral en vez de cruzar toda la pantalla.
   Cruzandola habria que bajar el menu y la barra superior, que son fijos y no
   los mueve el padding del body; correrlos desde la hoja de estilos resulto
   una pelea de cascada que no vale lo que cuesta mantener. Asi no tapa nada y
   no hay nada que correr. */
.aviso-version{
  position:fixed;top:0;left:var(--sidebar-w);right:0;z-index:1300;
  display:flex;align-items:center;justify-content:center;gap:12px;flex-wrap:wrap;
  padding:9px 16px;font-size:.85rem;font-weight:600;
  background:var(--nd-blue-dk);color:#fff;
  box-shadow:0 2px 10px rgba(0,0,0,.18)}
.aviso-version i{font-size:1rem}

/* El display:flex de arriba pisa el display:none que el navegador le da al
   atributo hidden, asi que sin esta regla la barra se ve SIEMPRE, anunciando
   una version nueva que no existe. Pasa con cualquier elemento al que se le
   fija display y se lo esconde con hidden. */
.aviso-version[hidden]{display:none}
.aviso-version .btn{padding:4px 14px;font-size:.8rem}

/* Corre el contenido para que la barra no le tape la primera linea. El alto
   lo mide el script y lo deja en --aviso-alto, porque cambia con el ancho de
   la pantalla: con poco lugar el texto envuelve y la barra crece. */
body.con-aviso-version{padding-top:var(--aviso-alto,42px)}

/* Abajo de 1000px el menu lateral se esconde y manda la barra superior, que
   mide 56px: la del aviso se ubica justo abajo. */
@media (max-width:1000px){
  .aviso-version{left:0;top:56px}
}

@media (max-width:560px){
  .aviso-version{font-size:.8rem;gap:8px;padding:8px 12px}
  .aviso-version .btn{width:auto}
}

/* ---------- Formularios ---------- */
.inp,select.inp,textarea.inp{border:1px solid var(--nd-border);border-radius:8px;padding:8px 11px;font-size:.83rem;
  background:#fff;color:var(--nd-ink);font-family:inherit;width:100%}
.inp:focus{outline:none;border-color:var(--nd-blue);box-shadow:0 0 0 3px var(--nd-blue-soft)}
.inp-sm{padding:5px 8px;font-size:.78rem}
.lbl{display:block;font-size:.7rem;font-weight:800;letter-spacing:.7px;text-transform:uppercase;color:var(--nd-muted);margin-bottom:5px}
.field{margin-bottom:14px}
.filters{display:flex;gap:10px;flex-wrap:wrap;align-items:flex-end;margin-bottom:16px}
.filters .field{margin:0;min-width:150px}
.filters .field.wide{flex:1;min-width:240px}

/* ---------- Indicadores ---------- */
.kpi{background:#fff;border:1px solid var(--nd-border);border-radius:12px;padding:18px}
.kpi-top{display:flex;align-items:center;justify-content:space-between;margin-bottom:10px}
.kpi-label{font-size:.68rem;letter-spacing:1.1px;text-transform:uppercase;color:var(--nd-muted);font-weight:800}
.kpi-ico{width:32px;height:32px;border-radius:9px;display:flex;align-items:center;justify-content:center;font-size:.95rem}
.kpi-val{font-size:1.7rem;font-weight:800;letter-spacing:-1px;line-height:1}
.kpi-foot{font-size:.74rem;color:var(--nd-muted);margin-top:8px}

.thumb{width:40px;height:40px;border-radius:8px;flex-shrink:0;border:1px solid var(--nd-border);background:var(--nd-blue-soft);
  display:flex;align-items:center;justify-content:center;font-size:.55rem;font-weight:800;color:var(--nd-blue-dk);
  text-align:center;line-height:1.1;padding:2px;overflow:hidden}
.thumb{position:relative}
/* La foto tapa a las iniciales, que quedan debajo como respaldo: si el
   archivo no esta, el onerror la saca y aparecen ellas. */
.thumb img{width:100%;height:100%;object-fit:contain;background:var(--nd-blue-soft)}
.prod-cell{display:flex;align-items:center;gap:11px}
.prod-name{font-weight:700}
.prod-meta{font-size:.72rem;color:var(--nd-muted)}

.alert{display:flex;gap:11px;padding:13px 15px;border-radius:10px;font-size:.83rem;align-items:flex-start;margin-bottom:16px}
.a-warn{background:var(--nd-warn-soft);color:#8A5C10;border:1px solid #F1DDB6}
.a-info{background:var(--nd-blue-soft);color:var(--nd-blue-dk);border:1px solid #D2DCF0}
.a-ok{background:var(--nd-ok-soft);color:#1F6B54;border:1px solid #C6E6DA}
.a-danger{background:var(--nd-danger-soft);color:#8A3E3C;border:1px solid #F0C9C8}
/* El amarillo de Mercado Libre es ilegible como fondo de texto, asi que se
   usa apenas como filete a la izquierda. */
.a-ml{background:#FFFBE0;color:#6B5A00;border:1px solid #EFE08A;border-left:4px solid var(--nd-ml)}

.mono{font-family:'Consolas','SF Mono',monospace;font-size:.78rem}
.mut{color:var(--nd-muted)}
.pos{color:var(--nd-ok);font-weight:700}
.neg{color:var(--nd-danger);font-weight:700}
.right{text-align:right}
.nowrap{white-space:nowrap}

.pager{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:16px;font-size:.8rem;color:var(--nd-muted);flex-wrap:wrap}
.pg-btns{display:flex;gap:5px}
.pg-btns .btn{padding:5px 11px}
.pg-btns .btn.on{background:var(--nd-blue);color:#fff;border-color:var(--nd-blue)}

.stock-bar{height:5px;border-radius:3px;background:#EEF1F7;overflow:hidden;width:70px;display:inline-block;vertical-align:middle}
.stock-bar i{display:block;height:100%;border-radius:3px}

/* ---------- Ingreso ---------- */
.login-page{min-height:100vh;display:flex;align-items:center;justify-content:center;
  background:linear-gradient(135deg,#FDF0F3 0%,#EEF2FA 55%,#E9F0FA 100%);padding:20px}
.login-card{background:#fff;border-radius:18px;box-shadow:0 20px 60px rgba(80,95,140,.16);padding:38px;width:100%;max-width:400px}
.login-brand{display:flex;align-items:center;gap:12px;justify-content:center;margin-bottom:8px}
.login-card h1{font-size:1.2rem;text-align:center;margin:18px 0 4px}
.login-card p.sub{text-align:center;color:var(--nd-muted);font-size:.85rem;margin:0 0 24px}

/* ---------- Movil ---------- */
.topbar{display:none}
@media(max-width:1000px){
  .sidebar{left:calc(-1 * var(--sidebar-w))}
  .sidebar.open{left:0;box-shadow:0 0 40px rgba(0,0,0,.16)}
  .main{margin-left:0;padding:70px 18px 50px}
  .topbar{display:flex;align-items:center;gap:12px;position:fixed;top:0;left:0;right:0;height:56px;
    background:#fff;border-bottom:1px solid var(--nd-border);z-index:900;padding:0 16px}
}

/* ============================================================
   Gráficos de los reportes
   El SVG lo arma el servidor; acá solo va lo que es presentación.
   ============================================================ */

/* El viewBox mide 900 de ancho. Sin tope, en una pantalla grande el SVG se
   escala al doble y un grafico de 180 px de alto pasa a medir 380: las barras
   quedan enormes y el resto es aire. Con max-width nunca se agranda mas alla
   de su tamano natural, y se centra cuando sobra lugar. */

/* Las marcas se aclaran al pasar por encima, así se sabe cuál está
   mostrando el globito con el valor. */
.g-col{transition:opacity .12s}
.g-col:hover{opacity:.78}

.g-tick{font-size:10.5px;fill:#8791AB}

/* El texto adentro de una barra de color va en blanco: es el único
   lugar donde el texto se apoya sobre el color del dato. */
.g-en{font-size:11.5px;font-weight:600;fill:#fff;dominant-baseline:middle}

.g-vacio{color:var(--nd-muted);font-size:.88rem;text-align:center;padding:26px 0;margin:0}

/* Referencia de colores: el cuadradito lleva la identidad, el texto queda en tinta */
.g-ref{display:flex;flex-wrap:wrap;gap:8px 20px;margin-top:12px}
.g-ref-i{display:inline-flex;align-items:center;gap:7px;font-size:.85rem}
.g-ref-i i{width:11px;height:11px;border-radius:3px;flex-shrink:0}
.g-ref-i b{font-weight:600}

/* La tabla que acompaña a cada gráfico: los valores exactos nunca quedan
   escondidos atrás de un globito que hay que cazar con el mouse. */
.g-tabla{margin-top:14px}
.g-tabla summary{font-size:.82rem;color:var(--nd-muted);cursor:pointer;padding:4px 0;user-select:none}
.g-tabla summary:hover{color:var(--nd-blue-dk)}
.g-tabla table{margin-top:8px}
.g-tabla td,.g-tabla th{font-variant-numeric:tabular-nums}

/* Barra apilada: HTML y no SVG, para que el alto no dependa del ancho.
   Los tramos se separan con dos píxeles del fondo, no con un borde. */
.g-apilada{display:flex;width:100%;height:34px;border-radius:5px;overflow:hidden;gap:2px}
.g-tramo{display:flex;align-items:center;padding:0 10px;min-width:2px;overflow:hidden}
.g-tramo b{font-size:.78rem;font-weight:600;color:#fff;white-space:nowrap}

/* ============================================================
   Galería de fotos de producto
   ============================================================ */

.galeria{display:flex;flex-wrap:wrap;gap:12px}
.foto{position:relative;width:132px;height:132px;border-radius:10px;overflow:hidden;
  border:2px solid var(--nd-line);background:#F7F9FC}
.foto.portada{border-color:var(--nd-blue)}
.foto img{width:100%;height:100%;object-fit:contain}

.foto-tag{position:absolute;top:6px;left:6px;background:var(--nd-blue-dk);color:#fff;
  border-radius:9px;padding:1px 8px;font-size:.66rem;font-weight:700}

/* Las acciones aparecen al pasar por encima: cuatro botones sobre cada
   miniatura serían más ruido que las fotos. */
.foto-acciones{position:absolute;left:0;right:0;bottom:0;display:flex;
  background:rgba(55,64,90,.86);opacity:0;transition:opacity .14s}
.foto:hover .foto-acciones,.foto:focus-within .foto-acciones{opacity:1}
.foto-acciones a{flex:1;text-align:center;padding:6px 0;color:#fff;font-size:.82rem;text-decoration:none}
.foto-acciones a:hover{background:rgba(0,0,0,.25)}

.galeria-vacia{color:var(--nd-muted);font-size:.88rem;padding:22px;text-align:center;
  border:1px dashed var(--nd-line);border-radius:10px;width:100%}
.galeria-vacia i{display:block;font-size:1.6rem;margin-bottom:8px;color:var(--nd-line)}

/* ---------- Overlay de alta y edicion ----------

   Un formulario de alta no va como card metida en el listado: empuja la tabla,
   mezcla "ver" con "crear" y deja al usuario sin saber si esta viendo o
   editando. Lo simple va en overlay; lo complejo, en su propia pagina.

   La visibilidad la maneja el Panel de WebForms con su propiedad Visible: si
   el postback deja el panel visible -por ejemplo porque fallo una validacion-
   el overlay sigue abierto solo, sin JavaScript que mantenga estado. */
/* La opacidad declarada y el "forwards" no son decoracion: sin eso el panel
   se abria INVISIBLE.
   Estos paneles los dibuja el servidor dentro del UpdatePanel, no los abre
   JavaScript. Cuando MS Ajax reemplaza el contenido, la animacion queda clavada
   en su primer cuadro -opacity:0- y nunca avanza: el panel ocupa la pantalla
   entera, con su contenido, y no se ve nada. Apretar "Modificar la formula"
   parecia no hacer nada.
   Con opacity:1 en la base, el estado en reposo es visible aunque la animacion
   no corra; con forwards, si corre, termina visible y se queda asi. */
.ov{
  position:fixed;inset:0;z-index:1200;
  background:rgba(38,45,66,.44);
  display:flex;align-items:flex-start;justify-content:center;
  padding:40px 18px;overflow-y:auto;
  opacity:1}

.ov-caja{
  background:var(--nd-card);border-radius:14px;width:100%;max-width:620px;
  box-shadow:0 18px 50px rgba(38,45,66,.24);
  animation:ov-entra .18s ease-out;
  margin:auto}

/* Para formularios con mas campos, que respiran mejor anchos */
.ov-caja.ancha{max-width:860px}

.ov-head{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:18px 22px;border-bottom:1px solid var(--nd-border)}
.ov-head h2{font-size:1rem;font-weight:800;margin:0}

.ov-cerrar{
  border:0;background:transparent;color:var(--nd-muted);cursor:pointer;
  font-size:1.15rem;line-height:1;padding:4px 6px;border-radius:6px;font-family:inherit}
.ov-cerrar:hover{background:var(--nd-bg);color:var(--nd-ink)}

.ov-cuerpo{padding:22px}
.ov-cuerpo .field+.field{margin-top:14px}
.ov-cuerpo .grid .field+.field{margin-top:0}

.ov-pie{
  display:flex;gap:8px;justify-content:flex-end;
  padding:16px 22px;border-top:1px solid var(--nd-border);background:#FBFCFE;
  border-radius:0 0 14px 14px}

/* La entrada mueve la caja y NO toca la opacidad. Es a proposito: una
   animacion de opacidad que no avanza deja el panel ocupando la pantalla
   entera, con su contenido, y completamente invisible. Pasa cuando el panel lo
   dibuja el servidor dentro del UpdatePanel y la pestania no esta al frente: la
   animacion arranca congelada en su primer cuadro. Moviendo solo el transform,
   el peor caso es que la caja no se deslice; nunca que no se vea. */
@keyframes ov-entra{from{transform:translateY(-10px)}to{transform:none}}

@media (prefers-reduced-motion:reduce){
  .ov-caja{animation:none}
}

@media (max-width:640px){
  .ov{padding:0}
  .ov-caja{max-width:none;min-height:100%;border-radius:0}
  .ov-pie{border-radius:0;position:sticky;bottom:0}
}

/* ---- Interruptor booleano ----

   Un si/no se lee mejor como interruptor que como casilla: la casilla del
   navegador obliga a leer la etiqueta para saber que significa estar tildado,
   y el interruptor muestra el estado por la posicion.

   Se estiliza el <input> que renderiza asp:CheckBox, no un marcado propio: asi
   sigue siendo un checkbox de verdad -viaja en el postback, se opera con la
   barra espaciadora y el lector de pantalla lo anuncia bien-. */
.sw{display:inline-flex;align-items:center;gap:10px}

.sw input[type=checkbox]{
  appearance:none;-webkit-appearance:none;
  flex:none;margin:0;width:42px;height:24px;border-radius:12px;
  background:var(--nd-border);cursor:pointer;position:relative;
  transition:background .22s ease}

/* La perilla */
.sw input[type=checkbox]::after{
  content:'';position:absolute;top:3px;left:3px;width:18px;height:18px;
  border-radius:50%;background:#fff;
  box-shadow:0 1px 3px rgba(38,45,66,.28);
  transition:transform .22s cubic-bezier(.4,.2,.2,1)}

.sw input[type=checkbox]:checked{background:var(--nd-blue)}
.sw input[type=checkbox]:checked::after{transform:translateX(18px)}

.sw input[type=checkbox]:hover:not(:disabled){filter:brightness(.97)}
.sw input[type=checkbox]:focus-visible{outline:2px solid var(--nd-blue-dk);outline-offset:2px}
.sw input[type=checkbox]:disabled{opacity:.5;cursor:not-allowed}

.sw label{cursor:pointer;user-select:none;line-height:1.3}

@media (prefers-reduced-motion:reduce){
  .sw input[type=checkbox],.sw input[type=checkbox]::after{transition:none}
}

/* ---- Zona de subida (arrastrar y soltar) ----

   El <input type=file> del navegador no se puede estilar, asi que se lo tapa
   con esta zona y se lo deja transparente encima: el clic sigue cayendo en el
   input de verdad, sin JavaScript que lo simule.

   Arrastrar y soltar tambien termina asignandole los archivos a ese mismo
   input, para que el postback de WebForms los reciba igual que siempre. */
.dz{
  position:relative;border:2px dashed var(--nd-border);border-radius:12px;
  background:#FBFCFE;padding:26px 20px;text-align:center;
  transition:border-color .18s,background .18s;cursor:pointer}
.dz:hover{border-color:var(--nd-blue);background:var(--nd-blue-soft)}

/* Mientras se arrastra algo encima */
.dz.dz-encima{border-color:var(--nd-blue);background:var(--nd-blue-soft);border-style:solid}

/* El input real: cubre toda la zona pero no se ve */
.dz-input{
  position:absolute;inset:0;width:100%;height:100%;
  opacity:0;cursor:pointer}

.dz-cara{display:flex;flex-direction:column;align-items:center;gap:8px;pointer-events:none}
.dz-ico{font-size:1.9rem;color:var(--nd-blue)}
.dz-txt{display:flex;flex-direction:column;gap:2px;font-size:.88rem}
.dz-txt strong{color:var(--nd-ink);font-weight:700}
.dz-txt span{color:var(--nd-muted);font-size:.8rem}

/* Los archivos elegidos, para que se vea que la seleccion quedo hecha */
.dz-lista{
  display:flex;flex-wrap:wrap;gap:6px;justify-content:center;
  margin-top:14px;pointer-events:none}
.dz-lista:empty{display:none}
.dz-chip{
  display:inline-flex;align-items:center;gap:6px;
  background:#fff;border:1px solid var(--nd-border);border-radius:16px;
  padding:4px 11px;font-size:.76rem;color:var(--nd-ink);max-width:220px}
.dz-chip i{color:var(--nd-blue);flex:none}
.dz-chip span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dz-chip .dz-peso{color:var(--nd-muted);flex:none}

@media (prefers-reduced-motion:reduce){ .dz{transition:none} }

/* ---- Desplegable buscable ----

   A partir de seis opciones el desplegable del navegador obliga a recorrer la
   lista a ojo. Este lo reemplaza por un boton que abre un panel con buscador.

   El <select> original sigue en el DOM, solo oculto: es el que viaja en el
   postback y el que dispara el AutoPostBack. Aca solo se lo maneja. */
.bs{position:relative;display:block}
.bs-oculto{position:absolute;opacity:0;pointer-events:none;width:0;height:0}

.bs-boton{
  display:flex;align-items:center;justify-content:space-between;gap:8px;
  width:100%;text-align:left;font-family:inherit;cursor:pointer}
.bs-valor{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bs-valor.bs-vacio{color:var(--nd-muted)}
.bs-flecha{font-size:.7rem;color:var(--nd-muted);flex:none;transition:transform .18s}
.bs-abierto .bs-flecha{transform:rotate(180deg)}

.bs-panel{
  display:none;position:absolute;top:calc(100% + 4px);left:0;right:0;z-index:1300;
  background:#fff;border:1px solid var(--nd-border);border-radius:10px;
  box-shadow:0 10px 30px rgba(38,45,66,.16);overflow:hidden}
.bs-abierto .bs-panel{display:block}

.bs-buscar{
  display:flex;align-items:center;gap:8px;padding:9px 12px;
  border-bottom:1px solid var(--nd-border);color:var(--nd-muted)}
.bs-buscar input{
  border:0;outline:none;background:transparent;width:100%;
  font-family:inherit;font-size:.85rem;color:var(--nd-ink)}

.bs-lista{max-height:260px;overflow-y:auto;padding:4px}
.bs-op{padding:8px 11px;border-radius:7px;font-size:.86rem;cursor:pointer;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bs-op:hover,.bs-op.bs-marcada{background:var(--nd-blue-soft)}
.bs-op.bs-sel{color:var(--nd-blue-dk);font-weight:700}
.bs-op.bs-off{display:none}

.bs-nada{display:none;padding:14px 12px;text-align:center;font-size:.83rem;color:var(--nd-muted)}

@media (prefers-reduced-motion:reduce){ .bs-flecha{transition:none} }

/* ---------- Mercado Libre · calificar al comprador ---------- */
/* Va separado del resto de la tarjeta por una regla: es una accion que no se
   puede deshacer y no conviene que se lea como un campo mas del formulario
   de arriba. */
.ml-calif{margin-top:18px;padding-top:16px;border-top:1px solid var(--nd-border)}
.mini-title{font-size:.78rem;font-weight:800;letter-spacing:.09em;text-transform:uppercase;
  color:var(--nd-muted);margin:0 0 12px}
.ml-calif-row{display:flex;flex-wrap:wrap;gap:14px;align-items:flex-end}
.ml-calif-row .field{margin-bottom:0;min-width:150px}

/* ---------- Foco visible ----------
   El panel se opera bastante con el teclado -cargar stock, moverse por una
   grilla-, y el contorno que pone el navegador se pierde sobre los bordes
   redondeados. Este se ve igual en todos.
   Va con :focus-visible y no con :focus para no dibujarlo tambien al hacer
   clic con el mouse, que es ruido. */
a:focus-visible,button:focus-visible,input:focus-visible,
select:focus-visible,textarea:focus-visible,
.btn:focus-visible,.bs-boton:focus-visible,.sb-item:focus-visible{
  outline:2px solid var(--nd-blue-dk);outline-offset:2px;border-radius:6px}

/* Las filas de una grilla larga: al recorrerlas con Tab conviene que se
   marque la fila entera, no solo el enlace. */
.tbl tbody tr:focus-within{background:var(--nd-blue-soft)}

@media (prefers-reduced-motion:reduce){
  .btn,.icon-btn,.card,.kpi,.sidebar{transition:none}
}

/* ---------- Envíos por la API ----------
   Va separado del seguimiento a mano por una regla: son dos formas distintas
   de despachar y mezclarlas confunde. */
.envio-api{padding-bottom:16px;margin-bottom:16px;border-bottom:1px solid var(--nd-border)}

/* El dia que se le prometio al comprador para el envio en moto.
   Va arriba de la direccion y no abajo: lo primero que hay que saber de un
   pedido en moto es si sale hoy, y la direccion no sirve de nada si el dia ya
   paso. El borde a la izquierda es lo que lo separa del resto de la ficha sin
   agregar otra tarjeta. */
.dia-moto{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;
  padding:10px 14px;margin:0 0 12px;border-radius:10px;
  background:var(--nd-blue-soft);border-left:3px solid var(--nd-blue-dk)}
.dia-moto .dia-moto-t{font-size:.72rem;font-weight:700;letter-spacing:.04em;
  text-transform:uppercase;color:var(--nd-blue-dk)}
.dia-moto .dia-moto-f{font-size:1.02rem;font-weight:700}

/* Atrasado: el dia prometido ya paso y el pedido sigue sin entregar. Es lo
   unico de la ficha que pide hacer algo ahora, asi que se pinta distinto. */
.dia-moto.tarde{background:var(--nd-danger-soft);border-left-color:var(--nd-danger)}
.dia-moto.tarde .dia-moto-t{color:var(--nd-danger)}
.envio-ficha{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px;margin-bottom:12px}
.envio-ficha>*{min-width:0}
.envio-dato{display:flex;flex-direction:column;gap:2px;min-width:0}
.envio-dato span{font-size:.72rem;text-transform:uppercase;letter-spacing:.08em;color:var(--nd-muted);font-weight:700}
.envio-dato strong{font-weight:600;overflow:hidden;text-overflow:ellipsis}

.envio-acciones{display:flex;flex-wrap:wrap;gap:8px;align-items:center}

/* Los movimientos del correo: una línea por evento, el más nuevo arriba. */
.envio-movs{margin-top:14px;border-top:1px solid var(--nd-border);padding-top:12px;
  max-height:280px;overflow-y:auto}
.envio-mov{display:flex;gap:12px;padding:7px 0;font-size:.83rem;border-bottom:1px solid #F0F3F9}
.envio-mov:last-child{border-bottom:0}
.envio-mov>span{min-width:78px;flex:none;margin:0}

/* =========================================================================
   Avisos flotantes y estados de espera
   -------------------------------------------------------------------------
   Los avisos de "se guardó" aparecían como un bloque arriba de la pantalla.
   El problema no era estético: en una pantalla larga el aviso quedaba fuera de
   la vista y la acción parecía no haber hecho nada. Este entra deslizándose
   desde el borde, donde el ojo lo agarra, y se va solo.

   Los de error NO se van solos: hay algo que leer y algo que corregir.
   ========================================================================= */

.nd-avisos{
  position:fixed;z-index:2000;right:18px;bottom:18px;
  display:flex;flex-direction:column;gap:10px;
  width:min(360px,calc(100vw - 36px));
  pointer-events:none}

.nd-aviso{
  pointer-events:auto;
  display:flex;align-items:flex-start;gap:11px;
  padding:13px 15px;border-radius:12px;
  background:#fff;border:1px solid var(--nd-border);
  box-shadow:0 8px 28px rgba(38,45,66,.16);
  font-size:.86rem;line-height:1.5;color:var(--nd-ink);
  /* Entra desde afuera del borde derecho */
  transform:translateX(calc(100% + 24px));opacity:0;
  transition:transform .34s cubic-bezier(.16,1,.3,1),opacity .24s ease}

.nd-aviso.nd-entra{transform:none;opacity:1}
.nd-aviso.nd-sale{transform:translateX(calc(100% + 24px));opacity:0}

/* Un filete al costado en vez de teñir todo el fondo: el texto se lee igual
   de bien y el color no compite con el resto de la pantalla. */
.nd-aviso::before{
  content:'';position:absolute;left:0;top:0;bottom:0;width:4px;
  border-radius:12px 0 0 12px;background:var(--nd-muted)}
.nd-aviso{position:relative;overflow:hidden}

.nd-aviso i.nd-ico{font-size:1.05rem;flex:none;margin-top:1px}
.nd-aviso .nd-texto{flex:1;min-width:0;word-wrap:break-word}

.nd-aviso .nd-cerrar{
  flex:none;border:0;background:transparent;cursor:pointer;padding:0 0 0 4px;
  color:var(--nd-muted);font-size:1rem;line-height:1;opacity:.7}
.nd-aviso .nd-cerrar:hover{opacity:1}

.nd-aviso.nd-ok::before{background:var(--nd-ok)}
.nd-aviso.nd-ok i.nd-ico{color:var(--nd-ok)}
.nd-aviso.nd-error::before{background:var(--nd-danger)}
.nd-aviso.nd-error i.nd-ico{color:var(--nd-danger)}
.nd-aviso.nd-alerta::before{background:var(--nd-warn)}
.nd-aviso.nd-alerta i.nd-ico{color:var(--nd-warn)}
.nd-aviso.nd-info::before{background:var(--nd-blue)}
.nd-aviso.nd-info i.nd-ico{color:var(--nd-blue-dk)}

/* En el celular va arriba: abajo lo tapa el teclado, y el pulgar lo roza al
   hacer scroll. */
@media (max-width:560px){
  .nd-avisos{right:12px;left:12px;bottom:auto;top:12px;width:auto}
  .nd-aviso{transform:translateY(-140%)}
  .nd-aviso.nd-entra{transform:none}
  .nd-aviso.nd-sale{transform:translateY(-140%)}
}

/* ---------- Botón trabajando ----------
   No se deshabilita el botón: un <button disabled> no viaja en el postback y
   WebForms se queda sin saber cuál se apretó. Se le tapan los clics con CSS,
   que consigue lo mismo sin romper el envío. */
.nd-trabajando{position:relative;pointer-events:none;opacity:.75}
.nd-trabajando > *{visibility:hidden}

.nd-trabajando::after{
  content:'';position:absolute;top:50%;left:50%;
  width:15px;height:15px;margin:-8px 0 0 -8px;
  border:2px solid currentColor;border-right-color:transparent;
  border-radius:50%;animation:nd-girar .6s linear infinite}

@keyframes nd-girar{to{transform:rotate(360deg)}}

/* ---------- Barra de progreso de la página ----------
   Mientras el servidor piensa. Es lo único que distingue "lo apreté y está
   cargando" de "lo apreté y no pasó nada". */
.nd-progreso{
  position:fixed;top:0;left:0;right:0;height:3px;z-index:2100;
  background:transparent;pointer-events:none;overflow:hidden;
  opacity:0;transition:opacity .2s}
.nd-progreso.nd-activa{opacity:1}
.nd-progreso::after{
  content:'';position:absolute;top:0;left:0;height:100%;width:40%;
  background:linear-gradient(90deg,transparent,var(--nd-blue-dk),transparent);
  animation:nd-avanzar 1.1s ease-in-out infinite}

@keyframes nd-avanzar{
  0%{transform:translateX(-100%)}
  100%{transform:translateX(350%)}
}

@media (prefers-reduced-motion:reduce){
  .nd-aviso{transition:opacity .2s ease}
  .nd-aviso,.nd-aviso.nd-entra,.nd-aviso.nd-sale{transform:none}
  .nd-trabajando::after,.nd-progreso::after{animation:none}
  .nd-progreso::after{width:100%;background:var(--nd-blue-dk);opacity:.5}
}

/* ---------- Comprobantes fiscales ---------- */
.comprobante{display:flex;justify-content:space-between;align-items:flex-start;gap:14px;
  padding:11px 0;border-bottom:1px solid var(--nd-border)}
.comprobante:last-child{border-bottom:0}
.comprobante>*{min-width:0}
.comprobante-der{display:flex;flex-direction:column;align-items:flex-end;gap:6px;flex:none}
.comprobante-total{font-weight:700;color:var(--nd-blue-dk);font-variant-numeric:tabular-nums}

/* =========================================================================
   Campos de fecha
   -------------------------------------------------------------------------
   El calendario que se despliega lo dibuja flatpickr, no el navegador. Antes
   era el nativo, y eso traia dos problemas que no se arreglan con CSS: se ve
   distinto en cada navegador, y sale en el idioma y el formato del sistema.
   En una maquina en ingles pide mm/dd/yyyy, que es el orden que hace que
   alguien cargue el 3 de julio y le quede el 7 de marzo.

   El campo sigue declarado TextMode="Date" en cada .aspx. flatpickr lo pasa a
   oculto y pone al lado uno de texto que muestra dd/mm/aaaa; el que viaja al
   servidor conserva el valor en ISO. Por eso ningun code-behind cambia.

   Lo de abajo son dos capas y las dos hacen falta:

     1. El input nativo. Es lo que se ve si el JavaScript no llega a correr, y
        lo que se ve siempre por un instante antes de que corra.
     2. El calendario de flatpickr, vestido con los colores del panel.
   ========================================================================= */
.inp[type="date"],
.inp[type="datetime-local"],
.inp[type="month"],
.inp[type="time"] {
    position: relative;
    padding-right: 34px;
    background-repeat: no-repeat;
    background-position: right 10px center;
    background-size: 16px 16px;
    /* Calendario dibujado a mano: sin esto habria que servir un archivo mas
       para un icono que aparece en trece campos. */
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%236B7280' stroke-width='1.4' stroke-linecap='round'%3E%3Crect x='1.8' y='3' width='12.4' height='11.2' rx='2'/%3E%3Cpath d='M1.8 6.6h12.4M5.2 1.6v2.6M10.8 1.6v2.6'/%3E%3C/svg%3E");
}

.inp[type="date"]:hover,
.inp[type="datetime-local"]:hover,
.inp[type="month"]:hover,
.inp[type="time"]:hover {
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%231B86EA' stroke-width='1.4' stroke-linecap='round'%3E%3Crect x='1.8' y='3' width='12.4' height='11.2' rx='2'/%3E%3Cpath d='M1.8 6.6h12.4M5.2 1.6v2.6M10.8 1.6v2.6'/%3E%3C/svg%3E");
}

/* Invisible y estirado sobre el icono: el click abre el calendario nativo. */
.inp[type="date"]::-webkit-calendar-picker-indicator,
.inp[type="datetime-local"]::-webkit-calendar-picker-indicator,
.inp[type="month"]::-webkit-calendar-picker-indicator,
.inp[type="time"]::-webkit-calendar-picker-indicator {
    position: absolute;
    right: 0;
    width: 34px;
    height: 100%;
    margin: 0;
    padding: 0;
    opacity: 0;
    cursor: pointer;
}

/* Los tres pedazos -dia, mes, anio- se seleccionan por separado; sin esto el
   resaltado lo pone el navegador con su propio azul. */
.inp[type="date"]::-webkit-datetime-edit,
.inp[type="datetime-local"]::-webkit-datetime-edit { padding: 0; }

.inp[type="date"]::-webkit-datetime-edit-fields-wrapper { padding: 0; }

.inp[type="date"]::-webkit-datetime-edit-day-field:focus,
.inp[type="date"]::-webkit-datetime-edit-month-field:focus,
.inp[type="date"]::-webkit-datetime-edit-year-field:focus {
    background: rgba(27, 134, 234, .14);
    color: inherit;
    border-radius: 3px;
    outline: none;
}

/* Un campo de fecha vacio muestra dd/mm/aaaa en negro pleno y parece cargado.
   Atenuarlo lo deja leerse como lo que es: un lugar donde falta escribir. */
.inp[type="date"]:not(:focus):in-range::-webkit-datetime-edit-year-field,
.inp[type="date"]:not(:focus):in-range::-webkit-datetime-edit-month-field,
.inp[type="date"]:not(:focus):in-range::-webkit-datetime-edit-day-field,
.inp[type="date"]:not(:focus):in-range::-webkit-datetime-edit-text { opacity: 1; }

.inp[type="date"]:invalid::-webkit-datetime-edit { opacity: .45; }

/* ---- El campo visible que arma flatpickr --------------------------------
   Es un input de texto, asi que ninguna de las reglas de arriba -que van por
   [type=date]- lo alcanza. Lleva el mismo icono y, a diferencia del nativo,
   se abre haciendo click en cualquier parte. */
.inp-fecha{padding-right:34px;cursor:pointer;
  background-repeat:no-repeat;background-position:right 10px center;background-size:16px 16px;
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%236B7280' stroke-width='1.4' stroke-linecap='round'%3E%3Crect x='1.8' y='3' width='12.4' height='11.2' rx='2'/%3E%3Cpath d='M1.8 6.6h12.4M5.2 1.6v2.6M10.8 1.6v2.6'/%3E%3C/svg%3E")}
.inp-fecha:hover,.inp-fecha:focus{
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%237E96C4' stroke-width='1.4' stroke-linecap='round'%3E%3Crect x='1.8' y='3' width='12.4' height='11.2' rx='2'/%3E%3Cpath d='M1.8 6.6h12.4M5.2 1.6v2.6M10.8 1.6v2.6'/%3E%3C/svg%3E")}

/* ---- El calendario ------------------------------------------------------
   flatpickr trae su hoja propia, con un azul y una tipografia que no son los
   del panel. Esto la repinta; no se toca ninguna medida ni posicion, que es
   lo que el script calcula. */
.flatpickr-calendar{
  background:var(--nd-card);border:1px solid var(--nd-border);border-radius:12px;
  box-shadow:0 12px 30px rgba(55,64,90,.14);font-family:inherit;font-size:.83rem;
  color:var(--nd-ink)}
.flatpickr-calendar.arrowTop:before{border-bottom-color:var(--nd-border)}
.flatpickr-calendar.arrowTop:after{border-bottom-color:var(--nd-card)}
.flatpickr-calendar.arrowBottom:before{border-top-color:var(--nd-border)}
.flatpickr-calendar.arrowBottom:after{border-top-color:var(--nd-card)}

.flatpickr-months{padding:6px 0 2px}
.flatpickr-months .flatpickr-month{color:var(--nd-ink);fill:var(--nd-ink);height:38px}
.flatpickr-current-month{font-size:.92rem;font-weight:700;padding-top:8px}
.flatpickr-current-month .flatpickr-monthDropdown-months{
  font-family:inherit;font-weight:700;border-radius:6px}
.flatpickr-current-month .flatpickr-monthDropdown-months:hover{background:var(--nd-blue-soft)}
.flatpickr-current-month input.cur-year{font-family:inherit;font-weight:700}

.flatpickr-months .flatpickr-prev-month,
.flatpickr-months .flatpickr-next-month{
  fill:var(--nd-muted);padding:8px 10px;border-radius:8px;top:4px}
.flatpickr-months .flatpickr-prev-month:hover svg,
.flatpickr-months .flatpickr-next-month:hover svg{fill:var(--nd-blue-dk)}

span.flatpickr-weekday{
  color:var(--nd-muted);font-weight:800;font-size:.66rem;
  letter-spacing:.7px;text-transform:uppercase}

.flatpickr-day{
  color:var(--nd-ink);border-radius:8px;border:1px solid transparent;
  font-variant-numeric:tabular-nums}
.flatpickr-day:hover,.flatpickr-day:focus{background:var(--nd-blue-soft);border-color:transparent}
.flatpickr-day.today{border-color:var(--nd-blue);font-weight:700}
.flatpickr-day.today:hover{background:var(--nd-blue-soft);color:var(--nd-ink)}
.flatpickr-day.selected,.flatpickr-day.selected:hover,
.flatpickr-day.selected:focus,.flatpickr-day.startRange,.flatpickr-day.endRange{
  background:var(--nd-blue);border-color:var(--nd-blue);color:#fff;font-weight:700}
.flatpickr-day.inRange{background:var(--nd-blue-soft);border-color:var(--nd-blue-soft);box-shadow:none}
.flatpickr-day.prevMonthDay,.flatpickr-day.nextMonthDay{color:var(--nd-muted);opacity:.55}
.flatpickr-day.flatpickr-disabled,.flatpickr-day.flatpickr-disabled:hover{color:var(--nd-muted);opacity:.35}

/* El pie con "Borrar" y "Hoy" lo agrega niddo-ui.js: flatpickr no trae uno.
   La mitad de los campos de fecha son filtros, y un filtro que se puede poner
   y no sacar obliga a recargar la pantalla para volver a ver todo. */
.fp-pie{display:flex;justify-content:space-between;gap:8px;
  padding:8px 10px;border-top:1px solid var(--nd-border)}
.fp-pie-btn{border:0;background:none;font-family:inherit;font-size:.78rem;font-weight:600;
  color:var(--nd-blue-dk);padding:4px 8px;border-radius:6px;cursor:pointer}
.fp-pie-btn:hover{background:var(--nd-blue-soft)}

/* ---- Listas de seleccion multiple, con slider ----------------------------
   Un CheckBoxList de Web Forms renderiza un <input type=checkbox> con su
   <label> al lado -en tabla o en flujo, segun RepeatLayout-. La clase .sw de
   arriba estiliza un interruptor suelto; esta hace lo mismo para cada item de
   una lista, para que "nada de checkboxes" valga tambien donde se eligen
   varias cosas: categorias de una prenda, familias alcanzadas por una promo,
   permisos de un perfil.

   El interruptor va mas chico que el suelto (34x20 contra 42x24): en una lista
   de veinte, uno del tamano completo ocupa mas que el texto que describe. */
.sw-lista input[type=checkbox]{
  appearance:none;-webkit-appearance:none;
  flex:none;margin:0 8px 0 0;width:34px;height:20px;border-radius:10px;
  background:var(--nd-border);cursor:pointer;position:relative;vertical-align:-5px;
  transition:background .22s ease}

.sw-lista input[type=checkbox]::after{
  content:'';position:absolute;top:3px;left:3px;width:14px;height:14px;
  border-radius:50%;background:#fff;
  box-shadow:0 1px 3px rgba(38,45,66,.28);
  transition:transform .22s cubic-bezier(.4,.2,.2,1)}

.sw-lista input[type=checkbox]:checked{background:var(--nd-blue)}
.sw-lista input[type=checkbox]:checked::after{transform:translateX(14px)}
.sw-lista input[type=checkbox]:hover:not(:disabled){filter:brightness(.97)}
.sw-lista input[type=checkbox]:focus-visible{outline:2px solid var(--nd-blue-dk);outline-offset:2px}
.sw-lista input[type=checkbox]:disabled{opacity:.5;cursor:not-allowed}

.sw-lista label{cursor:pointer;user-select:none;line-height:1.3;font-size:.9rem}
.sw-lista td{padding:5px 16px 5px 0;vertical-align:middle}

/* En RepeatLayout="Flow" los items salen separados por <br>, que con el
   interruptor mas alto quedan pegados. */
.sw-lista br{line-height:2.2}

@media (prefers-reduced-motion:reduce){
  .sw-lista input[type=checkbox],.sw-lista input[type=checkbox]::after{transition:none}
}

/* ---- Elegir de una lista larga -------------------------------------------
   Para cuando hay que marcar unas pocas cosas entre cientos: familias
   alcanzadas por una promocion, por ejemplo. Un CheckBoxList a dos columnas
   con 286 nombres largos es ilegible -envuelven, se mezclan, y no hay forma de
   encontrar uno-.

   La altura esta acotada y la lista scrollea adentro: sin eso el formulario se
   vuelve interminable y los botones de guardar quedan a mil pixeles. */
.elegir{border:1px solid var(--nd-border);border-radius:10px;overflow:hidden;background:var(--nd-bg)}

.elegir-barra{
  display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  padding:10px 12px;border-bottom:1px solid var(--nd-border);background:var(--nd-cream)}

.elegir-buscar{flex:1;min-width:180px;display:flex;align-items:center;gap:8px;
  background:var(--nd-bg);border:1px solid var(--nd-border);border-radius:8px;padding:6px 10px}
.elegir-buscar i{color:var(--nd-muted);font-size:.95rem;flex:none}
.elegir-buscar input{flex:1;min-width:0;border:0;outline:0;background:transparent;
  font:inherit;font-size:.9rem;color:var(--nd-ink)}

.elegir-solo{display:inline-flex;align-items:center;gap:7px;font-size:.85rem;
  color:var(--nd-muted);cursor:pointer;user-select:none}
.elegir-solo input[type=checkbox]{
  appearance:none;-webkit-appearance:none;margin:0;
  width:30px;height:18px;border-radius:9px;background:var(--nd-border);
  position:relative;cursor:pointer;transition:background .2s ease}
.elegir-solo input[type=checkbox]::after{
  content:'';position:absolute;top:3px;left:3px;width:12px;height:12px;border-radius:50%;
  background:#fff;box-shadow:0 1px 2px rgba(38,45,66,.28);transition:transform .2s ease}
.elegir-solo input[type=checkbox]:checked{background:var(--nd-blue)}
.elegir-solo input[type=checkbox]:checked::after{transform:translateX(12px)}

.elegir-cuenta{font-size:.82rem;color:var(--nd-muted);font-variant-numeric:tabular-nums}

.elegir-lista{max-height:340px;overflow-y:auto}

.elegir-fila{
  display:flex;align-items:center;gap:11px;padding:8px 12px;cursor:pointer;
  border-bottom:1px solid var(--nd-border)}
.elegir-fila:last-child{border-bottom:0}
.elegir-fila:hover{background:var(--nd-blue-soft)}
/* El filtro esconde las filas con el atributo hidden. hidden vale display:none,
   pero esa regla es del navegador y el display:flex de arriba le gana por
   especificidad: sin esto se escriben letras en el buscador y no pasa nada. */
.elegir-fila[hidden]{display:none}
.elegir-fila .sw{flex:none}

.elegir-foto{flex:none;width:38px;height:38px;border-radius:7px;overflow:hidden;
  background:var(--nd-cream);display:flex;align-items:center;justify-content:center}
.elegir-foto img{width:100%;height:100%;object-fit:cover;display:block}
.elegir-foto i{color:var(--nd-muted);font-size:1.05rem}

.elegir-texto{min-width:0;display:flex;flex-direction:column;gap:1px}
.elegir-nombre{font-size:.89rem;line-height:1.3;color:var(--nd-ink);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.elegir-codigo{font-size:.74rem;color:var(--nd-muted);font-family:ui-monospace,Consolas,monospace}

.elegir-vacio{margin:0;padding:18px 12px;text-align:center;font-size:.88rem;color:var(--nd-muted)}

/* ═══════════════════════════════════════════════════════════════════════
   Ayuda en la pantalla
   ---------------------------------------------------------------------
   El icono de informacion que acompana a un campo o a un titulo, y el
   globo que abre. Se abre con clic y no con hover: en un celular no hay
   hover, y una ayuda que solo aparece pasando el mouse no existe para la
   mitad de la gente.
   ═══════════════════════════════════════════════════════════════════════ */
.ayuda-i{
  display:inline-flex;align-items:center;justify-content:center;
  width:18px;height:18px;padding:0;margin-left:5px;vertical-align:-2px;
  border:0;border-radius:50%;background:transparent;cursor:pointer;
  color:var(--nd-muted);font-size:.82rem;line-height:1;transition:.15s}
.ayuda-i:hover{background:var(--nd-blue-soft);color:var(--nd-blue-dk)}
.ayuda-i:focus-visible{outline:2px solid var(--nd-blue);outline-offset:1px}
.ayuda-i[aria-expanded="true"]{background:var(--nd-blue);color:#fff}

.ayuda-globo{
  position:absolute;z-index:1200;width:320px;max-width:calc(100vw - 32px);
  background:var(--nd-card);border:1px solid var(--nd-border);border-radius:10px;
  box-shadow:0 12px 32px rgba(80,95,140,.18);padding:14px 16px;
  font-size:.82rem;line-height:1.55;color:var(--nd-ink)}
.ayuda-globo h4{margin:0 0 6px;font-size:.84rem;font-weight:800;color:var(--nd-blue-dk)}
.ayuda-globo p{margin:0}
.ayuda-globo .ayuda-aviso{
  margin:10px -16px -14px;padding:10px 16px;
  background:var(--nd-warn-soft);color:var(--nd-warn);
  border-top:1px solid var(--nd-border);border-radius:0 0 10px 10px;
  display:flex;gap:8px;align-items:flex-start;font-weight:600}
.ayuda-globo .ayuda-mas{
  display:inline-block;margin-top:10px;font-size:.78rem;font-weight:700;
  color:var(--nd-blue-dk);text-decoration:none}
.ayuda-globo .ayuda-mas:hover{text-decoration:underline}

/* ── El manual ─────────────────────────────────────────────────────── */
.man-indice{position:sticky;top:16px}
.man-indice a{
  display:block;padding:7px 12px;border-radius:7px;color:var(--nd-ink);
  text-decoration:none;font-size:.85rem;border-left:2px solid transparent}
.man-indice a:hover{background:var(--nd-blue-soft);color:var(--nd-blue-dk)}
.man-indice .man-sec{
  font-size:.66rem;letter-spacing:1.6px;text-transform:uppercase;font-weight:800;
  color:var(--nd-muted);padding:14px 12px 5px}

.man-tema{padding:22px 0;border-bottom:1px solid var(--nd-border)}
.man-tema:last-child{border-bottom:0}
.man-tema h3{margin:0 0 4px;font-size:1.02rem;font-weight:800;color:var(--nd-blue-dk)}
.man-tema .man-resumen{margin:0 0 12px;color:var(--nd-muted);font-size:.88rem}
.man-tema .man-detalle p{margin:0 0 10px;line-height:1.65}
.man-tema .man-detalle ul{margin:0 0 10px;padding-left:20px;line-height:1.65}
.man-tema .man-detalle li{margin-bottom:5px}
.man-tema .man-detalle p:last-child,.man-tema .man-detalle ul:last-child{margin-bottom:0}

.man-aviso{
  display:flex;gap:10px;align-items:flex-start;margin:14px 0 0;
  padding:11px 14px;border-radius:9px;
  background:var(--nd-warn-soft);color:var(--nd-warn);font-weight:600;font-size:.84rem}
.man-aviso i{font-size:1rem;line-height:1.3}

.man-captura{margin:14px 0 0}
.man-captura img{
  max-width:100%;border:1px solid var(--nd-border);border-radius:9px;display:block}
.man-captura figcaption{
  margin-top:7px;font-size:.78rem;color:var(--nd-muted)}

@media(max-width:900px){
  .man-indice{position:static}
  .ayuda-globo{width:280px}
}

/* Cuando una distribucion tiene una sola categoria no se dibuja la barra: se
   dice en una linea. Una barra entera de un color diciendo 100% ocupa media
   tarjeta para no informar nada. */
.g-unico{margin:0;font-size:1.05rem;color:var(--nd-ink)}
.g-unico strong{color:var(--nd-blue-dk)}

/* ── Los graficos entran animados ──────────────────────────────────────
   Las columnas crecen desde la linea de base y las barras desde la
   izquierda: en los dos casos la animacion va en el mismo sentido en que se
   lee el dato, asi que refuerza lo que el grafico dice en vez de decorarlo.

   Se escalonan de a poco para que se lea el orden, pero con tope: con noventa
   columnas, 18 ms cada una serian casi dos segundos de espera.

   transform-box:fill-box es lo que hace que el origen sea el propio rect y no
   el lienzo entero del SVG; sin eso, escalar una columna la manda a la esquina. */
@keyframes g-sube  { from { transform: scaleY(0); } to { transform: scaleY(1); } }
@keyframes g-crece { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes g-aparece { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

.g-col{transform-box:fill-box;transform-origin:bottom;
       animation:g-sube .45s cubic-bezier(.2,.8,.25,1) both}

.g-tramo{animation:g-crece .55s cubic-bezier(.2,.8,.25,1) both;transform-origin:left center}
.g-unico{animation:g-aparece .4s ease-out both}

/* Quien pidio menos movimiento ve el grafico armado, no armandose. */
@media (prefers-reduced-motion:reduce){
  .g-col,.g-tramo,.g-unico{animation:none}
}

/* El enlace a la pantalla real, al pie de cada tema del manual. */
.man-ir{margin-top:14px}


/* =========================================================================
   Barras horizontales de los reportes
   -------------------------------------------------------------------------
   Antes eran un SVG de 900 de ancho que se escalaba con la tarjeta: en media
   columna el nombre del producto quedaba en letra diminuta al lado de cifras
   del tamaño normal de la página, y sobraba aire arriba y abajo.

   Ahora cada fila es una grilla de tres columnas —nombre, pista, cifra—. El
   nombre y la cifra son texto de la página, con su tamaño real; la pista se
   queda con lo que sobra, sea cual sea el ancho.
   ========================================================================= */
.g-barras{display:flex;flex-direction:column;gap:2px}

.g-fila{display:grid;grid-template-columns:minmax(90px,34%) 1fr auto;
        align-items:center;gap:12px;padding:7px 8px;border-radius:8px;
        transition:background .14s}
.g-fila:hover{background:var(--nd-bg, #F5F7FC)}

.g-nombre{font-size:.86rem;color:var(--nd-ink);line-height:1.3;
          overflow:hidden;text-overflow:ellipsis;display:-webkit-box;
          -webkit-line-clamp:2;-webkit-box-orient:vertical}

/* La pista es el riel gris; el relleno es la barra. Tener el riel hace que
   las filas cortas se lean como "poco" y no como "cortado". */
.g-pista{display:block;height:12px;border-radius:99px;background:#EDF1F9;
         overflow:hidden;min-width:40px}

.g-relleno{display:block;height:100%;border-radius:99px;
           background:linear-gradient(90deg,#4A7BD4,#6C9BEA);
           transform-origin:left center;
           animation:g-crece .55s cubic-bezier(.2,.8,.25,1) both}

.g-cifra{font-size:.86rem;font-weight:700;color:var(--nd-blue-dk);
         white-space:nowrap;font-variant-numeric:tabular-nums}

/* El valor arriba de cada columna del gráfico de barras verticales. */

@media (max-width:640px){
  .g-fila{grid-template-columns:1fr auto;gap:4px 10px;padding:8px}
  .g-nombre{grid-column:1/-1}
  .g-pista{min-width:0}
}

@media (prefers-reduced-motion:reduce){
  .g-relleno{animation:none}
}


/* =========================================================================
   Gráfico de columnas
   -------------------------------------------------------------------------
   En HTML y no en SVG: un lienzo con viewBox tiene un ancho fijo y solo sabe
   estirarse o encogerse entero. Con lienzo ancho, dos columnas quedaban
   perdidas a un tercio y a dos tercios; con lienzo angosto sobraban trescientos
   píxeles de tarjeta vacía al costado. El ancho correcto es "el que tenga la
   tarjeta", y eso un viewBox no lo sabe.

   Acá el gráfico ocupa su tarjeta, las columnas se reparten lo que haya, y las
   cifras son texto de la página: no se achican cuando la tarjeta es angosta.
   ========================================================================= */
.g-cols{display:grid;grid-template-columns:auto 1fr;gap:10px;align-items:stretch}

/* El eje: las marcas repartidas de arriba a abajo. El padding de abajo deja
   lugar a los nombres, para que el cero quede a la altura de la base. */
.g-eje{display:flex;flex-direction:column;justify-content:space-between;
       height:var(--g-alto,200px);padding-bottom:20px;
       font-size:.74rem;color:#8791AB;text-align:right;
       font-variant-numeric:tabular-nums;white-space:nowrap}

.g-plot{position:relative;height:var(--g-alto,200px)}

/* Las líneas de referencia. Van detrás de las columnas. */
.g-lineas{position:absolute;inset:0 0 20px 0;display:flex;
          flex-direction:column;justify-content:space-between;pointer-events:none}
.g-lineas i{display:block;height:1px;background:#E7ECF6}

/* Las columnas se reparten el ancho por igual, sea cual sea la cantidad. */
/* La separación entre barras la manda el servidor según cuántas haya.
   Con cuatro píxeles fijos y noventa días son ochenta y nueve huecos —
   trescientos cincuenta y seis píxeles que no se achican—, y el gráfico se salía
   de la tarjeta en un celular arrastrando afuera los nombres del eje.

   No se puede hacer con un porcentaje, aunque sería lo natural: el porcentaje se
   calcula sobre el ancho del gráfico, que es el que quedó desbordado por culpa
   del hueco. Se muerde la cola. Por eso el servidor manda dos medidas y acá se
   elige según el ancho de la pantalla, que es el dato que a él le falta. */
.g-cols-in{position:relative;height:100%;display:flex;align-items:stretch;
           gap:var(--g-hueco,4px)}

@media (max-width:700px){
  .g-cols-in{gap:var(--g-hueco-angosto,var(--g-hueco,4px))}
}

.g-col-w{flex:1 1 0;min-width:0;height:100%;display:flex;flex-direction:column}

/* La barra y su cifra viven acá; el nombre queda afuera, debajo. Cuando estaban
   los tres en la misma caja, el nombre terminaba pintado encima de la barra. */
.g-col-caja{flex:1 1 auto;min-height:0;position:relative;display:flex;
            align-items:flex-end;justify-content:center;width:100%}

/* El tope de 74px evita que con dos o tres columnas cada una se vuelva un
   bloque enorme; sin él, dos ventas ocupaban media tarjeta cada una. */
.g-col{display:block;width:100%;max-width:74px;border-radius:5px 5px 2px 2px;
       background:linear-gradient(180deg,#6C9BEA,#4A7BD4);
       transform-origin:bottom center;
       animation:g-sube .45s cubic-bezier(.2,.8,.25,1) both;
       transition:filter .12s}
.g-col-w:hover .g-col{filter:brightness(1.08)}

/* Se apoya justo arriba de la barra: el "bottom" lo pone el gráfico, con la
   misma altura que tiene la barra. */
.g-cima{position:absolute;left:0;right:0;text-align:center;margin-bottom:3px;
        font-size:.76rem;font-weight:700;color:#37405A;
        font-variant-numeric:tabular-nums;white-space:nowrap}

/* El nombre de abajo de la columna.
   Ocupa el ancho que de verdad le toca, no el de su columna: cuando hay muchas
   columnas los nombres se saltean -uno cada --g-cada- y el que se dibuja tiene
   el lugar de todas las que se saltearon. Encerrado en la suya, en un celular
   medía ocho píxeles y los días de dos cifras salían cortados en la primera: el
   eje decía "1 4 7 1 1 1 2 2 2".

   El margen negativo lo vuelve a centrar sobre su columna. Los porcentajes se
   miden contra la columna, así que con --g-cada en 3 el nombre mide tres
   columnas y arranca una antes. La elipsis queda igual, de red: ahora recorta
   contra el ancho real y casi nunca hace falta. */
.g-pie{flex:0 0 auto;height:20px;line-height:20px;text-align:center;
       font-size:.72rem;color:#8791AB;white-space:nowrap;overflow:hidden;
       text-overflow:ellipsis;
       width:calc(var(--g-cada,1) * 100%);
       margin-left:calc((1 - var(--g-cada,1)) * 50%)}

/* El nombre que no entra lo esconde el JavaScript, después de medir: cuántos
   entran depende del ancho de la tarjeta, que el servidor no conoce. Se usa
   visibility y no display para que la fila no cambie de alto al esconderlos. */
.g-pie.g-oculta{visibility:hidden}

/* El mes viaja pegado al día y no se oculta por ancho. Ocultarlo en pantalla
   chica dejaba el eje de noventa días saltando de "30" a "6" sin decir que
   había arrancado otro mes, que es justo el dato que hace falta. Si un nombre
   no entra, se esconde entero: medio nombre no sirve. */

/* ---- Responsive ---- */
@media (max-width:640px){
  .g-cols{gap:6px}
  .g-eje{font-size:.68rem}
  /* Acá había un "gap:2px" para el hueco entre barras. Lo maneja la regla de
     arriba, que además sabe cuántas barras hay; este pisaba aquella por estar
     más abajo en la hoja, con la misma especificidad, y dejaba el gráfico
     desbordado en el celular aunque el servidor mandara el valor correcto. */
  .g-col{max-width:44px;border-radius:4px 4px 2px 2px}
  .g-cima{font-size:.68rem}

  /* En un celular no entran catorce nombres: se muestran de a pocos y el
     resto se consulta tocando la columna. */
  .g-pie{font-size:.64rem}
}

@media (max-width:420px){
  .g-cima{display:none}
}

@media (prefers-reduced-motion:reduce){
  .g-col{animation:none}
}


/* =========================================================================
   Mosaico de tarjetas
   -------------------------------------------------------------------------
   Las tarjetas de los reportes tienen alturas muy distintas: una dice una
   línea, otra lista veinte prendas. Emparejadas en una grilla de dos columnas,
   la más baja dejaba media tarjeta de aire al lado de la más alta, y una
   cantidad impar dejaba la última sola con toda la columna vecina vacía.

   Con columnas de texto cada tarjeta mide lo que necesita y la siguiente
   arranca donde terminó la anterior. break-inside evita que una tarjeta se
   parta al medio entre dos columnas.
   ========================================================================= */
/* Las tarjetas de los reportes.
   -------------------------------------------------------------------------
   Grilla de dos columnas, a secas. Probé dos formas de encajarlas sin huecos y
   las dos salieron peor:

     - columns: el navegador reparte por altura, y una lista larga que no se
       puede partir le desarma el balanceo. Mandaba todo a una columna.
     - grid con filas de 8px y el alto de cada tarjeta calculado por
       JavaScript: cuando la medición queda corta -y queda corta apenas algo
       cambia de alto después de medir- la tarjeta desborda su celda y se
       superpone con la de abajo. Se ve mucho peor que un hueco.

   El hueco no se arregla con el layout sino con el contenido: tarjetas de
   altura parecida encajan solas. Por eso las listas largas están acotadas. */
/* El minmax(0,...) no es adorno. Una pista "1fr" tiene como mínimo el ancho del
   contenido más ancho que lleva adentro, así que una tarjeta con algo que no
   entra no lo recorta: estira la pista, y con ella la tarjeta y la página. En un
   celular el gráfico de noventa días medía 460 y arrastraba la tarjeta a 460 en
   una pantalla de 375. El minmax(0,...) dice que la pista puede ser más angosta
   que su contenido, que es lo que uno espera. */
.mosaico{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:16px;
         align-items:stretch;margin-bottom:16px}

/* Las dos tarjetas de cada fila miden lo mismo. Con align-items:start cada una
   media lo suyo y entre fila y fila quedaban escalones: 44, 46 y 43 pixeles de
   hueco, medidos en produccion el 29/09. Emparejarlas por tema o por tamano no
   alcanza, porque la altura depende de los datos del periodo elegido: "Por
   donde entro" mide 142 con un solo canal y 300 con cuatro. */
.mosaico > .card{margin:0;display:flex;flex-direction:column}

/* Cuando un grafico tiene un solo valor no se dibuja: sale una linea de texto.
   Esa tarjeta, estirada, quedaria con la mitad de abajo muerta. El margen
   automatico reparte el aire arriba y abajo en vez de amontonarlo al final, y
   en las tarjetas que se llenan solas no hace nada. */
.mosaico > .card > .g-unico{margin-top:auto;margin-bottom:auto}

@media (max-width:1100px){
  /* En una sola columna no hay tetris que armar: las tarjetas vuelven a medir
     lo que miden y se apilan. */
  .mosaico{grid-template-columns:minmax(0,1fr)}
}


/* El fondo que aparece detrás del menú lateral en pantallas chicas. Da dónde
   tocar para cerrarlo y deja claro que el resto de la pantalla espera. */
.sb-fondo{position:fixed;inset:0;background:rgba(23,31,51,.42);
          opacity:0;visibility:hidden;transition:opacity .18s ease;z-index:899}
.sb-fondo.on{opacity:1;visibility:visible}

/* Mientras el menú está abierto, el fondo no se scrollea. */
body.sb-abierto{overflow:hidden}

/* El menú por encima del fondo. */
@media(max-width:1000px){
  .sidebar{z-index:901}
}

@media (min-width:1001px){
  /* En escritorio el menú está siempre a la vista: no hay nada que oscurecer. */
  .sb-fondo{display:none}
  body.sb-abierto{overflow:auto}
}

@media (prefers-reduced-motion:reduce){
  .sb-fondo{transition:none}
}


/* =========================================================================
   Imágenes de la portada
   -------------------------------------------------------------------------
   Tres columnas: la miniatura, los datos y los botones. Sin esto la imagen se
   dibujaba a su tamaño natural —media pantalla de alto— y todo lo demás caía
   debajo, dejando el costado derecho vacío.

   La miniatura es chica a propósito: acá se viene a ordenar y a elegir a qué
   producto lleva cada una, no a mirar la foto. Para eso está el botón que abre
   la portada.
   ========================================================================= */
.port-fila{display:grid;grid-template-columns:150px 1fr auto;gap:18px;align-items:start}

.port-foto{position:relative;width:150px;aspect-ratio:4/3;background:#fff;
           border:1px solid var(--nd-border);border-radius:10px;overflow:hidden}
.port-foto img{width:100%;height:100%;object-fit:contain;display:block}
.port-foto .badge{position:absolute;left:6px;top:6px}

.port-datos{display:flex;flex-direction:column;gap:10px;min-width:0}

/* La miniatura y el "cambiar la foto" son una sola columna. Sueltos serian dos
   hijos mas de la grilla y le correrian el reparto a todo lo demas. */
.port-izq{display:flex;flex-direction:column;gap:8px}

/* El campo de archivo es ancho por naturaleza: acotado al ancho de la
   miniatura, si no empuja la columna del medio. */
.port-cambiar{display:flex;flex-direction:column;gap:6px;width:150px}
.port-cambiar .inp{font-size:.74rem;padding:5px 7px}

/* Cuando la foto grande no esta elegida, el recuadro dice de donde sale, en vez
   de quedar como una caja vacia que parece un error de carga. */
.port-sinfoto{display:flex;align-items:center;justify-content:center;height:100%;
              padding:10px;text-align:center;font-size:.74rem;color:var(--nd-muted)}
.port-datos .field{margin:0}

.port-check{display:flex;align-items:center;gap:8px;font-size:.88rem;
            color:var(--nd-ink);cursor:pointer}

/* En columna y pegados arriba: así el botón de guardar queda a la altura de
   los campos que se acaban de tocar. */
.port-acciones{display:flex;flex-direction:column;gap:6px;min-width:110px}

@media (max-width:820px){
  .port-fila{grid-template-columns:110px 1fr;gap:12px}
  .port-foto{width:110px}
  .port-cambiar{width:110px}
  /* Los botones pasan abajo, ocupando las dos columnas y en fila. */
  .port-acciones{grid-column:1/-1;flex-direction:row;flex-wrap:wrap;min-width:0}
}


/* =========================================================================
   Elegir varios modelos y cambiarles la categoria de una
   -------------------------------------------------------------------------
   La barra se dibuja siempre —para quien pueda editar— y la abre el
   JavaScript al tildar el primer casillero, sin ir al servidor: contar
   casilleros no vale un viaje. La clase "on" tambien la puede poner el
   servidor, para cuando quedan modelos elegidos de otra pagina.
   ========================================================================= */
.lote{display:none;align-items:center;gap:12px;flex-wrap:wrap;
      margin:0 0 14px;padding:10px 14px;border-radius:10px;
      background:var(--nd-blue-soft);border:1px solid var(--nd-border)}
.lote.on{display:flex}

.lote-cuenta{font-weight:600;font-size:.87rem;color:var(--nd-blue-dk)}

/* El campo y su etiqueta en una sola linea: la barra es angosta y una
   etiqueta arriba la haria el doble de alta. */
.lote-campos{display:flex;align-items:center;gap:8px}
.lote-campos .lbl{margin:0}
.lote-campos .inp{width:auto;min-width:180px}

/* La columna de casilleros, lo mas angosta posible. */
.tbl th.tilde,.tbl td.tilde{width:34px;padding-left:12px;padding-right:0;text-align:center}
.tbl .tilde input{width:16px;height:16px;cursor:pointer;accent-color:var(--nd-blue-dk)}

/* La fila elegida se nota, si no hay que ir mirando casillero por casillero
   cual quedo tildado. */
.tbl tr.elegida{background:var(--nd-blue-soft)}

@media (max-width:700px){
  .lote{gap:8px}
  .lote-campos{flex:1 1 100%}
  .lote-campos .inp{flex:1}
}


/* =========================================================================
   El bloque de "ver mas" de las grillas
   -------------------------------------------------------------------------
   Reemplaza al paginador. Se muestra solo si hay una tanda siguiente, y
   desaparece cuando se llego al final.
   ========================================================================= */
.mas{display:flex;align-items:center;justify-content:center;gap:10px;
     padding:16px 0 4px}

/* Mientras llega la tanda, el boton se apaga y aparece el aviso: sin eso,
   apretar dos veces pide dos tandas y aparecen filas repetidas. */
.mas.cargando [data-ver-mas]{opacity:.45;pointer-events:none}
.mas-cargando{display:none;align-items:center;gap:6px;font-size:.84rem;color:var(--nd-muted)}
.mas.cargando .mas-cargando{display:inline-flex}
.mas.cargando .mas-cargando .bi{animation:mas-gira .8s linear infinite}

@keyframes mas-gira{to{transform:rotate(360deg)}}

/* El total va abajo de todo y en letra chica: es un dato de contexto, no algo
   que haya que leer para usar la pantalla. */
.mas-cuenta{text-align:center;font-size:.82rem;margin:4px 0 0}

@media (prefers-reduced-motion:reduce){
  .mas.cargando .mas-cargando .bi{animation:none}
}


/* =========================================================================
   Soltar fotos para subirlas
   -------------------------------------------------------------------------
   El campo de archivo de verdad vive adentro del recuadro, tapado. No se
   reemplaza por un boton falso a proposito: el label lo abre al tocarlo sin
   JavaScript, y soltar una foto lo unico que hace es ponersela a ese mismo
   campo. Si el JavaScript no corre, queda el campo de siempre y la pantalla
   funciona igual.
   ========================================================================= */
.subir{display:flex;flex-direction:column;gap:14px}

.suelta{position:relative;display:flex;flex-direction:column;align-items:center;
        justify-content:center;gap:4px;text-align:center;
        padding:30px 20px;cursor:pointer;
        border:2px dashed var(--nd-border);border-radius:14px;
        background:#FBFCFE;transition:border-color .15s,background .15s}
.suelta:hover{border-color:var(--nd-blue);background:var(--nd-blue-soft)}

/* Mientras hay algo encima. La clase la pone el JavaScript: el CSS solo no
   distingue un arrastre de un puntero cualquiera. */
.suelta.encima{border-color:var(--nd-blue-dk);background:var(--nd-blue-soft)}
.suelta.encima .suelta-icono{transform:translateY(-3px) scale(1.06)}

/* El campo tapa todo el recuadro para que el arrastre le caiga a el, pero no
   se ve: lo que se ve es el dibujo de abajo. */
.suelta-campo{position:absolute;left:0;top:0;width:100%;height:100%;
              opacity:0;cursor:pointer}

.suelta-icono{font-size:2rem;color:var(--nd-blue);transition:transform .15s}
.suelta-titulo{font-weight:600;font-size:.95rem;color:var(--nd-ink)}
.suelta-o{font-size:.84rem;color:var(--nd-muted)}
.suelta-nota{font-size:.78rem;color:var(--nd-muted);max-width:420px;margin-top:6px}

/* Las elegidas, antes de subir. Vacio no se dibuja: un hueco gris debajo del
   recuadro parece que algo fallo. */
.suelta-elegidas{display:none;flex-wrap:wrap;gap:10px}
.suelta-elegidas.hay{display:flex}

.suelta-una{position:relative;width:96px}
.suelta-una img{width:96px;height:72px;object-fit:contain;background:#fff;
                border:1px solid var(--nd-border);border-radius:8px;display:block}
.suelta-una span{display:block;font-size:.7rem;color:var(--nd-muted);
                 margin-top:4px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

.subir-pie{display:flex;align-items:flex-end;gap:14px;flex-wrap:wrap}

@media (max-width:700px){
  .suelta{padding:22px 14px}
  .subir-pie .btn{width:100%}
}

@media (prefers-reduced-motion:reduce){
  .suelta,.suelta-icono{transition:none}
  .suelta.encima .suelta-icono{transform:none}
}

/* Una fila de una lista que esta oculta: sigue existiendo y sigue funcionando,
   solo que no esta en uso. Se atenua en vez de esconderse porque la pantalla
   tiene un interruptor para verlas, y si se vieran iguales a las activas no se
   entenderia para que sirve el interruptor. */
.fila-off { opacity: .55; }
.fila-off:hover { opacity: 1; }

/* Una direccion larga dentro de una celda: monoespaciada para que se distinga
   del texto, y cortada para que no estire la tabla a lo ancho. */
.mono-corta { font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
  font-size: .76rem; word-break: break-all; }

/* Una barra al lado de un numero, para comparar filas de un saque. No es un
   grafico: la pregunta es "cual trae mas", y para eso alcanza el ancho
   relativo al mayor. */
.barra { background: var(--nd-border, #e4e4e7); border-radius: 999px; height: 8px; overflow: hidden; }
.barra > span { display: block; height: 100%; background: var(--nd-blue-dk, #5B7AAE); border-radius: 999px; }
