/* =====================================================================
   SOMOS · capa de diseño (Fase 1: cimientos)
   Se carga después de template.css. Define tipografía, tokens de
   Bootstrap 5.3 alineados al acento de la app, tabla estándar, estados
   y las clases que las vistas usan pero ningún CSS definía.
   ===================================================================== */

/* ---------- Fuente: Inter variable, servida en local ---------- */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("../fonts/Inter-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("../fonts/Inter-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ---------- Escala tipográfica y tokens de Bootstrap ---------- */
:root {
  --fs-page: 22px;      /* título de página */
  --fs-section: 16px;   /* título de sección / tarjeta */
  --fs-body: 14px;      /* cuerpo, formularios, menús */
  --fs-table: 13px;     /* celdas de tabla (escritorio) */
  --fs-small: 12px;     /* texto auxiliar */
  --fs-label: 11px;     /* encabezados de tabla, etiquetas en mayúsculas */

  --app-accent-rgb: 47, 111, 237;
  --app-accent-strong: #1d5be0;

  --bs-body-font-family: "Inter", "Segoe UI", system-ui, -apple-system, Roboto, "Helvetica Neue", Arial, sans-serif;
  --bs-body-font-size: var(--fs-body);
  --bs-body-line-height: 1.5;
  --bs-primary: var(--app-accent);
  --bs-primary-rgb: var(--app-accent-rgb);
  --bs-link-color: var(--app-accent);
  --bs-link-color-rgb: var(--app-accent-rgb);
  --bs-link-hover-color: var(--app-accent-strong);
  --bs-link-hover-color-rgb: 29, 91, 224;
  --bs-focus-ring-color: rgba(var(--app-accent-rgb), 0.25);
  --bs-border-color: var(--app-border);
  --bs-border-radius: 8px;
  --bs-border-radius-sm: 6px;
}
[data-bs-theme="dark"] {
  --app-accent-rgb: 109, 155, 255;
  --app-accent-strong: #9ab9ff;
  --bs-link-hover-color-rgb: 154, 185, 255;
  --bs-body-color: var(--app-text-main);
  --bs-body-bg: var(--app-bg-body);
  --bs-secondary-color: var(--app-text-sub);
}

/* ---------- Base ---------- */
body {
  font-family: var(--bs-body-font-family);
  font-size: var(--fs-body);
  line-height: 1.5;
  font-feature-settings: "tnum" 1, "cv11" 1;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4, h5, h6 {
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: var(--app-text-main);
}
h1 { font-size: 28px; }
h2 { font-size: 24px; }
h3, h4 { font-size: var(--fs-page); }
h5 { font-size: var(--fs-section); }
h6 { font-size: var(--fs-body); }
small, .small { font-size: var(--fs-small); }
strong, b { font-weight: 600; }

a { text-decoration: none; }
a:hover { text-decoration: underline; }
.btn:hover, .app-menu-link:hover, .dropdown-item:hover, .page-link:hover, .nav-link:hover { text-decoration: none; }

:focus-visible { outline: 2px solid var(--app-accent); outline-offset: 2px; }
.btn:focus-visible, .form-control:focus-visible, .form-select:focus-visible { outline: none; }

/* Transiciones específicas (template.css usa "all") */
.btn-toggle-theme { transition: background-color .15s, color .15s, border-color .15s; }
.app-menu-link { transition: background-color .15s, color .15s; }
.search-clean { transition: border-color .15s, box-shadow .15s; }
.app-card, .action-card, .card-body.clickable { transition: box-shadow .2s, transform .2s, border-color .2s; }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
}

/* ---------- Botones ---------- */
.btn { --bs-btn-font-weight: 500; --bs-btn-border-radius: 8px; }
.btn-sm { --bs-btn-font-size: var(--fs-small); --bs-btn-border-radius: 6px; }
.btn-primary {
  --bs-btn-bg: var(--app-accent);
  --bs-btn-border-color: var(--app-accent);
  --bs-btn-hover-bg: var(--app-accent-strong);
  --bs-btn-hover-border-color: var(--app-accent-strong);
  --bs-btn-active-bg: var(--app-accent-strong);
  --bs-btn-active-border-color: var(--app-accent-strong);
  --bs-btn-disabled-bg: var(--app-accent);
  --bs-btn-disabled-border-color: var(--app-accent);
}
.btn-outline-primary {
  --bs-btn-color: var(--app-accent);
  --bs-btn-border-color: var(--app-accent);
  --bs-btn-hover-bg: var(--app-accent);
  --bs-btn-hover-border-color: var(--app-accent);
  --bs-btn-active-bg: var(--app-accent);
  --bs-btn-active-border-color: var(--app-accent);
}
.btn-link { --bs-btn-color: var(--app-accent); --bs-btn-hover-color: var(--app-accent-strong); --bs-btn-font-weight: 500; }
.btn-light { --bs-btn-bg: var(--app-bg-surface); --bs-btn-border-color: var(--app-border); --bs-btn-color: var(--app-text-main); --bs-btn-hover-bg: var(--app-bg-body); --bs-btn-hover-border-color: var(--app-border); --bs-btn-active-bg: var(--app-bg-body); }

/* ---------- Formularios ---------- */
.form-label, label.small, label.text-muted { font-size: var(--fs-small); font-weight: 500; color: var(--app-text-sub); margin-bottom: .25rem; }
.form-control, .form-select { font-size: var(--fs-body); border-color: var(--app-border); border-radius: 8px; min-height: 38px; }
.form-control-sm, .form-select-sm { font-size: var(--fs-small); min-height: 32px; border-radius: 6px; }
.form-control:focus, .form-select:focus {
  border-color: var(--app-accent);
  box-shadow: 0 0 0 .2rem rgba(var(--app-accent-rgb), .2);
}
.form-check-input:checked { background-color: var(--app-accent); border-color: var(--app-accent); }
.form-check-input:focus { border-color: var(--app-accent); box-shadow: 0 0 0 .2rem rgba(var(--app-accent-rgb), .2); }
.form-check-label { font-size: var(--fs-body); }

/* ---------- Componentes de Bootstrap alineados al acento ---------- */
.pagination {
  --bs-pagination-active-bg: var(--app-accent);
  --bs-pagination-active-border-color: var(--app-accent);
  --bs-pagination-color: var(--app-text-main);
  --bs-pagination-border-color: var(--app-border);
  --bs-pagination-hover-bg: var(--app-accent-hover);
  --bs-pagination-hover-color: var(--app-accent);
  --bs-pagination-focus-box-shadow: 0 0 0 .2rem rgba(var(--app-accent-rgb), .2);
}
.dropdown-menu {
  --bs-dropdown-border-color: var(--app-border);
  --bs-dropdown-border-radius: 10px;
  --bs-dropdown-font-size: var(--fs-body);
  --bs-dropdown-link-active-bg: var(--app-accent);
  --bs-dropdown-link-hover-bg: var(--app-bg-body);
  box-shadow: 0 8px 24px rgba(0, 0, 0, .10);
}
.progress { --bs-progress-bar-bg: var(--app-accent); --bs-progress-bg: var(--app-bg-body); }
.list-group { --bs-list-group-active-bg: var(--app-accent); --bs-list-group-active-border-color: var(--app-accent); --bs-list-group-border-color: var(--app-border); }
.nav-pills { --bs-nav-pills-link-active-bg: var(--app-accent); }
.nav-tabs { --bs-nav-tabs-border-color: var(--app-border); --bs-nav-tabs-link-active-color: var(--app-text-main); }
.card { --bs-card-border-color: var(--app-border); --bs-card-border-radius: 10px; --bs-card-bg: var(--app-bg-surface); }
.card-header { font-weight: 600; }
.modal-content { border-radius: 12px; border-color: var(--app-border); }
.badge { font-weight: 600; letter-spacing: .01em; }

/* Colores de estado "suaves": la tinta del texto en el color, fondo al 14 %.
   Sirven para badges dentro de tablas y para las tarjetas de conteo. */
.table .badge.bg-success, .badge-soft.bg-success { --bs-bg-opacity: .14; color: var(--bs-success-text-emphasis); }
.table .badge.bg-danger,  .badge-soft.bg-danger  { --bs-bg-opacity: .14; color: var(--bs-danger-text-emphasis); }
.table .badge.bg-warning, .badge-soft.bg-warning { --bs-bg-opacity: .18; color: var(--bs-warning-text-emphasis); }
.table .badge.bg-info,    .badge-soft.bg-info    { --bs-bg-opacity: .16; color: var(--bs-info-text-emphasis); }
.table .badge.bg-primary, .badge-soft.bg-primary { --bs-bg-opacity: .14; color: var(--app-accent-strong); }
.table .badge.bg-secondary, .badge-soft.bg-secondary { --bs-bg-opacity: .14; color: var(--bs-secondary-text-emphasis); }
.table .badge.bg-warning.text-dark { color: var(--bs-warning-text-emphasis) !important; }
.table .badge.bg-light { --bs-bg-opacity: 1; background-color: var(--app-bg-body) !important; color: var(--app-text-main) !important; border: 1px solid var(--app-border); font-weight: 500; font-variant-numeric: tabular-nums; }
.table .badge.bg-dark { background-color: var(--app-text-main) !important; color: var(--app-bg-surface); }

/* Clases que las vistas usan y ningún CSS definía */
.bg-pill, .bg-warning-soft, .bg-success-soft, .bg-info-soft, .bg-primary-soft, .bg-danger-soft, .bg-secondary-soft {
  background-color: rgba(128, 128, 128, .12);
  background-color: color-mix(in srgb, currentColor 14%, transparent);
  border-radius: 999px;
}
.border-start-primary   { border-left: 4px solid var(--app-accent) !important; }
.border-start-success   { border-left: 4px solid var(--bs-success) !important; }
.border-start-danger    { border-left: 4px solid var(--bs-danger) !important; }
.border-start-warning   { border-left: 4px solid var(--bs-warning) !important; }
.border-start-info      { border-left: 4px solid var(--bs-info) !important; }
.border-start-secondary { border-left: 4px solid var(--bs-secondary) !important; }

/* Tintes pastel de style.css en modo oscuro */
[data-bs-theme="dark"] .bg-danger-a    { background-color: rgba(var(--bs-danger-rgb), .28); }
[data-bs-theme="dark"] .bg-primary-a,
[data-bs-theme="dark"] .bg-info-a      { background-color: rgba(var(--app-accent-rgb), .28); }
[data-bs-theme="dark"] .bg-success-a   { background-color: rgba(var(--bs-success-rgb), .28); }
[data-bs-theme="dark"] .bg-warning-a,
[data-bs-theme="dark"] .bg-yellow-a    { background-color: rgba(var(--bs-warning-rgb), .28); }
[data-bs-theme="dark"] .bg-secondary-a { background-color: rgba(var(--bs-secondary-rgb), .28); }
[data-bs-theme="dark"] .bg-purple-a    { background-color: rgba(120, 90, 220, .35); }

/* ---------- Tabla estándar ---------- */
.table {
  --bs-table-bg: transparent;
  --bs-table-border-color: var(--app-border);
  --bs-table-hover-bg: var(--app-bg-body);
  --bs-table-striped-bg: rgba(128, 128, 128, .04);
  font-size: var(--fs-table);
  font-variant-numeric: tabular-nums;
  margin-bottom: .75rem;
}
/* Las celdas arrancan arriba. Con vertical-align:middle, en un listado donde una
   fila puede medir 200px por culpa de una dirección o una nota larga, los campos
   cortos —la clave, el teléfono, una píldora— quedaban flotando a media altura y
   nada alineaba con nada. Arriba, todas las columnas empiezan en la misma línea. */
.table > :not(caption) > * > * { padding: .5rem .625rem; vertical-align: top; }
.table.table-sm > :not(caption) > * > * { padding: .45rem .625rem; }
/* Salvo lo que es un control suelto y se lee mejor centrado con su fila. */
.table td.col-check, .table td.col-acciones { vertical-align: middle; }
.table thead th {
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--app-text-sub);
  white-space: nowrap;
  border-bottom: 1px solid var(--app-border);
  vertical-align: bottom;
}
.table thead th .small, .table thead th .text-muted { font-size: inherit; color: inherit !important; }
.table thead th .bi { font-size: 12px; cursor: pointer; opacity: .55; vertical-align: -.1em; }
.table thead th .bi:hover { opacity: 1; color: var(--app-accent); }
/* Un icono suelto (conexión, señal, TV) hace de dato y se dibuja a 16px. */
.table tbody td .bi { font-size: 16px; line-height: 1; vertical-align: -.2em; }
/* Uno que acompaña a un texto es parte de ese texto y toma su tamaño: a 16px
   junto a un auxiliar de 12px se veía como si cada fila usara otra escala. */
.table tbody td .btn .bi,
.table tbody td .badge .bi,
.table tbody td .dropdown-item .bi,
.table tbody td .cell-sub .bi,
.table tbody td .cell-title .bi,
.table tbody td a:not(.btn) > .bi { font-size: inherit; vertical-align: -.12em; }
.table .badge { font-size: var(--fs-label); padding: .3em .55em; border-radius: 6px; }
.table .btn-sm { --bs-btn-font-size: var(--fs-small); --bs-btn-padding-y: .2rem; --bs-btn-padding-x: .5rem; }
.table td a:not(.btn):not(.dropdown-item) { color: var(--app-accent); }
.table td .text-secondary, .table td .text-muted { color: var(--app-text-sub) !important; }
.table td.num, .table th.num { text-align: right; white-space: nowrap; }
.table .form-check-input, .table input[type="checkbox"] { width: 15px; height: 15px; margin: 0; vertical-align: middle; cursor: pointer; }
@media (max-width: 767.98px) {
  .table { font-size: var(--fs-body); }
}

/* Círculo de iniciales (antes morado fijo) */
.circulo-iniciales {
  width: 26px; height: 26px; line-height: 26px;
  font-size: 11px; font-weight: 600;
  background-color: var(--app-accent-hover);
  color: var(--app-accent);
}

