/* ============================================================================
   brand.css — Sistema de diseño unificado de Deglia (BI + Consola)
   ----------------------------------------------------------------------------
   Fuente de verdad ÚNICA de la estética. Tanto el tablero (index.html) como la
   consola (console.html) enlazan este archivo y usan los mismos tokens y
   componentes base. Lenguaje visual tomado de la web nueva (deglia-web3d):
   fondos oscuros, tipografía display Bricolage Grotesque + mono JetBrains,
   acentos rosa/violeta, hover con lift sutil, radios y sombras generosas.

   COLOR POR-TENANT (crítico)
   --------------------------
   El color de marca es una CSS-var: --brand (primario) y --accent (acento).
   Deglia por default = rosa #E7399A (brand y accent) — negro/gris/rosa.
   Para tematizar un cliente NO se toca ningún componente: basta con inyectar
   un override de estas dos vars en el <html> o en un <style> por-tenant, ej:

       <html data-theme="dark" style="--brand:#0aa; --accent:#f60">

   o servido dinámicamente por el backend:

       :root{ --brand:#0aa; --brand-rgb:0,170,170; --accent:#f60; --accent-rgb:255,102,0; }

   Todo lo demás (grises, spacing, radios, tipografía) es neutro y compartido.
   NB: --pink queda como alias de --accent por retrocompatibilidad (el CSS y el
   JS histórico referencian --pink); no hardcodear #E7399A en componentes nuevos.
   ============================================================================ */

/* ---------------------------------------------------------------------------
   1) TOKENS DE MARCA (por-tenant) — lo único que un cliente sobreescribe
   --------------------------------------------------------------------------- */
:root{
  /* Marca Deglia por default: ROSA #E7399A es el primario (negro/gris/rosa). Cada tenant puede pisar estas 4 vars. */
  --brand:#E7399A;         /* primario  — rosa Deglia */
  --brand-rgb:231,57,154;  /* mismo rosa en RGB para rgba()/color-mix legacy */
  --accent:#E7399A;        /* acento    — rosa Deglia */
  --accent-rgb:231,57,154; /* mismo rosa en RGB */

  /* Realces derivados (no tocar por-tenant salvo casos avanzados) */
  --brand-soft:color-mix(in srgb, var(--brand) 14%, transparent);
  --brand-line:color-mix(in srgb, var(--brand) 34%, transparent);
  --accent-soft:color-mix(in srgb, var(--accent) 14%, transparent);
  --accent-line:color-mix(in srgb, var(--accent) 34%, transparent);

  /* Alias de compatibilidad — el CSS/JS histórico usa --pink */
  --pink:var(--accent);

  /* --------- Estados semánticos (neutros, compartidos) --------- */
  --pos:#2fb47c; --pos-rgb:47,180,124;
  --neg:#e0604f; --neg-rgb:224,96,79;
  --amber:#e0a23f; --amber-rgb:224,162,63;
  --blue:#4f8ef0; --blue-rgb:79,142,240;

  /* --------- Tipografía --------- */
  --font-sans:'Open Sans',system-ui,-apple-system,Segoe UI,Roboto,sans-serif;
  --font-display:'Sora','Bricolage Grotesque','Open Sans',system-ui,sans-serif;  /* Sora en TODOS los temas (estética web) */
  --font-mono:'JetBrains Mono',ui-monospace,Menlo,Consolas,monospace;

  /* --------- Escala tipográfica --------- */
  --fs-xs:10.5px; --fs-sm:11.5px; --fs-md:12.5px; --fs-base:13px;
  --fs-lg:14.5px; --fs-xl:16px; --fs-2xl:20px; --fs-3xl:26px;

  /* --------- Spacing (base 4) --------- */
  --sp-1:4px; --sp-2:8px; --sp-3:12px; --sp-4:16px; --sp-5:20px; --sp-6:24px; --sp-8:32px;

  /* --------- Radios --------- */
  --r-xs:6px; --r-sm:7px; --r-md:9px; --r-lg:12px; --r-xl:16px; --r-pill:999px;

  /* --------- Duraciones/curvas --------- */
  --dur:.16s; --ease:cubic-bezier(.4,0,.2,1);
}

/* ---------------------------------------------------------------------------
   2) TOKENS DE SUPERFICIE (tema oscuro / claro) — compartidos BI + consola
   --------------------------------------------------------------------------- */
html[data-theme=dark]{
  color-scheme:dark;
  --bg:#0e1014; --panel:#161a20; --panel2:#1c2028; --line:#242a33;
  --txt:#e6e9ef; --mut:#818a99;
  --sb:#11131a; --sbtx:#9aa3b2; --sbstrong:#ffffff; --sbhover:#1c2028; --sbline:#21252e;
  --head:#12141a; --sh:rgba(0,0,0,.22);
  --sh-lg:0 12px 36px rgba(0,0,0,.45);
  --sh-pop:0 12px 30px rgba(0,0,0,.4);
}
html[data-theme=light]{
  color-scheme:light;
  --bg:#eceff4; --panel:#ffffff; --panel2:#f5f7fa; --line:#e2e6ec;
  --txt:#1a1f28; --mut:#697080;
  --sb:#ffffff; --sbtx:#5b636f; --sbstrong:#141414; --sbhover:#eef1f5; --sbline:#e2e6ec;
  --head:#fff; --sh:rgba(20,30,50,.05);
  --sh-lg:0 14px 40px rgba(20,30,50,.14);
  --sh-pop:0 12px 30px rgba(20,30,50,.12);
}
/* Estética de la WEB pública (deglia.xyz): Sora + glass. OPT-IN (perfil → "Estética web"). DOS variantes
   como la web: 'noir' (oscura) y 'noirlight' (clara). "Modo oscuro" alterna dentro del look. Glass sólo en cards/shell. */
