/* Paleta de marca Hisense: cian oficial #00B3AC (PANTONE 7465 C). */
:root{
  --hs:#00b3ac; --hs-dark:#00857f; --hs-deep:#054b4e; --hs-50:#e6f7f6; --hs-100:#c9ecea;
  --ink:#0e2226; --muted:#5d7378; --line:#e2eaeb; --bg:#ffffff; --card:#fff;
  /* Contorno de tarjetas, KPIs y tablas. Era casi negro (#111418) y recortaba
     demasiado sobre el fondo blanco; ahora es el mismo gris suave que el resto
     de separadores, así la definición la da la sombra y no una línea dura. */
  --stroke:var(--line);
  --ok:#15a34a; --warn:#ef8f1c; --bad:#e11d48; --info:#0284c7; --na:#9aa9ac;
  --shadow:0 1px 2px rgba(5,75,78,.06),0 10px 28px rgba(5,75,78,.07);
}
*{box-sizing:border-box}
body{margin:0;font-family:'DM Sans','Segoe UI',system-ui,-apple-system,Roboto,Arial,sans-serif;color:var(--ink);background:var(--bg);font-size:14px;-webkit-font-smoothing:antialiased}
/* ── Estructura bsc: sidebar izquierdo + topbar + contenido ── */
.app{display:flex;min-height:100vh;align-items:flex-start}
.sidebar{width:236px;flex-shrink:0;position:sticky;top:0;height:100vh;display:flex;flex-direction:column;
  background:linear-gradient(160deg,var(--hs-deep) 0%,var(--hs-dark) 55%,var(--hs) 130%);color:#fff;
  box-shadow:2px 0 18px rgba(5,75,78,.10);z-index:30}
.side-brand{display:flex;align-items:center;justify-content:center;gap:12px;cursor:pointer;padding:22px 18px 16px;
  border-bottom:1px solid rgba(255,255,255,.14)}
.side-brand:hover{opacity:.9}
.side-nav{flex:1;overflow-y:auto;padding:12px 12px;display:flex;flex-direction:column;gap:4px}
.side-foot{padding:16px 18px;border-top:1px solid rgba(255,255,255,.14);font-size:13px;font-weight:800;line-height:1.3}
.side-foot span{display:block;font-size:10.5px;font-weight:600;opacity:.8;margin-top:3px;letter-spacing:.3px}
.main-col{flex:1;min-width:0;display:flex;flex-direction:column;min-height:100vh}
.topbar{position:sticky;top:0;z-index:28;background:#fff;border-bottom:1px solid var(--line);
  box-shadow:0 1px 8px rgba(5,75,78,.05);padding:14px 26px;min-height:64px;display:flex;align-items:center;gap:16px}