/* ---------- Sidebar y header (ajustes de escala) ---------- */
.app-menu-link { font-size: var(--fs-body); }
.app-submenu .app-menu-link { font-size: var(--fs-body); }
.app-menu-icon { font-size: 18px; }
.search-clean { font-size: var(--fs-body); }

/* En móvil el buscador es la acción principal del header: al ocultar el globito
   de comentario queda sitio, así que se le da más alto y más tipografía. */
@media (max-width: 991px) {
    .search-wrapper { margin: 0 6px; max-width: none; }
    .search-clean {
        height: 44px;
        font-size: 1rem;
        padding-left: 2.5rem;
    }
    .search-icon { left: 14px; font-size: 1rem; }
}
.dropdown-header { font-size: var(--fs-label); letter-spacing: .06em; font-weight: 600; color: var(--app-text-sub); }

/* ---------- Login ---------- */
/* =====================================================================
   INICIO DE SESIÓN
   Escritorio: panel de marca a la izquierda, formulario a la derecha.
   Móvil: sólo el formulario, a pantalla completa.
   ===================================================================== */

.login-body {
    min-height: 100vh;
    margin: 0;
    background: var(--app-bg-body);
}

.login-split {
    min-height: 100vh;
    display: grid;
    grid-template-columns: 1.1fr 1fr;
}

/* --- Panel de marca --- */

.login-brand {
    position: relative;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    padding: 48px 56px;
    color: #fff;
    /* Verde de la marca degradado hacia un grafito profundo. */
    background: linear-gradient(155deg, #0d1b23 0%, #10352a 52%, #17603d 100%);
}

/* Halo cálido: recoge el amarillo del logo sin competir con el formulario. */
.login-brand-glow {
    position: absolute;
    width: 620px;
    height: 620px;
    right: -220px;
    top: -180px;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(244, 196, 48, .20) 0%, rgba(244, 196, 48, 0) 68%);
    pointer-events: none;
}

/* Todo el contenido va por encima del halo, que es absoluto.
   Se aplica a los hijos directos y no a clases concretas, para que el panel
   siga viéndose bien aunque cambie el marcado. */
.login-brand > *:not(.login-brand-glow):not(.login-ondas) {
    position: relative;
    z-index: 1;
}

.login-brand-top {
    display: flex;
    align-items: center;
    gap: 12px;
}
.login-brand-badge {
    width: 40px;
    height: 40px;
    border-radius: 11px;
    box-shadow: 0 6px 18px rgba(0, 0, 0, .3);
}
.login-brand-name {
    color: #fff;
    font-weight: 700;
    letter-spacing: .16em;
    font-size: .95rem;
}

.login-brand h1 {
    /* Explícito: los estilos globales pintan los encabezados de color oscuro
       y sobre este fondo desaparecerían. */
    color: #fff;
    font-size: 2rem;
    font-weight: 700;
    line-height: 1.22;
    margin: 0 0 14px;
    max-width: 13em;
}
.login-brand p {
    color: rgba(255, 255, 255, .72);
    max-width: 34em;
    margin: 0 0 30px;
    line-height: 1.6;
}

.login-brand-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 14px;
}
.login-brand-list li {
    display: flex;
    align-items: center;
    gap: 12px;
    color: rgba(255, 255, 255, .9);
    font-size: var(--fs-body);
}
.login-brand-list i {
    width: 34px;
    height: 34px;
    flex: 0 0 34px;
    display: grid;
    place-items: center;
    border-radius: 10px;
    background: rgba(255, 255, 255, .1);
    border: 1px solid rgba(255, 255, 255, .14);
    font-size: .95rem;
}

.login-brand-foot {
    color: rgba(255, 255, 255, .45);
    font-size: var(--fs-small);
}

/* --- Formulario --- */

.login-panel {
    position: relative;
    overflow: hidden;
    display: grid;
    place-items: center;
    padding: 40px 24px;
    background: var(--app-bg-surface);
}

.login-card {
    position: relative;   /* por encima de las ondas del fondo */
    z-index: 1;
    width: 100%;
    max-width: 380px;
}

.login-card .logo {
    width: 60%;
    max-width: 200px;
    display: block;
    margin: 0 auto 32px;
}

.login-title {
    font-size: 1.4rem;
    font-weight: 650;
    margin: 0 0 6px;
    color: var(--app-text-main);
}
.login-sub {
    color: var(--app-text-sub);
    font-size: var(--fs-body);
    margin: 0 0 28px;
}

.login-field { margin-bottom: 18px; }
.login-field .form-label {
    font-size: var(--fs-label);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--app-text-sub);
    margin-bottom: 7px;
}

.login-input { position: relative; }
.login-input > i {
    position: absolute;
    left: 14px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--app-text-sub);
    font-size: 1rem;
    pointer-events: none;
}
.login-input .form-control {
    height: 50px;
    padding-left: 44px;
    padding-right: 44px;
    border-radius: 11px;
    border: 1px solid var(--app-border);
    background: var(--app-bg-body);
    font-size: 1rem;
}
.login-input .form-control:focus {
    background: var(--app-bg-surface);
    border-color: var(--app-accent);
    box-shadow: 0 0 0 4px rgba(47, 111, 237, .13);
}

.login-ojo {
    position: absolute;
    right: 6px;
    top: 50%;
    transform: translateY(-50%);
    width: 36px;
    height: 36px;
    display: grid;
    place-items: center;
    border: 0;
    background: transparent;
    border-radius: 9px;
    color: var(--app-text-sub);
}
.login-ojo:hover { color: var(--app-text-main); }

.login-btn {
    width: 100%;
    height: 50px;
    border-radius: 11px;
    font-weight: 600;
    font-size: 1rem;
    margin-top: 26px;
}

#alertSesion:not(:empty) { margin-top: 18px; }

/* --- Descarga de la APK (sólo Android por navegador) --- */

.login-apk {
    display: flex;
    align-items: center;
    gap: 11px;
    margin-top: 28px;
    padding: 12px 14px;
    border-radius: 13px;
    border: 1px solid var(--app-border);
    background: var(--app-bg-body);
    color: var(--app-text-main);
    text-decoration: none;
}
.login-apk:active { background: var(--app-accent-hover); }

/* El logo de SOMOS ya es una placa cuadrada con fondo propio: sólo hay que
   redondearlo, sin recuadro de color detrás. */
.login-apk-logo {
    width: 38px;
    height: 38px;
    flex: 0 0 38px;
    border-radius: 10px;
    object-fit: cover;
}
.login-apk-txt {
    display: flex;
    flex-direction: column;
    line-height: 1.35;
    min-width: 0;
    flex: 1;
}
.login-apk-txt strong { font-size: var(--fs-body); font-weight: 600; }
.login-apk-txt small { color: var(--app-text-sub); font-size: var(--fs-label); }

.login-footer {
    color: var(--app-text-sub);
    font-size: var(--fs-small);
    text-align: center;
    margin-top: 30px;
}

/* --- Móvil: se cae el panel de marca --- */

@media (max-width: 991px) {
    .login-split { grid-template-columns: 1fr; }
    .login-brand { display: none; }

    /* Sin tarjeta: el formulario se apoya directo sobre el fondo. */
    .login-panel {
        background: var(--app-bg-surface);
        padding: 28px 24px;
        align-content: center;
    }
    .login-card { max-width: 360px; }

    /* Ritmo más apretado que en escritorio: en un teléfono el formulario debe
       caber de un vistazo, sin que la vista tenga que recorrerlo. */
    .login-card .logo {
        width: 46%;
        max-width: 152px;
        margin-bottom: 22px;
    }

    /* Centrados, para que acompañen al logo en vez de pelearse con él. */
    .login-title {
        font-size: 1.22rem;
        margin-bottom: 3px;
        text-align: center;
    }
    .login-sub {
        font-size: .85rem;
        margin-bottom: 22px;
        text-align: center;
    }

    /* Las etiquetas se ocultan a la vista pero siguen ahí para quien use
       lector de pantalla: el icono y el texto de ejemplo ya dicen qué va en
       cada campo, y así la pantalla respira sin crecer. */
    .login-field .form-label {
        position: absolute;
        width: 1px;
        height: 1px;
        padding: 0;
        margin: -1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        white-space: nowrap;
        border: 0;
    }

    .login-field { margin-bottom: 11px; }
    .login-input .form-control {
        height: 48px;
        border-radius: 12px;
        font-size: .95rem;
    }

    .login-btn {
        height: 48px;
        border-radius: 12px;
        font-size: .95rem;
        margin-top: 18px;
    }

    .login-apk {
        margin-top: 20px;
        padding: 10px 12px;
        gap: 10px;
        border-radius: 12px;
    }
    .login-apk-logo { width: 34px; height: 34px; flex: 0 0 34px; }
    .login-apk-txt strong { font-size: .875rem; }
    .login-apk-txt small { font-size: .72rem; }

    .login-footer { margin-top: 22px; }
}

@media (max-width: 380px) {
    .login-panel { padding: 24px 18px; }
    .login-card .logo { max-width: 138px; margin-bottom: 18px; }
}

/* --- El logo en tema oscuro ---
   El subtítulo del logo es texto negro dentro del PNG y sobre fondo oscuro
   desaparece. Se le pone una placa clara detrás: se lee bien y la marca
   conserva sus colores. */
[data-bs-theme="dark"] .login-card .logo {
    background: #fff;
    border-radius: 14px;
    padding: 14px 18px;
    box-sizing: border-box;
    width: 72%;
    max-width: 230px;
}

/* --- Animación ---
   Discreta y lenta: entra el contenido y el halo respira. La regla global de
   prefers-reduced-motion que hay más arriba la desactiva por completo. */

@keyframes login-entra {
    from { opacity: 0; transform: translateY(14px); }
    to   { opacity: 1; transform: none; }
}

@keyframes login-respira {
    0%, 100% { transform: translate(0, 0) scale(1); opacity: 1; }
    50%      { transform: translate(-40px, 30px) scale(1.12); opacity: .75; }
}

@keyframes login-aparece {
    from { opacity: 0; }
    to   { opacity: 1; }
}

.login-brand-glow {
    animation: login-respira 18s ease-in-out infinite;
}

/* --- Pulsos de señal ---
   Anillos que salen de un punto y se desvanecen, como la onda de una antena.
   Van detrás del contenido y con muy poca opacidad: dan movimiento sin
   estorbar la lectura. */

.login-ondas {
    position: absolute;
    top: 32%;
    right: 12%;
    width: 0;
    height: 0;
    pointer-events: none;
}
.login-ondas span {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 380px;
    height: 380px;
    margin: -190px 0 0 -190px;
    border: 1px solid rgba(255, 255, 255, .16);
    border-radius: 50%;
    opacity: 0;
    animation: login-onda 8s ease-out infinite;
}
.login-ondas span:nth-child(1) { animation-delay: 0s; }
.login-ondas span:nth-child(2) { animation-delay: 2s; }
.login-ondas span:nth-child(3) { animation-delay: 4s; }
.login-ondas span:nth-child(4) { animation-delay: 6s; }

@keyframes login-onda {
    0%   { transform: scale(.12); opacity: 0; }
    12%  { opacity: .55; }
    100% { transform: scale(1.9); opacity: 0; }
}

/* Punto emisor, con su propio latido. */
.login-ondas::before {
    content: "";
    position: absolute;
    top: -4px;
    left: -4px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: rgba(255, 255, 255, .85);
    box-shadow: 0 0 14px rgba(255, 255, 255, .7);
    animation: login-late 2s ease-in-out infinite;
}

@keyframes login-late {
    0%, 100% { transform: scale(1); opacity: .9; }
    50%      { transform: scale(1.5); opacity: .45; }
}

/* Las mismas ondas detrás del formulario en móvil, donde no hay panel de marca.
   Aquí el fondo es claro, así que se tiñen con el verde de la marca en vez de
   blanco; en tema oscuro vuelven a ser blancas. */
.login-ondas-movil { display: none; }

@media (max-width: 991px) {
    .login-ondas-movil {
        display: block;
        /* Arriba del logo: es la única zona libre, y así el punto emisor
           no queda encima de ningún texto. */
        top: 11%;
        left: 50%;
        right: auto;
    }
    .login-ondas-movil span {
        width: 320px;
        height: 320px;
        margin: -160px 0 0 -160px;
        border-color: rgba(23, 96, 61, .16);
    }
    .login-ondas-movil::before {
        background: rgba(23, 96, 61, .45);
        box-shadow: 0 0 14px rgba(23, 96, 61, .35);
    }

    [data-bs-theme="dark"] .login-ondas-movil span {
        border-color: rgba(255, 255, 255, .10);
    }
    [data-bs-theme="dark"] .login-ondas-movil::before {
        background: rgba(255, 255, 255, .5);
        box-shadow: 0 0 14px rgba(255, 255, 255, .35);
    }
}

/* El degradado del panel también se mueve, muy despacio. */
.login-brand {
    background-size: 160% 160%;
    animation: login-fondo 26s ease-in-out infinite;
}

@keyframes login-fondo {
    0%, 100% { background-position: 0% 50%; }
    50%      { background-position: 100% 50%; }
}

/* Segundo halo, verde y en la esquina opuesta, para que el fondo no quede
   plano. Se dibuja con un pseudoelemento: no hace falta más marcado. */
.login-brand::after {
    content: "";
    position: absolute;
    width: 520px;
    height: 520px;
    left: -200px;
    bottom: -220px;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(45, 190, 120, .18) 0%, rgba(45, 190, 120, 0) 70%);
    pointer-events: none;
    animation: login-respira 24s ease-in-out infinite reverse;
}

/* Entrada escalonada: cada bloque llega un poco después que el anterior. */
.login-brand > *:not(.login-brand-glow),
.login-card > *,
.login-card form > * {
    animation: login-entra .55s cubic-bezier(.22, .61, .36, 1) both;
}