html[data-theme=noir]{
  color-scheme:dark; --font-display:'Sora','Bricolage Grotesque',system-ui,sans-serif;
  --bg:#08080b; --panel:#15141c; --panel2:#1c1a24; --line:#2c2935; --txt:#f4f1ec; --mut:#948e97;
  --sb:#0c0b0e; --sbtx:#9a949c; --sbstrong:#ffffff; --sbhover:#1c1a24; --sbline:#221f26;
  --head:#0c0b0e; --sh:rgba(0,0,0,.35); --sh-lg:0 18px 50px rgba(0,0,0,.6); --sh-pop:0 14px 34px rgba(0,0,0,.55);
  --glass:color-mix(in srgb, var(--panel) 80%, transparent); --amb1:rgba(231,57,154,.10); --amb2:rgba(231,57,154,.055); --card-sh:0 1px 0 rgba(255,255,255,.05) inset,0 16px 38px -16px rgba(0,0,0,.6);
}
html[data-theme=noirlight]{
  color-scheme:light; --font-display:'Sora','Bricolage Grotesque',system-ui,sans-serif;
  --bg:#f1f4f9; --panel:#ffffff; --panel2:#eef1f7; --line:#e3e8f0; --txt:#1a1f2b; --mut:#6b7280;
  --sb:#f7f9fc; --sbtx:#6b7280; --sbstrong:#1a1f2b; --sbhover:#eef1f7; --sbline:#e3e8f0;
  --head:#ffffff; --sh:rgba(20,26,40,.05); --sh-lg:0 16px 44px rgba(20,26,40,.12); --sh-pop:0 12px 30px rgba(20,26,40,.10);
  --glass:color-mix(in srgb, var(--panel) 82%, transparent); --amb1:rgba(231,57,154,.06); --amb2:rgba(231,57,154,.04); --card-sh:0 1px 0 rgba(255,255,255,.6) inset,0 12px 28px -14px rgba(20,16,24,.16);
  /* QA 2026-10-10: --pos (verde de variación positiva, ej. "▲15.3% vs mes ant.") se definía UNA sola vez en
     :root para ambos temas -- #2fb47c sobre fondo blanco (noirlight) da 2.64:1 de contraste, bajo el mínimo
     de 4.5:1 para texto chico (WCAG AA). Oscurecido SOLO acá (noir sigue con el verde original, que sí
     contrasta bien sobre fondo oscuro). ~5.4:1 sobre blanco. */
  --pos:#15804a; --pos-rgb:21,128,74;
}
/* fondo ambiente (glow rosa sutil, como el bg de la web) para dar profundidad al glass — ambas variantes */
html[data-theme=noir] body, html[data-theme=noirlight] body{
  background:
    radial-gradient(1200px 820px at 80% -10%, var(--amb1), transparent 60%),
    radial-gradient(1000px 700px at 5% 110%, var(--amb2), transparent 60%),
    var(--bg);
  background-attachment:fixed;
}
/* BENTO SUTIL (Franco: sacar los recuadros pesados). Tiles del tablero = fondo sólido + sombra suave, SIN borde duro
   ni glass/blur (el blur daba sensación de 'marco'). Un hairline apenas visible para definir en claro. */
html[data-theme=noir] .card, html[data-theme=noirlight] .card{
  background:var(--panel);
  border:1px solid color-mix(in srgb,var(--line) 45%,transparent); border-radius:var(--r-xl); box-shadow:var(--card-sh);
}
/* .card-sec usa --panel2 (no --panel): tiene que leerse como "mini-card DENTRO de la card grande" (mismo
   criterio que ya usa .acc, brand.css ~L510) — con --panel (el mismo token que su .card padre) se fundía con
   el fondo y solo se distinguía por el borde/sombra (Franco 2026-10-01: colores distintos entre Roles/Ajustes,
   causa real: dos tokens de fondo —panel/--panel2— mezclados en profundidades de anidamiento distintas). */
html[data-theme=noir] .card-sec, html[data-theme=noirlight] .card-sec{
  background:var(--panel2);
  border:1px solid color-mix(in srgb,var(--line) 45%,transparent); border-radius:var(--r-xl); box-shadow:var(--card-sh);
}
/* Bug real confirmado (Franco 2026-10-01, capturas Marca/Roles: "todo el texto pegado a los bordes"): esta regla
   le dio a `.card-sec` fondo+borde+radio+sombra propios (mini-card visible) pero `.card-sec` (definido más abajo,
   sección 6 CARDS) solo tiene `margin-bottom` — CERO padding propio. Mientras `.card-sec` no tenía caja visible
   (antes de esta regla) no se notaba (heredaba el aire del `.card` padre); ahora que SÍ es su propia caja, su
   contenido queda pegado contra SU PROPIO borde. Confirmado con getComputedStyle: `.card-sec-hd` quedaba a 1px
   del borde de `.card-sec` (el ancho del borde, nada más). Le damos su propio padding (más chico que el del
   `.card` contenedor, 15px/17px, para marcar la jerarquía "mini-card" dentro de la card grande). */
html[data-theme=noir] .card-sec, html[data-theme=noirlight] .card-sec{padding:14px 16px}
html[data-theme=noir] .sb, html[data-theme=noirlight] .sb{
  background:color-mix(in srgb,var(--sb) 84%,transparent);
  backdrop-filter:blur(16px); -webkit-backdrop-filter:blur(16px);
}
html[data-theme=noir] .top, html[data-theme=noirlight] .top{
  background:color-mix(in srgb,var(--bg) 88%,transparent);
  backdrop-filter:blur(18px) saturate(1.2); -webkit-backdrop-filter:blur(18px) saturate(1.2);
}

/* ---------------------------------------------------------------------------
   3) BASE / RESET
   --------------------------------------------------------------------------- */