.tb-title{font-weight:800;font-size:18px;letter-spacing:.2px;color:var(--ink)}
.tb-title small{font-weight:500;color:var(--muted);font-size:12.5px;margin-left:8px}
.logo-wrap{display:flex;align-items:center}
.logo-img{height:22px;display:block;filter:brightness(0) invert(1)}
.brand .title{font-weight:800;font-size:21px;letter-spacing:.3px;line-height:1.12}
.brand .title small{display:block;font-weight:500;opacity:.92;font-size:12.5px;letter-spacing:.2px;margin-top:3px}
.spacer{flex:1}
.userbox{display:flex;align-items:center;gap:11px;color:var(--ink)}
.userbox .uav{width:38px;height:38px;border-radius:50%;background:linear-gradient(135deg,var(--hs),var(--hs-dark));color:#fff;display:flex;align-items:center;justify-content:center;font-weight:800;font-size:14px;flex-shrink:0}
.userbox .uinfo{line-height:1.25;text-align:right;max-width:210px}
.userbox .uname{font-weight:700;font-size:13.5px;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.userbox .urole{font-size:11px;color:var(--muted)}
.userbox .ulogout{margin-left:4px;color:var(--hs-dark);font-size:12.5px;font-weight:700;text-decoration:none;border:1px solid var(--line);padding:7px 13px;border-radius:9px;transition:.14s;white-space:nowrap}
.userbox .ulogout:hover{background:var(--hs-50);border-color:var(--hs)}
@media(max-width:620px){.userbox .uinfo{display:none}}
.upddate{color:var(--muted);font-size:12px;line-height:1.35;text-align:right;padding-right:16px;margin-right:4px;border-right:1px solid var(--line)}
.upddate b{display:block;font-size:13px;font-weight:700;color:var(--ink)}
@media(max-width:760px){.upddate{display:none}}
/* Pestañas de equipo */
.tab{appearance:none;border:none;background:transparent;color:rgba(255,255,255,.82);font-weight:700;font-size:13.5px;
  padding:10px 14px;cursor:pointer;border-radius:11px;display:flex;align-items:center;gap:10px;width:100%;text-align:left;
  transition:.12s;flex-shrink:0}
.tab:hover{color:#fff;background:rgba(255,255,255,.10)}
.tab.on{color:var(--hs-deep);background:#fff;font-weight:800;box-shadow:0 5px 14px rgba(5,75,78,.20)}
.tab .cnt{font-size:11px;font-weight:800;background:rgba(255,255,255,.22);color:#fff;padding:1px 8px;border-radius:999px;margin-left:auto}
.tab-ic{width:18px;height:18px;flex-shrink:0}
.tab.on .cnt{background:var(--hs);color:#fff}
.wrap{display:flex;flex:1;min-width:0}
aside{width:300px;flex-shrink:0;background:var(--card);border-right:1px solid var(--line);padding:14px;position:sticky;top:64px;height:calc(100vh - 64px);overflow:auto}
main{flex:1;min-width:0;padding:20px 26px;overflow:auto}
.controls{display:flex;gap:10px;flex-wrap:wrap;align-items:end;margin-bottom:18px}
.field{display:flex;flex-direction:column;gap:5px}
.field label{font-size:11px;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);font-weight:700}
select,input[type=search]{padding:9px 12px;border:1px solid var(--line);border-radius:10px;font-size:14px;background:#fff;color:var(--ink)}
select:focus,input:focus{outline:2px solid var(--hs);border-color:var(--hs)}
.search{width:100%;margin-bottom:10px}
.sortrow{display:flex;align-items:center;justify-content:space-between;margin:0 2px 10px}
.sortlbl{font-size:11px;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);font-weight:700}
.sortbtn{border:1px solid var(--line);background:#fff;color:var(--hs-dark);font-weight:700;font-size:12.5px;padding:6px 12px;border-radius:9px;cursor:pointer}
.sortbtn:hover{border-color:var(--hs);background:var(--hs-50)}
.asidehead{font-size:11px;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);font-weight:700;margin:2px 2px 8px}
.plist{list-style:none;margin:0;padding:0}
.plist li{padding:9px 11px;border-radius:10px;cursor:pointer;margin-bottom:3px;border:1px solid transparent;transition:.12s}
.plist li:hover{background:var(--hs-50)}
.plist li.active{background:var(--hs-50);border-color:var(--hs-100)}
.plist .pn{font-weight:600;display:flex;align-items:center;justify-content:space-between;gap:8px}
.plist .pnm{display:flex;align-items:center;gap:6px;min-width:0}
.plist .pc{font-size:12px;color:var(--muted);display:flex;justify-content:space-between;align-items:center;gap:6px;margin-top:4px}
/* Conmutador de equipo al frente de la lista. Es un <li> para ocupar el sitio
   que tenía el resumen, pero no es seleccionable: se le quitan el cursor y el
   hover que `.plist li` da por hecho. */
.plist li.eqrow{padding:0 0 9px;margin-bottom:8px;border-bottom:1px solid var(--line);
  border-radius:0;cursor:default}
.plist li.eqrow:hover{background:transparent}
.plist li.eqrow .toggle button{flex:1;padding:8px 10px;font-size:12.5px}
.flags{display:flex;gap:5px;align-items:center;flex-shrink:0}
.flag{font-size:10px;font-weight:700;padding:2px 7px;border-radius:999px;letter-spacing:.2px;border:1px solid}
.flag.y{background:#e7f7ee;color:var(--ok);border-color:#b7e6c9}
.flag.n{background:#fde8ec;color:var(--bad);border-color:#f6c2cd}
.mini{font-size:10px;font-weight:700;padding:1px 6px;border-radius:999px;background:var(--hs-50);color:var(--hs-dark);text-transform:uppercase;letter-spacing:.3px}
.dot{width:9px;height:9px;border-radius:50%;display:inline-block;margin-right:5px;vertical-align:middle}
.kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:13px;margin-bottom:18px}
.kpi{--kc:var(--hs);background:var(--card);border:2px solid var(--kc);border-radius:14px;padding:15px 17px;box-shadow:var(--shadow)}
.kpi .v{font-size:27px;font-weight:800;line-height:1}
.kpi .l{font-size:12px;color:var(--muted);margin-top:7px}
.kpi .v.ok{color:var(--ok)} .kpi .v.warn{color:var(--warn)} .kpi .v.bad{color:var(--bad)} .kpi .v.info{color:var(--info)}
/* ── KPI liso ──────────────────────────────────────────────────────────────
   Variante sin semáforo: título arriba, cifra y detalle. Todas las tarjetas
   iguales, para que lo que dirija la vista sea la cifra y no el color.      */
.kpi-liso{border-width:1px;border-color:var(--stroke)}
.kpi-liso .kpi-t{font-size:10.5px;text-transform:uppercase;letter-spacing:.6px;
  color:var(--muted);font-weight:800;margin-bottom:9px}
.kpi-liso .v{font-size:25px}
.kpi-liso .l{line-height:1.45}
.phead{background:var(--card);border:1px solid var(--stroke);border-radius:14px;padding:16px 18px;margin-bottom:16px;box-shadow:var(--shadow);display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.phead h2{margin:0;font-size:20px}
.phead .sub{color:var(--muted);font-size:13px;margin-top:3px}
.avatar{width:48px;height:48px;border-radius:13px;background:linear-gradient(135deg,var(--hs),var(--hs-dark));color:#fff;display:flex;align-items:center;justify-content:center;font-weight:800;font-size:18px;flex-shrink:0}
.badges{display:flex;gap:8px;flex-wrap:wrap;margin-left:auto}
.src-badge{font-size:12px;padding:5px 11px;border-radius:999px;font-weight:600;border:1px solid}
.src-ok{background:#e7f7ee;color:var(--ok);border-color:#b7e6c9}
.src-no{background:#fde8ec;color:var(--bad);border-color:#f6c2cd}
.src-mm{background:var(--hs-50);color:var(--hs-dark);border-color:var(--hs-100)}
.src-mut{background:#f1f5f6;color:var(--muted);border-color:#e2eaeb}
table{width:100%;border-collapse:collapse;background:var(--card);border:1px solid var(--stroke);border-radius:14px;overflow:hidden;box-shadow:var(--shadow)}
th,td{padding:11px 13px;text-align:left;border-bottom:1px solid var(--line);font-size:13.5px}
th{background:var(--hs-50);font-size:11px;text-transform:uppercase;letter-spacing:.4px;color:var(--hs-dark);position:sticky;top:0;font-weight:700}
tbody tr:last-child td{border-bottom:none}
tbody tr:hover{background:var(--hs-50)}
th.ctr,td.ctr{text-align:center}
td.ctr{font-variant-numeric:tabular-nums;font-weight:600}
.tag{font-size:11.5px;padding:3px 10px;border-radius:999px;font-weight:700;white-space:nowrap;display:inline-block}
.t-ok{background:#e7f7ee;color:var(--ok)} .t-warn{background:#fef1e0;color:#b4690e}
.t-bad{background:#fde8ec;color:var(--bad)} .t-info{background:#e2f1fb;color:var(--info)}
.t-na{background:#f1f5f6;color:var(--na)} .t-mut{background:#eef2f3;color:var(--muted)}
.chk{font-weight:800}.chk.y{color:var(--ok)}.chk.n{color:var(--bad)}.chk.u{color:var(--na)}
.narep{color:var(--na);font-style:italic;font-size:12.5px}
.empty{padding:42px;text-align:center;color:var(--muted)}
.toggle{display:flex;gap:6px}
.toggle button{border:1px solid var(--line);background:#fff;padding:9px 15px;border-radius:10px;cursor:pointer;font-weight:600;font-size:13px;color:var(--muted)}
.toggle button:hover{border-color:var(--hs)}
.toggle button.on{background:var(--hs);color:#fff;border-color:var(--hs)}
.warnbox{background:#fff8e6;border:1px solid #f3d98a;color:#7a5b09;border-radius:12px;padding:11px 14px;margin-bottom:14px;font-size:13px}
/* Hermano de .warnbox para lo que no es un matiz sino una pérdida de datos:
   filas que no se van a importar, registros que se descartan. */
.errbox{background:#fdeaee;border:1px solid #f3b3c1;color:#8f1734;border-radius:12px;padding:11px 14px;margin-bottom:14px;font-size:13px}
.section-title{font-weight:800;margin:4px 0 10px;font-size:15px}
/* Qué se está mirando, al lado del selector de semana: tienda y equipo. El
   relleno inferior lo alinea con el texto del desplegable y no con su borde.
   Vacío se esconde, o dejaría el hueco de la separación de .controls.       */
.gwctx{align-self:end;padding-bottom:10px;font-size:12px;text-transform:uppercase;
  letter-spacing:.5px;color:var(--muted);font-weight:700}
.gwctx:empty{display:none}


/* La semana de cada tienda en la lista lateral. Va al lado del nombre porque
   sin ella no se sabría que la tienda de abajo va dos semanas por detrás. */
.psem{font-size:9.5px;font-weight:800;letter-spacing:.3px;text-transform:uppercase;
  border-radius:5px;padding:1px 5px;margin-left:6px;white-space:nowrap}
.psem.al-dia {background:#e8f7ee;color:var(--ok)}
.psem.atras  {background:#fdf1e3;color:var(--warn)}
.psem.no     {background:#fdeaee;color:var(--bad)}
/* Nadie le ha marcado la gama, así que sale en los dos equipos hasta que se
   arregle. Es un aviso de configuración, no del estado de sus informes. */
.psem.singama{background:#eef2f3;color:var(--muted);border:1px dashed var(--line)}
.gtag{display:inline-block;font-size:11px;font-weight:800;letter-spacing:.4px;padding:2px 9px;border-radius:999px;border:1px solid}
.gtag.g-tv{color:#0369a1;background:#e0f2fe;border-color:#bae6fd}
.gtag.g-wg{color:#9a3412;background:#ffedd5;border-color:#fed7aa}
.gtag.g-mix{color:#0f766e;background:#ccfbf1;border-color:#99f6e4}
/* Fila total en tablas de detalle/stock */
table tr.tot td{font-weight:800;background:var(--hs-50);color:var(--ink);border-top:2px solid var(--stroke)}
.gcards{display:grid;grid-template-columns:repeat(2,1fr);gap:18px}
@media(max-width:1024px){.gcards{grid-template-columns:1fr}}
/* Varias tarjetas apiladas dentro de una sola celda de la rejilla. Lo usa el
   planograma: una tienda puede tener dos muebles de la misma gama y los dos
   tienen que quedarse en la columna izquierda, frente a su exposición. */
.gcol{display:flex;flex-direction:column;gap:18px;min-width:0}
.gteam{background:var(--card);border:1px solid var(--stroke);border-radius:18px;box-shadow:var(--shadow);padding:18px 20px 20px;margin:0}
.gteam-h{font-weight:800;font-size:17px;margin:0 0 14px;display:flex;align-items:center;gap:11px;color:var(--ink)}
.gstore{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;flex:none}
.gstore svg{width:24px;height:24px;fill:none;stroke:currentColor;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round}
.gteam .kpis{margin-bottom:0;grid-template-columns:repeat(2,1fr);gap:11px}
footer{padding:16px 26px;color:var(--muted);font-size:12px;text-align:center}
@media(max-width:880px){aside{display:none}}

/* ══════════════════════════════════════════════════════════════════
   V2.0 — Componentes nuevos (CRUD, auth, feedback)
   Misma paleta y lenguaje visual que la v1.0.
   ══════════════════════════════════════════════════════════════════ */

/* ── Login ── */
#login{position:fixed;inset:0;z-index:100;display:none;align-items:center;justify-content:center;
  background:linear-gradient(160deg,var(--hs-deep) 0%,var(--hs-dark) 55%,var(--hs) 130%);padding:20px}
#login.show{display:flex}
.login-card{width:100%;max-width:400px;background:#fff;border-radius:20px;padding:38px 34px;
  box-shadow:0 24px 60px rgba(5,75,78,.32)}
.login-card .logo-img{height:30px;filter:none;margin:0 auto 22px}
.login-card h1{font-size:20px;margin:0 0 5px;text-align:center}
.login-card .sub{color:var(--muted);font-size:13px;text-align:center;margin-bottom:26px}
.login-card .field{margin-bottom:14px}
.login-card input{width:100%;padding:11px 13px;border:1px solid var(--line);border-radius:10px;font:inherit;font-size:14px}
.login-err{display:none;background:#fde8ec;color:var(--bad);border:1px solid #f6c2cd;border-radius:10px;
  padding:10px 13px;font-size:13px;margin-bottom:14px}
.login-err.show{display:block}

/* ── Botones ── */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:7px;border:1px solid var(--line);
  background:#fff;color:var(--ink);font:inherit;font-size:13.5px;font-weight:700;padding:9px 16px;
  border-radius:10px;cursor:pointer;transition:.14s;white-space:nowrap}
.btn:hover{border-color:var(--hs);background:var(--hs-50)}
.btn:disabled{opacity:.5;cursor:not-allowed}
.btn svg{flex-shrink:0}
.btn-primary{border:none;color:#fff;background:linear-gradient(105deg,var(--hs-deep) 0%,var(--hs-dark) 48%,var(--hs) 100%);box-shadow:var(--shadow)}
.btn-primary:hover{filter:brightness(1.07);background:linear-gradient(105deg,var(--hs-deep) 0%,var(--hs-dark) 48%,var(--hs) 100%)}
.btn-danger{border-color:#f6c2cd;color:var(--bad);background:#fff}
.btn-danger:hover{background:#fde8ec;border-color:var(--bad)}
.btn-sm{font-size:12.5px;padding:6px 11px;border-radius:9px}
.btn-icon{padding:6px;width:30px;height:30px;border-radius:8px}
.rowacts{display:flex;gap:5px;justify-content:flex-end}

/* ── Barra de acciones sobre tabla ── */
.tbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:14px}
.tbar .spacer{flex:1}
.tbar .count{font-size:12.5px;color:var(--muted);font-weight:600}

/* ── Modal ── */
.modal{position:fixed;inset:0;z-index:90;display:none;align-items:flex-start;justify-content:center;
  background:rgba(5,75,78,.42);backdrop-filter:blur(2px);padding:40px 20px;overflow-y:auto}
.modal.show{display:flex}
.modal-card{width:100%;max-width:430px;background:#fff;border-radius:14px;box-shadow:0 24px 60px rgba(5,75,78,.3);
  animation:mpop .16s ease-out}
@keyframes mpop{from{transform:translateY(-10px);opacity:0}to{transform:none;opacity:1}}
.modal-card.wide{max-width:760px}
.modal-h{display:flex;align-items:center;gap:10px;padding:13px 18px;border-bottom:1px solid var(--line)}
.modal-h h3{margin:0;font-size:15px;font-weight:800}
.modal-h .x{margin-left:auto;border:none;background:transparent;cursor:pointer;color:var(--muted);
  font-size:20px;line-height:1;padding:0 4px;border-radius:7px}
.modal-h .x:hover{background:var(--hs-50);color:var(--ink)}
.modal-b{padding:16px 18px;max-height:calc(100vh - 210px);overflow-y:auto}
.modal-f{display:flex;gap:8px;justify-content:flex-end;padding:11px 18px;border-top:1px solid var(--line);background:#fbfdfd;border-radius:0 0 14px 14px}

/* ── Formularios ──────────────────────────────────────────────────────────
   Compactos a propósito: etiqueta pequeña pegada a su campo y nada más. Las
   mayúsculas con letter-spacing de la v1.0 ocupaban el doble y gritaban en un
   diálogo de cinco campos. Lo que se pueda decir en el placeholder no se dice
   en una nota debajo.                                                        */
.form-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:10px 12px}
.form-grid .full{grid-column:1 / -1}
@media(max-width:620px){.form-grid{grid-template-columns:1fr}}
.frm{display:flex;flex-direction:column;gap:3px}
.frm label{font-size:11.5px;color:var(--muted);font-weight:600;line-height:1.2}
.frm label .req{color:var(--bad);margin-left:2px}
/* :not([type=checkbox]) es imprescindible. Sin él, este `width:100%` gana por
   especificidad a `.switch{width:34px}` (0-1-1 frente a 0-1-0) y el
   interruptor se estira a todo el ancho aplastando su etiqueta. */
.frm input:not([type=checkbox]),.frm select,.frm textarea{padding:7px 10px;border:1px solid var(--line);
  border-radius:8px;font:inherit;font-size:13.5px;background:#fff;color:var(--ink);width:100%}
.frm textarea{resize:vertical;min-height:60px}
.frm input:not([type=checkbox]):focus,.frm select:focus,.frm textarea:focus{outline:2px solid var(--hs);border-color:var(--hs);outline-offset:-1px}
.frm input.err,.frm select.err,.chk-list.err{border-color:var(--bad);outline-color:var(--bad)}
.frm .hint{font-size:11px;color:var(--muted);line-height:1.3}
/* ── Interruptor ──────────────────────────────────────────────────────────
   Sustituye a la casilla nativa: se ve el estado de un vistazo desde lejos y
   el área pulsable es el propio control, no la fila entera.                  */
/* Se cualifica como input.switch para no depender del orden de las reglas:
   cualquier estilo genérico de input del formulario queda por debajo. */
input.switch{appearance:none;-webkit-appearance:none;flex:0 0 34px;position:relative;cursor:pointer;
  width:34px;min-width:34px;max-width:34px;height:19px;box-sizing:border-box;
  margin:0;padding:0;border:none;border-radius:999px;
  background:#cfdadc;transition:background .16s}
.switch::after{content:"";position:absolute;top:2px;left:2px;width:15px;height:15px;border-radius:50%;
  background:#fff;box-shadow:0 1px 3px rgba(5,75,78,.28);transition:transform .16s}
.switch:checked{background:var(--hs)}
.switch:checked::after{transform:translateX(15px)}
.switch:focus-visible{outline:2px solid var(--hs);outline-offset:2px}
.switch:disabled{opacity:.45;cursor:not-allowed}
@media (prefers-reduced-motion: reduce){.switch,.switch::after{transition:none}}

/* Booleano suelto del formulario: etiqueta a la izquierda, interruptor a la
   derecha, alineado con el borde de los demás campos. */
.frm-check{flex-direction:row;align-items:center;justify-content:space-between;gap:12px;
  min-height:31px;padding:0 2px}
.frm-check label{font-size:13px;color:var(--ink);font-weight:600;cursor:pointer}

/* ── Toasts ── */
#toasts{position:fixed;right:20px;bottom:20px;z-index:120;display:flex;flex-direction:column;gap:9px;align-items:flex-end}
.toast{display:flex;align-items:center;gap:10px;background:#fff;border:1px solid var(--line);border-left:4px solid var(--hs);
  border-radius:11px;padding:12px 17px;box-shadow:0 10px 30px rgba(5,75,78,.18);font-size:13.5px;font-weight:600;
  max-width:380px;animation:tin .18s ease-out}
@keyframes tin{from{transform:translateX(18px);opacity:0}to{transform:none;opacity:1}}
.toast.out{animation:tout .2s ease-in forwards}
@keyframes tout{to{transform:translateX(18px);opacity:0}}
.toast.ok{border-left-color:var(--ok)} .toast.err{border-left-color:var(--bad)} .toast.warn{border-left-color:var(--warn)}

/* ── Estados de carga / vacío ── */
.loading{display:flex;align-items:center;justify-content:center;gap:11px;padding:46px;color:var(--muted);font-size:13.5px}
.spin{width:17px;height:17px;border:2.5px solid var(--hs-100);border-top-color:var(--hs);border-radius:50%;animation:sp .7s linear infinite}
/* Velo de espera. Por encima del modal (90) porque a veces lo sustituye al
   cerrarse, y por debajo de los toasts (120) para no tapar el resultado. */
.velo{position:fixed;inset:0;z-index:95;display:none;align-items:center;justify-content:center;background:rgba(5,75,78,.26)}
.velo.show{display:flex}
.velo-caja{display:flex;align-items:center;gap:11px;background:#fff;border-radius:14px;
  padding:16px 24px;box-shadow:var(--shadow);font-size:14px;font-weight:600;color:var(--ink)}
@keyframes sp{to{transform:rotate(360deg)}}
.empty-cta{padding:52px 24px;text-align:center;color:var(--muted)}
.empty-cta h4{margin:0 0 7px;font-size:15.5px;color:var(--ink);font-weight:800}
.empty-cta p{margin:0 0 18px;font-size:13.5px}

/* ── Permisos: badges de rol ── */
.role{font-size:10.5px;font-weight:800;padding:2px 9px;border-radius:999px;letter-spacing:.3px;
  text-transform:uppercase;border:1px solid}
.role.admin{background:var(--hs-50);color:var(--hs-dark);border-color:var(--hs-100)}
.role.editor{background:#e2f1fb;color:var(--info);border-color:#bae0f7}
.role.viewer{background:#f1f5f6;color:var(--muted);border-color:#e2eaeb}
/* ── Permisos, por bloques ────────────────────────────────────────────────
   Un bloque por tipo de permiso —Ver, Crear, Editar, Borrar— y dentro UNA
   FILA POR APARTADO, a lo ancho: casilla, nombre y el estado escrito.

   Antes fue una matriz de apartados por acciones y luego una rejilla de
   varias columnas. Las dos fallaban por lo mismo: la vista se cruzaba entre
   celdas de apartados que no tienen nada que ver y no se sabía qué estaba
   marcando cada casilla. En una lista de una columna eso no puede pasar.

   Los bloques sí van en dos columnas cuando el modal da el ancho: son
   independientes entre sí, y apilados en vertical harían 1.000 px de scroll. */
.perm-bloques{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));
  gap:14px;align-items:start}
.perm-bloque{border:1px solid var(--line);border-radius:12px;overflow:hidden}
.perm-bloque>header{padding:9px 13px;background:var(--hs-50);
  border-bottom:1px solid var(--line);display:grid;
  grid-template-columns:1fr auto;gap:2px 9px;align-items:baseline}
.pb-tit{font-size:13px;font-weight:800;letter-spacing:.4px;text-transform:uppercase;
  color:var(--hs-dark)}
/* De cuántos apartados tiene ESTE permiso: la respuesta a «qué permisos
   tiene» se lee en las cuatro cabeceras, sin recorrer las listas. */
.pb-cuenta{justify-self:end;font-size:11px;font-weight:800;letter-spacing:.3px;
  padding:2px 9px;border-radius:999px;background:#fff;border:1px solid var(--hs-100);
  color:var(--hs-dark);white-space:nowrap}
.pb-cuenta.cero{background:#f1f5f6;border-color:#e2eaeb;color:var(--muted)}
.pb-cuenta.todos{background:#e7f7ee;border-color:#b7e6c9;color:var(--ok)}
/* Qué significa el permiso. En la cabecera y no en un tooltip: es la duda que
   aparece justo al repartirlos. */
.pb-que{font-size:12px;color:var(--muted);grid-column:1}
.pb-atajos{display:flex;gap:9px;justify-self:end;grid-column:2}

/* La lista: una fila por apartado, sin columnas. */
.pb-lista{padding:4px 0 6px}
/* El grupo del menú, como separador de la lista: así los apartados del Panel
   Admin se buscan donde se buscan en el menú. */
.pb-grupo{font-size:10px;font-weight:800;letter-spacing:.6px;text-transform:uppercase;
  color:var(--na);padding:9px 13px 4px;margin-top:4px;border-top:1px solid var(--line)}
.pb-grupo:first-child{margin-top:0;border-top:none}

/* La fila entera es el área pulsable, no los 13 px del cuadradito. */
.pb-fila{display:flex;align-items:center;gap:10px;padding:6px 13px;
  font-size:13.5px;cursor:pointer;border-left:3px solid transparent}
.pb-fila:hover{background:var(--hs-50)}
.pb-fila input{accent-color:var(--hs);margin:0;cursor:pointer;flex:none;
  width:15px;height:15px}
.pb-nom{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* El estado, escrito. Un cuadradito marcado o sin marcar se lee mal de un
   vistazo cuando hay veintiocho; «Sí» y «No» no tienen esa duda. Lo pone el
   CSS a partir de la propia casilla, sin JS que pueda desincronizarse. */
.pb-estado{flex:none;font-size:11px;font-weight:800;letter-spacing:.3px;
  color:var(--na);min-width:22px;text-align:right}
.pb-estado::after{content:'No'}
.pb-fila input:checked ~ .pb-estado{color:var(--ok)}
.pb-fila input:checked ~ .pb-estado::after{content:'Sí'}
/* Lo que se aparta del rol base, que es lo único que se guarda. */
.pb-fila.dif{background:#fff8e6;border-left-color:#e8bf4d}
.pb-fila:has(input:disabled){cursor:default}
.pb-fila:has(input:disabled):hover{background:transparent}
.perm-ref{color:#7a5b09;background:#fff8e6;border:1px solid #f3d98a;
  border-radius:5px;padding:0 5px}

/* «todo» y «nada» de cada bloque. Discretos: son atajos, no la acción
   principal, pero sin ellos repartir permisos son veintiocho clics. */
.perm-todo{border:none;background:none;padding:0;cursor:pointer;
  font:inherit;font-size:10px;font-weight:700;letter-spacing:.3px;
  text-transform:uppercase;color:var(--na);text-decoration:underline}
.perm-todo:hover{color:var(--hs)}

.perm-atajos{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:14px}
.perm-atajos>span{font-size:12px;color:var(--muted);font-weight:600}

/* ── Tabla: fila clicable + sin datos ── */
tbody tr.clickable{cursor:pointer}
td.acts{width:1%;white-space:nowrap;text-align:right}

/* ── Selección múltiple con casillas ─────────────────────────────────────── */
.chk-list{border:1px solid var(--line);border-radius:8px;max-height:190px;
  overflow-y:auto;overflow-x:hidden;background:#fff}
.chk-item{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:6px 10px;cursor:pointer;border-bottom:1px solid var(--line);font-size:13px;transition:.1s}
.chk-item:last-child{border-bottom:none}
.chk-item:hover{background:var(--hs-50)}
/* Nombre y detalle juntos a la izquierda; el detalle en gris, a continuación
   del nombre y no descolgado al otro extremo de la fila.
   min-width:0 permite que el nombre se recorte con puntos suspensivos en vez
   de ensanchar la fila y sacar el interruptor fuera de la caja. */
.chk-txt{display:flex;align-items:baseline;gap:7px;min-width:0;flex:1}
.chk-lbl{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
.chk-nota{font-size:11px;color:var(--muted);white-space:nowrap;flex:none}
/* Buscador de las listas largas. Se cualifica el ocultado con la clase porque
   .chk-item trae su propio display:flex y con [hidden] a secas ganaría el que
   estuviera escrito después. */
.chk-find{margin-bottom:7px}
/* Filtro de un desplegable largo: va justo encima y más discreto que él, para
   que no compita con el control de verdad. */
.frm input.sel-find{padding:5px 9px;margin-bottom:4px;font-size:12px}
.frm input.sel-find.sin-resultado{border-color:var(--bad);background:#fff7f8}
.chk-item[hidden]{display:none}
.chk-nada{padding:14px 12px;text-align:center;font-size:12.5px;color:var(--muted)}
.chk-nada[hidden]{display:none}
/* Recuento junto a la etiqueta: con la lista filtrada hay que poder saber
   cuántos llevas marcados sin borrar la búsqueda. */
.chk-cuenta{float:right;font-weight:600;font-size:11px;color:var(--hs-dark);text-transform:none;letter-spacing:0}

/* ── Secciones apiladas en una misma vista ────────────────────────────────
   Con la exposición y el stock en la misma pantalla hacen falta separadores
   claros y tarjetas más densas que a página completa.                       */
.sec-h{display:flex;align-items:center;gap:10px;margin:22px 0 10px}
.sec-h:first-child{margin-top:0}
.sec-h .spacer{flex:1}
.sec-h .section-title{margin:0;font-size:14px;text-transform:uppercase;
  letter-spacing:.5px;color:var(--hs-dark)}

/* Cabecera de tarjeta reducida */
.gteam-h.compacta{font-size:14px;margin-bottom:10px;gap:8px}
.gteam-h.compacta .tit{font-weight:700;min-width:0;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.gteam-h.compacta .badges{gap:6px}
.gteam-h.compacta .src-badge{font-size:11px;padding:3px 8px}

/* ── Tabla dentro de tarjeta ───────────────────────────────────────────────
   Más apretada que las de pantalla completa y con contorno propio.

   Llevaba `class="mini"`, que es la píldora de las etiquetas: fondo cian,
   texto turquesa, negrita, versalitas y esquinas de 999px. Las celdas lo
   heredaban todo, así que las cifras de stock salían en turquesa sobre
   turquesa —3.4:1 de contraste— y no se podían leer. Con clase propia no hay
   colisión posible.

   Cabecera y fila de total son de marca, en cian sólido con el texto en
   blanco y no turquesa sobre turquesa: así son 4.5:1 de contraste en vez de
   3.4:1. Entre las dos encierran la tabla, y el cuerpo se queda neutro porque
   lo que hay que leer ahí son cifras.                                        */
/* La tabla es blanca y la tarjeta también, así que sin ayuda se funden. Aquí
   el trazo sí va en negro: es la excepción a haberlos quitado de tarjetas y
   KPIs, porque allí el borde delimitaba algo que ya estaba suelto sobre el
   fondo y aquí tiene que recortar una tabla incrustada en otra caja blanca.

   `border-collapse:separate` es imprescindible. Con el `collapse` que traen
   todas las tablas, el borde de la tabla se funde con el de las celdas y el
   navegador deja de aplicar el `border-radius`: el trazo salía recto por fuera
   del contenido redondeado, y en vez de recortar la tabla parecía un cuadro
   suelto alrededor de la tarjeta. Con `separate` el borde es de la tabla y
   sigue sus esquinas; `border-spacing:0` mantiene las celdas pegadas.        */
.gtabla{border-collapse:separate;border-spacing:0;border-radius:10px;border:1px solid #000}
.gtabla th{background:var(--hs-dark);color:#fff;font-size:10px;padding:7px 9px}
.gtabla td{padding:6px 9px;font-size:12.5px}
.gtabla tbody tr:hover{background:var(--hs-50)}
/* El total cierra la tabla igual que la cabecera la abre. Va en el td y no en
   el tr para que el fondo se pinte por encima del hover de la fila.
   Por dentro, los separadores se quedan en la línea suave de siempre: el negro
   es el contorno de la tabla, no su rejilla. */
.gtabla tr.tot td{background:var(--hs-dark);color:#fff;
  border-top:1px solid var(--line)}
.gtabla .tag{font-size:10.5px;padding:2px 7px}

/* ═══════════════════════════════════════════════════════════════════════════
   PLANOGRAMA DIBUJADO · lo pinta js/planograma-vista.js
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Isla · el mueble visto desde arriba ───────────────────────────────────
   Rejilla de tres por tres: los huecos ocupan los cuatro lados y el mueble va
   en el centro. Las esquinas se quedan vacías a propósito, que es donde un
   mueble real no tiene frente que mirar.                                     */
.pgmap{display:grid;grid-template-columns:auto minmax(0,1fr) auto;
  grid-template-rows:auto minmax(0,1fr) auto;gap:9px;margin:4px 0 2px}
.pg-ar{grid-area:1/2}   .pg-ab{grid-area:3/2}
.pg-iz{grid-area:2/1}   .pg-de{grid-area:2/3}
.pg-ar,.pg-ab{display:flex;gap:9px}
.pg-iz,.pg-de{display:flex;flex-direction:column;gap:9px}
.pg-ar>*,.pg-ab>*,.pg-iz>*,.pg-de>*{flex:1}

/* El cuerpo del mueble. El degradado de marca lo separa de los huecos sin
   competir con ellos: el color que informa es el del borde de cada hueco. */
.pg-isla{grid-area:2/2;min-height:150px;border-radius:14px;position:relative;
  background:linear-gradient(150deg,var(--hs-deep) 0%,var(--hs-dark) 60%,var(--hs) 140%);
  color:#fff;display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:6px;padding:20px 40px;text-align:center}
.pg-isla .n{font-weight:800;font-size:17px;letter-spacing:.2px}
.pg-isla .d{font-size:12px;opacity:.85;font-weight:600;letter-spacing:.3px}

.pgh{border:1.8px solid var(--line);border-radius:11px;background:#fff;
  padding:11px 12px;display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:4px;min-width:0;min-height:56px}
.pgh .m{font-weight:800;font-size:14px;letter-spacing:.2px;line-height:1.15;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.pgh .e{font-size:9.5px;font-weight:800;text-transform:uppercase;letter-spacing:.6px}

/* Los complementos atados a una tele van dentro de su hueco, separados por una
   línea: acompañan a ese producto y no al mueble.

   Separación y línea en propiedades lógicas —`block-start` y no `top`— porque
   en los laterales de la isla el texto va girado: con las físicas la línea
   salía por encima en vez de por delante del nombre. */
.pg-acomp{display:block;margin-block-start:5px;padding-block-start:4px;
  border-block-start:1px dashed var(--line);
  font-size:10px;font-weight:700;color:var(--muted);letter-spacing:.2px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.ptv .pg-acomp{border-block-start-color:rgba(255,255,255,.22);color:rgba(255,255,255,.72)}

/* Los extremos rotulados sobre el propio cuerpo del mueble, pegados a su lado.
   Ahí es donde se identifican de un vistazo: en el lateral se confundirían con
   un hueco más, y en el mueble se leen como lo que son, dos partes de la isla.

   Van dentro del relleno lateral de .pg-isla, que por eso es más ancho que el
   de arriba y abajo; sin ese hueco el nombre del mueble se les echaría encima. */
/* `justify-content` y no `align-items`: con `writing-mode:vertical-rl` los ejes
   del flex giran con el texto, así que el eje principal pasa a ser el vertical.
   Con `align-items:center` el rótulo se centraba de lado a lado y se quedaba
   pegado arriba. */
.pg-ext{position:absolute;top:0;bottom:0;display:flex;
  align-items:center;justify-content:center;
  writing-mode:vertical-rl;font-size:9px;font-weight:800;text-transform:uppercase;
  letter-spacing:1.6px;color:rgba(255,255,255,.55);padding:0 9px;
  pointer-events:none;user-select:none}
.pg-ext.izq{left:0;transform:rotate(180deg)}
.pg-ext.der{right:0}

/* Los laterales llevan el texto girado, como en un planograma de verdad: de
   abajo arriba en el lado izquierdo y de arriba abajo en el derecho, que es
   como se leen rodeando el mueble. */
.pg-iz .pgh,.pg-de .pgh{writing-mode:vertical-rl;padding:12px 11px;min-height:120px}
.pg-iz .pgh{transform:rotate(180deg)}

/* ── Wall · la pared vista de frente ───────────────────────────────────────
   Se compone por columnas y cada columna puede llevar varias teles apiladas:
   dos pequeñas una encima de otra ocupan el mismo frente que una grande sin
   robarle protagonismo.                                                      */
.pared{border:1px solid var(--line);border-radius:14px;
  background:linear-gradient(180deg,#fbfdfd 0%,#eef5f5 100%);
  padding:26px 22px 0;margin:4px 0 2px}
.pared-fila{display:flex;align-items:center;justify-content:center;gap:10px;
  min-height:140px;margin:0 auto}
.pared-col{display:flex;flex-direction:column;align-items:center;gap:10px;flex:none}

/* El suelo cierra la pared por abajo. Sin él las teles flotan y el dibujo no
   se lee como un lineal. */
.pared-suelo{height:14px;margin:22px -22px 0;border-top:2px solid var(--hs-dark);
  background:repeating-linear-gradient(135deg,#e7eeee 0 6px,#f4f8f8 6px 12px);
  border-radius:0 0 13px 13px}

/* El ancho va en porcentaje del frente y la proporción la fija `aspect-ratio`,
   así que con solo dar el ancho ya sale a escala: una de 100" se ve del doble
   que una de 50" sin calcular la altura. */
.ptv{aspect-ratio:16/9;border-radius:6px;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:2px;overflow:hidden;
  padding:4px;text-align:center;flex:none}
.ptv .m{font-weight:800;font-size:13px;letter-spacing:.2px;line-height:1.15;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.ptv .p{font-size:10px;font-weight:700;opacity:.75}

/* ── Estados ───────────────────────────────────────────────────────────────
   En la isla el color va en el borde y en el rótulo, no en el fondo: con seis
   huecos rellenos de color la tarjeta se convertía en un semáforo.

   En el wall se aprovecha que la tele es un objeto: montada es una pantalla
   encendida y ausente es el hueco de la pared, vacío y con el contorno
   partido. La diferencia se ve antes de leer ningún rótulo.                  */
.pgh.plano{border-color:var(--line)}  .pgh.plano .m{color:var(--ink)}
.pgh.ok   {border-color:var(--ok)}    .pgh.ok    .m,.pgh.ok    .e{color:var(--ok)}
.pgh.falta{border-color:var(--bad)}   .pgh.falta .m,.pgh.falta .e{color:var(--bad)}
.pgh.nd   {border-style:dashed}       .pgh.nd    .m,.pgh.nd    .e{color:var(--na)}

/* Otro modelo en el hueco. Arriba y en ámbar el que HAY puesto, debajo y en
   gris el que el planograma pide. El hueco NO está vacío, así que no puede
   leerse igual que un rojo. */
.pgh.otro {border-color:var(--warn)}
.pgh.otro .m,.pgh.otro .e{color:var(--warn)}
.pgh .s{font-size:11px;font-weight:700;color:var(--na);letter-spacing:.2px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}

.ptv.plano{background:linear-gradient(160deg,#1b3c46,#12262e);color:#fff;
           box-shadow:0 3px 10px rgba(5,75,78,.22)}
.ptv.ok   {background:linear-gradient(160deg,#12303a,#0a1c22);color:#fff;
           box-shadow:0 3px 10px rgba(5,75,78,.28);outline:1.5px solid var(--ok);
           outline-offset:-1.5px}
/* Encendida igual que una correcta —hay una tele puesta— pero con el marco
   ámbar: lo que falla es el modelo, no la exposición. */
.ptv.otro {background:linear-gradient(160deg,#12303a,#0a1c22);color:#fff;
           box-shadow:0 3px 10px rgba(5,75,78,.28);outline:2px solid var(--warn);
           outline-offset:-2px}
.ptv.falta{background:#fff;border:2px dashed var(--bad);color:var(--bad)}
.ptv.nd   {background:#fff;border:2px dashed var(--line);color:var(--na)}
/* Lo que el planograma pide, debajo del que hay puesto: en gris, que es la
   referencia y no el dato. */
.ptv .s{font-size:10.5px;font-weight:700;color:rgba(255,255,255,.55);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.ptv.otro .m{color:var(--warn)}

/* ── Expuestas fuera del planograma ────────────────────────────────────────
   Las teles que están en la tienda y el mueble no pide. Se dibujan a la misma
   escala que los muebles —de ahí que compartan `.ptv`— pero sin pared ni
   suelo: no son un mueble, están sueltas.                                    */
.pgsueltas{margin-top:2px}
.pgsueltas .t{font-size:10px;font-weight:800;text-transform:uppercase;
  letter-spacing:.5px;color:var(--warn);margin-bottom:9px}

/* Tarjeta propia, cruzando las dos columnas de la rejilla: lo que está fuera
   no es de ningún mueble, es de la tienda. */
.gfuera{grid-column:1 / -1}
/* Las teles van de lado a lado y las que no caben pasan solas a la siguiente
   fila. Con la escala en píxeles, el envoltorio se encarga de la
   responsividad: no hay que repartirlas a mano ni recalcular al cambiar el
   ancho de la ventana.

   Alineadas abajo y a la izquierda para que todas apoyen en la misma línea y
   sus tamaños se puedan comparar de un vistazo. */
.pgsueltas .fila{display:flex;flex-wrap:wrap;align-items:flex-end;gap:10px 12px}

/* El ancho a escala lo lleva la columna y la tele ocupa todo el suyo.
   `max-width` para la pantalla estrecha: una de 100" mide 240px y en un móvil
   se saldría de la tarjeta. */
.pgcol-tv{display:flex;flex-direction:column;flex:0 0 auto;
  min-width:0;max-width:100%}
.pgcol-tv .ptv{width:100%}

/* Quitar de la exposición. En la esquina y solo al pasar por encima: es
   destructivo y no debe estar pidiendo que lo pulsen.

   En los dos, hueco de isla y tele de wall. Antes solo se revelaba sobre
   `.ptv` y en las islas se quedaba invisible para siempre. */
.ptv,.pgh{position:relative}
.pgquitar{position:absolute;top:3px;right:3px;width:18px;height:18px;padding:0;
  border:none;border-radius:50%;background:rgba(0,0,0,.14);color:var(--ink);
  font-size:14px;line-height:1;cursor:pointer;opacity:0;transition:.12s}
.ptv .pgquitar{background:rgba(255,255,255,.16);color:#fff}
.ptv:hover .pgquitar,.pgh:hover .pgquitar{opacity:1}
.pgquitar:hover{background:var(--bad);color:#fff}
.pgquitar:focus-visible{opacity:1;outline:2px solid var(--hs)}
/* Vacío es solo la zona de soltada, así que se apaga: en gris y con el borde
   partido, para que no parezca una sección con contenido que falta. */
.pgsueltas.sin{border:1px dashed var(--line);border-top:1px dashed var(--line);
  padding:11px 12px;text-align:center}
.pgsueltas.sin .t{color:var(--na);margin:0;text-transform:none;
  font-weight:600;letter-spacing:0;font-size:11.5px}

/* Encendidas y sin color: están puestas y no son un fallo. Que no vayan en el
   planograma ya lo dice el sitio donde están, y pintarlas de ámbar las hacía
   parecer un problema que resolver. */
.ptv.suelta{background:linear-gradient(160deg,#12303a,#0a1c22);color:#fff;
  box-shadow:0 3px 10px rgba(5,75,78,.24);cursor:grab}
.ptv.suelta:active{cursor:grabbing}

/* Lo que no tiene hueco donde ir: complementos y lo montado que el planograma
   no pide. El brand display no dice en qué hueco está cada cosa, así que va
   debajo del dibujo y no dentro. */
.pg-fuera{display:flex;flex-wrap:wrap;align-items:center;gap:7px;
  margin-top:12px;padding-top:11px;border-top:1px solid var(--line)}
.pg-fuera .t{font-size:10px;font-weight:800;text-transform:uppercase;
  letter-spacing:.5px;color:var(--muted)}
.pg-chip{border:1.4px dashed var(--warn);color:var(--warn);border-radius:999px;
  padding:3px 10px;font-size:11.5px;font-weight:800}
.pg-chip.compl{border-style:solid;border-color:var(--line);color:var(--muted)}

/* ═══════════════════════════════════════════════════════════════════════════
   CONSECUCIÓN DE INFORMES · rejilla de tiendas por semanas
   ═══════════════════════════════════════════════════════════════════════════ */

/* Pie de leyenda. Se quitó en la limpieza al dejar de usarlo Gestión Tiendas
   y vuelve aquí: una rejilla de puntos de colores no se entiende sin él. */
.legend{display:flex;gap:14px;flex-wrap:wrap;margin:14px 2px 0;font-size:12px;color:var(--muted)}
.legend span{display:flex;align-items:center;gap:5px}

/* Con quince columnas de marcas la tabla puede irse del ancho de la pantalla.
   Se desplaza ella sola en vez de encoger las columnas hasta que no se lean, y
   el nombre de la tienda se queda fijo a la izquierda. */
.cs-scroll{overflow-x:auto;padding-bottom:4px}
.cs-tabla{min-width:100%}
.cs-tabla td,.cs-tabla th{white-space:nowrap}
.cs-tabla tbody td:first-child{position:sticky;left:0;background:#fff;z-index:1}
.cs-tabla tbody tr:hover td:first-child{background:var(--hs-50)}

/* Cinco semanas seguidas hacen quince columnas de marcas: sin una línea al
   empezar cada semana no se sabe qué ✓ es de cuál. Va donde arranca el grupo,
   no rodeándolo, que sería una rejilla.

   Las columnas van estrechas para que las quince quepan sin desplazar la
   tabla: dentro solo hay un ✓ o una ✗. */
.cs-g{border-left:1px solid var(--line)}
.cs-inf{font-size:9px;letter-spacing:.4px;color:var(--muted);width:42px}

/* ── Centrado ──────────────────────────────────────────────────────────────
   En Planogramas el dibujo se acota y se centra, pero conserva su tamaño: las
   piezas, los colores y las proporciones son los mismos que en Gestión
   Tiendas. Lo que sobraba era el estirón — a lo ancho de un monitor grande la
   isla separaba tanto los huecos que dejaba de leerse como un mueble.        */
.pgv-centrado{max-width:860px;margin-left:auto;margin-right:auto}

/* ── Cambiar un modelo de sitio ────────────────────────────────────────────
   Se arrastra una pieza sobre otra y se intercambian. Intercambio y no
   inserción: en un mueble los huecos son sitios fijos, así que mover uno no
   debe desplazar a los demás en cadena.                                      */
.pgv-mover .pgh,.pgv-mover .ptv{cursor:grab}
.pgv-mover .pgh:active,.pgv-mover .ptv:active{cursor:grabbing}
/* Los rótulos de dentro no reciben eventos: si los recibieran, pasar el cursor
   de la pieza a su texto contaría como salir de la pieza y el recuadro de
   destino parpadearía todo el rato.

   El botón de quitar sí, que para eso está. Sin esta excepción no se podía
   pulsar dentro de un mueble, ni en isla ni en wall. */
.pgv-mover .pgh>*,.pgv-mover .ptv>*,
.pgv-colocar .pgh>*,.pgv-colocar .ptv>*{pointer-events:none}
.pgv-mover .pgquitar,.pgv-colocar .pgquitar{pointer-events:auto}

/* ── Colocar lo reportado en su hueco (Gestión Tiendas) ────────────────────
   Se arrastra desde la tabla de exposición, desde las etiquetas de sobrantes
   y desde los propios huecos.                                               */
/* El sitio es una suposición por pulgadas: el informe dice que está montada,
   no en qué hueco. El punteado bajo el modelo lo avisa; al arrastrarla, deja
   de serlo. */
.pgh[data-supuesto] .m,.ptv[data-supuesto] .m{border-bottom:1.5px dotted currentColor}

.pgv-colocar .pgh,.pgv-colocar .ptv{cursor:grab}
.pgv-colocar .pgh:active,.pgv-colocar .ptv:active{cursor:grabbing}
.pg-fuera[data-modelos] .pg-chip,.pg-fuera[data-compls] .pg-chip{cursor:grab}
.pg-fuera[data-modelos] .pg-chip:active,.pg-fuera[data-compls] .pg-chip:active{cursor:grabbing}
.pg-chip.pgv-llevando{opacity:.35}
.pg-fuera.pgv-diana{outline:2.5px dashed var(--hs);outline-offset:3px;border-radius:8px}
/* Sacar una tele de un hueco es devolverla a las expuestas fuera, así que ese
   bloque entero es zona de soltada. Con alto mínimo para que se pueda apuntar
   a él cuando aún no hay ninguna. */
.pgsueltas{min-height:40px;border-radius:8px}
.pgsueltas.pgv-diana{outline:2.5px dashed var(--hs);outline-offset:3px}
.ptv.suelta.pgv-llevando{opacity:.35}
/* El asidero de «Exposición vs stock»: se agarra el nombre del modelo, no la
   fila entera. Arrastrar la fila llevaba tras el cursor una franja de tabla
   con sus cifras y su estado, cuando lo que se coloca es un producto. */
.pg-agarre{display:inline-block;cursor:grab;border-radius:6px;
  padding:1px 6px;margin:-1px -6px;transition:background .12s,box-shadow .12s}
.pg-agarre:hover{background:var(--hs-50);box-shadow:inset 0 0 0 1px var(--hs-100)}
.pg-agarre:active{cursor:grabbing}
.pg-agarre.pgv-llevando{opacity:.35}

/* Expuesto según el stock, pero el informe no lo menciona. Ni sí ni no: la
   pregunta no se le hizo a nadie, y por eso no vale el ✓/✗ de las demás. */
.chk.f{background:#fdf1e3;color:var(--warn);border:1px solid #f7dcb8;
  border-radius:999px;padding:1px 8px;font-size:10px;font-weight:800;
  letter-spacing:.5px}

.pgv-llevando{opacity:.35}
.pgv-diana{outline:2.5px dashed var(--hs);outline-offset:2px}
.pgv-ayuda{font-size:11.5px;color:var(--muted);margin:10px 2px 0;
  display:flex;align-items:center;gap:6px}
.pgv-ayuda svg{width:13px;height:13px;flex:none;color:var(--hs)}
/* La última columna respira: con el relleno normal, una marca centrada en una
   columna estrecha queda encajada contra el trazo del borde. */
.gtabla th:last-child,.gtabla td:last-child{padding-right:16px}

/* ── Listado lateral plegable ─────────────────────────────────────────────
   Se anima el ancho y no `display`, para que el colapso se vea. El contenido
   se recorta con overflow en lugar de reflowarse mientras encoge.          */
aside{transition:width .18s ease,padding .18s ease,border-color .18s ease}
aside.plegado{width:0;padding-left:0;padding-right:0;overflow:hidden;border-right-color:transparent}

.asidetop{display:flex;align-items:center;gap:8px;margin:2px 2px 8px}
.asidetop .asidehead{margin:0;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

.aside-tog{flex:none;display:inline-flex;align-items:center;justify-content:center;
  width:24px;height:24px;border:1px solid var(--line);background:#fff;border-radius:7px;
  color:var(--muted);cursor:pointer;transition:.12s}
.aside-tog:hover{border-color:var(--hs);background:var(--hs-50);color:var(--hs-dark)}

/* Pestaña de reapertura, pegada al borde del contenido */
.aside-show{display:none;position:sticky;top:78px;align-self:flex-start;flex:none;
  width:22px;height:52px;margin:14px 0 0;border:1px solid var(--line);border-left:none;
  background:#fff;border-radius:0 9px 9px 0;color:var(--muted);cursor:pointer;
  align-items:center;justify-content:center;box-shadow:2px 0 8px rgba(5,75,78,.06);transition:.12s}
.aside-show:hover{background:var(--hs-50);border-color:var(--hs);color:var(--hs-dark)}
.aside-show.on{display:flex}

@media(max-width:880px){.aside-show{display:none !important}}
@media (prefers-reduced-motion: reduce){aside{transition:none}}


/* ── Grupos plegables del sidebar ────────────────────────────────────────── */
.navgroup{display:flex;flex-direction:column;flex-shrink:0}
.navgroup-h{appearance:none;border:none;background:transparent;color:rgba(255,255,255,.72);
  font-family:inherit;font-weight:700;font-size:11px;text-transform:uppercase;letter-spacing:.6px;
  padding:11px 14px 9px;cursor:pointer;border-radius:11px;display:flex;align-items:center;gap:10px;
  width:100%;text-align:left;transition:.12s}
.navgroup-h:hover{color:#fff;background:rgba(255,255,255,.08)}
.navgroup-h .gcaret{margin-left:auto;flex:none;transition:transform .16s ease;opacity:.75}
.navgroup.open .navgroup-h{color:#fff}
.navgroup.open .navgroup-h .gcaret{transform:rotate(90deg)}
.navgroup-h .tab-ic{width:16px;height:16px}

/* El plegado anima sobre grid-template-rows: sirve sin conocer la altura de
   antemano, a diferencia de max-height con un valor inventado a ojo. */
.navgroup-b{display:grid;grid-template-rows:0fr;transition:grid-template-rows .18s ease}
.navgroup.open .navgroup-b{grid-template-rows:1fr}
.navgroup-b>div{overflow:hidden;display:flex;flex-direction:column;gap:3px}
.navgroup-b .tab{font-size:13px;padding:9px 13px 9px 22px;margin-top:2px;position:relative}

/* Guía vertical que ata visualmente los hijos a su grupo */
.navgroup-b .tab::before{content:"";position:absolute;left:11px;top:7px;bottom:7px;width:2px;
  border-radius:2px;background:rgba(255,255,255,.16)}
.navgroup-b .tab.on::before{background:var(--hs)}

/* Grupo cerrado con la sección activa dentro: un punto avisa de dónde estás */
.navgroup-h .gdot{width:6px;height:6px;border-radius:50%;background:var(--hs);flex:none;
  margin-left:auto;box-shadow:0 0 0 3px rgba(0,179,172,.25)}
.navgroup.open .navgroup-h .gdot{display:none}
@media (prefers-reduced-motion: reduce){
  .navgroup-b{transition:none}
  .navgroup-h .gcaret{transition:none}
}