.login-brand-top          { animation-delay: .05s; }
.login-brand > div:nth-of-type(2) { animation-delay: .14s; }
.login-brand-foot         { animation-delay: .22s; }

.login-card .logo         { animation-delay: .10s; }
.login-title              { animation-delay: .16s; }
.login-sub                { animation-delay: .20s; }
.login-card form          { animation: none; }
.login-field:nth-of-type(1) { animation-delay: .26s; }
.login-field:nth-of-type(2) { animation-delay: .32s; }
.login-btn                { animation-delay: .38s; }
.login-apk                { animation-delay: .44s; }
.login-footer             { animation-delay: .50s; }

/* Los elementos de la lista entran uno tras otro. */
.login-brand-list li {
    animation: login-entra .5s cubic-bezier(.22, .61, .36, 1) both;
}
.login-brand-list li:nth-child(1) { animation-delay: .30s; }
.login-brand-list li:nth-child(2) { animation-delay: .38s; }
.login-brand-list li:nth-child(3) { animation-delay: .46s; }

/* Micro-interacciones */
.login-btn {
    transition: transform .15s ease, box-shadow .2s ease, background-color .15s;
}
.login-btn:hover {
    transform: translateY(-1px);
    box-shadow: 0 8px 20px rgba(var(--app-accent-rgb), .32);
}
.login-btn:active { transform: translateY(0); }

.login-input .form-control { transition: border-color .18s, box-shadow .18s, background-color .18s; }

.login-apk { transition: transform .15s ease, border-color .15s, background-color .15s; }
.login-apk:hover { transform: translateY(-1px); border-color: var(--app-accent); }

.login-brand-list li i { transition: background-color .2s, transform .2s; }
.login-brand-list li:hover i { transform: scale(1.06); background: rgba(255, 255, 255, .16); }

/* Las tablas anchas se desplazan dentro de su contenedor; la página nunca scrollea de lado */
#div_tabla, .table-responsive { overflow-x: auto; -webkit-overflow-scrolling: touch; }
#div_tabla > .table { margin-bottom: .25rem; }

/* Anchos de columna: las clases col-table-N (porcentajes) aplastaban celdas cortas;
   con el contenedor desplazable, el contenido define el ancho. */
.table [class*="col-table-"] { width: auto; }
.table td:first-child, .table th:first-child { white-space: nowrap; }
.table td .badge { white-space: nowrap; }
.table td .fs-6 { font-size: var(--fs-body) !important; font-weight: 500; }
.table td > a:not(.btn) { white-space: nowrap; }

/* =====================================================================
   Fase 2 · barra de herramientas, chips, panel de filtros, estados,
   celdas y tablas en modo tarjeta (móvil)
   ===================================================================== */