*{box-sizing:border-box;margin:0;padding:0;scrollbar-width:thin;scrollbar-color:var(--line) transparent}
::-webkit-scrollbar{width:11px;height:11px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{background:var(--line);border-radius:8px;border:2px solid var(--bg);background-clip:padding-box}
::-webkit-scrollbar-thumb:hover{background:var(--mut)}
::selection{background:var(--accent);color:#fff}
body{font-family:var(--font-sans);background:var(--bg);color:var(--txt);font-size:var(--fs-base);-webkit-font-smoothing:antialiased}
a{color:inherit;text-decoration:none}
h1,h2,h3{font-family:var(--font-display);letter-spacing:-.02em;line-height:1.06;font-weight:800}
.mono{font-family:var(--font-mono)}

/* Etiqueta "eyebrow" (mono, mayúsculas, acento) tomada de la web */
.eyebrow{font-family:var(--font-mono);color:var(--accent);font-size:var(--fs-xs);
  letter-spacing:.24em;text-transform:uppercase;font-weight:600}

/* ---------------------------------------------------------------------------
   4) BOTONES — primario (brand), acento, secundario, ghost
   --------------------------------------------------------------------------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:7px;
  background:var(--panel);color:var(--txt);border:1px solid var(--line);
  border-radius:var(--r-sm);padding:7px 12px;font-family:inherit;font-size:var(--fs-md);
  font-weight:600;cursor:pointer;line-height:1;white-space:nowrap;
  transition:transform .12s var(--ease),filter var(--dur) var(--ease),
    border-color var(--dur) var(--ease),background var(--dur) var(--ease),box-shadow var(--dur) var(--ease)
}
.btn:hover{border-color:var(--brand);transform:translateY(-1px)}
.btn:active{transform:translateY(0) scale(.98)}
.btn:focus-visible{outline:none;box-shadow:0 0 0 3px color-mix(in srgb,var(--brand) 30%,transparent)}
.btn:disabled{opacity:.45;cursor:not-allowed;transform:none}
.btn:disabled:hover{border-color:var(--line)}

/* primario = brand (violeta) */
.btn.primary,.btn.brand{background:var(--brand);color:#fff;border-color:var(--brand);font-weight:700;
  box-shadow:0 6px 22px color-mix(in srgb,var(--brand) 32%,transparent)}
.btn.primary:hover,.btn.brand:hover{filter:brightness(1.08);border-color:var(--brand)}

/* acento = rosa (CTAs cálidas / .pk y .pink son alias históricos) */
.btn.accent,.btn.pk,.btn.pink{background:var(--accent);color:#fff;border-color:var(--accent);font-weight:700}
.btn.accent:hover,.btn.pk:hover,.btn.pink:hover{filter:brightness(1.08);border-color:var(--accent)}

/* secundario = borde neutro (default .btn ya lo es) */
.btn.ghost{background:transparent;border-color:transparent}
.btn.ghost:hover{background:var(--panel2);border-color:var(--line)}

.btn.sm{padding:5px 9px;font-size:var(--fs-sm)}
.btn.danger:hover{border-color:var(--neg);color:var(--neg)}
/* primario destructivo = accent + danger → botón RELLENO rojo (confirmar acción irreversible) */
.btn.accent.danger{background:var(--neg);border-color:var(--neg);color:#fff}
.btn.accent.danger:hover{filter:brightness(1.08);border-color:var(--neg);color:#fff}

/* soft = botón secundario CON afordancia en reposo (borde sutil + fondo tenue),
   para acciones de fila/tabla donde .ghost (transparente) parece un link. En fondo
   claro se ve claramente como botón. Se combina con .sm/.danger/.icon. */
.btn.soft{background:var(--panel2);border-color:var(--line);color:var(--txt)}
.btn.soft:hover{background:color-mix(in srgb,var(--brand) 8%,var(--panel2));border-color:var(--brand)}
.btn.soft.danger{color:var(--neg);border-color:color-mix(in srgb,var(--neg) 30%,var(--line))}
.btn.soft.danger:hover{background:color-mix(in srgb,var(--neg) 9%,var(--panel2));border-color:var(--neg);color:var(--neg)}

/* .cellsel es un select compacto inline (fila de indicadores): al sumarle .field (canon)
   mantiene su ancho automático en cualquier contexto (no el width:100% de select.field). */
select.cellsel.field,.cellsel.dd-trigger{width:auto}

/* colorpick = <input type=color> del editor Studio (chrome unificado; el tamaño va inline). */
.dash-colorpick{padding:2px;border:1px solid var(--line);border-radius:7px;background:var(--panel2)}

/* tplcard = variante de .btn como tarjeta de selección: bloque a ancho completo,
   texto a la izquierda, con título + descripción (usado en "Nuevo tablero"). */
.btn.dash-tplcard{display:block;width:100%;text-align:left;margin:0 0 7px;padding:10px 12px;white-space:normal}

/* icon = botón de sólo-ícono: cajita cuadrada, ícono centrado (usar con icon('...')). */
.btn.icon{padding:0;width:32px;height:32px;flex:none}
.btn.icon.sm{width:28px;height:28px}
.btn.icon .ic-svg{--ic-sz:16px}

/* ---------------------------------------------------------------------------
   5) INPUTS / BUSCADORES — mismos en BI y consola
   --------------------------------------------------------------------------- */
.input,
input.field,textarea.field,select.field,.dd-trigger{
  width:100%;background:var(--panel2);color:var(--txt);border:1px solid var(--line);
  border-radius:var(--r-sm);padding:8px 11px;font-family:inherit;font-size:var(--fs-md);outline:none;
  transition:border-color var(--dur) var(--ease),box-shadow var(--dur) var(--ease)
}
.input:focus,input.field:focus,textarea.field:focus,select.field:focus,.dd-trigger:focus{
  border-color:var(--brand);box-shadow:0 0 0 3px color-mix(in srgb,var(--brand) 18%,transparent)
}
textarea.field{resize:vertical}

/* Buscador con lupa (patrón .search unificado) */
.searchbox{position:relative;flex:0 1 560px;max-width:560px;min-width:140px}
.searchbox input{
  width:100%;background:var(--panel2);border:1px solid var(--line);border-radius:var(--r-sm);
  padding:7px 34px 7px 12px;color:var(--txt);font-family:inherit;font-size:var(--fs-md);outline:none;
  transition:border-color var(--dur) var(--ease),box-shadow var(--dur) var(--ease)
}
.searchbox input:focus{border-color:var(--brand);box-shadow:0 0 0 3px color-mix(in srgb,var(--brand) 18%,transparent)}
.searchbox .searchic{position:absolute;right:11px;top:50%;transform:translateY(-50%);
  width:16px;height:16px;color:var(--mut);pointer-events:none}

/* ---------------------------------------------------------------------------
   6) CARDS
   --------------------------------------------------------------------------- */
.card{background:var(--panel);border:1px solid color-mix(in srgb,var(--line) 45%,transparent);border-radius:var(--r-lg);
  padding:15px 17px;margin-bottom:15px;box-shadow:var(--card-sh,0 1px 3px var(--sh));
  transition:border-color var(--dur) var(--ease),box-shadow var(--dur) var(--ease)}
.card:hover{border-color:color-mix(in srgb,var(--brand) 18%,var(--line))}
.card h2{font-family:var(--font-display);font-size:var(--fs-xl);font-weight:800;
  margin-bottom:6px;display:flex;align-items:center;gap:8px;letter-spacing:-.01em}
.card h2::before{content:'';width:6px;height:6px;background:var(--accent);border-radius:2px;flex:none}
.card h2.nodot::before{display:none}
.card .hint{color:var(--mut);font-size:var(--fs-sm);margin-bottom:12px;line-height:1.5}
/* Sub-bloque canónico DENTRO de un .card/panel (reemplaza .usrblk y las cajas internas ad-hoc).
   `.card-sec` = bloque con separación uniforme; `.card-sec-hd` = su encabezado (label chico en mayúsculas). */
.card-sec{margin-bottom:16px}
.card-sec:last-child{margin-bottom:0}
.card-sec-hd{display:flex;align-items:center;font-size:11px;text-transform:uppercase;letter-spacing:.5px;
  color:var(--mut);font-weight:700;margin-bottom:8px}

/* ---------------------------------------------------------------------------
   7) TABLAS
   --------------------------------------------------------------------------- */
table{width:100%;border-collapse:collapse;font-size:var(--fs-md)}
th,td{padding:8px 10px;text-align:left;border-bottom:1px solid var(--line);vertical-align:top}
th{font-size:var(--fs-xs);text-transform:uppercase;color:var(--mut);letter-spacing:.5px;font-weight:700;user-select:none}
th.s{cursor:pointer}th.s:hover{color:var(--txt)}
td.num,th.num{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap}
.tbwrap{max-height:460px;overflow:auto;border:1px solid var(--line);border-radius:var(--r-sm)}
.usradminblk{margin-bottom:12px}
.tbwrap table thead th{position:sticky;top:0;background:var(--panel2);z-index:1}
/* QA mystery-shopper 22/10: 05-views-2.js::usrMatrixUnified arma un <colgroup> con estas clases pero el CSS
   nunca se escribió -- sin table-layout:fixed la columna Rol (con un <select>) quedaba cortada a la derecha. */
.usrmxfix{table-layout:fixed}
.usrmxfix .c-persona{width:26%}.usrmxfix .c-estado{width:11%}.usrmxfix .c-origen{width:19%}
.usrmxfix .c-rol{width:19%}.usrmxfix .c-ajustes{width:9%}.usrmxfix .c-acc{width:16%}
/* FIX QA 21/10: columna Fecha del historial de altas/bajas (Consola->Facturación) se veía cortada --
   la columna "Detalle" (texto libre, a veces largo) le robaba ancho a la tabla sin table-layout:fixed,
   y la fecha (19 caracteres, sin nowrap) se partía/recortaba. white-space:nowrap en la 1ª columna de esa
   tabla puntual (igual que ya hacían las columnas .num) evita que la fecha se corte. */
#fg_ev_table td:first-child,#fg_ev_table th:first-child{white-space:nowrap}
tbody tr.click{cursor:pointer}
tbody tr.click:hover{background:color-mix(in srgb,var(--accent) 8%,transparent)}
/* tabla ordenable canónica (kit, docs/UI-KIT.md #12) — makeSortable(tableEl).
   Cada th ordenable lleva aria-sort; la flecha la pinta el CSS (sin armarla el caller).
   La columna activa se resalta en color de texto/acento. */
table.sortable th[aria-sort]{cursor:pointer}
table.sortable th[aria-sort]:hover{color:var(--txt)}
table.sortable th[aria-sort]::after{content:'\2195';margin-left:5px;opacity:.32;font-weight:400}
table.sortable th[aria-sort=ascending]::after{content:'\25B2';opacity:1}
table.sortable th[aria-sort=descending]::after{content:'\25BC';opacity:1}
table.sortable th[aria-sort=ascending],table.sortable th[aria-sort=descending]{color:var(--accent)}
table.sortable th.num[aria-sort]{text-align:right}

/* ---------------------------------------------------------------------------
   8) CHIPS / TABS / BADGES / SEG
   --------------------------------------------------------------------------- */
.chip{display:inline-flex;align-items:center;gap:5px;background:var(--accent-soft);color:var(--accent);
  border:1px solid var(--accent-line);border-radius:var(--r-pill);padding:3px 10px;
  font-size:var(--fs-sm);font-weight:600;cursor:pointer;line-height:1.3;transition:all var(--dur) var(--ease)}
.chip.clr{background:none;color:var(--mut);border-color:var(--line)}

/* pill toggle (los "ibub" del BI) */
.pill{display:inline-flex;align-items:center;gap:8px;padding:8px 13px;border:1px solid var(--line);
  border-radius:var(--r-pill);background:var(--panel2);cursor:pointer;font-family:inherit;
  font-size:var(--fs-md);font-weight:600;color:var(--txt);line-height:1;transition:all .15s var(--ease)}
.pill:hover{border-color:var(--brand);transform:translateY(-1px)}
.pill.on{border-color:var(--brand);background:color-mix(in srgb,var(--brand) 11%,var(--panel));
  box-shadow:0 0 0 2px color-mix(in srgb,var(--brand) 16%,transparent)}

/* tabs (píldora) — componente CANÓNICO ÚNICO. Hasta 2026-09-30 convivían dos looks (subrayado
   de base + píldora de .subnav.usrmtab); Franco prefiere la píldora en TODA la plataforma, así
   que pasa a ser el default de las 5 clases de golpe (sin migrar className en cada caller) y
   .subnav.usrmtab quedó redundante (eliminada, ver docs/UI-KIT.md). Familias históricas
   (.watabs/.subnav/.ss-tabs/.subtabs) = modificadores que preservan el detalle fino
   (gap/font/padding) de cada superficie sobre el MISMO look. */
.tabs,.watabs,.subnav,.ss-tabs,.subtabs{display:inline-flex;gap:2px;background:var(--panel2);padding:3px;border-radius:9px;
  max-width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}   /* QA 2026-10-14 (relevamiento, mobile/tablet): con muchas pestañas (ej. Ajustes) y sin ancho propio, inline-flex+nowrap hacía que las últimas quedaran pisadas/cortadas en viewports angostos — ahora, si no entran, se deslizan en vez de solaparse */
.tabs button,.watab,.subnav button,.ss-tab,.subtabs button{
  background:none;border:none;color:var(--mut);border-radius:7px;margin-bottom:0;
  font-family:inherit;font-weight:700;cursor:pointer;transition:all var(--dur) var(--ease)}
.tabs button:hover,.watab:hover,.subnav button:hover,.ss-tab:hover,.subtabs button:hover{color:var(--txt)}
.tabs button.on,.watab.on,.subnav button.on,.ss-tab.on,.subtabs button.on{
  background:var(--panel);color:var(--txt);box-shadow:0 1px 3px var(--sh,rgba(0,0,0,.22))}
/* dims por familia */
.tabs{gap:4px}
.tabs button{font-size:var(--fs-md);padding:7px 13px}
.watabs{gap:6px}
.watab{padding:8px 14px;font-size:12.5px}
.subnav{gap:3px;margin:0}.subnav:empty{display:none}
.subnav button{padding:7px 13px;font-size:12.5px}
/* .ss-tabs: 5 pestañas (Agregar/Yoko/Tablero/Propiedades/Objetivo) en el panel angosto (~300px).
   Compactamos (menos padding/font) y permitimos scroll-x suave para que TODAS entren y se lean sin pisarse.
   flex-wrap:nowrap + min-width:0 evita que se corten; el label no se parte con white-space:nowrap.
   padding vertical 3px (igual al resto) para que la píldora de fondo no quede pegada arriba/abajo. */
.ss-tabs{flex:none;padding:3px 8px;overflow-x:auto;flex-wrap:nowrap;scrollbar-width:thin;-webkit-overflow-scrolling:touch}
.ss-tabs::-webkit-scrollbar{height:4px}
.ss-tabs::-webkit-scrollbar-thumb{background:var(--line);border-radius:3px}
.ss-tab{flex:1 1 auto;min-width:0;white-space:nowrap;padding:7px 8px;font-size:12px;transition:color .13s,background .13s}
.subtabs{gap:2px;overflow-x:auto;flex-wrap:nowrap}.subtabs:empty{display:none}
.subtabs button{padding:9px 13px;font-size:var(--fs-md);white-space:nowrap;display:inline-flex;align-items:center;gap:6px;transition:.15s}

/* ── Rail vertical con píldora móvil (componente CANÓNICO de plataforma) ─────────────────────
   Rail vertical de íconos a la DERECHA del contenido; el fondo del rail = base oscura (--bg) y el
   contenido es una tarjeta --panel encima. La pestaña ACTIVA es UNA píldora --panel que se CONECTA a
   la tarjeta con la unión izquierda CÓNCAVA (SVG, misma línea --line) y VIAJA entre pestañas con morph
   estilo Apple (la actual se deforma, la nueva se forma). Ícono rosa (--brand) en la activa; íconos
   centrados. Es un MODIFICADOR `.rail` sobre `.ss-tabs` → NO afecta a las tabs horizontales (que no lo
   llevan). Markup: `<div class="ss-tabs rail">` con `<span class="ss-pill">` (SVG) como PRIMER hijo +
   `<button class="ss-tab"><span class="ss-tico"><svg/></span><span class="ss-tlbl">…</span></button>`.
   JS al cambiar (idx=índice activa, PITCH = alto tab + gap):
     pill.style.transform='translateY('+(idx*PITCH)+'px)';
     pill.classList.remove('morph'); void pill.offsetWidth; pill.classList.add('morph');
   La tarjeta de contenido lleva `border-right:1px solid var(--line)`. Doc: UI-KIT.md #24. */
.ss-tabs.rail{position:relative;display:flex;flex-direction:column;gap:8px;padding:12px 6px 12px 0;flex:none;width:58px;overflow:visible;background:var(--bg);border-bottom:none}
.ss-tabs.rail .ss-tab{position:relative;z-index:1;flex:none;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;width:52px;height:48px;padding:0;margin:0;border:none;border-bottom:none;background:none;color:var(--mut);font-size:8px;font-weight:700;cursor:pointer}
.ss-tabs.rail .ss-tab .ss-tico,.ss-tabs.rail .ss-tab .ss-tlbl{position:relative;z-index:1;transition:color .22s var(--ease,ease)}
.ss-tabs.rail .ss-tab.on .ss-tico,.ss-tabs.rail .ss-tab.on .ss-tlbl{color:var(--brand)}
/* Indicador RECTANGULAR (Franco 2026-09-30, versión final tras corrección: "quedamos que era ese que tenía la
   línea rosa a la derecha… un hover que cubra todo el ícono y a la derecha tenga la línea rosa" — NO tinte rosa
   de fondo, un hover NEUTRO que cubre toda la pestaña + una barra de acento rosa pegada al borde derecho).
   Mismo tamaño que la pestaña (52×48, sin bleed) para que no se salga del borde redondeado de la barra. */
/* ancho 58px = TODO el rail (no sólo los 52px de la pestaña): la pestaña vive con 6px de aire antes del borde
   real por el padding del rail (.ss-tabs.rail{padding:12px 6px 12px 0}), así que un hover de 52px se quedaba
   corto 6px antes de llegar al borde (Franco 2026-09-30: "no llega hasta la derecha totalmente"). */
.ss-pill{position:absolute;left:0;top:12px;width:58px;height:48px;border-radius:var(--r-sm);z-index:0;pointer-events:none;
  background:var(--panel2);
  transition:transform .26s cubic-bezier(.4,0,.2,1)}
.ss-pill::after{content:'';position:absolute;right:0;top:0;bottom:0;width:3px;
  border-radius:0 var(--r-sm) var(--r-sm) 0;background:var(--brand)}
.ss-tabs.rail .ss-tab .ss-tico{width:17px;height:17px;display:flex;align-items:center;justify-content:center}
.ss-tabs.rail .ss-tab .ss-tico svg{width:16px;height:16px}

/* filterbar — wrapper del componente Filter (renderFilter). Reusa .subnav/.field. */
.filterbar{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin:0 0 10px}
.filter-lbl{font-size:var(--fs-sm);color:var(--mut);font-weight:600}

/* segmented control */
.seg{display:inline-flex;background:var(--panel);border:1px solid var(--line);border-radius:var(--r-sm);overflow:hidden}
.seg button{background:none;border:none;color:var(--mut);padding:6px 10px;cursor:pointer;
  font-size:var(--fs-md);font-family:inherit;font-weight:700;transition:all var(--dur) var(--ease)}
.seg button.on{background:var(--brand);color:#fff}

/* badges — chip de estado con COLOR semántico (kit canónico, docs/UI-KIT.md #13).
   Set canónico por INTENCIÓN: --ok (verde) / --warn (ámbar) / --err (rojo) /
   --info (azul) / --neutral (gris) / --brand (acento). Las clases históricas
   (.ok/.off/.mid/.mut/.own y .bd-ok/.bd-no/.bd-mid) quedan como ALIAS byte-idénticos
   para no romper el legacy. Usar el helper JS window.renderBadge(spec) para pintarlas. */
.badge{display:inline-block;padding:2px 8px;border-radius:var(--r-pill);font-size:var(--fs-xs);font-weight:700;line-height:1.5}
.badge.own,.badge--brand{background:var(--accent-soft);color:var(--accent)}
.badge.ok,.bd-ok,.badge--ok{background:color-mix(in srgb,var(--pos) 20%,transparent);color:var(--pos)}
.badge.off,.bd-no,.badge--err{background:color-mix(in srgb,var(--neg) 20%,transparent);color:var(--neg)}
.badge.mid,.bd-mid,.badge--warn{background:color-mix(in srgb,var(--amber) 22%,transparent);color:var(--amber)}
.badge.mut,.badge--neutral{background:var(--panel2);color:var(--mut)}
.badge--info{background:color-mix(in srgb,var(--blue) 20%,transparent);color:var(--blue)}
/* punto opcional dentro del badge (mismo color que el texto) */
.badge .bdot{display:inline-block;width:6px;height:6px;border-radius:50%;background:currentColor;margin-right:5px;vertical-align:1px}

/* ---------------------------------------------------------------------------
   9) ESTADOS: loading / empty / error
   --------------------------------------------------------------------------- */
.spin{width:32px;height:32px;border:3px solid var(--line);border-top-color:var(--accent);
  border-radius:50%;animation:brand-sp 1s linear infinite}
.spin.sm{width:18px;height:18px;border-width:2.5px}
@keyframes brand-sp{to{transform:rotate(360deg)}}
.loadrow{display:flex;align-items:center;justify-content:center;gap:9px;color:var(--mut);padding:22px;font-size:var(--fs-base)}
/* Skeleton de carga: placeholders pulsantes del tablero mientras llega la data (evita el overlay full-screen bloqueante) */
.skl-card{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-lg);position:relative;overflow:hidden}
.skl-kpi{height:96px}.skl-wide{height:280px}
.skl-card::after{content:"";position:absolute;inset:0;transform:translateX(-100%);
  background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--line) 45%,transparent),transparent);
  animation:brand-shimmer 1.3s ease-in-out infinite}
@keyframes brand-shimmer{100%{transform:translateX(100%)}}
.empty{color:var(--mut);text-align:center;padding:26px 16px;font-size:var(--fs-base);line-height:1.6}
.errstate{color:var(--neg);font-size:var(--fs-md);padding:4px 0}
.mut{color:var(--mut)}
.muted{color:var(--mut);font-size:var(--fs-sm);text-align:center;margin:16px 0}

/* dot de status (conexión) */
.status{display:flex;align-items:center;gap:6px;font-size:var(--fs-sm);color:var(--mut);
  background:var(--panel);border:1px solid var(--line);border-radius:var(--r-sm);padding:5px 10px}
.status .dot{width:7px;height:7px;border-radius:50%;background:var(--mut)}
.status.ok .dot{background:var(--pos);box-shadow:0 0 0 3px color-mix(in srgb,var(--pos) 25%,transparent)}
.status.err .dot{background:var(--neg);box-shadow:0 0 0 3px color-mix(in srgb,var(--neg) 25%,transparent)}
.status b{color:var(--txt);font-weight:600}

/* ---------------------------------------------------------------------------
   10) SIDEBAR / NAV — mismo lenguaje en BI y consola
   --------------------------------------------------------------------------- */
.sb{background:var(--sb);color:var(--sbtx);display:flex;flex-direction:column;
  position:sticky;top:0;height:100vh;border-right:1px solid var(--sbline);
  /* QA mystery-shopper 22/10: la barra de Yoko (fixed, ~150px) tapaba el pie del sidebar en DESKTOP --
     la reserva --yoko-space ya existía pero solo para .sb.open (mobile/drawer), nunca para el sidebar fijo. */
  padding-bottom:var(--yoko-space,150px);box-sizing:border-box}
.sb .brand{display:flex;align-items:center;gap:9px;padding:16px 14px}
.sb .brand b{color:var(--sbstrong);font-weight:800;font-size:14px;line-height:1.1;font-family:var(--font-display)}
.sb .brand small{display:block;color:var(--mut);font-size:8.5px;letter-spacing:2px;text-transform:uppercase;margin-top:3px}
.sb .foot{padding:10px 14px;border-top:1px solid var(--sbline);font-size:var(--fs-xs);color:var(--mut)}
.sb .foot a{color:var(--sbtx);font-weight:600;cursor:pointer}
.sb .foot a:hover{color:var(--accent)}
.nav{display:flex;flex-direction:column;gap:1px;padding:6px 8px;flex:1;overflow:auto}
.nav a{display:flex;align-items:center;gap:9px;padding:9px 11px;border-radius:var(--r-sm);
  color:var(--sbtx);font-weight:600;font-size:var(--fs-md);cursor:pointer;transition:all var(--dur) var(--ease)}
.nav a:hover{background:var(--sbhover);color:var(--sbstrong)}
.nav a.on{background:var(--brand);color:#fff}
.nav a .ic{width:18px;text-align:center;flex:none}

/* topbar compartida */
.top{background:var(--head);border-bottom:1px solid var(--line);padding:11px 20px;
  display:flex;align-items:center;gap:10px;position:sticky;top:0;z-index:30}
.top b{font-weight:800;font-size:15px;font-family:var(--font-display)}
.sp{margin-left:auto}

/* ---------------------------------------------------------------------------
   11) GRÁFICOS — realce/leyenda coherentes (Chart.js toma defaults por JS)
   --------------------------------------------------------------------------- */
.chartbox{position:relative;height:250px}
.chartbox.sm{height:190px}.chartbox.lg{height:320px}

/* ---------------------------------------------------------------------------
   12) TOAST / MODAL genéricos
   --------------------------------------------------------------------------- */
/* QA 2026-10-10: bottom era 22px fijo, igual que #yokobar -- el toast se dibujaba justo sobre el campo de
   texto de la barra de Yoko. Usa el alto REAL de la barra (--yoko-space, sincronizado por 12-yokobar.js;
   "22px" de fallback si la barra todavía no montó) para levantarse por encima siempre. */
.toast{position:fixed;bottom:var(--yoko-space,22px);left:50%;transform:translateX(-50%);background:var(--panel);
  border:1px solid var(--line);color:var(--txt);padding:10px 18px;border-radius:var(--r-lg);
  box-shadow:var(--sh-lg);z-index:100;font-size:var(--fs-base);font-weight:600;
  opacity:0;transition:opacity .2s var(--ease);pointer-events:none}

/* toggle / switch (canónico del design-system) — ver docs/DESIGN-SYSTEM.md */
.tgl{position:relative;display:inline-block;width:36px;height:20px;flex:none}
.tgl input{opacity:0;width:0;height:0;position:absolute}
.tgl .sl{position:absolute;inset:0;background:var(--line);border-radius:20px;transition:.2s;cursor:pointer}
.tgl .sl:before{content:"";position:absolute;height:14px;width:14px;left:3px;top:3px;background:#fff;border-radius:50%;transition:.2s}
.tgl input:checked+.sl{background:var(--accent)}
.tgl input:checked+.sl:before{transform:translateX(16px)}

/* ---------------------------------------------------------------------------
   DRAWER canónico — panel lateral derecho (ver docs/COMPONENTS-DRAWER-FILTER.md).
   Ancho por `--drawer-w` (default 340; ej. Usuarios usa 440). Backdrop opcional (.drawer-back).
   --------------------------------------------------------------------------- */
.drawer-back{position:fixed;inset:0;background:rgba(0,0,0,.35);opacity:0;transition:opacity .2s;z-index:140;pointer-events:none}
.drawer-back.on{opacity:1;pointer-events:auto}
.drawer{position:fixed;top:0;right:0;bottom:0;height:100vh;width:var(--drawer-w,340px);max-width:94vw;
  background:var(--panel);border-left:1px solid var(--line);box-shadow:-14px 0 40px var(--sh,rgba(0,0,0,.28));
  display:flex;flex-direction:column;z-index:var(--drawer-z,141);transform:translateX(100%);
  transition:transform var(--drawer-dur,.24s) var(--drawer-ease,cubic-bezier(.4,0,.2,1));will-change:transform}
.drawer.on{transform:translateX(0)}
.drawer-hd{display:flex;align-items:flex-start;gap:12px;padding:16px 18px 14px;border-bottom:1px solid var(--line);flex:none}
.drawer-bd{flex:1;overflow-y:auto;padding:14px 18px 24px;min-height:0}
.drawer-ft{padding:12px 18px;border-top:1px solid var(--line);display:flex;align-items:center;gap:10px;flex:none}
/* checkbox/radio tematizados: usar accent-color:var(--accent) (no hardcodear #E7399A) */

/* ---------------------------------------------------------------------------
   POPOVER canónico — panel CHICO anclado a un trigger (campana, menú contextual…), SIN backdrop de
   pantalla completa (a diferencia del .drawer de arriba). Posición: el que lo abre calcula
   getBoundingClientRect() del trigger y fija top/left/right por JS como estilo inline (layout puro,
   no chrome — mismo criterio que `.ss-tilemenu`, dash-studio-edit-2.js). Ancho por `--popover-w`
   (default 300px); alto acotado con scroll interno (`.popover-bd`) para no crecer sin límite si hay
   mucho contenido. Ver docs/UI-KIT.md #26. Usos: notificaciones (#propBell, 13-proposals.js). */
.popover{position:fixed;z-index:145;width:var(--popover-w,300px);max-width:92vw;max-height:70vh;
  background:var(--panel);border:1px solid var(--line);border-radius:var(--r-lg);
  box-shadow:var(--sh-lg,0 14px 40px rgba(0,0,0,.3));display:flex;flex-direction:column;
  opacity:0;transform:translateY(-6px) scale(.97);pointer-events:none;
  transition:opacity .16s ease,transform .16s ease}
.popover.on{opacity:1;transform:none;pointer-events:auto}
.popover-hd{display:flex;align-items:flex-start;gap:10px;padding:13px 15px 11px;border-bottom:1px solid var(--line);flex:none}
.popover-bd{flex:1;min-height:0;overflow-y:auto;padding:10px 12px}

/* RANGE/SLIDER canónico — accent-color:var(--accent), sin chrome inline. `.dash-rangebar` = fila
   (label+valor+slider) sobre la .card; lo usa "Proyección de caja" (Tesorería) para el horizonte. */
.dash-rangebar{display:flex;align-items:center;gap:10px;margin:2px 0 10px}
.dash-rangebar .dash-range{flex:1;min-width:80px}
.dash-rangebar .dash-rangeval{font-weight:700;color:var(--accent);white-space:nowrap;font-size:.9rem}
.dash-rangebar .dash-rangelbl{color:var(--mut);font-size:.85rem;white-space:nowrap}
input.dash-range[type=range]{accent-color:var(--accent);height:22px;cursor:pointer}

/* ---------------------------------------------------------------------------
   MODAL / POPUP (catálogo #11) — canónico. UN solo modal (mata confirm()/alert()
   nativos y popups ad-hoc). Motor: openModal() en ui-kit.js. Overlay oscuro + card
   centrada con header/body/footer. Todo con tokens del tema. Ver docs/UI-KIT.md.
   --------------------------------------------------------------------------- */
.modalOv{position:fixed;inset:0;background:rgba(0,0,0,.5);z-index:1300;display:flex;align-items:center;justify-content:center;padding:20px;opacity:0;transition:opacity .18s ease}   /* QA 2026-10-14 (Franco, repro exacta): arriba de [data-tip]:hover (1201) -- el tooltip de un botón bajo el cursor quedaba dibujado ENCIMA del modal recién abierto (el mouse no se movió del botón) */
.modalOv.on{opacity:1}
.modalCard{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--sh-lg,0 20px 60px var(--sh));width:440px;max-width:100%;max-height:86vh;overflow:auto;transform:scale(.96);transition:transform .18s ease}
.modalOv.on .modalCard{transform:none}.dash-text{display:flex;align-items:center;width:100%;height:100%;font-family:var(--font-display);font-size:var(--fs-2xl);font-weight:700;color:var(--txt);line-height:1.25;padding:2px 4px;overflow:hidden;word-break:break-word}.dash-text.ac{justify-content:center;text-align:center}.dash-text.ar{justify-content:flex-end;text-align:right}.dash-text.b{font-weight:800}.dash-text.gs-editing{outline:2px solid var(--brand);outline-offset:2px;border-radius:6px}
.modalHd{display:flex;align-items:center;justify-content:space-between;padding:14px 16px;border-bottom:1px solid var(--line)}
.modalHd h2{font-size:var(--fs-lg,14px)}
.modalX{cursor:pointer;color:var(--mut);font-size:15px;padding:4px 8px;border-radius:var(--r-sm,7px)}
.modalX:hover{background:var(--panel2);color:var(--txt)}
.modalBd{padding:16px}
.modalFt{padding:12px 16px;border-top:1px solid var(--line);display:flex;align-items:center;justify-content:flex-end;gap:8px}
.modalErr{margin-right:auto;color:var(--neg);font-size:12px;line-height:1.4}

/* ---------------------------------------------------------------------------
   13) ACORDEÓN (canónico del design-system) — ver docs/DESIGN-SYSTEM.md
   Usar `.acc/.acc-hd/.acc-bd` en código nuevo; `.ss-acc*` = alias legacy (Studio).
   Es EL acordeón de toda la plataforma (BI + consola). No inventar otro.
   --------------------------------------------------------------------------- */
@keyframes intfade{from{opacity:0}to{opacity:1}}
.acc,.ss-acc{border:1px solid var(--line);border-radius:var(--r-md,9px);margin-bottom:11px;overflow:hidden;background:var(--panel2)}
.acc-hd,.ss-acc-hd{display:flex;align-items:center;gap:9px;width:100%;background:none;border:none;text-align:left;padding:12px 13px;cursor:pointer;font-family:inherit;font-size:var(--fs-base,13px);font-weight:700;color:var(--txt);transition:background .13s}
.acc-hd:hover,.ss-acc-hd:hover{background:color-mix(in srgb,var(--brand) 6%,var(--panel2))}
.acc-hd .acc-ico,.ss-acc-hd .ss-ico{font-size:15px;flex:none}
.acc-hd .acc-cv,.ss-acc-hd .ss-cv{margin-left:auto;color:var(--mut);transition:transform .18s;font-size:11px}
.acc.open .acc-hd .acc-cv,.ss-acc.open .ss-acc-hd .ss-cv{transform:rotate(90deg)}
.acc-bd,.ss-acc-bd{display:none;padding:4px 13px 14px;border-top:1px solid var(--line)}
.acc.open .acc-bd,.ss-acc.open .ss-acc-bd{display:block;animation:intfade .18s ease}

/* ---------------------------------------------------------------------------
   14) CAMPO DE FORMULARIO (catálogo #15) — patrón único label+.field+.hint+error.
   Motor: renderField() en ui-kit.js. TODO formulario nuevo se arma con este patrón.
   Reusa .field (§5). `.field-row` apila label/control/hint; `.has-err` pinta el error.
   --------------------------------------------------------------------------- */
.field-row{display:flex;flex-direction:column;gap:5px;margin-bottom:13px}
.field-row:last-child{margin-bottom:0}
.field-lbl{font-size:var(--fs-sm);color:var(--txt);font-weight:600;line-height:1.3}
.field-hint{font-size:var(--fs-xs);color:var(--mut);line-height:1.5}
.field-err{font-size:var(--fs-xs);color:var(--neg);font-weight:600;line-height:1.4}
.field-row.has-err .field,.field-row.has-err .input{border-color:var(--neg)}
.field-row.has-err .field:focus{box-shadow:0 0 0 3px color-mix(in srgb,var(--neg) 18%,transparent)}

/* ---------------------------------------------------------------------------
   15) NOTA / HINT / CALLOUT (catálogo #16) — UNA sola nota canónica `.note` con
   4 variantes por color de token: info(azul)/warn(ámbar)/tip(verde)/danger(rojo).
   CANÓNICO = `.note` (bloque con realce). `.hint`/`.microcopy` legacy = texto auxiliar
   inline gris (no se borran aún). Motor: renderNote() en ui-kit.js.
   --------------------------------------------------------------------------- */
.note{display:flex;gap:9px;align-items:flex-start;padding:10px 13px;border-radius:var(--r-md);
  border:1px solid var(--line);background:var(--panel2);font-size:var(--fs-sm);line-height:1.5;
  color:var(--txt);border-left-width:3px}
.note .note-ic{flex:none;line-height:1.4;display:inline-flex;align-items:center}
.note .note-bd{min-width:0}
.note--info{border-left-color:var(--blue);background:color-mix(in srgb,var(--blue) 9%,var(--panel2))}
.note--warn{border-left-color:var(--amber);background:color-mix(in srgb,var(--amber) 10%,var(--panel2))}
.note--tip{border-left-color:var(--pos);background:color-mix(in srgb,var(--pos) 9%,var(--panel2))}
.note--danger{border-left-color:var(--neg);background:color-mix(in srgb,var(--neg) 9%,var(--panel2))}


/* Transición suave entre paneles/pestañas del BI (Franco 2026-09-30): 04-nav.js render() hace replay de .vfade en #view. */
#view.vfade{animation:viewFade .2s var(--ease,cubic-bezier(.4,0,.2,1))}
@keyframes viewFade{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
@media(prefers-reduced-motion:reduce){#view.vfade{animation:none}}
