  /* ===================== base.css — núcleo de shell compartido =====================
     Extraído verbatim de css/styles.css (Task 2 · separación de módulos).
     Reglas de reporting/RRHH específicas permanecen en css/styles.css (se reparten
     en tasks posteriores). Es correcto que haya solape leve: el objetivo es que una
     página de shell estilada solo con base.css se vea correctamente. */

  :root{
    --bg:#eef1f4; --panel:#ffffff; --ink:#1e2a36; --muted:#76838f;
    --line:#e7ebf0; --brand:#15a07a; --brand-d:#0f8062; --brand-soft:#e6f4ef; --brand-ink:#0d7053;
    --pos:#1f9d6b; --neg:#dd5b4d; --warn:#c79233; --blue:#3168c4; --blue-soft:#e9f1fb;
    /* Tintes de superficie y variantes "soft" de estado. Ya existían, pero como
       hex a pelo repetidos aquí y en hub.css/rrhh.css, cada uno con su regla
       body.dark al lado — justo lo que CONTRATO-APPS.md §1 pide a las apps que
       NO hagan ("el tema oscuro funciona gratis sin escribir body.dark .algo").
       Como tokens, el oscuro se hereda solo. Completan el patrón que ya estaba a
       medias con --brand-soft/--blue-soft. Los valores son los que ya se usaban:
       este cambio no altera ni un color en pantalla. */
    --surface-hover:#f4f6f8;   /* hover de fila, pestaña, item de nav */
    --surface-alt:#eef1f4;     /* chip/etiqueta, fila de sección agrupada */
    --surface-raised:#f6f8fa;  /* fila de totales, KPI destacado */
    --neg-soft:#fdecea; --warn-soft:#fcf3e1;
    --shadow:0 1px 2px rgba(16,38,64,.04),0 6px 18px rgba(16,38,64,.06);
    --shadow-sm:0 1px 2px rgba(16,38,64,.05);
  }
  *{box-sizing:border-box}
  body{margin:0;font-family:"Segoe UI",Roboto,Arial,sans-serif;background:var(--bg);color:var(--ink);font-size:13px}
  svg{display:block}

  /* ---------- Color de la app (manifest "color", CONTRATO-APPS.md §1) ----------
     El shell (pintarColorApp() en shell.js) pone el color como --app inline +
     data-app-color en <body> mientras la app está activa, y en cada elemento que
     la representa (tarjeta del launcher, entrada de #col1). Aquí, y no en ui.css,
     porque es chrome: las apps standalone vendorizan base.css + shell.js, no la
     ui.css del portal. Tokens en body (no :root) para que color-mix() mezcle con
     el --panel/--ink de body.dark; y en [data-app-color] para que un elemento con
     su propio --app recalcule sus tonos. Sin color, --app cae en --brand. */
  body, [data-app-color]{
    --app: var(--brand);
    --app-d:      color-mix(in srgb, var(--app) 82%, #000);             /* hover de lo sólido */
    --app-soft:   color-mix(in srgb, var(--app) 12%, var(--panel));     /* fondos suaves (seleccionado, badge) */
    --app-soft-2: color-mix(in srgb, var(--app) 22%, var(--panel));     /* hover sobre suave */
    --app-line:   color-mix(in srgb, var(--app) 38%, var(--panel));     /* bordes/foco */
    --app-ink:    color-mix(in srgb, var(--app) 72%, var(--ink));       /* texto de color legible sobre panel/suave */
    --app-ring:   color-mix(in srgb, var(--app) 28%, transparent);      /* halo de foco */
    --app-on: #fff;                                                     /* texto sobre --app sólido */
  }
  /* El color de la app llega SOLO hasta aquí: el chrome (barras, banda, pestaña
     activa, ítem de menú, logo de columna y avatar) se pinta con --app*, y el
     contenido de #vista no se entera. Aquí vivía un remapeo
     (body[data-app-color]{--brand:var(--app)}) que hacía que declarar `color`
     repintara además .btn/.panel/.kpi y cualquier regla de la app que use
     var(--brand*) — es decir, chrome y contenido iban en el mismo paquete.
     Quien SÍ quiera su color dentro del contenido lo pide en su propio ámbito,
     con una línea en su CSS (CONTRATO-UI.md §A2.3):

       #vista.mi-scope{ --brand:var(--app); --brand-d:var(--app-d);
                        --brand-soft:var(--app-soft); --brand-ink:var(--app-ink); }

     Así las cuatro combinaciones son posibles: color sin guía de estilo, guía
     sin color, las dos o ninguna. */
  /* Banda de cabecera (.page-head: título, migas, pestañas, acciones) en el color
     sólido de la app, como GMAO — solo con app que declara color; sin él
     (launcher, Configuración, apps sin color) sigue en blanco. */
  body[data-app-color] .page-head{background:var(--app);border-bottom-color:var(--app-d);color:var(--app-on)}
  body[data-app-color] .page-head .page-title h1{color:var(--app-on)}
  body[data-app-color] .page-head .page-sub,
  body[data-app-color] .page-head .crumb-sep{color:color-mix(in srgb, var(--app-on) 75%, transparent)}
  body[data-app-color] .page-head .crumb-cur{color:var(--app-on);font-weight:700}
  body[data-app-color] .page-head .crumb-link:hover{color:var(--app-on)}
  body[data-app-color] .page-head .htab{color:color-mix(in srgb, var(--app-on) 88%, transparent)}
  body[data-app-color] .page-head .htab:hover{background:color-mix(in srgb, var(--app-on) 14%, transparent);color:var(--app-on)}
  /* Pestaña activa sobre la banda: pastilla en --app-on con el texto en el color
     de la app (CONTRATO-UI.md §A5) — no var(--panel), que en tema oscuro deja
     una pastilla casi negra en vez de la blanca de GMAO. */
  body[data-app-color] .page-head .htab.active{background:var(--app-on);color:var(--app)}
  body[data-app-color] .page-head .htabs-empty{color:color-mix(in srgb, var(--app-on) 75%, transparent)}
  /* Botones sobre la banda (CONTRATO-UI.md §A5): el primario no puede ir en el
     color de la app sobre el color de la app, así que se invierte — relleno
     --app-on con el texto en --app. El .ghost, transparente con borde --app-on. */
  body[data-app-color] .page-head .btn{background:var(--app-on);color:var(--app);border:1px solid var(--app-on);box-shadow:none}
  body[data-app-color] .page-head .btn:hover{background:color-mix(in srgb, var(--app-on) 86%, transparent);color:var(--app-d)}
  body[data-app-color] .page-head .btn.ghost{background:transparent;color:var(--app-on);border-color:color-mix(in srgb, var(--app-on) 55%, transparent)}
  body[data-app-color] .page-head .btn.ghost:hover{background:color-mix(in srgb, var(--app-on) 14%, transparent);color:var(--app-on);border-color:var(--app-on)}
  body[data-app-color] .page-head .btn.ghost svg{fill:none;stroke:currentColor}

  /* Scrollbars modernas en toda la app (incluida la del documento, que es la que
     se ve "detrás" de #content) — Firefox (scrollbar-width/color) + Chrome/Edge/
     Safari (::-webkit-scrollbar-*). Usa los tokens de :root, así que el tema
     oscuro las hereda gratis, igual que el resto del sistema de diseño (ver
     CONTRATO-APPS.md "Sistema de diseño compartido"). Cualquier app acoplada que
     cargue este base.css la tiene sin escribir una sola regla propia. */
  *{scrollbar-width:thin;scrollbar-color:var(--line) transparent}
  *::-webkit-scrollbar{width:9px;height:9px}
  *::-webkit-scrollbar-track{background:transparent}
  *::-webkit-scrollbar-thumb{background:var(--line);border-radius:8px}
  *::-webkit-scrollbar-thumb:hover{background:var(--muted)}

  /* ===================== Shell ===================== */
  .app{display:flex;min-height:100vh}
  .main{flex:1;min-width:0}
  /* nivel 3 = pestañas horizontales en el borde superior */
  /* .htabs vive ahora DENTRO de .page-head (misma fila que el título — ver
     más abajo), CENTRADA entre el título y las acciones: el reparto lo hacen
     .page-title/.page-actions con flex:1 1 0 y el orden, no esta regla (ver
     "Cabecera de página"). Si no caben todas las pestañas, bajan a su propia
     línea (flex-wrap) dentro de ese mismo hueco, igual que ya hacían solas. */
  .htabs{display:flex;flex-wrap:wrap;gap:6px 4px;align-items:center}
  .htabs:empty{display:none}
  .htabs::-webkit-scrollbar{height:6px}
  .htab{display:inline-flex;align-items:center;gap:6px;padding:8px 14px;border-radius:9px;font-size:12.5px;font-weight:600;color:var(--muted);cursor:pointer;white-space:nowrap;flex:0 0 auto;text-decoration:none}
  .htab:hover{background:var(--surface-hover);color:var(--ink)}
  .htab.active{background:var(--app-soft);color:var(--app-ink)}
  .htabs-empty{font-size:12px;color:var(--muted);padding:6px 10px}

  /* ===================== Cabecera de página ===================== */
  /* Banda a sangre (sin padding lateral en .content, ver más abajo) con los
     tres bloques en UNA fila: título a la izquierda, pestañas centradas y
     acciones a la derecha. Para que las pestañas queden centradas respecto a
     la banda y no respecto al hueco sobrante, título y acciones se reparten
     ese sobrante a partes iguales (flex:1 1 0) aunque el título sea largo y
     no haya ni un botón — por eso .page-actions no lleva :empty{display:none}.
     No es sticky: la banda se va con el scroll, como en GMAO (antes lo era, y
     shell.js le calculaba el 'top' con ajustarPageHeadTop()). */
  .page-head{display:flex;flex-wrap:wrap;align-items:center;gap:8px 16px;background:var(--panel);border-top:1px solid var(--line);border-bottom:1px solid var(--line);padding:10px 24px;margin-bottom:16px}
  .page-title{flex:1 1 0;min-width:0;order:1}
  .page-title h1{margin:0;font-size:28px;font-weight:800;letter-spacing:-.015em;line-height:1.15}
  .page-sub{margin:4px 0 0;font-size:12.5px;color:var(--muted)}
  .page-actions{flex:1 1 0;order:3;display:flex;gap:8px;align-items:center;justify-content:flex-end}
  /* Acciones de OTRA app (ver chromeId en shell.js): se ocultan los botones, no
     la caja — tiene que seguir ocupando su mitad del sobrante o las pestañas
     dejarían de estar centradas. */
  .page-actions.chrome-off > *{display:none}
  #htabsBar{flex:0 1 auto;order:2;justify-content:center}
  /* En pantallas estrechas no caben los tres en una fila: título y acciones se
     quedan arriba y las pestañas bajan a su propia línea. */
  @media (max-width:900px){
    .page-title{flex:1 1 auto}
    .page-actions{flex:0 0 auto}
    #htabsBar{order:3;flex:1 0 100%;justify-content:flex-start;padding-top:8px}
  }
  /* Al imprimir, los navegadores omiten los fondos: sin esto, el título de una
     app con color (banda sólida, texto en --app-on) saldría invisible sobre el
     papel. Pestañas y botones son controles, no contenido. */
  @media print{
    .page-head,body[data-app-color] .page-head{background:#fff;border-color:#ddd}
    .page-head .page-title h1,body[data-app-color] .page-head .page-title h1{color:#000}
    .page-head .page-sub,body[data-app-color] .page-head .page-sub,
    .page-head .crumb-sep,body[data-app-color] .page-head .crumb-sep{color:#555}
    .page-head .crumb-cur,body[data-app-color] .page-head .crumb-cur{color:#000}
    #htabsBar,.page-actions{display:none}
  }
  /* navegación en cascada de 3 columnas (colapsables / fijas) */
  .navcol{width:200px;flex:0 0 auto;background:var(--panel);border-right:1px solid var(--line);display:flex;flex-direction:column;position:sticky;top:0;height:100vh;transition:width .15s}
  .navcol.collapsed{width:40px}
  /* min-height (no height fija): la cabecera de columna crece si su contenido
     lo pide, y con el padding queda a la altura de .topbar (12px 24px) para
     que #col1/#col2/#topbar lean como una sola barra continua arriba. */
  .navcol-h{display:flex;align-items:center;gap:8px;padding:13px 10px;border-bottom:1px solid var(--line);min-height:52px}
  .navcol-h .logo.sm{width:28px;height:28px;border-radius:8px;font-size:14px;background:var(--app);color:var(--app-on);display:grid;place-items:center;font-weight:800;flex:0 0 auto}
  .navcol-title{flex:1;font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);white-space:nowrap;overflow:hidden}
  .navcol-tog{background:none;border:1px solid var(--line);color:var(--muted);cursor:pointer;font-size:14px;line-height:1;width:24px;height:24px;border-radius:7px;flex:0 0 auto;display:grid;place-items:center}
  .navcol-tog:hover{background:var(--surface-hover);color:var(--ink)}
  .navcol.collapsed .navcol-title,.navcol.collapsed .navcol-foot,.navcol.collapsed .logo.sm{display:none}
  .navcol.collapsed .navcol-h{padding:13px 6px;justify-content:center}
  .navcol.collapsed .navcol-tog{transform:rotate(180deg)}
  /* #col2 plegada: el nombre de la app en vertical al pie de la columna (se lee de abajo arriba), como píldora en el color de la app (mismos tonos que .nav-it.sel). */
  .navcol-vtitle{display:none}
  .navcol.collapsed .navcol-vtitle:not(:empty){display:block;writing-mode:vertical-rl;transform:rotate(180deg);align-self:center;margin:12px 0;padding:12px 5px;border-radius:999px;background:var(--app-soft);max-height:60vh;overflow:hidden;white-space:nowrap;font-size:12px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;color:var(--app-ink)}
  /* Colapsadas, #col1/#col2 quedan como un rail de iconos (como en GMAO): todas
     sus entradas siguen visibles y clicables, solo con el icono (o una inicial
     si no traen icono — ver navIco() en shell.js) y la etiqueta en el tooltip. */
  .navcol.collapsed .navcol-body{padding:8px 4px;overflow:visible}
  .navcol.collapsed .nav-it{justify-content:center;padding:9px 0;gap:0}
  .navcol.collapsed .nav-it .lbl,.navcol.collapsed .nav-it .chev,.navcol.collapsed .nav-it .soon,.navcol.collapsed .nav-it .nav-badge{display:none}
  .nav-ini{width:20px;height:20px;flex:0 0 auto;border-radius:6px;display:none;place-items:center;font-size:11px;font-weight:800;background:var(--surface-alt);color:var(--muted)}
  .navcol.collapsed .nav-ini{display:grid}
  .nav-it.sel .nav-ini{background:var(--app);color:var(--app-on)}
  .navcol-body{flex:1;overflow-y:auto;padding:8px;display:flex;flex-direction:column;gap:3px}
  /* Apps con pinLast (p.ej. "Configuración"): la primera entrada pinned se empuja
     al fondo de #col1Body (flex-column) y lleva una línea separadora, para que
     quede claramente aparte de las apps normales aunque haya pocas encima. */
  .nav-it-pinned-first{margin-top:auto;padding-top:11px;border-top:1px solid var(--line)}
  .navcol-foot{padding:10px 12px;border-top:1px solid var(--line);display:flex;align-items:center;gap:7px;font-size:11px;color:var(--muted)}
  .nav-it{display:flex;align-items:center;gap:9px;padding:9px 10px;border-radius:10px;color:var(--ink);font-size:12.5px;font-weight:600;cursor:pointer;white-space:normal;line-height:1.25;text-decoration:none}
  .nav-it svg{width:18px;height:18px;flex:0 0 auto;fill:none;stroke:var(--muted);stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
  .nav-it .lbl{flex:1;min-width:0}
  .nav-empty{padding:18px 12px;text-align:center;font-size:12px;color:var(--muted);line-height:1.6}
  .nav-empty span{font-size:8.5px;font-weight:700;text-transform:uppercase;letter-spacing:.3px;background:var(--surface-alt);border-radius:6px;padding:2px 6px}
  .nav-it:hover{background:var(--surface-hover)}
  .nav-it.sel{background:var(--app-soft);color:var(--app-ink)}
  .nav-it.sel svg{stroke:var(--app)}
  .nav-it.disabled{color:var(--muted);opacity:.6;cursor:default}
  .nav-it.disabled:hover{background:transparent}
  .nav-it .chev{margin-left:auto;font-size:11px;color:var(--muted);flex:0 0 auto}
  .nav-it .soon{margin-left:auto;font-size:8.5px;font-weight:700;text-transform:uppercase;letter-spacing:.3px;color:var(--muted);background:var(--surface-alt);border-radius:6px;padding:2px 5px;flex:0 0 auto}
  .nav-badge{margin-left:auto;min-width:18px;height:18px;padding:0 5px;border-radius:9px;background:var(--neg-soft);color:var(--neg);font-size:10.5px;font-weight:800;display:none;align-items:center;justify-content:center}
  .nav-badge.show{display:inline-flex}

  .main{display:flex;flex-direction:column;min-width:0}
  /* Sin alto fijo: lo da su contenido (36px de los controles + 12px arriba y
     abajo = los mismos 52px de min-height que .navcol-h, misma barra visual
     arriba de las tres columnas), así el aviso de simulación o un logo más
     alto no obligan a recalcular nada. */
  .topbar{display:flex;align-items:center;gap:16px;padding:12px 24px;position:sticky;top:0;z-index:30;background:var(--bg)}
  .crumbs{font-size:13px;color:var(--muted)} .crumbs b{color:var(--ink);font-weight:700}
  /* .crumb-link/.crumb-sep/.crumb-cur (crumbHtml() en shell.js) ya NO van
     escopados bajo .crumbs: cuando una app no tiene #crumbTitle en su topbar
     (RR.HH.), la misma ruta navegable se pinta dentro de #pageSub en vez de
     .crumbs — necesitan verse igual en los dos sitios. */
  .crumb-link{cursor:pointer}
  .crumb-link:hover{text-decoration:underline;color:var(--brand-ink)}
  .crumb-sep{color:var(--muted);font-weight:400}
  .crumb-cur{color:var(--ink)}

  /* ===================== Logo y buscador global (#topbarSearch) ===================== */
  /* Logo · buscador centrado · .tb-actions, los tres EN EL FLUJO del .topbar
     (antes el buscador iba en position:absolute centrado sobre la barra): así
     nunca se solapa con el logo ni con los controles de la derecha. */
  .tb-brand{display:flex;align-items:center;flex:0 0 auto;cursor:pointer}
  .tb-logo{height:28px;width:auto;display:block}
  .topbar-search{flex:1;display:flex;justify-content:center;padding:0 16px;min-width:0}
  .tb-search-box{position:relative;display:flex;align-items:center;gap:8px;width:100%;max-width:420px;height:36px;padding:0 12px;background:var(--panel);border:1px solid var(--line);border-radius:10px}
  .tb-search-box > svg{width:15px;height:15px;flex:0 0 auto;fill:none;stroke:var(--muted);stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
  #topbarSearchInput{flex:1;min-width:0;border:none;outline:none;background:transparent;font:inherit;font-size:13px;color:var(--ink)}
  #topbarSearchInput::placeholder{color:var(--muted)}
  .topbar-search-results{position:absolute;top:calc(100% + 6px);left:0;width:100%;max-height:60vh;overflow-y:auto;background:var(--panel);border:1px solid var(--line);border-radius:12px;box-shadow:var(--shadow);z-index:60;padding:6px}
  .topbar-search-results[hidden]{display:none}
  .topbar-search-item{padding:9px 10px;border-radius:8px;font-size:12.5px;cursor:pointer;color:var(--muted)}
  .topbar-search-item:hover{background:var(--surface-hover)}
  .topbar-search-empty{padding:9px 10px;font-size:12.5px;color:var(--muted)}
  @media(max-width:900px){.topbar-search{padding:0 8px}}

  .tb-actions{display:flex;align-items:center;gap:10px;margin-left:auto}
  #langSel{background:var(--panel);border:1px solid var(--line);border-radius:10px;color:var(--ink);font-size:13px;padding:6px 8px;cursor:pointer}
  .tb-toggle{display:flex;background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:3px;cursor:pointer}
  .tb-toggle span{width:28px;height:24px;display:grid;place-items:center;border-radius:7px}
  .tb-toggle span svg{width:15px;height:15px;fill:none;stroke:var(--muted);stroke-width:1.8}
  .tb-toggle span.on{background:#fdf3df}.tb-toggle span.on svg{stroke:var(--warn)}
  .tb-ic{position:relative;width:36px;height:36px;border-radius:10px;background:var(--panel);border:1px solid var(--line);display:grid;place-items:center;cursor:pointer}
  .tb-ic svg{width:17px;height:17px;fill:none;stroke:var(--muted);stroke-width:1.8;stroke-linejoin:round}
  /* Contador de la campana: lo pone el shell con lo que publica la app (Shell.avisos). Sin avisos, nada. */
  .tb-badge{position:absolute;top:-6px;right:-6px;min-width:18px;height:18px;padding:0 4px;box-sizing:border-box;border-radius:9px;background:var(--neg);color:#fff;font-size:10.5px;font-weight:700;line-height:14px;text-align:center;border:2px solid var(--panel)}
  .avatar{width:36px;height:36px;border-radius:50%;background:var(--app);color:var(--app-on);display:grid;place-items:center;font-size:12px;font-weight:800;cursor:pointer;box-shadow:0 0 0 2px var(--panel),0 0 0 3px transparent;transition:box-shadow .15s,transform .15s}
  .avatar:hover{transform:translateY(-1px);box-shadow:0 0 0 2px var(--panel),0 0 0 3px var(--app)}
  .user-menu-wrap{position:relative}
  .user-menu{position:absolute;top:46px;right:0;background:var(--panel);border:1px solid var(--line);border-radius:14px;box-shadow:var(--shadow);padding:0;min-width:236px;z-index:60;overflow:hidden;animation:userMenuIn .15s ease}
  @keyframes userMenuIn{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}
  .user-menu[hidden]{display:none}
  /* Cabecera tipo "tarjeta de perfil": avatar grande + nombre + rol juntos,
     sobre un fondo ligeramente distinto del resto del menú. */
  .user-menu-cabecera{display:flex;align-items:center;gap:11px;padding:14px 16px;background:var(--bg)}
  .user-menu-avatar-grande{width:40px;height:40px;border-radius:50%;background:var(--app);color:var(--app-on);display:grid;place-items:center;font-size:13px;font-weight:800;flex:0 0 auto}
  .user-menu-identidad{min-width:0}
  .user-menu-nombre{font-weight:700;font-size:13.5px;color:var(--ink);line-height:1.3;word-break:break-all}
  .user-menu-rol{display:inline-block;margin-top:4px;padding:2px 9px;border-radius:20px;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;background:var(--line);color:var(--muted)}
  .user-menu-rol-admin{background:var(--app-soft);color:var(--app-ink)}
  .user-menu-rol:empty{display:none}
  .user-menu-div{height:1px;background:var(--line)}
  .user-menu-acciones{padding:6px}
  .user-menu-salir,.user-menu-simular{display:flex;align-items:center;gap:10px;width:100%;padding:9px 10px;border:none;background:transparent;border-radius:9px;cursor:pointer;font-size:13px;font-weight:600;text-align:left;transition:background .12s}
  .user-menu-salir{color:var(--neg)}
  .user-menu-simular{color:var(--warn)}
  .user-menu-salir:hover,.user-menu-simular:hover{background:var(--bg)}
  .user-menu-simular[hidden]{display:none}
  .user-menu-salir svg,.user-menu-simular svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linejoin:round;flex:0 0 auto}
  /* Aviso fijo mientras dura la simulación — imposible de confundir con la
     sesión real, visible desde cualquier vista. Altura fija (no al gusto del
     contenido) porque body.simulando-no-admin necesita saber cuánto empujar
     hacia abajo — si no, taparía la parte de arriba de .topbar (sticky top:0,
     no sabe nada de este banner). */
  .simulacion-banner{position:fixed;top:0;left:0;right:0;z-index:9998;height:36px;box-sizing:border-box;display:flex;align-items:center;justify-content:center;gap:14px;padding:0 16px;background:var(--warn);color:#241c04;font-size:12.5px;font-weight:700}
  .simulacion-banner button{border:1px solid #241c04;background:transparent;color:inherit;font-weight:700;font-size:12px;padding:3px 10px;border-radius:7px;cursor:pointer}
  .simulacion-banner button:hover{background:rgba(0,0,0,.08)}
  body.simulando-no-admin{padding-top:36px}

  /* Barra DEV "Simular rol" (pintarBarraDev() en shell.js): solo en entornos de
     desarrollo y solo mientras la app activa la declara (`dev` en su registro).
     Fija abajo; body.con-devbar recorta las columnas y el contenido para que no
     tape nada — sin eso, la entrada fija de #col1 (Configuración) quedaba debajo. */
  .dev-bar{position:fixed;left:0;right:0;bottom:0;z-index:9998;height:30px;display:flex;align-items:center;gap:8px;padding:0 12px;background:#1e2a36;color:#e7edf3;font-size:11px}
  .dev-bar-tag,.dev-bar-lbl{opacity:.65}
  .dev-bar-nota{margin-left:auto;opacity:.55;font-style:italic;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
  .dev-bar-btn{padding:2px 8px;border-radius:6px;border:1px solid #4a5568;background:transparent;color:#9ca3af;cursor:pointer;font:inherit;font-size:11px;flex:0 0 auto}
  .dev-bar-btn:hover{color:#e7edf3;border-color:#9ca3af}
  .dev-bar-btn.on{background:var(--app);border-color:var(--app);color:var(--app-on)}
  body.con-devbar .navcol{height:calc(100vh - 30px)}
  body.con-devbar .content{padding-bottom:70px}
  body.con-devbar #buildBadge{bottom:36px !important}
  @media print{.dev-bar{display:none}}

  /* Sin padding lateral: la banda de cabecera va a sangre de borde a borde y el
     margen lateral lo ponen #pageHead (padding:10px 24px) y #vista por su
     cuenta — ver "Cabecera de página". */
  .content{padding:0 0 40px;flex:1}
  #vista{padding:0 24px}
  /* Los demás bloques del esqueleto (filtros y KPIs de la app activa, p.ej. los
     del Hub) reciben ese mismo margen lateral POR FUERA: llevan fondo y padding
     propios (tarjeta), así que tocarles el padding les cambiaría el interior. */
  #filterbar,#kpisTop,#kpisAbove,#kpisBelow{margin-left:24px;margin-right:24px}
  /* Las vistas que envuelven su contenido en .panelpad a primer nivel dentro de
     #vista ya no deben añadir el lateral otra vez (lo pone #vista). */
  #vista > .panelpad{padding-left:0;padding-right:0}

  .btn{display:inline-flex;align-items:center;gap:8px;background:var(--brand);color:#fff;border:none;border-radius:11px;padding:10px 16px;font-size:13px;font-weight:600;cursor:pointer;box-shadow:0 1px 2px color-mix(in srgb, var(--brand) 35%, transparent)}
  .btn:hover{background:var(--brand-d)}
  .btn svg{width:15px;height:15px;fill:currentColor;stroke:none}
  .btn.ghost{background:var(--panel);color:var(--ink);border:1px solid var(--line);box-shadow:none}
  .btn.ghost svg{fill:none;stroke:currentColor;stroke-width:1.9}
  .btn.ghost:hover{border-color:var(--brand);color:var(--brand)}
  .btn.mini{padding:6px 12px;font-size:12px;border-radius:9px}
  /* Botón solo icono (CONTRATO-UI.md §A5): cuadrado de 36px, sin texto. El SVG
     lo trae la app; aquí solo se fija su tamaño y trazo, para que todas las
     apps tengan el mismo icono aunque cada una dibuje el suyo. 'title' y
     'aria-label' son obligación de la app: sin texto no hay otra pista. */
  .btn.ico{width:36px;height:36px;padding:0;justify-content:center;gap:0}
  .btn.ico svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
  .btn.danger{background:var(--neg);box-shadow:0 1px 2px color-mix(in srgb, var(--neg) 35%, transparent)}
  .btn.danger:hover{filter:brightness(.92)}

  /* ===================== KPI genérico ===================== */
  .kpi{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:14px 16px;box-shadow:var(--shadow);position:relative}
  .kpi .lbl{font-size:10px;text-transform:uppercase;letter-spacing:.4px;color:var(--muted);font-weight:700}
  .kpi .val{font-size:23px;font-weight:800;margin-top:6px;color:var(--ink)}
  .kpi .val small{font-size:11px;font-weight:600;color:var(--muted)}
  .kpi .sub{font-size:11px;color:var(--muted);margin-top:4px}

  /* ===================== Panels & tables ===================== */
  .panel{background:var(--panel);border:1px solid var(--line);border-radius:16px;box-shadow:var(--shadow);margin-bottom:18px;overflow:hidden}
  .panel .phead{display:flex;align-items:center;gap:10px;padding:16px 18px;border-bottom:1px solid var(--line)}
  .panel .phead h3{margin:0;font-size:16px;font-weight:700}
  .panel .phead .note{font-size:12px;color:var(--muted)}
  /* Colapsar tarjetas con tabla (no las KPI) para reducir scroll vertical */
  .pcoll-tog{flex:0 0 auto;width:22px;height:22px;border:1px solid var(--line);border-radius:7px;background:var(--panel);color:var(--muted);cursor:pointer;font-size:11px;line-height:1;display:flex;align-items:center;justify-content:center;transition:transform .15s,color .15s}
  .pcoll-tog:hover{color:var(--brand-ink);border-color:var(--brand)}
  .panel.pcoll .pcoll-tog{transform:rotate(-90deg)}
  .panel.pcoll .phead{border-bottom:none}
  .panel.pcoll > *:not(.phead){display:none}
  .panelpad{padding:16px 18px}
  /* Tarjeta desplegada a pantalla completa */
  .panel.panel-full{position:fixed;inset:0;z-index:300;margin:0;border:none;border-radius:0;box-shadow:none;
    display:flex;flex-direction:column;background:var(--panel)}
  .panel.panel-full .phead{flex:0 0 auto}
  .panel.panel-full .panelpad{flex:1 1 auto;min-height:0;display:flex;padding:0 16px 16px}
  body.has-full{overflow:hidden}

  /* ===================== Guía / Wiki de usuario (#nav-l2-guia) ===================== */
  /* Motor genérico (GuiaContenido.register() + <app>/js/views/guia.js) que ya
     usan RR.HH. y Hub — antes esta MISMA hoja de estilos vivía duplicada en
     rrhh.css Y en portal.css (portal.css la traía porque nunca carga
     rrhh.css) — consolidada aquí, fuente única para las tres apps. */
  #guiaWrap{display:flex;align-items:flex-start;gap:0}
  #guiaMenu{flex:0 0 260px;position:sticky;align-self:flex-start;overflow:auto;padding:12px 14px}
  #guiaMenuHead{margin-bottom:10px}
  #guiaBuscador{width:100%;background:var(--panel);border:1px solid var(--line);border-radius:9px;color:var(--ink);font-size:12.5px;padding:8px 10px}
  #guiaToc{display:flex;flex-direction:column;gap:4px}
  .guia-grupo{margin-bottom:10px}
  .guia-grupo-tit{font-size:10.5px;font-weight:800;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);padding:6px 8px 2px}
  .guia-link{display:block;padding:6px 10px;border-radius:8px;color:var(--ink);font-size:12.5px;text-decoration:none;line-height:1.3}
  .guia-link:hover{background:var(--surface-hover)}
  .guia-link.activa{background:var(--brand-soft);color:var(--brand-ink);font-weight:600}
  #guiaDoc{flex:1;min-width:0;border-left:1px solid var(--line);padding:8px 28px 40px}
  #guiaDocTitulo{margin:4px 0 14px;font-size:20px}
  #guiaDocCuerpo{font-size:13.5px;line-height:1.65;max-width:820px}
  #guiaDocCuerpo h3{margin:22px 0 6px;font-size:15px;color:var(--brand-ink)}
  #guiaDocCuerpo p{margin:6px 0}
  #guiaDocCuerpo ul,#guiaDocCuerpo ol{margin:6px 0 6px 20px}
  #guiaDocCuerpo code{background:var(--surface-hover);border-radius:5px;padding:1px 5px;font-size:12px}
  #guiaDocCuerpo table{border-collapse:collapse;margin:8px 0;font-size:12.5px}
  #guiaDocCuerpo th,#guiaDocCuerpo td{border:1px solid var(--line);padding:5px 9px;text-align:left}
  #guiaDocCuerpo a[data-guia]{color:var(--brand-ink);text-decoration:underline;cursor:pointer}
  #guiaNav{display:flex;justify-content:space-between;gap:12px;margin-top:28px;border-top:1px solid var(--line);padding-top:14px}
  @media (max-width:860px){
    #guiaWrap{flex-direction:column}
    #guiaMenu{position:static;flex-basis:auto;width:100%;max-height:none}
    #guiaDoc{border-left:none;border-top:1px solid var(--line);padding:12px}
  }

  /* ===================== Tema oscuro ===================== */
  body.dark{
    --bg:#0f141b; --panel:#1a212b; --ink:#e7edf3; --muted:#8b97a4; --line:#2a323d;
    --brand:#1bb189; --brand-d:#159372; --brand-soft:#16302a; --brand-ink:#62d3ad;
    --blue:#5b8def; --blue-soft:#1b2740; --warn:#d6a447; --neg:#e9695b; --pos:#3bbd86;
    --surface-hover:#232c37; --surface-alt:#222b36; --surface-raised:#202833;
    --neg-soft:#3a1f1d; --warn-soft:#33291a;
    --shadow:0 1px 2px rgba(0,0,0,.4),0 8px 24px rgba(0,0,0,.45); --shadow-sm:0 1px 2px rgba(0,0,0,.4);
  }
  body.dark .tb-toggle span.on{background:#26303d}
  body.dark .tb-toggle span.on svg{stroke:#9fb3c8}

  @media(max-width:760px){.navcol{width:150px}.navcol#col2{display:none}}