/* ---------- Barra de herramientas ---------- */
.tb { margin-bottom: 12px; }
.tb-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }
.tb-title { display: flex; align-items: baseline; flex-wrap: wrap; gap: 6px 10px; margin-right: auto; }
.tb-h { margin: 0; font-size: var(--fs-page); display: inline-flex; align-items: center; gap: 8px; }
.tb-h .loader { width: 16px; height: 16px; }
.tb-count { color: var(--app-text-sub); font-size: var(--fs-body); font-variant-numeric: tabular-nums; }
.tb-sub { flex-basis: 100%; color: var(--app-text-sub); font-size: var(--fs-small); }
.tb-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.tb-btn { height: 32px; display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.tb-btn .bi { font-size: 14px; }
.tb-badge { background: var(--app-accent); color: #fff; border-radius: 999px; font-size: 10px; font-weight: 600; padding: 0 6px; line-height: 16px; min-width: 16px; text-align: center; }
.tb-select { width: auto; height: 32px; min-height: 32px; font-size: var(--fs-small); }
.tb-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 8px; }
.tb-chip { display: inline-flex; align-items: center; gap: 4px; padding: 3px 6px 3px 10px; border-radius: 999px; background: var(--app-accent-hover); color: var(--app-accent-strong); font-size: var(--fs-small); font-weight: 500; text-decoration: none; }
.tb-chip b { font-weight: 600; opacity: .75; }
.tb-chip .bi { font-size: 14px; opacity: .7; }
.tb-chip:hover { text-decoration: none; filter: brightness(.95); }
.tb-clear { font-size: var(--fs-small); color: var(--app-text-sub); margin-left: 4px; }
/* Sólo la lista de columnas se desplaza; la ayuda y el botón de restablecer
   quedan siempre a la vista al pie. Antes el menú entero era el que scrolleaba
   y en una tabla con muchas columnas la nota salía cortada a media línea y el
   botón se quedaba fuera de la vista. */
/* .show hace falta para ganarle al display:block de .dropdown-menu.show de
   Bootstrap; sin él la caja no era flex y la lista no cedía altura al pie. */
/* Solo cuando Bootstrap lo abre. Sin el ".show", el "display: flex" pisaba el
   "display: none" del .dropdown-menu y el panel de columnas se veía desplegado
   desde que cargaba la página. */
.tb-columns.show { display: flex; flex-direction: column; }
.tb-columns { min-width: 250px; max-height: min(60vh, 400px); overflow: hidden; padding: 6px 0 0; }
.tb-columns-lista { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.tb-columns label { display: flex; align-items: center; gap: 8px; padding: 5px 14px; margin: 0; font-size: var(--fs-body); cursor: pointer; }
.tb-columns label:hover { background: var(--app-bg-body); }
.tb-columns .form-check-input { flex-shrink: 0; }
.tb-columns-tip {
  flex: none; display: flex; gap: 8px; align-items: flex-start;
  border-top: 1px solid var(--app-border); margin-top: 6px; padding: 9px 14px;
  color: var(--app-text-sub); font-size: var(--fs-small); line-height: 1.45;
}
.tb-columns-tip .bi { flex: none; font-size: 14px; margin-top: .1em; }
.tb-columns-reset { flex: none; border-top: 1px solid var(--app-border); padding: 4px 0; }
.tb-columns-reset .dropdown-item { display: flex; align-items: center; gap: 8px; padding: 7px 14px; font-size: var(--fs-body); }
.tb-columns-reset .dropdown-item .bi { font-size: 14px; color: var(--app-text-sub); }
.col-oculta { display: none !important; }

/* ---------- Panel lateral de filtros ---------- */
.tb-offcanvas { --bs-offcanvas-width: 400px; --bs-offcanvas-bg: var(--app-bg-surface); --bs-offcanvas-color: var(--app-text-main); border-left: 1px solid var(--app-border); }
.tb-offcanvas .offcanvas-header { border-bottom: 1px solid var(--app-border); padding: 14px 20px; }
.tb-offcanvas .offcanvas-title { font-size: var(--fs-section); }
.tb-offcanvas form { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.tb-offcanvas .offcanvas-body { padding: 16px 20px; }
.tb-offcanvas-footer { display: flex; justify-content: space-between; align-items: center; gap: 8px; padding: 12px 20px; border-top: 1px solid var(--app-border); background: var(--app-bg-surface); }
.filtro-grupo { margin-bottom: 20px; }
.filtro-grupo h6 { font-size: var(--fs-label); text-transform: uppercase; letter-spacing: .06em; color: var(--app-text-sub); margin-bottom: 8px; }
.filtro-grupo .form-check { margin-bottom: 4px; min-height: 0; }
.filtro-grupo .form-check-label { font-size: var(--fs-body); }
.filtro-grupo .form-check-label .cnt { color: var(--app-text-sub); font-variant-numeric: tabular-nums; }
.filtro-grupo .form-check-label .bi { font-size: 13px; margin-right: 2px; }
.filtro-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 0 12px; }
.filtro-fechas { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }

/* ---------- Estados ---------- */
.estado { display: inline-flex; align-items: center; gap: 5px; padding: 2px 8px; border-radius: 999px; font-size: var(--fs-label); font-weight: 600; line-height: 1.6; white-space: nowrap; vertical-align: middle; }
.estado .bi { font-size: 12px; line-height: 1; }
.estado-ok      { background: rgba(var(--bs-success-rgb), .14); color: var(--bs-success-text-emphasis); }
.estado-warn    { background: rgba(var(--bs-warning-rgb), .22); color: var(--bs-warning-text-emphasis); }
.estado-bad     { background: rgba(var(--bs-danger-rgb), .14); color: var(--bs-danger-text-emphasis); }
.estado-info    { background: rgba(var(--app-accent-rgb), .14); color: var(--app-accent-strong); }
.estado-neutral { background: rgba(128, 128, 128, .14); color: var(--app-text-sub); }
.table tbody td .estado .bi { font-size: 12px; vertical-align: baseline; }

/* ---------- Celdas ---------- */
.cell-principal { display: flex; align-items: center; gap: 8px; min-width: 200px; }
.cell-title { font-weight: 500; color: var(--app-accent); white-space: nowrap; }
.cell-title:hover { color: var(--app-accent-strong); }
.cell-sub { display: block; color: var(--app-text-sub); font-size: var(--fs-small); line-height: 1.4; white-space: nowrap; }
.cell-sub.wrap { white-space: normal; }
.cell-lines { line-height: 1.45; }
.cell-lines > * + * { margin-top: 3px; }

/* Línea auxiliar que empieza con icono. Sin esto el texto envuelto vuelve al
   margen y pasa por debajo del símbolo, que es lo que hacía ver amontonadas las
   direcciones largas; así las líneas siguientes alinean con la primera palabra. */
.cell-sub.con-icono { display: flex; align-items: flex-start; gap: 5px; }
.cell-sub.con-icono > .bi { flex: none; margin-top: .2em; opacity: .75; }

/* Recorta el texto a unas pocas líneas y deja el resto en el title, para que una
   nota larga no dispare el alto de toda la fila. */
.texto-recortado { display: -webkit-box; -webkit-box-orient: vertical; overflow: hidden; }
.texto-recortado-2 { -webkit-line-clamp: 2; }
.texto-recortado-3 { -webkit-line-clamp: 3; }

/* Nota citada dentro de una celda. El filo de color distingue de un vistazo lo
   que se reportó de lo que se resolvió, sin tener que leer las dos. */
.nota-bloque {
  display: block; margin-top: 6px; padding: 1px 0 1px 8px;
  border-left: 2px solid var(--app-border);
  font-size: var(--fs-small); line-height: 1.45; color: var(--app-text-sub);
}
.nota-bloque b { display: block; font-weight: 600; }
.nota-problema { border-left-color: rgba(var(--bs-danger-rgb), .55); }
.nota-problema b { color: var(--bs-danger-text-emphasis); }
.nota-solucion { border-left-color: rgba(var(--bs-success-rgb), .55); }
.nota-solucion b { color: var(--bs-success-text-emphasis); }

/* Pares "quién · cuándo" (quién creó, quién revisó, quién validó). La etiqueta
   va en línea con el nombre y la fecha debajo: en una columna estrecha, poner
   cada cosa en su renglón convertía el historial en una columna de siete líneas
   que estiraba toda la fila. */
.meta-lista { display: grid; gap: 6px; font-size: var(--fs-small); line-height: 1.4; color: var(--app-text-sub); }
.meta-lista > div { min-width: 0; }
.meta-lista b { color: var(--app-text-main); font-weight: 600; }
.meta-lista .fecha { display: block; opacity: .85; }
.mono, .id-chip { font-family: ui-monospace, "Cascadia Mono", "Segoe UI Mono", Consolas, monospace; font-size: var(--fs-small); }
.id-chip { display: inline-block; padding: 0 6px; border: 1px solid var(--app-border); border-radius: 5px; background: var(--app-bg-body); color: var(--app-text-main); line-height: 18px; white-space: nowrap; }
.ico-estado { display: inline-flex; align-items: center; gap: 4px; vertical-align: middle; }
.ico-estado > i { order: 1; font-size: 16px; line-height: 1; }
.ico-estado > span[hidden] { display: inline !important; order: 2; font-size: var(--fs-small); color: var(--app-text-sub); }
.ico-estado .loader { width: 14px; height: 14px; }
.table .col-check { width: 28px; }
.table .col-acciones { width: 44px; text-align: right; }
.table td.col-acciones .dropdown { display: inline-block; }
.table .celda-texto { max-width: 280px; white-space: normal; }
.table td .btn-link.btn-sm { padding: 0; font-size: var(--fs-small); vertical-align: baseline; }

/* Menú de acciones por fila */
.btn-acciones { width: 28px; height: 28px; padding: 0; display: inline-flex; align-items: center; justify-content: center; border: 1px solid var(--app-border); border-radius: 6px; background: var(--app-bg-surface); color: var(--app-text-sub); cursor: pointer; }
.btn-acciones:hover, .btn-acciones[aria-expanded="true"] { background: var(--app-bg-body); color: var(--app-text-main); }
.btn-acciones::after { display: none; }
.btn-acciones .bi { font-size: 15px; }
.menu-acciones { min-width: 200px; padding: 6px 0; }
.menu-acciones .dropdown-item { display: flex; align-items: center; gap: 9px; padding: 7px 14px; font-size: var(--fs-body); font-weight: 400; }
.menu-acciones .dropdown-item .bi { font-size: 14px; color: var(--app-text-sub); width: 16px; text-align: center; }
.menu-acciones .dropdown-item.text-danger .bi { color: inherit; }
.menu-acciones .dropdown-item[hidden] { display: none; }
.menu-acciones .dropdown-divider { margin: 4px 0; }

/* Encabezados ordenables */
.table thead th.sortable { cursor: pointer; user-select: none; }
.table thead th .sort-ico { font-size: 12px; opacity: .35; margin-left: 4px; cursor: pointer; }
.table thead th.sortable:hover .sort-ico { opacity: .8; }
.table thead th.sort-asc, .table thead th.sort-desc { color: var(--app-text-main); }
.table thead th.sort-asc .sort-ico, .table thead th.sort-desc .sort-ico { opacity: 1; color: var(--app-accent); }

/* Celdas que solo existen para el modo tarjeta: en escritorio las sustituye
   el rowspan que agrupa las filas de un mismo registro. */
.table-cards td.solo-tarjeta { display: none; }

/* ---------- Tablas en modo tarjeta (móvil) ----------
   Cada <tr> es una tarjeta: cabecera con el nombre del registro (y el menú de
   acciones anclado a su derecha) y debajo los demás campos en dos columnas,
   con la etiqueta encima del valor.

   Antes cada <td> era un grid "etiqueta | valor" de dos columnas. Eso obligaba
   a que el valor cupiera en un solo hijo: en cuanto la celda traía un segundo
   bloque —.cell-sub, un <br>, una píldora extra— ese bloque caía en la celda
   izquierda del grid, debajo de la etiqueta ("Solicitado: 60 MB" bajo PLAN,
   "250.00" bajo la Q del total, "Serie B21X" bajo DOCUMENTO...). Volviendo el
   <td> a un bloque normal el contenido fluye como en escritorio, y las dos
   columnas por tarjeta reducen el alto a algo más de la mitad. */
@media (max-width: 767.98px) {
    .table-cards thead { display: none; }
    .table-cards, .table-cards tbody, .table-cards tfoot { display: block; width: 100%; }
    .table-cards .solo-escritorio { display: none !important; }

    /* Con tarjetas no hay desbordamiento horizontal que justifique el scroll
       del contenedor, y ese scroll sí atraparía los menús de acciones. */
    #div_tabla:has(> .table-cards),
    .table-responsive:has(> .table-cards) { overflow: visible; }

    /* Sin overflow:hidden: el menú de acciones cuelga del propio <tr> y se
       recortaría. Las esquinas superiores las redondea la cabecera. */
    .table-cards tr {
        position: relative;
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        align-content: start;
        font-size: var(--fs-body);
        border: 1px solid var(--app-border);
        border-radius: var(--app-radius);
        background: var(--app-bg-surface);
        box-shadow: var(--app-shadow);
        margin: 0 0 10px;
    }

    /* El rayado de table-striped alterna por celda, no por tarjeta, y deja un
       damero dentro de cada una. La tarjeta ya se distingue por su borde. */
    .table-cards.table-striped > :is(tbody, tfoot) > tr > :is(td, th) {
        --bs-table-bg-type: transparent;
    }

    /* Campo: etiqueta pequeña encima, valor debajo. Las celdas de cabecera de
       fila y las del pie de totales se dibujan igual que las normales. */
    .table-cards :is(tbody, tfoot) :is(td, th) {
        display: block; width: auto; min-width: 0;
        border: 0; border-top: 1px solid var(--app-border);
        padding: 8px 12px;
        overflow-wrap: anywhere;
    }
    /* Un campo que se queda solo en su fila la cruza entera, para que el
       separador no corte a media tarjeta (lo marca tablas.js). */
    .table-cards :is(tbody, tfoot) :is(td, th).celda-sola { grid-column: 1 / -1; }
    .table-cards :is(tbody, tfoot) :is(td, th)::before {
        content: attr(data-label);
        display: block; margin-bottom: 1px;
        font-size: 10px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
        color: var(--app-text-sub);
        white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    }
    .table-cards :is(tbody, tfoot) :is(td, th):not([data-label])::before { content: none; }
    /* Los textos largos ocupan la tarjeta entera; el max-width de escritorio
       los dejaría cortos y el separador no llegaría al borde. */
    .table-cards :is(tbody, tfoot) :is(td, th).celda-texto,
    .table-cards :is(tbody, tfoot) :is(td, th).col-ancha { grid-column: 1 / -1; max-width: none; }
    /* En la tarjeta todo se lee en columna, así que ni los montos ni las
       columnas centradas conservan su alineación de escritorio. El !important
       es para ganarle a las utilidades de Bootstrap, que ya lo traen. */
    .table-cards :is(tbody, tfoot) :is(td, th).num,
    .table-cards :is(tbody, tfoot) :is(td, th).text-center,
    .table-cards :is(tbody, tfoot) :is(td, th).text-end { text-align: left !important; }
    .table-cards :is(tbody, tfoot) :is(td, th).col-oculta,
    .table-cards :is(tbody, tfoot) :is(td, th).celda-vacia { display: none !important; }
    .table-cards :is(tbody, tfoot) :is(td, th).solo-tarjeta { display: block; }

    /* Cabecera de la tarjeta */
    .table-cards :is(tbody, tfoot) :is(td, th).td-principal {
        grid-column: 1 / -1; order: -8;
        border-top: 0;
        border-radius: calc(var(--app-radius) - 1px) calc(var(--app-radius) - 1px) 0 0;
        padding: 11px 46px 11px 12px;
        background: var(--app-bg-body);
    }
    .table-cards :is(tbody, tfoot) :is(td, th).td-principal::before { content: none; }
    .table-cards .cell-principal { min-width: 0; gap: 10px; align-items: flex-start; }
    .table-cards .cell-principal > .circulo-iniciales { flex: none; margin-top: 1px; }
    .table-cards .cell-title { font-size: var(--fs-section); font-weight: 600; }
    .table-cards .cell-title, .table-cards .cell-sub, .table-cards td > a:not(.btn) { white-space: normal; }
    /* En media columna las píldoras se parten en vez de desbordar la tarjeta */
    .table-cards .estado { white-space: normal; max-width: 100%; align-items: flex-start; text-align: left; }
    .table-cards .estado .bi { margin-top: 3px; }

    /* Casilla y menú de acciones: anclados a la cabecera, sin gastar una fila */
    .table-cards :is(tbody, tfoot) :is(td, th).col-check {
        position: absolute; top: 0; left: 0; z-index: 2;
        width: auto; border-top: 0; padding: 13px 10px 13px 12px;
    }
    .table-cards :is(tbody, tfoot) :is(td, th).col-check::before { content: none; }
    .table-cards tr:has(> .col-check) .td-principal { padding-left: 42px; }
    @supports not selector(:has(*)) {
        .table-cards :is(tbody, tfoot) :is(td, th).col-check {
            position: static; grid-column: 1 / -1; order: -9;
            padding: 10px 12px 0;
        }
    }
    .table-cards :is(tbody, tfoot) :is(td, th).col-acciones {
        position: absolute; top: 8px; right: 8px; z-index: 2;
        width: auto; border-top: 0; padding: 0; text-align: right;
    }
    .table-cards :is(tbody, tfoot) :is(td, th).col-acciones::before { content: none; }
}

/* Estado vacío de listados */
.estado-vacio { text-align: center; padding: 40px 16px; color: var(--app-text-sub); }
.estado-vacio .bi { font-size: 32px; display: block; margin-bottom: 8px; opacity: .6; }
.estado-vacio p { margin: 0 0 12px; }

/* =====================================================================
   Fase 4 · sidebar activo, dashboard, detalle de cliente, formularios
   ===================================================================== */

/* ---------- Dashboard: cabeceras de tarjeta suavizadas ---------- */
.dashboard-grid .card { border: 1px solid var(--app-border); box-shadow: var(--app-shadow); }
.dashboard-grid .card-header {
    background: var(--app-bg-body) !important;
    color: var(--app-text-main) !important;
    border-bottom: 1px solid var(--app-border);
    padding: 10px 14px !important;
}
.dashboard-grid .card-header .fs-6 { font-size: var(--fs-section) !important; font-weight: 600; }
/* El acento de cada panel pasa a un borde superior fino en vez de fondo saturado */
.dashboard-grid .border-start-primary { border-top: 3px solid var(--app-accent); }
.dashboard-grid .border-start-danger  { border-top: 3px solid var(--bs-danger); }
.dashboard-grid .border-start-warning { border-top: 3px solid var(--bs-warning); }
.dashboard-grid .border-start-info    { border-top: 3px solid var(--bs-info); }
.dashboard-grid .border-start-success { border-top: 3px solid var(--bs-success); }
.dashboard-grid [class*="border-start-"] { border-left: 1px solid var(--app-border) !important; }
/* El botón redondo del encabezado toma el color del panel, no un fondo lleno */
.dashboard-grid .card-header .btn-outline-light,
.dashboard-grid .card-header .btn-outline-dark {
    --bs-btn-color: var(--app-text-sub);
    --bs-btn-border-color: var(--app-border);
    --bs-btn-hover-bg: var(--app-accent);
    --bs-btn-hover-border-color: var(--app-accent);
    --bs-btn-hover-color: #fff;
}
.dashboard-grid .card-footer { background: var(--app-bg-surface); border-top: 1px solid var(--app-border); }
.dashboard-grid .progress { height: 8px !important; background: var(--app-bg-body); }
.dashboard-grid .border-bottom-dashed { border-bottom: 1px dashed var(--app-border); }

/* ---------- Detalle de cliente ---------- */
.cliente-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: flex-start; gap: 16px; margin-bottom: 18px; }
.cliente-head .titulo { font-size: var(--fs-page); font-weight: 600; margin: 0; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.cliente-head .plan { color: var(--app-text-sub); font-weight: 500; }
.cliente-fechas { display: flex; flex-wrap: wrap; gap: 6px 18px; margin-top: 8px; font-size: var(--fs-small); }
.cliente-fechas span { display: inline-flex; align-items: center; gap: 5px; color: var(--app-text-sub); }
.cliente-fechas b { color: var(--app-text-main); font-weight: 600; }
.cliente-head .lado { text-align: right; display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }
.cliente-acciones { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 20px; }
.cliente-acciones .btn { display: inline-flex; align-items: center; gap: 6px; }

/* Pestañas del cliente: reemplaza el custom-tab negro por nav-tabs con el sistema */
.custom-tab.nav-tabs { border-bottom: 1px solid var(--app-border); gap: 2px; flex-wrap: wrap; }
.custom-tab .nav-link {
    background: transparent; border: 0; border-bottom: 2px solid transparent;
    color: var(--app-text-sub); font-weight: 500; font-size: var(--fs-body);
    padding: 8px 14px; border-radius: 0; display: inline-flex; align-items: center; gap: 6px;
}
.custom-tab .nav-link .bi { font-size: 15px; }
.custom-tab .nav-link:hover { background: var(--app-bg-body); color: var(--app-text-main); border-color: transparent; }
.custom-tab .nav-link.active { background: transparent; color: var(--app-accent); border-bottom-color: var(--app-accent); font-weight: 600; }

/* ---------- Formularios (pulido, sin reestructurar) ---------- */
.card-header.bg-primary, .card-header.bg-secondary { font-weight: 600; }
.form-outline > .form-control { margin-bottom: 0; }
fieldset legend, .form-section-title { font-size: var(--fs-label); text-transform: uppercase; letter-spacing: .05em; color: var(--app-text-sub); font-weight: 600; margin-bottom: 8px; }

/* =====================================================================
   Sidebar compacto (menos alto y estrecho, misma estructura)
   ===================================================================== */
:root { --app-sb-width: 236px; }

/* Logo con menos aire */
.app-sidebar > .text-center img { width: 60% !important; margin-top: .6rem !important; margin-bottom: .4rem !important; }

/* Bloque de usuario más compacto */
.app-sidebar > .d-flex.align-items-center { padding: .45rem .7rem !important; margin-bottom: .15rem !important; }
.app-sidebar .user-avatar { width: 30px; height: 30px; }

/* Contenedor de menú: aire entre grupos */
.app-sidebar > .flex-grow-1.overflow-auto { gap: 3px !important; padding-top: .3rem !important; padding-bottom: .3rem !important; }

/* Enlaces principales: estrechos, con tipografía ajustada y alto cómodo */
.app-menu-link { padding: .5rem .65rem; margin: 0 .5rem; font-size: 13px; border-radius: 8px; }
.app-menu-icon { font-size: 16px; min-width: 1.8rem; }
.app-menu-arrow { font-size: .7rem; }

/* Submenús: sangría menor, pero las opciones desplegadas necesitan respirar,
   tanto entre ellas como contra los bordes del grupo. */
.app-submenu { margin: 2px 8px 5px; padding: 4px 0; }
.app-submenu .app-menu-link { padding: .48rem .65rem .48rem 2.4rem; font-size: 12.5px; }
.app-submenu .app-menu-icon { min-width: 1.55rem; font-size: 14px; }
.app-submenu li + li { margin-top: 2px; }

/* Botones "Nuevo …" dentro de submenús: más compactos */
.app-submenu .btn.btn-sm { padding: .3rem .5rem; font-size: 12px; }

/* Salir */
.app-sidebar .app-menu-link.text-danger { padding: .55rem .65rem; }

/* =====================================================================
   Tarjetas de total (stat cards) sobre las tablas
   ===================================================================== */
.stat-card .card-body { padding: 14px 16px; }
.stat-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.stat-num { font-size: 1.7rem; font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums; }
.stat-ico {
    width: 36px; height: 36px; border-radius: 9px; flex-shrink: 0;
    display: inline-flex; align-items: center; justify-content: center; font-size: 1.05rem;
    background: rgba(120, 120, 120, .10);
    background: color-mix(in srgb, currentColor 13%, transparent);
}
.stat-label { color: var(--app-text-sub); font-size: .78rem; line-height: 1.25; margin-top: 4px; }
.stat-bar { height: 4px; margin-top: 12px; background: var(--app-bg-body); border-radius: 999px; overflow: hidden; }
.stat-bar .progress-bar { border-radius: 999px; }

/* =====================================================================
   Comentarios · chat estilo WhatsApp
   ===================================================================== */
.chat-wa {
    --wa-bg: #efeae2; --wa-sent: #d9fdd3; --wa-recv: #ffffff;
    --wa-text: #111b21; --wa-time: #667781; --wa-shadow: 0 1px .5px rgba(11,20,26,.13);
    background-color: var(--wa-bg);
    background-image: radial-gradient(rgba(11,20,26,.035) 1px, transparent 1px);
    background-size: 22px 22px;
    border: 1px solid var(--app-border);
    border-radius: 14px;
    padding: 14px clamp(10px, 4vw, 40px);
    max-height: 70vh;
    overflow-y: auto;
}
[data-bs-theme="dark"] .chat-wa {
    --wa-bg: #0b141a; --wa-sent: #005c4b; --wa-recv: #202c33;
    --wa-text: #e9edef; --wa-time: #8696a0; --wa-shadow: 0 1px .5px rgba(0,0,0,.2);
    background-image: radial-gradient(rgba(255,255,255,.03) 1px, transparent 1px);
}
.chat-empty { text-align: center; color: var(--wa-time); padding: 40px 16px; }
.chat-empty .bi { font-size: 30px; display: block; margin-bottom: 8px; opacity: .6; }

/* Separador de fecha */
.chat-date { display: flex; justify-content: center; margin: 14px 0; }
.chat-date span {
    background: rgba(255,255,255,.9); color: #54656f;
    font-size: .72rem; font-weight: 500; padding: 5px 12px; border-radius: 8px;
    box-shadow: var(--wa-shadow);
}
[data-bs-theme="dark"] .chat-date span { background: #182229; color: #8696a0; }

/* Fila y burbuja */
.chat-row { display: flex; align-items: flex-end; gap: 8px; margin-bottom: 8px; }
.chat-row.sent { justify-content: flex-end; }
.chat-avatar { width: 32px; height: 32px; border-radius: 50%; object-fit: cover; flex-shrink: 0; }
.chat-avatar-txt { display: inline-flex; align-items: center; justify-content: center; font-size: .7rem; font-weight: 600; color: #fff; background: var(--app-accent); }
.chat-bubble {
    position: relative; max-width: min(78%, 560px);
    background: var(--wa-recv); color: var(--wa-text);
    padding: 6px 9px 5px; border-radius: 8px; box-shadow: var(--wa-shadow);
    font-size: .9rem; line-height: 1.35;
}
.chat-row.recv .chat-bubble { border-top-left-radius: 0; }
.chat-row.sent .chat-bubble { background: var(--wa-sent); border-top-right-radius: 0; }
/* Cola de la burbuja */
.chat-row.recv .chat-bubble::before,
.chat-row.sent .chat-bubble::before {
    content: ""; position: absolute; top: 0; width: 8px; height: 12px;
}
.chat-row.recv .chat-bubble::before { left: -8px; background: var(--wa-recv); clip-path: polygon(100% 0, 0 0, 100% 100%); }
.chat-row.sent .chat-bubble::before { right: -8px; background: var(--wa-sent); clip-path: polygon(0 0, 100% 0, 0 100%); }
.chat-head { display: flex; align-items: center; gap: 6px; margin-bottom: 2px; }
.chat-name { font-size: .78rem; font-weight: 600; }
.chat-area { font-size: .62rem; font-weight: 600; letter-spacing: .02em; text-transform: uppercase; padding: 1px 6px; border-radius: 5px; }
.chat-del { margin-left: auto; color: inherit; opacity: .35; font-size: .8rem; line-height: 1; text-decoration: none; }
.chat-del:hover { opacity: .9; color: var(--bs-danger); }
.chat-msg { white-space: pre-wrap; word-break: break-word; }
.chat-img { max-height: 180px; border-radius: 6px; margin-top: 4px; display: block; }
.chat-time { font-size: .64rem; color: var(--wa-time); text-align: right; margin-top: 2px; white-space: nowrap; }
.chat-ref { font-size: .7rem; color: var(--wa-time); }

/* Cabecera del chat de comentarios */
.chat-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 12px; }
.chat-toolbar .chat-filtros { display: flex; flex-wrap: wrap; gap: 6px; }
.chat-chip {
    display: inline-flex; align-items: center; gap: 5px; padding: 4px 10px; border-radius: 999px;
    font-size: .8rem; font-weight: 500; text-decoration: none;
    border: 1px solid var(--app-border); color: var(--app-text-sub); background: var(--app-bg-surface);
}
.chat-chip:hover { background: var(--app-bg-body); color: var(--app-text-main); }
.chat-chip.active { background: var(--app-accent); border-color: var(--app-accent); color: #fff; }
.chat-chip .n { font-variant-numeric: tabular-nums; opacity: .8; }

/* Compositor del chat de comentarios */
.chat-composer {
    background: var(--app-bg-surface);
    border: 1px solid var(--app-border);
    border-radius: 14px;
    padding: 10px 12px;
    margin-top: 10px;
    position: relative;
}
.chat-composer-target { position: relative; margin-bottom: 8px; }
.chat-target-pick { display: flex; align-items: center; gap: 8px; background: var(--app-bg-body); border: 1px solid var(--app-border); border-radius: 10px; padding: 4px 10px; }
.chat-target-pick > .bi { color: var(--app-text-sub); }
.chat-target-input { flex: 1; border: 0; background: transparent; color: var(--app-text-main); font-size: var(--fs-body); outline: none; min-width: 0; padding: 6px 0; }
.chat-area-select { border: 0; background: transparent; color: var(--app-text-sub); font-size: var(--fs-small); outline: none; cursor: pointer; }
.chat-target-results { position: absolute; left: 0; right: 0; bottom: calc(100% + 4px); z-index: 20; background: var(--app-bg-surface); border: 1px solid var(--app-border); border-radius: 10px; box-shadow: 0 8px 24px rgba(0,0,0,.12); max-height: 240px; overflow-y: auto; }
.chat-target-item { padding: 8px 12px; font-size: var(--fs-body); cursor: pointer; border-bottom: 1px solid var(--app-border); }
.chat-target-item:last-child { border-bottom: 0; }
.chat-target-item:hover { background: var(--app-bg-body); }
.chat-target-sel { display: inline-flex; align-items: center; gap: 6px; margin-top: 6px; background: var(--app-accent-hover); color: var(--app-accent-strong); border-radius: 999px; padding: 3px 6px 3px 10px; font-size: var(--fs-small); font-weight: 500; }
.chat-target-clear { border: 0; background: transparent; color: inherit; line-height: 1; cursor: pointer; padding: 0 2px; }
.chat-composer-row { display: flex; align-items: flex-end; gap: 8px; }
.chat-attach { display: inline-flex; align-items: center; justify-content: center; width: 38px; height: 38px; border-radius: 50%; color: var(--app-text-sub); cursor: pointer; flex-shrink: 0; }
.chat-attach:hover { background: var(--app-bg-body); color: var(--app-accent); }
.chat-attach .bi { font-size: 1.1rem; }
.chat-input { flex: 1; border: 1px solid var(--app-border); border-radius: 20px; padding: 8px 14px; font-size: var(--fs-body); resize: none; background: var(--app-bg-body); color: var(--app-text-main); line-height: 1.4; max-height: 120px; }
.chat-input:focus { outline: none; border-color: var(--app-accent); }
.chat-send { flex-shrink: 0; width: 40px; height: 40px; border-radius: 50%; border: 0; background: var(--app-accent); color: #fff; display: inline-flex; align-items: center; justify-content: center; cursor: pointer; transition: background-color .15s; }
.chat-send:hover:not(:disabled) { background: var(--app-accent-strong); }
.chat-send:disabled { opacity: .45; cursor: not-allowed; }
.chat-composer-preview { position: relative; display: inline-block; margin-top: 8px; }
.chat-composer-preview img { max-height: 90px; border-radius: 8px; border: 1px solid var(--app-border); }
.chat-composer-preview .chat-target-clear { position: absolute; top: -8px; right: -8px; background: var(--bs-danger); color: #fff; border-radius: 50%; width: 20px; height: 20px; }

/* =====================================================================
   Ruta de navegación (breadcrumb) bajo el header
   ===================================================================== */
/* El header ya no lleva mb-4: el breadcrumb aporta la separación justa. */
.app-breadcrumb {
    display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
    font-size: var(--fs-small);
    color: var(--app-text-sub);
    padding: 7px 0 8px;
    margin-bottom: 12px;
    border-bottom: 1px solid var(--app-border);
}
.app-breadcrumb a { color: var(--app-text-sub); display: inline-flex; align-items: center; }
.app-breadcrumb a:hover { color: var(--app-accent); text-decoration: none; }
.app-breadcrumb a .bi { font-size: 14px; }
.app-breadcrumb .sep { font-size: 10px; opacity: .5; }
.app-breadcrumb .actual { color: var(--app-text-main); font-weight: 500; }

/* =====================================================================
   Botones de acción del sidebar, cada uno con el color de su módulo
   ===================================================================== */
/* Crear pago → verde */
.app-submenu .btn[href$="crear-pago"] {
    --bs-btn-bg: #198754;        --bs-btn-border-color: #198754;
    --bs-btn-hover-bg: #157347;  --bs-btn-hover-border-color: #146c43;
    --bs-btn-active-bg: #146c43; --bs-btn-active-border-color: #13653f;
    --bs-btn-color: #fff;        --bs-btn-hover-color: #fff;
}
/* Crear ticket → celeste */
.app-submenu .btn[href$="crear-tickets"] {
    --bs-btn-bg: #0dcaf0;        --bs-btn-border-color: #0dcaf0;
    --bs-btn-hover-bg: #31d2f2;  --bs-btn-hover-border-color: #25cff2;
    --bs-btn-active-bg: #3dd5f3; --bs-btn-active-border-color: #25cff2;
    --bs-btn-color: #000;        --bs-btn-hover-color: #000;
}
/* Crear tablero → naranja */
.app-submenu .btn[href$="crear-grupos"] {
    --bs-btn-bg: #fd7e14;        --bs-btn-border-color: #fd7e14;
    --bs-btn-hover-bg: #e8710f;  --bs-btn-hover-border-color: #dc6a0e;
    --bs-btn-active-bg: #dc6a0e; --bs-btn-active-border-color: #ca610d;
    --bs-btn-color: #fff;        --bs-btn-hover-color: #fff;
}
/* Crear plan → morado */
.app-submenu .btn[href$="crear-plan"] {
    --bs-btn-bg: #6f42c1;        --bs-btn-border-color: #6f42c1;
    --bs-btn-hover-bg: #62399f;  --bs-btn-hover-border-color: #5c359a;
    --bs-btn-active-bg: #5c359a; --bs-btn-active-border-color: #563091;
    --bs-btn-color: #fff;        --bs-btn-hover-color: #fff;
}
/* Crear empleado → gris */
.app-submenu .btn[href$="crear-empleado"] {
    --bs-btn-bg: #6c757d;        --bs-btn-border-color: #6c757d;
    --bs-btn-hover-bg: #5c636a;  --bs-btn-hover-border-color: #565e64;
    --bs-btn-active-bg: #565e64; --bs-btn-active-border-color: #51585e;
    --bs-btn-color: #fff;        --bs-btn-hover-color: #fff;
}
/* Nueva instalación mantiene el azul del sistema (btn-primary) */


/* =====================================================================
   COMENTARIO RÁPIDO (globito del header)
   ===================================================================== */

.ico-comentario {
    color: #7048e8;
}
.ico-comentario:hover,
.ico-comentario:focus {
    color: #5f3dc4;
}

.qc-menu {
    width: 320px;
    max-width: calc(100vw - 1.5rem);
    padding-bottom: .5rem;
}

.qc-form {
    padding: 0 .75rem;
    display: flex;
    flex-direction: column;
    gap: .5rem;
}

.qc-campo {
    display: flex;
    align-items: center;
    gap: .5rem;
    border: 1px solid var(--bs-border-color);
    border-radius: .5rem;
    padding: .35rem .6rem;
}
.qc-campo i {
    color: var(--bs-secondary-color);
    font-size: .95rem;
}
.qc-input {
    border: 0;
    background: transparent;
    color: inherit;
    width: 100%;
    font-size: var(--fs-body, .875rem);
    outline: none;
}

.qc-resultados {
    border: 1px solid var(--bs-border-color);
    border-radius: .5rem;
    max-height: 170px;
    overflow-y: auto;
}
.qc-item {
    padding: .4rem .6rem;
    font-size: var(--fs-label, .75rem);
    cursor: pointer;
    line-height: 1.3;
}
.qc-item:hover {
    background: var(--bs-tertiary-bg);
}

.qc-seleccion {
    display: flex;
    align-items: center;
    gap: .4rem;
    font-size: var(--fs-label, .75rem);
    background: var(--bs-tertiary-bg);
    border-radius: .5rem;
    padding: .3rem .5rem;
}
.qc-seleccion span {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.qc-quitar {
    border: 0;
    background: transparent;
    color: var(--bs-secondary-color);
    line-height: 1;
    padding: 0 .15rem;
}

.qc-mensaje {
    resize: vertical;
    min-height: 68px;
}

.qc-pie {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
}
.qc-aviso {
    font-size: var(--fs-label, .75rem);
    color: var(--bs-secondary-color);
}
.qc-aviso-ok  { color: var(--bs-success); }
.qc-aviso-mal { color: var(--bs-danger); }

.qc-enviar {
    --bs-btn-bg: #7048e8;        --bs-btn-border-color: #7048e8;
    --bs-btn-hover-bg: #5f3dc4;  --bs-btn-hover-border-color: #5f3dc4;
    --bs-btn-active-bg: #5535b0; --bs-btn-active-border-color: #5535b0;
    --bs-btn-disabled-bg: #7048e8; --bs-btn-disabled-border-color: #7048e8;
    --bs-btn-color: #fff;        --bs-btn-hover-color: #fff;
    --bs-btn-disabled-color: #fff;
    white-space: nowrap;
}


/* =====================================================================
   PANEL DE ALERTAS (campana)
   ===================================================================== */

.alerta-vacia {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .35rem;
    padding: 1.25rem .5rem;
    color: var(--bs-secondary-color);
    font-size: var(--fs-label, .75rem);
}
.alerta-vacia i {
    font-size: 1.5rem;
    color: var(--bs-success);
}

.alerta-item {
    display: flex;
    gap: .6rem;
    padding: .5rem;
    border-radius: .5rem;
    text-decoration: none;
    color: inherit;
}
.alerta-item + .alerta-item {
    border-top: 1px solid var(--bs-border-color);
    border-radius: 0;
}
.alerta-item:hover {
    background: var(--bs-tertiary-bg);
}

.alerta-avatar {
    width: 34px;
    height: 34px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
}
.alerta-avatar-txt {
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bs-secondary-bg);
    color: var(--bs-secondary-color);
    font-size: .7rem;
    font-weight: 600;
}

.alerta-cuerpo {
    display: flex;
    flex-direction: column;
    gap: .1rem;
    min-width: 0;
}
.alerta-cabecera {
    display: flex;
    align-items: center;
    gap: .35rem;
    font-size: var(--fs-label, .75rem);
}
.alerta-area {
    font-size: .6rem;
    font-weight: 500;
}
.alerta-cliente {
    font-size: var(--fs-label, .75rem);
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.alerta-mensaje {
    font-size: var(--fs-label, .75rem);
    color: var(--bs-secondary-color);
    line-height: 1.35;
}
.alerta-fecha {
    font-size: .65rem;
    color: var(--bs-secondary-color);
}

/* =====================================================================
   Fase 6 · reparto de columnas en las tablas de listado
   =====================================================================
   Antes el ancho lo decidía el contenido (table-layout automático): la
   columna con los nombres se llevaba 350 px y el resto quedaba apretado,
   además de desbordar el contenedor. Ahora cada <th> declara su ancho con
   una clase col-w-* y el navegador reparte el sobrante en proporción, así
   que las columnas guardan siempre la misma relación entre sí.
   Solo aplica en escritorio: en móvil manda el modo tarjeta. */

@media (min-width: 768px) {

    .tabla-cols { table-layout: fixed; width: 100%; }

    /* Escala de anchos, en porcentaje. El número de la clase sigue siendo el
       ancho de referencia en píxeles sobre una tabla de 1000: col-w-176 son
       17,6%. Va en porcentaje y no en px porque con table-layout:fixed una
       tabla nunca se estrecha por debajo de la suma de sus columnas en píxeles:
       en cuanto la ventana bajaba de esa suma aparecía scroll horizontal aunque
       hubiera sitio de sobra. En porcentaje el navegador reparte el ancho real
       manteniendo la misma proporción entre columnas, y la tabla ocupa siempre
       el 100%. Las dos columnas de control se quedan en píxeles: llevan un
       botón, no texto, y no tienen por qué encoger. */
    .tabla-cols th.col-w-48  { width: 4.8%; }
    .tabla-cols th.col-w-64  { width: 6.4%; }
    .tabla-cols th.col-w-80  { width: 8%; }
    .tabla-cols th.col-w-96  { width: 9.6%; }
    .tabla-cols th.col-w-112 { width: 11.2%; }
    .tabla-cols th.col-w-128 { width: 12.8%; }
    .tabla-cols th.col-w-144 { width: 14.4%; }
    .tabla-cols th.col-w-160 { width: 16%; }
    .tabla-cols th.col-w-176 { width: 17.6%; }
    .tabla-cols th.col-w-192 { width: 19.2%; }
    .tabla-cols th.col-w-208 { width: 20.8%; }
    .tabla-cols th.col-w-216 { width: 21.6%; }
    .tabla-cols th.col-w-240 { width: 24%; }
    .tabla-cols th.col-check { width: 34px; }
    .tabla-cols th.col-acciones { width: 46px; }

    /* Con ancho fijo el contenido tiene que acomodarse dentro de su
       columna: se permite el salto de línea que antes se prohibía. */
    .tabla-cols thead th { white-space: normal; }
    .tabla-cols th, .tabla-cols td { overflow-wrap: break-word; }
    .tabla-cols td:first-child,
    .tabla-cols .cell-title,
    .tabla-cols .cell-sub,
    .tabla-cols .estado,
    .tabla-cols td .badge,
    .tabla-cols td > a:not(.btn) { white-space: normal; }
    .tabla-cols .cell-principal { min-width: 0; }
    .tabla-cols .cell-principal > div { min-width: 0; }
    .tabla-cols td.num { white-space: nowrap; }

    /* El indicador de orden nunca se queda solo en una línea. */
    .tabla-cols thead th .sort-ico { margin-left: 3px; }
}


/* ---------- Columnas redimensionables (resources/js/tablas.js) ----------
   El filo derecho de cada columna se puede arrastrar desde cualquier fila,
   no solo desde el encabezado: el JS mira la posición del puntero contra los
   bordes de las columnas y avisa con el cursor y con una guía vertical. */
@media (min-width: 768px) {

    /* Puntero sobre un filo: el cursor manda en toda la tabla, también encima
       de los enlaces y botones de las celdas. */
    .tabla-cols.col-filo,
    .tabla-cols.col-filo * { cursor: col-resize !important; }

    /* Guía vertical del filo. Se dibuja sobre la página (position:fixed) para
       no depender de que la tabla o su contenedor estén posicionados. */
    .col-guia {
        position: fixed;
        width: 2px;
        margin-left: -1px;
        border-radius: 2px;
        background: var(--app-accent);
        opacity: .35;
        pointer-events: none;
        z-index: 1080;
    }
    .col-guia.activa { opacity: .9; }

    /* Mientras se arrastra: el cursor manda en toda la página y no se
       selecciona texto por accidente. */
    body.redimensionando-col { cursor: col-resize; user-select: none; }
    body.redimensionando-col .table { pointer-events: none; }

    /* Con anchos elegidos a mano la tabla ya no se estira al 100%: su ancho
       es exactamente la suma de las columnas (lo fija el JS en línea). */
    /* Con anchos a medida la tabla vale lo que suman sus columnas, pero nunca
       menos que el contenedor: si no, al estrechar columnas queda una franja
       vacía a la derecha en vez de repartirse el sobrante. */
    .tabla-cols.anchos-manuales { width: max-content; min-width: 100%; }
}

/* =====================================================================
   Comentarios en modal (botón "Comentarios" del menú de acciones)
   =====================================================================
   Reusa el chat de la pantalla de Mensajes, pero con el hilo arriba y el
   cuadro de escritura abajo, fijo, como cualquier conversación. */

.comentarios-modal { display: flex; flex-direction: column; gap: 10px; }

/* El hilo ocupa el alto disponible y se desplaza solo él. */
.comentarios-hilo .chat-modal {
    height: 46vh;
    min-height: 240px;
    max-height: 46vh;
    padding: 12px clamp(10px, 3vw, 22px);
}

/* Cabecera del modal: de quién es el hilo y de qué área. */
.com-titulo { display: flex; align-items: center; gap: 10px; }
.com-titulo-icono {
    width: 38px; height: 38px; flex-shrink: 0;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%; background: var(--app-accent-hover); color: var(--app-accent);
    font-size: 17px;
}
.com-titulo-txt { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
.com-titulo-txt strong { font-size: var(--fs-section); }
.com-titulo-txt small { color: var(--app-text-sub); font-size: var(--fs-small); }

/* Imagen dentro de una burbuja: todas del mismo tamaño y recortadas al
   centro, para que el hilo no salte según venga la foto. */
.chat-foto-link { position: relative; display: block; width: 210px; max-width: 100%; margin-top: 5px; }
.chat-foto {
    display: block; width: 100%; aspect-ratio: 4 / 3;
    object-fit: cover; border-radius: 8px;
    background: rgba(0, 0, 0, .06);
}
.chat-foto-lupa {
    position: absolute; right: 6px; bottom: 6px;
    width: 26px; height: 26px; border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    background: rgba(0, 0, 0, .45); color: #fff; font-size: 12px;
    opacity: 0; transition: opacity .15s ease;
}
.chat-foto-link:hover .chat-foto-lupa { opacity: 1; }

/* Cuadro de escritura */
.comentario-form { margin: 0; }
.comentario-barra {
    display: flex; align-items: flex-end; gap: 8px;
    background: var(--app-bg-body);
    border: 1px solid var(--app-border);
    border-radius: 14px;
    padding: 6px 8px;
}
.comentario-barra:focus-within { border-color: var(--app-accent); }
.comentario-barra textarea {
    flex: 1; min-width: 0; resize: none; border: 0; background: transparent;
    color: var(--app-text-main); font-size: var(--fs-body); line-height: 1.4;
    padding: 6px 2px; max-height: 120px; outline: none;
}
.comentario-adjuntar,
.comentario-enviar {
    width: 34px; height: 34px; flex-shrink: 0;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%; border: 0; cursor: pointer; font-size: 15px;
    transition: background-color .15s ease, color .15s ease;
}
.comentario-adjuntar { background: transparent; color: var(--app-text-sub); margin: 0; }
.comentario-adjuntar:hover { background: var(--app-bg-surface); color: var(--app-accent); }
.comentario-enviar { background: var(--app-accent); color: #fff; }
.comentario-enviar:hover { filter: brightness(1.08); }

/* Vista previa de la foto adjunta, antes de enviarla */
.comentario-adjunto { position: relative; width: 96px; margin-bottom: 2px; }
.comentario-adjunto img {
    width: 96px; height: 72px; object-fit: cover;
    border-radius: 8px; border: 1px solid var(--app-border); display: block;
}
.comentario-quitar {
    position: absolute; top: -6px; right: -6px;
    width: 22px; height: 22px; border-radius: 50%; border: 0;
    background: var(--bs-danger); color: #fff; font-size: 10px;
    display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
}

@media (max-width: 575.98px) {
    .comentarios-hilo .chat-modal { height: 52vh; max-height: 52vh; }
    .chat-foto-link { width: 170px; }
}

/* =====================================================================
   Galería de imágenes y mapa dentro del modal (menú de acciones)
   ===================================================================== */

/* Todas las fotos al mismo tamaño y recortadas al centro: da igual si una
   viene apaisada y otra vertical, la cuadrícula no se descuadra. */
.galeria {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 12px;
}
.galeria-item {
    position: relative;
    display: block;
    border: 1px solid var(--app-border);
    border-radius: 10px;
    overflow: hidden;
    background: var(--app-bg-body);
    text-decoration: none;
    transition: border-color .15s ease, transform .15s ease;
}
.galeria-item:hover { border-color: var(--app-accent); transform: translateY(-2px); }
.galeria-item img {
    display: block;
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
}
.galeria-pie {
    display: block;
    padding: 7px 10px;
    font-size: var(--fs-small);
    color: var(--app-text-main);
    background: var(--app-bg-surface);
    border-top: 1px solid var(--app-border);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.galeria-lupa {
    position: absolute;
    top: 8px; right: 8px;
    width: 28px; height: 28px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%;
    background: rgba(0, 0, 0, .45);
    color: #fff; font-size: 12px;
    opacity: 0;
    transition: opacity .15s ease;
}
.galeria-item:hover .galeria-lupa { opacity: 1; }

/* Mapa embebido */
.mapa-modal {
    border: 1px solid var(--app-border);
    border-radius: 12px;
    overflow: hidden;
    line-height: 0;
}
.mapa-modal iframe { width: 100%; height: 380px; border: 0; }
.mapa-acciones {
    display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
    margin-top: 12px;
}
.mapa-coords {
    margin-right: auto;
    font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
    font-size: var(--fs-small);
    color: var(--app-text-sub);
}

@media (max-width: 575.98px) {
    .galeria { grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 10px; }
    .mapa-modal iframe { height: 300px; }
    .mapa-coords { flex-basis: 100%; margin-bottom: 4px; }
}

/* =====================================================================
   Bitácora del cliente (pestaña Logs de la ficha)
   ===================================================================== */
.log-linea { list-style: none; margin: 0; padding: 0; position: relative; }

/* Línea vertical que hilvana los movimientos */
.log-linea::before {
    content: "";
    position: absolute;
    left: 15px; top: 4px; bottom: 4px;
    width: 2px;
    background: var(--app-border);
}

.log-dia {
    position: relative;
    margin: 14px 0 10px;
    padding-left: 44px;
    font-size: var(--fs-label);
    font-weight: 600;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--app-text-sub);
}
.log-dia:first-child { margin-top: 0; }

.log-item {
    position: relative;
    display: flex;
    gap: 12px;
    padding: 0 0 14px 0;
}

.log-icono {
    position: relative;
    z-index: 1;
    width: 32px; height: 32px; flex-shrink: 0;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%;
    background: var(--app-bg-surface);
    border: 2px solid var(--app-border);
    color: var(--app-text-sub);
    font-size: 14px;
}
.log-item.log-warn .log-icono { border-color: var(--bs-warning); color: var(--bs-warning-text-emphasis); }
.log-item.log-bad .log-icono { border-color: var(--bs-danger); color: var(--bs-danger); }

.log-cuerpo { min-width: 0; flex: 1; padding-top: 3px; }

.log-cabecera { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-bottom: 2px; }
.log-modulo {
    font-size: var(--fs-label);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--app-accent);
}
.log-hora { margin-left: auto; font-size: var(--fs-small); color: var(--app-text-sub); font-variant-numeric: tabular-nums; }

.log-mensaje { font-size: var(--fs-body); color: var(--app-text-main); word-break: break-word; }

.log-pie {
    display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px;
    margin-top: 3px;
    font-size: var(--fs-small);
    color: var(--app-text-sub);
}

@media (max-width: 575.98px) {
    .log-hora { margin-left: 0; }
}

/* =====================================================================
   TABLERO KANBAN (grupos) — estilo Trello
   ===================================================================== */

:root {
    --kb-col-w: 250px;
    --kb-gap: 14px;
    --kb-radius: 12px;
    --kb-col-bg: #f1f4f9;
    --kb-card-bg: #ffffff;
    --kb-ease: cubic-bezier(.2, .8, .3, 1);
}
[data-bs-theme="dark"] {
    --kb-col-bg: #16202f;
    --kb-card-bg: #1e293b;
}

/* ---------- Barra superior ---------- */
.kanban-topbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 14px;
}
.kanban-topbar-title { display: flex; align-items: center; gap: 12px; min-width: 0; }
.kanban-topbar-icon {
    display: grid;
    place-items: center;
    width: 38px; height: 38px;
    flex: 0 0 38px;
    border-radius: 10px;
    background: linear-gradient(135deg, rgba(var(--app-accent-rgb), .16), rgba(var(--app-accent-rgb), .06));
    color: var(--app-accent);
    font-size: 18px;
}
.kanban-topbar-title h5 {
    font-size: var(--fs-section);
    font-weight: 650;
    letter-spacing: -.01em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.kanban-topbar-sub { font-size: var(--fs-small); color: var(--app-text-sub); }

.kanban-topbar-tools { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.kanban-search { position: relative; }
.kanban-search i {
    position: absolute; left: 10px; top: 50%; transform: translateY(-50%);
    color: var(--app-text-sub); font-size: 13px; pointer-events: none;
}
.kanban-search input {
    width: 210px;
    padding-left: 30px;
    border-radius: 999px;
    background: var(--app-bg-surface);
    transition: width .25s var(--kb-ease), box-shadow .2s var(--kb-ease);
}
.kanban-search input:focus { width: 250px; box-shadow: 0 0 0 3px rgba(var(--app-accent-rgb), .18); }
.kanban-search input::-webkit-search-cancel-button { cursor: pointer; }
.kanban-select { width: auto; min-width: 210px; max-width: 320px; border-radius: 999px; }

/* ---------- Contenedor del tablero ---------- */
.kanban-wrap { position: relative; }

.kanban-board {
    display: flex;
    align-items: flex-start;
    gap: var(--kb-gap);
    overflow-x: auto;
    overflow-y: hidden;
    padding: 2px 2px 12px;
    scroll-behavior: smooth;
    scroll-snap-type: x proximity;
    scrollbar-width: thin;
    scrollbar-color: var(--app-border) transparent;
}
.kanban-board::-webkit-scrollbar { height: 8px; }
.kanban-board::-webkit-scrollbar-track { background: transparent; }
.kanban-board::-webkit-scrollbar-thumb { background: var(--app-border); border-radius: 999px; }
.kanban-board::-webkit-scrollbar-thumb:hover { background: var(--app-text-sub); }

/* ---------- Columna ---------- */
.kanban-col {
    flex: 1 1 var(--kb-col-w);
    min-width: var(--kb-col-w);
    max-width: 460px;
    display: flex;
    flex-direction: column;
    background: var(--kb-col-bg);
    border: 1px solid var(--app-border);
    border-radius: var(--kb-radius);
    scroll-snap-align: start;
    overflow: hidden;
    transition: box-shadow .25s var(--kb-ease), border-color .25s var(--kb-ease);
}
.kanban-col::before {
    content: "";
    display: block;
    height: 3px;
    background: var(--col-accent, var(--app-accent));
}

.kanban-col-head {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 12px;
    background: var(--app-bg-surface);
    border-bottom: 1px solid var(--app-border);
}
.kanban-col-dot {
    width: 8px; height: 8px;
    flex: 0 0 8px;
    border-radius: 50%;
    background: var(--col-accent, var(--app-accent));
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--col-accent, var(--app-accent)) 18%, transparent);
}
.kanban-col-title {
    margin: 0;
    flex: 1 1 auto;
    min-width: 0;
    font-size: var(--fs-body);
    font-weight: 650;
    color: var(--app-text-main);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.kanban-col-count {
    flex: 0 0 auto;
    min-width: 24px;
    padding: 2px 8px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--col-accent, var(--app-accent)) 12%, transparent);
    color: var(--col-accent, var(--app-accent));
    font-size: var(--fs-label);
    font-weight: 700;
    text-align: center;
    font-variant-numeric: tabular-nums;
    transition: transform .25s var(--kb-ease);
}
.kanban-col-count.bump { transform: scale(1.3); }

.kanban-col-nav { display: flex; gap: 4px; }
.kanban-icon-btn {
    display: grid; place-items: center;
    width: 26px; height: 26px;
    padding: 0;
    border: 1px solid var(--app-border);
    border-radius: 7px;
    background: var(--app-bg-surface);
    color: var(--app-text-sub);
    font-size: 12px;
    transition: background .18s var(--kb-ease), color .18s var(--kb-ease);
}
.kanban-icon-btn:hover { background: var(--app-bg-body); color: var(--app-text-main); }

.kanban-col-body {
    flex: 1 1 auto;
    padding: 8px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-height: 110px;
    max-height: 68vh;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
    scrollbar-color: transparent transparent;
    transition: background .2s var(--kb-ease), box-shadow .2s var(--kb-ease);
}
.kanban-col-body::-webkit-scrollbar { width: 8px; }
.kanban-col-body::-webkit-scrollbar-thumb { background: transparent; border-radius: 999px; }
.kanban-col-body:hover { scrollbar-color: var(--app-border) transparent; }
.kanban-col-body:hover::-webkit-scrollbar-thumb { background: var(--app-border); }

/* Zona activa al arrastrar sobre la columna */
.kanban-col-body.highlight {
    background: color-mix(in srgb, var(--col-accent, var(--app-accent)) 8%, transparent);
    box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--col-accent, var(--app-accent)) 45%, transparent);
    border-radius: 8px;
}
.kanban-col.is-drop-target { box-shadow: 0 8px 24px rgba(15, 23, 42, .12); }

.kanban-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 22px 10px;
    border: 1px dashed var(--app-border);
    border-radius: 10px;
    color: var(--app-text-sub);
    font-size: var(--fs-small);
}
.kanban-empty i { font-size: 20px; opacity: .6; }
.kanban-empty[hidden] { display: none; }

/* ---------- Tarjeta ---------- */
.kanban-card {
    position: relative;
    border: 1px solid var(--app-border);
    border-left: 3px solid var(--card-accent, var(--app-accent));
    border-radius: 10px;
    background: var(--kb-card-bg);
    box-shadow: 0 1px 2px rgba(15, 23, 42, .06);
    cursor: grab;
    animation: kbCardIn .28s var(--kb-ease) both;
    transition: transform .18s var(--kb-ease), box-shadow .18s var(--kb-ease), border-color .18s var(--kb-ease);
}
.kanban-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 18px rgba(15, 23, 42, .12);
    border-color: color-mix(in srgb, var(--card-accent, var(--app-accent)) 45%, var(--app-border));
}
.kanban-card:active { cursor: grabbing; }
[data-bs-theme="dark"] .kanban-card:hover { box-shadow: 0 8px 20px rgba(0, 0, 0, .45); }

.kanban-card-head {
    display: flex;
    align-items: flex-start;
    gap: 4px;
    padding: 7px 9px;
    background: transparent;
    border: 0;
    cursor: pointer;
}
.kanban-card-main { flex: 1 1 auto; min-width: 0; }

.kanban-grip {
    flex: 0 0 auto;
    margin-left: -4px;
    color: var(--app-text-sub);
    opacity: 0;
    font-size: 13px;
    line-height: 1.3;
    transition: opacity .18s var(--kb-ease);
}
.kanban-card:hover .kanban-grip { opacity: .55; }

.kanban-card-title {
    margin: 0;
    font-size: var(--fs-body);
    font-weight: 500;
    line-height: 1.3;
    color: var(--app-text-main);
    word-break: break-word;
}
.kanban-card-title strong { font-weight: 600; color: var(--app-text-sub); font-size: var(--fs-small); }

.kanban-card-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 5px; }
.kanban-card-tags:empty { display: none; }
.kanban-tag {
    display: inline-flex;
    align-items: center;
    padding: 1px 7px;
    border-radius: 999px;
    font-size: var(--fs-label);
    font-weight: 600;
    line-height: 1.5;
    white-space: nowrap;
}
.kanban-tag.is-success { background: rgba(22, 163, 74, .12); color: #15803d; }
.kanban-tag.is-danger  { background: rgba(220, 38, 38, .12); color: #b91c1c; }
.kanban-tag.is-warning { background: rgba(217, 119, 6, .14); color: #b45309; }
.kanban-tag.is-info    { background: rgba(47, 111, 237, .12); color: #1d5be0; }
[data-bs-theme="dark"] .kanban-tag.is-success { background: rgba(34, 197, 94, .18); color: #4ade80; }
[data-bs-theme="dark"] .kanban-tag.is-danger  { background: rgba(248, 113, 113, .18); color: #fca5a5; }
[data-bs-theme="dark"] .kanban-tag.is-warning { background: rgba(251, 191, 36, .18); color: #fcd34d; }
[data-bs-theme="dark"] .kanban-tag.is-info    { background: rgba(109, 155, 255, .18); color: #93b4ff; }

/* Botones de mover (movil), inyectados por grupos.js */
.mov-btn-container { display: flex; gap: 6px; margin-top: 6px; }
.mov-btn-container .btn {
    flex: 1 1 0;
    border-radius: 7px;
    border-color: var(--app-border);
    background: var(--app-bg-body);
    color: var(--app-text-sub);
    padding: 3px 0;
}
.mov-btn-container .btn:hover { color: var(--app-accent); border-color: var(--app-accent); }

/* ---------- Arrastre ---------- */
/* La tarjeta original queda como hueco tenue mientras se arrastra. */
.kanban-card.being-dragged {
    animation: none;
    opacity: .28;
    filter: grayscale(.5);
}

/* El clon que sigue al cursor: inclinado y levantado, estilo Trello.
   animation: none es imprescindible: kbCardIn tambien anima transform y una
   animacion gana en la cascada sobre una declaracion normal, asi que sin esto
   la inclinacion nunca llegaba a verse. La inclinacion va como declaracion
   (no como animacion) para que se aplique aunque el navegador tenga las
   animaciones pausadas. */
.kanban-card.dragging-helper,
.dragging-helper {
    animation: none;
    transform: rotate(4deg) scale(1.04);
    transition: transform .18s cubic-bezier(.2, .8, .3, 1);
    width: calc(var(--kb-col-w) - 20px) !important;
    box-shadow: 0 18px 38px rgba(15, 23, 42, .3) !important;
    border-color: color-mix(in srgb, var(--card-accent, var(--app-accent)) 55%, var(--app-border)) !important;
    cursor: grabbing !important;
    pointer-events: none;
    z-index: 2000;
}
[data-bs-theme="dark"] .kanban-card.dragging-helper,
[data-bs-theme="dark"] .dragging-helper { box-shadow: 0 18px 38px rgba(0, 0, 0, .6) !important; }

.kanban-card.just-dropped { animation: kbDrop .5s var(--kb-ease); }
.kanban-board.is-dragging .kanban-card:not(.dragging-helper):hover { transform: none; box-shadow: 0 1px 2px rgba(15, 23, 42, .06); }
.kanban-card.filtrado-oculto { display: none; }

@keyframes kbCardIn {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: translateY(0); }
}
@keyframes kbDrop {
    0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--card-accent, var(--app-accent)) 55%, transparent); }
    100% { box-shadow: 0 0 0 12px transparent; }
}

/* ---------- Flechas de navegacion horizontal ---------- */
.kanban-nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 5;
    display: none;
    place-items: center;
    width: 34px; height: 34px;
    border: 1px solid var(--app-border);
    border-radius: 50%;
    background: var(--app-bg-surface);
    color: var(--app-text-main);
    box-shadow: 0 4px 14px rgba(15, 23, 42, .14);
    opacity: .45;
    transition: background .18s var(--kb-ease), transform .18s var(--kb-ease), opacity .18s var(--kb-ease);
}
.kanban-nav:hover { background: var(--app-bg-body); transform: translateY(-50%) scale(1.08); opacity: 1; }
.kanban-wrap:hover .kanban-nav { opacity: 1; }
.kanban-nav-prev { left: 2px; }
.kanban-nav-next { right: 2px; }
.kanban-wrap.tiene-scroll .kanban-nav { display: grid; }
.kanban-nav.esta-deshabilitado { opacity: .3; pointer-events: none; }

/* ---------- Responsive ---------- */
@media (max-width: 991.98px) {
    .kanban-col-body { max-height: 62vh; }
}
@media (max-width: 767.98px) {
    :root { --kb-col-w: 84vw; }
    .kanban-col { max-width: 84vw; }
    .kanban-board { scroll-snap-type: x mandatory; }
    .kanban-topbar-tools { width: 100%; }
    .kanban-search { flex: 1 1 auto; }
    .kanban-search input, .kanban-search input:focus { width: 100%; }
    .kanban-select { flex: 1 1 100%; max-width: none; }
    .kanban-grip { display: none; }
}

@media (prefers-reduced-motion: reduce) {
    .kanban-card, .kanban-col, .kanban-nav, .kanban-col-count { transition: none; animation: none; }
    .kanban-card.dragging-helper, .dragging-helper { animation: none; transition: none; transform: rotate(3deg); }
    .kanban-board { scroll-behavior: auto; }
}

/* =====================================================================
   TARJETAS KPI DEL DASHBOARD
   ===================================================================== */

/* Las tarjetas KPI no se estiran a la altura de la mas alta: cada una mide lo
   que pide su contenido. Estirarlas dejaba un hueco enorme al pie de las que
   tienen menos filas. */
.kpi-row-top { align-items: flex-start; }

.kpi-card {
    display: flex;
    flex-direction: column;
    height: 100%;
    background: var(--app-bg-surface);
    border: 1px solid var(--app-border);
    border-radius: 12px;
    overflow: hidden;
    transition: box-shadow .2s var(--kb-ease, ease), border-color .2s var(--kb-ease, ease);
}
.kpi-card:hover {
    box-shadow: 0 8px 22px rgba(15, 23, 42, .1);
    border-color: color-mix(in srgb, var(--kpi-accent, var(--app-accent)) 35%, var(--app-border));
}
[data-bs-theme="dark"] .kpi-card:hover { box-shadow: 0 8px 22px rgba(0, 0, 0, .4); }
.kpi-card::before {
    content: "";
    height: 3px;
    background: var(--kpi-accent, var(--app-accent));
}

.kpi-head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 9px;
    padding: 11px 13px 9px;
}
/* En tarjetas angostas los controles del encabezado bajan a su propia linea
   en vez de comerse el titulo. Sin margin-left:auto a proposito: los margenes
   automaticos se comen el espacio libre antes de que flex-grow lo reparta, y
   eso dejaba el titulo recortado aunque sobrara ancho. */
.kpi-head-tools { flex: 0 0 auto; }
.kpi-icon {
    display: grid;
    place-items: center;
    width: 30px; height: 30px;
    flex: 0 0 30px;
    border-radius: 9px;
    background: color-mix(in srgb, var(--kpi-accent, var(--app-accent)) 14%, transparent);
    color: var(--kpi-accent, var(--app-accent));
    font-size: 15px;
}
.kpi-title {
    margin: 0;
    /* Base chica a proposito: el titulo se recorta antes que empujar el total
       del encabezado a una segunda linea en las tarjetas angostas. */
    flex: 1 1 90px;
    min-width: 0;
    font-size: var(--fs-body);
    font-weight: 650;
    color: var(--app-text-main);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.kpi-total {
    font-size: var(--fs-page);
    font-weight: 700;
    line-height: 1;
    color: var(--app-text-main);
    font-variant-numeric: tabular-nums;
}
.kpi-total-sub {
    display: block;
    font-size: var(--fs-label);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--app-text-sub);
    text-align: right;
    margin-top: 2px;
}
.kpi-link {
    display: grid; place-items: center;
    width: 26px; height: 26px;
    flex: 0 0 26px;
    border-radius: 7px;
    color: var(--app-text-sub);
    text-decoration: none;
    font-size: 15px;
    transition: background .18s ease, color .18s ease;
}
.kpi-link:hover { background: var(--app-bg-body); color: var(--kpi-accent, var(--app-accent)); }

.kpi-list {
    list-style: none;
    margin: 0;
    padding: 2px 13px 12px;
    display: flex;
    flex-direction: column;
    gap: 9px;
    flex: 1 1 auto;
}
.kpi-row { display: block; }
.kpi-row > a {
    display: flex;
    align-items: center;
    gap: 7px;
    text-decoration: none;
    color: inherit;
    padding: 1px 0;
    border-radius: 6px;
}
.kpi-row > a:hover .kpi-label { color: var(--app-text-main); }
.kpi-row > a:hover .kpi-value { transform: translateX(-1px); }

.kpi-dot {
    width: 7px; height: 7px;
    flex: 0 0 7px;
    border-radius: 50%;
    background: var(--tono, var(--app-text-sub));
}
.kpi-label {
    flex: 1 1 auto;
    min-width: 0;
    font-size: var(--fs-small);
    font-weight: 500;
    color: var(--app-text-sub);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: color .18s ease;
}
.kpi-value {
    font-size: var(--fs-body);
    font-weight: 700;
    color: var(--app-text-main);
    font-variant-numeric: tabular-nums;
    transition: transform .18s ease;
}
.kpi-pct {
    min-width: 34px;
    text-align: right;
    font-size: var(--fs-label);
    color: var(--app-text-sub);
    font-variant-numeric: tabular-nums;
}

.kpi-bar {
    height: 4px;
    margin-top: 5px;
    border-radius: 999px;
    background: var(--app-bg-body);
    overflow: hidden;
}
[data-bs-theme="dark"] .kpi-bar { background: rgba(255, 255, 255, .07); }
.kpi-bar > span {
    display: block;
    height: 100%;
    width: 0;
    border-radius: 999px;
    background: var(--tono, var(--app-accent));
    animation: kpiBar .6s cubic-bezier(.2, .8, .3, 1) forwards;
}
@keyframes kpiBar { from { width: 0; } }

/* Tonos por fila */
.tono-warning { --tono: #d97706; }
.tono-danger  { --tono: #dc2626; }
.tono-info    { --tono: #0891b2; }
.tono-success { --tono: #16a34a; }
.tono-primary { --tono: #2f6fed; }
.tono-muted   { --tono: #94a3b8; }
[data-bs-theme="dark"] .tono-warning { --tono: #fbbf24; }
[data-bs-theme="dark"] .tono-danger  { --tono: #f87171; }
[data-bs-theme="dark"] .tono-info    { --tono: #22d3ee; }
[data-bs-theme="dark"] .tono-success { --tono: #4ade80; }
[data-bs-theme="dark"] .tono-primary { --tono: #6d9bff; }

.kpi-foot {
    padding: 9px 13px;
    border-top: 1px solid var(--app-border);
    background: var(--app-bg-body);
}
.kpi-foot a {
    font-size: var(--fs-small);
    font-weight: 600;
    color: var(--app-accent);
    text-decoration: none;
}
.kpi-foot a:hover { text-decoration: underline; }

.kpi-nota {
    padding: 0 13px 10px;
    font-size: var(--fs-label);
    color: var(--app-text-sub);
}

@media (prefers-reduced-motion: reduce) {
    .kpi-card, .kpi-value, .kpi-label, .kpi-link { transition: none; }
    .kpi-bar > span { animation: none; }
}

/* Variante de kpi-card para las tarjetas de lista del dashboard */
.kpi-body { flex: 1 1 auto; padding: 0; }
.kpi-scroll {
    height: 320px;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 12px 13px;
    scrollbar-width: thin;
    scrollbar-color: transparent transparent;
}
.kpi-scroll::-webkit-scrollbar { width: 8px; }
.kpi-scroll::-webkit-scrollbar-thumb { background: transparent; border-radius: 999px; }
.kpi-card:hover .kpi-scroll { scrollbar-color: var(--app-border) transparent; }
.kpi-card:hover .kpi-scroll::-webkit-scrollbar-thumb { background: var(--app-border); }

.kpi-head-tools { display: flex; align-items: center; gap: 5px; }
.kpi-head-tools .form-select,
.kpi-head-tools .form-control {
    height: 27px;
    padding: 1px 6px;
    font-size: var(--fs-label);
    border-radius: 7px;
}
.kpi-head-tools .btn {
    height: 27px;
    padding: 0 8px;
    border-radius: 7px;
    border: 1px solid var(--app-border);
    background: var(--app-bg-surface);
    color: var(--app-text-sub);
    font-size: var(--fs-small);
    display: inline-flex; align-items: center;
}
.kpi-head-tools .btn:hover { color: var(--kpi-accent, var(--app-accent)); border-color: var(--kpi-accent, var(--app-accent)); }

.kpi-foot-split {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}
.kpi-foot-split .kpi-foot-label {
    font-size: var(--fs-small);
    color: var(--app-text-sub);
}
.kpi-foot-split .kpi-foot-value {
    font-size: var(--fs-section);
    font-weight: 700;
    color: var(--kpi-accent, var(--app-accent));
    font-variant-numeric: tabular-nums;
}

/* Item de lista reutilizable dentro de las tarjetas de lista */
.kpi-item {
    display: block;
    padding: 8px 10px;
    margin-bottom: 6px;
    border: 1px solid var(--app-border);
    border-left: 3px solid var(--kpi-accent, var(--app-accent));
    border-radius: 9px;
    background: var(--app-bg-surface);
    text-decoration: none;
    transition: transform .16s ease, box-shadow .16s ease;
}
.kpi-item:last-child { margin-bottom: 0; }
.kpi-item:hover { transform: translateY(-1px); box-shadow: 0 6px 14px rgba(15, 23, 42, .1); }
.kpi-item-title {
    display: block;
    font-size: var(--fs-small);
    font-weight: 600;
    color: var(--app-text-main);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.kpi-item-meta {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 5px;
    font-size: var(--fs-label);
    color: var(--app-text-sub);
}
.kpi-item-meta .kpi-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 1px 7px;
    border-radius: 999px;
    background: var(--app-bg-body);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}
[data-bs-theme="dark"] .kpi-item-meta .kpi-chip { background: rgba(255, 255, 255, .07); }

.kpi-vacio {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    height: 100%;
    color: var(--app-text-sub);
    font-size: var(--fs-small);
    text-align: center;
}
.kpi-vacio i { font-size: 24px; opacity: .5; }

@media (prefers-reduced-motion: reduce) {
    .kpi-item { transition: none; }
}

/* =====================================================================
   MODAL DE DETALLE DE TARJETA DEL TABLERO
   ===================================================================== */

.modal-ticket .modal-content {
    border: 1px solid var(--app-border);
    border-radius: 14px;
    overflow: hidden;
}
.modal-ticket .modal-header {
    padding: 12px 18px;
    background: var(--app-bg-body);
    border-bottom: 1px solid var(--app-border);
}
.modal-ticket .modal-title {
    font-size: var(--fs-body);
    font-weight: 650;
    color: var(--app-text-main);
    display: flex;
    align-items: center;
}
.modal-ticket .modal-body { padding: 0; }

/* ---------- Encabezado del ticket ---------- */
.tk-encabezado {
    padding: 16px 20px 14px;
    border-bottom: 1px solid var(--app-border);
    border-left: 4px solid var(--tk-accent, var(--app-accent));
    background: var(--app-bg-surface);
}
.tk-nombre {
    margin: 0 0 6px;
    font-size: var(--fs-page);
    font-weight: 650;
    line-height: 1.25;
    color: var(--app-text-main);
    word-break: break-word;
}
.tk-sub {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 16px;
    margin-bottom: 10px;
    font-size: var(--fs-small);
    color: var(--app-text-sub);
}
.tk-sub span { display: inline-flex; align-items: center; gap: 5px; }
.tk-sub i { opacity: .75; }
.tk-etiquetas { display: flex; flex-wrap: wrap; gap: 5px; }
.tk-etiquetas .kanban-tag i { margin-right: 3px; }

/* ---------- Bloques de datos ---------- */
.tk-secciones {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1px;
    background: var(--app-border);
    border-bottom: 1px solid var(--app-border);
}
.tk-bloque {
    padding: 14px 20px 16px;
    background: var(--app-bg-surface);
}
.tk-bloque-titulo {
    margin: 0 0 10px;
    font-size: var(--fs-label);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--app-accent);
    display: flex;
    align-items: center;
    gap: 6px;
}

.tk-lista {
    display: grid;
    grid-template-columns: minmax(90px, auto) 1fr;
    gap: 7px 14px;
    margin: 0;
    font-size: var(--fs-small);
}
.tk-lista dt {
    font-weight: 500;
    color: var(--app-text-sub);
    white-space: nowrap;
}
.tk-lista dd {
    margin: 0;
    color: var(--app-text-main);
    font-weight: 500;
    word-break: break-word;
}
.tk-lista dd a { color: var(--app-accent); text-decoration: none; font-weight: 600; }
.tk-lista dd a:hover { text-decoration: underline; }

/* ---------- Nota ---------- */
.tk-nota {
    padding: 14px 20px 16px;
    background: var(--app-bg-body);
    border-bottom: 1px solid var(--app-border);
}
.tk-nota p {
    margin: 0;
    font-size: var(--fs-small);
    line-height: 1.55;
    color: var(--app-text-main);
    word-break: break-word;
}

/* ---------- Acciones ---------- */
.tk-acciones {
    display: flex;
    flex-wrap: wrap;
    gap: 7px;
    padding: 14px 20px;
    background: var(--app-bg-surface);
}
.tk-acciones .btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    border-radius: 8px;
    font-size: var(--fs-small);
    font-weight: 600;
    padding: 5px 12px;
}
.tk-acciones .btn[hidden] { display: none; }
.tk-acciones .tk-accion-final { margin-left: auto; }

@media (max-width: 575.98px) {
    .tk-secciones { grid-template-columns: minmax(0, 1fr); }
    .tk-encabezado, .tk-bloque, .tk-nota, .tk-acciones { padding-left: 14px; padding-right: 14px; }
    .tk-lista { grid-template-columns: minmax(0, 1fr); gap: 2px; }
    .tk-lista dd { margin-bottom: 6px; }
    .tk-acciones .btn { flex: 1 1 auto; justify-content: center; }
    .tk-acciones .tk-accion-final { margin-left: 0; flex-basis: 100%; }
}

/* =====================================================================
   DESPLEGABLE DEL BUSCADOR DEL HEADER
   ===================================================================== */

.buscador-panel {
    display: none;
    position: absolute;
    left: 0;
    right: 0;
    top: calc(100% + 6px);
    z-index: 1050;
    margin: 0;
    padding: 6px;
    list-style: none;
    max-height: min(60vh, 420px);
    overflow-y: auto;
    overscroll-behavior: contain;
    background: var(--app-bg-surface);
    border: 1px solid var(--app-border);
    border-radius: 12px;
    box-shadow: 0 12px 30px rgba(15, 23, 42, .16);
}
[data-bs-theme="dark"] .buscador-panel { box-shadow: 0 12px 30px rgba(0, 0, 0, .5); }

.buscador-item { border-radius: 9px; }
.buscador-item + .buscador-item { margin-top: 2px; }
.buscador-item > a {
    display: block;
    padding: 8px 10px;
    border-radius: 9px;
    text-decoration: none;
    color: inherit;
    transition: background .15s ease;
}
.buscador-item > a:hover,
.buscador-item.activo > a {
    background: color-mix(in srgb, var(--app-accent) 12%, transparent);
}

.buscador-nombre {
    display: block;
    font-size: var(--fs-small);
    font-weight: 600;
    color: var(--app-text-main);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.buscador-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 2px 12px;
    margin-top: 3px;
    font-size: var(--fs-label);
    color: var(--app-text-sub);
}
.buscador-meta span { display: inline-flex; align-items: center; gap: 4px; }
.buscador-meta i { opacity: .75; }

.buscador-msg {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 12px 10px;
    font-size: var(--fs-small);
    color: var(--app-text-sub);
}
.buscador-msg.es-error { color: var(--bs-danger); }

@media (max-width: 767.98px) {
    /* El buscador del header es angosto en movil; el panel se ensancha para
       que la clave, el sector y la ONU no queden en tres renglones. */
    .buscador-panel { max-height: 55vh; min-width: min(88vw, 340px); }
}
