/* GENERADO por el Target BundleFrontendAssets de ZeroWallet.Web.csproj (B-03). NO EDITAR A MANO: el proximo build lo pisa.
   Fuente, en este orden: theme.css, layout.css, components.css, site.css. Editar esos archivos, no este. */
/* Tema Dark Mode de Zero.Wallet (UI-001).
   Estética Binance con el amarillo característico (#fcd535) reemplazado por verde esmeralda como
   color de acento, según la especificación funcional §6.

   Se carga entre bootstrap.min.css y site.css. La estrategia es no reescribir reglas de Bootstrap
   sino reasignar sus custom properties: Bootstrap 5.3 expone --bs-* a nivel global y por componente,
   así que el tema se define una sola vez acá y ninguna vista necesita clases propias.

   Estructura del archivo:
     1. Tokens --zw-* (la paleta, independiente de Bootstrap)
     2. Mapeo de los tokens a las variables globales --bs-*
     3. Componentes donde Bootstrap deja el azul #0d6efd compilado literal
     4. Anillo de foco
     5. Select2 (librería externa, no participa del sistema de variables de Bootstrap) */

/* ============================================================================
   1. TOKENS
   ============================================================================ */

:root {
  /* Superficies. Tres niveles: la página, lo que se apoya sobre ella (cards, navbar) y lo que se
     apoya sobre eso (inputs, filas resaltadas, dropdowns). */
  --zw-bg: #0b0e11;
  --zw-surface: #181a20;
  --zw-elevated: #1e2329;
  --zw-overlay: #252930;

  /* Overlay translúcido para hover y filas alternadas: al no ser un color opaco funciona igual
     sobre la página que dentro de una card, sin necesidad de una variante por contenedor. */
  --zw-hover: rgba(255, 255, 255, 0.04);

  /* Bordes */
  --zw-border: #2b3139;
  --zw-border-md: #363c45;
  --zw-border-lg: #474d57;

  /* Texto */
  --zw-text: #eaecef;
  --zw-text-muted: #848e9c;
  --zw-text-dim: #707a8a;

  /* Acento. Ocupa el lugar del amarillo de Binance. --zw-on-accent es el color de texto que va
     ENCIMA del esmeralda: el blanco sobre #10b981 da 2.5:1 y no llega a AA, el fondo oscuro da
     7.5:1. */
  --zw-accent: #10b981;
  --zw-accent-hover: #34d399;
  --zw-accent-active: #059669;
  --zw-accent-rgb: 16, 185, 129;
  --zw-accent-bg: rgba(16, 185, 129, 0.1);
  --zw-accent-border: rgba(16, 185, 129, 0.25);
  --zw-on-accent: #0b0e11;

  /* Semánticos. En una aplicación de cartera el verde ya significa "ganancia", así que --zw-success
     comparte tono con el acento a propósito en vez de introducir un segundo verde. */
  --zw-success: #10b981;
  --zw-success-rgb: 16, 185, 129;
  --zw-success-bg: rgba(16, 185, 129, 0.12);
  --zw-success-border: rgba(16, 185, 129, 0.3);

  --zw-danger: #f6465d;
  --zw-danger-rgb: 246, 70, 93;
  --zw-danger-bg: rgba(246, 70, 93, 0.12);
  --zw-danger-border: rgba(246, 70, 93, 0.3);

  --zw-warning: #f59e0b;
  --zw-warning-rgb: 245, 158, 11;
  --zw-warning-bg: rgba(245, 158, 11, 0.12);
  --zw-warning-border: rgba(245, 158, 11, 0.3);

  --zw-info: #38bdf8;
  --zw-info-rgb: 56, 189, 248;
  --zw-info-bg: rgba(56, 189, 248, 0.1);
  --zw-info-border: rgba(56, 189, 248, 0.3);

  /* Paleta del gráfico de distribución (DASH-003). Vive en variables y no en el JS para que el tema
     pueda redefinirla sin tocar el código del gráfico; dashboard-distribucion.js las busca por
     nombre con getComputedStyle. El esmeralda va primero porque es el color de acento; el resto
     sigue un orden de contraste decreciente entre porciones vecinas. */
  --zw-chart-1: #10b981;
  --zw-chart-2: #38bdf8;
  --zw-chart-3: #a78bfa;
  --zw-chart-4: #f59e0b;
  --zw-chart-5: #fb923c;
  --zw-chart-6: #f87171;
  --zw-chart-7: #64748b;
  --zw-chart-8: #34d399;
}

/* ============================================================================
   2. VARIABLES GLOBALES DE BOOTSTRAP
   ============================================================================
   Bootstrap 5.3 ya trae su propio bloque [data-bs-theme=dark]; acá se lo pisa con los tokens del
   tema. Misma especificidad que el original, pero este archivo se carga después. */

[data-bs-theme="dark"] {
  color-scheme: dark;

  /* Superficies y texto */
  --bs-body-bg: var(--zw-bg);
  --bs-body-bg-rgb: 11, 14, 17;
  --bs-body-color: var(--zw-text);
  --bs-body-color-rgb: 234, 236, 239;
  --bs-emphasis-color: #ffffff;
  --bs-emphasis-color-rgb: 255, 255, 255;
  --bs-secondary-bg: var(--zw-surface);
  --bs-secondary-bg-rgb: 24, 26, 32;
  --bs-secondary-color: var(--zw-text-muted);
  --bs-secondary-color-rgb: 132, 142, 156;
  --bs-tertiary-bg: var(--zw-elevated);
  --bs-tertiary-bg-rgb: 30, 35, 41;
  --bs-tertiary-color: var(--zw-text-dim);
  --bs-tertiary-color-rgb: 112, 122, 138;
  --bs-heading-color: var(--zw-text);
  --bs-border-color: var(--zw-border);
  --bs-border-color-translucent: rgba(255, 255, 255, 0.1);

  /* Acento. --bs-primary-rgb alimenta a .text-primary y .bg-primary. */
  --bs-primary: var(--zw-accent);
  --bs-primary-rgb: var(--zw-accent-rgb);
  --bs-primary-text-emphasis: var(--zw-accent-hover);
  --bs-primary-bg-subtle: var(--zw-accent-bg);
  --bs-primary-border-subtle: var(--zw-accent-border);

  --bs-link-color: var(--zw-accent);
  --bs-link-color-rgb: var(--zw-accent-rgb);
  --bs-link-hover-color: var(--zw-accent-hover);
  --bs-link-hover-color-rgb: 52, 211, 153;

  /* Semánticos. Los *-text-emphasis / *-bg-subtle / *-border-subtle son los que consumen las alerts
     y los utilitarios .text-*-emphasis, así que redefinirlos acá alcanza para las 17 alerts de la
     aplicación sin escribir una regla por variante. */
  --bs-success: var(--zw-success);
  --bs-success-rgb: var(--zw-success-rgb);
  --bs-success-text-emphasis: var(--zw-accent-hover);
  --bs-success-bg-subtle: var(--zw-success-bg);
  --bs-success-border-subtle: var(--zw-success-border);

  --bs-danger: var(--zw-danger);
  --bs-danger-rgb: var(--zw-danger-rgb);
  --bs-danger-text-emphasis: var(--zw-danger);
  --bs-danger-bg-subtle: var(--zw-danger-bg);
  --bs-danger-border-subtle: var(--zw-danger-border);

  --bs-warning: var(--zw-warning);
  --bs-warning-rgb: var(--zw-warning-rgb);
  --bs-warning-text-emphasis: var(--zw-warning);
  --bs-warning-bg-subtle: var(--zw-warning-bg);
  --bs-warning-border-subtle: var(--zw-warning-border);

  --bs-info: var(--zw-info);
  --bs-info-rgb: var(--zw-info-rgb);
  --bs-info-text-emphasis: var(--zw-info);
  --bs-info-bg-subtle: var(--zw-info-bg);
  --bs-info-border-subtle: var(--zw-info-border);

  --bs-code-color: var(--zw-accent-hover);
  --bs-highlight-bg: var(--zw-warning-bg);
  --bs-highlight-color: var(--zw-text);

  /* Validación de formularios (asp-validation-for). */
  --bs-form-valid-color: var(--zw-accent-hover);
  --bs-form-valid-border-color: var(--zw-accent);
  --bs-form-invalid-color: var(--zw-danger);
  --bs-form-invalid-border-color: var(--zw-danger);
}

/* ============================================================================
   3. COMPONENTES
   ============================================================================
   Bootstrap compila el azul #0d6efd literal dentro de cada componente, así que redefinir
   --bs-primary no alcanza: hay que reasignar las variables locales del componente. Solo están los
   componentes que la aplicación usa hoy. */

/* --- Botones --- */

.btn-primary {
  --bs-btn-color: var(--zw-on-accent);
  --bs-btn-bg: var(--zw-accent);
  --bs-btn-border-color: var(--zw-accent);
  --bs-btn-hover-color: var(--zw-on-accent);
  --bs-btn-hover-bg: var(--zw-accent-hover);
  --bs-btn-hover-border-color: var(--zw-accent-hover);
  --bs-btn-focus-shadow-rgb: var(--zw-accent-rgb);
  --bs-btn-active-color: var(--zw-on-accent);
  --bs-btn-active-bg: var(--zw-accent-active);
  --bs-btn-active-border-color: var(--zw-accent-active);
  --bs-btn-disabled-color: var(--zw-on-accent);
  --bs-btn-disabled-bg: var(--zw-accent);
  --bs-btn-disabled-border-color: var(--zw-accent);
}

/* .btn-outline-primary es además el estado no seleccionado de los btn-check del dashboard
   (agrupación y moneda del gráfico de distribución). */
.btn-outline-primary {
  --bs-btn-color: var(--zw-accent);
  --bs-btn-border-color: var(--zw-accent-border);
  --bs-btn-hover-color: var(--zw-on-accent);
  --bs-btn-hover-bg: var(--zw-accent);
  --bs-btn-hover-border-color: var(--zw-accent);
  --bs-btn-focus-shadow-rgb: var(--zw-accent-rgb);
  --bs-btn-active-color: var(--zw-on-accent);
  --bs-btn-active-bg: var(--zw-accent);
  --bs-btn-active-border-color: var(--zw-accent);
  --bs-btn-disabled-color: var(--zw-text-dim);
  --bs-btn-disabled-border-color: var(--zw-border);
}

/* Los botones de exportación a Excel usan la variante success, que comparte tono con el acento. */
.btn-outline-success {
  --bs-btn-color: var(--zw-success);
  --bs-btn-border-color: var(--zw-success-border);
  --bs-btn-hover-color: var(--zw-on-accent);
  --bs-btn-hover-bg: var(--zw-success);
  --bs-btn-hover-border-color: var(--zw-success);
  --bs-btn-focus-shadow-rgb: var(--zw-success-rgb);
  --bs-btn-active-color: var(--zw-on-accent);
  --bs-btn-active-bg: var(--zw-success);
  --bs-btn-active-border-color: var(--zw-success);
  --bs-btn-disabled-color: var(--zw-text-dim);
  --bs-btn-disabled-border-color: var(--zw-border);
}

.btn-outline-danger {
  --bs-btn-color: var(--zw-danger);
  --bs-btn-border-color: var(--zw-danger-border);
  --bs-btn-hover-color: var(--zw-on-accent);
  --bs-btn-hover-bg: var(--zw-danger);
  --bs-btn-hover-border-color: var(--zw-danger);
  --bs-btn-focus-shadow-rgb: var(--zw-danger-rgb);
  --bs-btn-active-color: var(--zw-on-accent);
  --bs-btn-active-bg: var(--zw-danger);
  --bs-btn-active-border-color: var(--zw-danger);
  --bs-btn-disabled-color: var(--zw-text-dim);
  --bs-btn-disabled-border-color: var(--zw-border);
}

.btn-outline-secondary {
  --bs-btn-color: var(--zw-text-muted);
  --bs-btn-border-color: var(--zw-border-md);
  --bs-btn-hover-color: var(--zw-text);
  --bs-btn-hover-bg: var(--zw-elevated);
  --bs-btn-hover-border-color: var(--zw-border-lg);
  --bs-btn-focus-shadow-rgb: 132, 142, 156;
  --bs-btn-active-color: var(--zw-text);
  --bs-btn-active-bg: var(--zw-elevated);
  --bs-btn-active-border-color: var(--zw-border-lg);
  --bs-btn-disabled-color: var(--zw-text-dim);
  --bs-btn-disabled-border-color: var(--zw-border);
}

.btn-link {
  --bs-btn-disabled-color: var(--zw-text-dim);
  --bs-btn-focus-shadow-rgb: var(--zw-accent-rgb);
}

/* --- Cards --- */

.card {
  --bs-card-bg: var(--zw-surface);
  --bs-card-border-color: var(--zw-border);
  --bs-card-cap-bg: var(--zw-elevated);
  --bs-card-color: var(--zw-text);
}

/* --- Formularios ---
   Los inputs van sobre --zw-elevated y no sobre el fondo de página (que es lo que hace Bootstrap
   por defecto vía --bs-body-bg): sobre #0b0e11 el campo se confunde con la página y solo lo delata
   el borde. */

.form-control,
.form-select {
  background-color: var(--zw-elevated);
  border-color: var(--zw-border-md);
  color: var(--zw-text);
}

.form-control:focus,
.form-select:focus {
  background-color: var(--zw-elevated);
  border-color: var(--zw-accent);
  box-shadow: 0 0 0 0.25rem var(--zw-accent-bg);
  color: var(--zw-text);
}

.form-control::placeholder {
  color: var(--zw-text-muted);
}

.form-control:disabled,
.form-select:disabled {
  background-color: var(--zw-surface);
  color: var(--zw-text-dim);
}

/* El botón de "elegir archivo" del input de comprobante (MOVEMENT-002 / DRIVE-004). */
.form-control::file-selector-button {
  background-color: var(--zw-surface);
  color: var(--zw-text);
  border-color: var(--zw-border-md);
}

/* La etiqueta flotante (form-floating, usada en el login) se apoya sobre un rectángulo que Bootstrap
   pinta del color del fondo de página. Como acá el input NO usa ese color, sin esto la etiqueta
   queda como un recuadro más oscuro flotando dentro del campo. */
.form-floating > .form-control:focus ~ label::after,
.form-floating > .form-control:not(:placeholder-shown) ~ label::after,
.form-floating > .form-control-plaintext ~ label::after,
.form-floating > .form-select ~ label::after {
  background-color: var(--zw-elevated);
}

.form-floating > label {
  color: var(--zw-text-muted);
}

.form-check-input {
  background-color: var(--zw-elevated);
  border-color: var(--zw-border-lg);
}

.form-check-input:checked {
  background-color: var(--zw-accent);
  border-color: var(--zw-accent);
}

.form-check-input:focus {
  border-color: var(--zw-accent);
  box-shadow: 0 0 0 0.25rem var(--zw-accent-bg);
}

/* El tilde y el punto del radio vienen blancos en Bootstrap; sobre esmeralda quedan en 2.5:1.
   Se redibujan con el mismo color oscuro que el texto de los botones (%230b0e11 = --zw-on-accent). */
.form-check-input:checked[type="checkbox"] {
  --bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%230b0e11' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3e%3c/svg%3e");
}

.form-check-input:checked[type="radio"] {
  --bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%230b0e11'/%3e%3c/svg%3e");
}

/* --- Tablas ---
   --bs-table-bg transparente en vez de un color propio: la misma tabla aparece suelta sobre la
   página y dentro de una card, y así hereda el fondo del contenedor en ambos casos. */
.table {
  --bs-table-bg: transparent;
  --bs-table-color: var(--zw-text);
  --bs-table-border-color: var(--zw-border);
  --bs-table-striped-color: var(--zw-text);
  --bs-table-striped-bg: var(--zw-hover);
  --bs-table-hover-color: var(--zw-text);
  --bs-table-hover-bg: rgba(255, 255, 255, 0.07);
}

/* --- Badges ---
   Las variantes de color llevan texto oscuro por la misma razón que los botones: el blanco de
   Bootstrap sobre esmeralda o sobre el rojo del tema no llega a AA. */
.badge.bg-success,
.badge.bg-danger,
.badge.bg-warning,
.badge.bg-info,
.badge.bg-primary {
  --bs-badge-color: var(--zw-on-accent);
}

/* --- Alertas ---
   Borde izquierdo grueso en vez del borde completo tenue de Bootstrap: sobre fondo oscuro un contorno
   translúcido de 1px alrededor de un relleno también translúcido casi no se ve, y las alertas de las
   distintas variantes terminaban leyéndose todas igual. El borde de color es el que las diferencia. */

.alert {
  border-left-width: 3px;
}

.alert-success {
  border-left-color: var(--zw-success);
}

.alert-danger {
  border-left-color: var(--zw-danger);
}

.alert-warning {
  border-left-color: var(--zw-warning);
}

.alert-info {
  border-left-color: var(--zw-info);
}

/* --- Texto de detalle ---
   Bootstrap deja <kbd> con "background:#212529; color:#fff" compilado literal, así que en el tema
   queda como un rectángulo negro. Se usa en la clave manual del setup de 2FA. */

kbd {
  background-color: var(--zw-elevated);
  color: var(--zw-accent-hover);
}

/* En un <dl> ambos lados heredan el color de cuerpo y no se distingue la etiqueta del valor. */
dt {
  color: var(--zw-text-muted);
}

/* --- Navbar y dropdowns ---
   La estructura del navbar (y el sidebar) se rehace en UI-002; acá solo se define su color para que
   el layout actual no quede con texto oscuro sobre fondo oscuro. */
.navbar {
  --bs-navbar-color: var(--zw-text-muted);
  --bs-navbar-hover-color: var(--zw-text);
  --bs-navbar-active-color: var(--zw-accent);
  --bs-navbar-disabled-color: var(--zw-text-dim);
  --bs-navbar-brand-color: var(--zw-text);
  --bs-navbar-brand-hover-color: var(--zw-accent);
  background-color: var(--zw-surface);
  border-bottom: 1px solid var(--zw-border);
}

.dropdown-menu {
  --bs-dropdown-bg: var(--zw-surface);
  --bs-dropdown-border-color: var(--zw-border);
  --bs-dropdown-color: var(--zw-text);
  --bs-dropdown-link-color: var(--zw-text);
  --bs-dropdown-link-hover-bg: var(--zw-elevated);
  --bs-dropdown-link-active-bg: var(--zw-accent);
  --bs-dropdown-link-active-color: var(--zw-on-accent);
}

/* El sidebar ya usa Offcanvas, pero pinta su fondo aparte en layout.css sin pasar por esta variable
   (por eso el hueco no se notaba). El popover de filtros (UI-xxx) sí depende de ella para su modo
   mobile, así que queda remapeada acá para cualquier offcanvas presente y futuro. */
.offcanvas {
  --bs-offcanvas-bg: var(--zw-surface);
  --bs-offcanvas-color: var(--zw-text);
}

/* ============================================================================
   4. FOCO
   ============================================================================
   Un solo anillo esmeralda para todo lo interactivo, en lugar del blanco + azul del scaffold.
   :focus-visible y no :focus para que no aparezca al hacer click con el mouse. */

:focus-visible {
  outline: 2px solid var(--zw-accent);
  outline-offset: 2px;
}

.btn:focus-visible,
.form-control:focus-visible,
.form-select:focus-visible,
.form-check-input:focus-visible {
  outline: none;
  box-shadow: 0 0 0 0.25rem var(--zw-accent-bg);
}

/* Los btn-check del dashboard ocultan el input real, así que el foco tiene que dibujarse sobre la
   etiqueta que hace de botón. */
.btn-check:focus-visible + .btn {
  box-shadow: 0 0 0 0.25rem var(--zw-accent-bg);
}

/* ============================================================================
   5. SELECT2
   ============================================================================
   Select2 no usa custom properties, así que sus colores se escriben acá directamente. Los ajustes
   de alto y radio existen porque el tema default de Select2 fue diseñado para Bootstrap 3: sin
   ellos el control queda más bajo y con otro radio que un .form-select vecino. Se resuelve así en
   vez de sumar el paquete select2-bootstrap-5-theme, que traería otra dependencia solo por estilos.

   Prefijo .zw-app (la clase del <body>, siempre presente) en cada selector: el CSS de Select2 se
   agrega por página vía @section Styles, que en _Layout.cshtml carga después de theme.css. Sin el
   prefijo, estas reglas empatan en especificidad con las del vendor y pierden el desempate de
   cascada por orden de carga —el control vuelve al blanco/28px por defecto de Select2—. Con el
   prefijo ganan siempre, sin tocar el orden de las hojas ni usar !important. */

.zw-app .select2-container--default .select2-selection--single {
  height: calc(1.5em + 0.75rem + 2px);
  border: var(--bs-border-width) solid var(--zw-border-md);
  border-radius: var(--bs-border-radius);
  background-color: var(--zw-elevated);
}

.zw-app .select2-container--default .select2-selection--single .select2-selection__rendered {
  line-height: calc(1.5em + 0.75rem);
  padding-left: 0.75rem;
  color: var(--zw-text);
}

.zw-app .select2-container--default .select2-selection--single .select2-selection__placeholder {
  color: var(--zw-text-muted);
}

.zw-app .select2-container--default .select2-selection--single .select2-selection__arrow {
  height: calc(1.5em + 0.75rem);
}

.zw-app .select2-container--default.select2-container--focus .select2-selection--single,
.zw-app .select2-container--default.select2-container--open .select2-selection--single {
  border-color: var(--zw-accent);
  box-shadow: 0 0 0 0.25rem var(--zw-accent-bg);
}

.zw-app .select2-container--default .select2-dropdown {
  background-color: var(--zw-surface);
  border-color: var(--zw-border-md);
  color: var(--zw-text);
}

.zw-app .select2-container--default .select2-results__option {
  color: var(--zw-text);
}

.zw-app .select2-container--default .select2-results__option--highlighted[aria-selected],
.zw-app .select2-container--default .select2-results__option--highlighted[data-selected] {
  background-color: var(--zw-accent);
  color: var(--zw-on-accent);
}

.zw-app .select2-container--default .select2-results__option[aria-selected="true"],
.zw-app .select2-container--default .select2-results__option[data-selected="true"] {
  background-color: var(--zw-elevated);
  color: var(--zw-text);
}

.zw-app .select2-container--default .select2-search--dropdown .select2-search__field {
  border: var(--bs-border-width) solid var(--zw-border-md);
  border-radius: var(--bs-border-radius);
  padding: 0.375rem 0.75rem;
  background-color: var(--zw-elevated);
  color: var(--zw-text);
}

.zw-app .select2-container--default .select2-search--dropdown .select2-search__field:focus {
  border-color: var(--zw-accent);
  outline: none;
}

/* La flecha y el botón de limpiar (allowClear:true en select2-remote.js) traen color fijo (#888 /
   #999) en el tema default de Select2, ajeno a estas custom properties: sin esto quedan grises
   contra el resto del control ya tematizado. Mismo tono que .select2-selection__placeholder porque
   los tres son elementos secundarios, no el valor elegido. */
.zw-app .select2-container--default .select2-selection--single .select2-selection__arrow b {
  border-color: var(--zw-text-muted) transparent transparent transparent;
}

.zw-app .select2-container--default.select2-container--open
  .select2-selection--single .select2-selection__arrow b {
  border-color: transparent transparent var(--zw-text-muted) transparent;
}

.zw-app .select2-container--default .select2-selection--single .select2-selection__clear {
  color: var(--zw-text-muted);
}

.zw-app .select2-container--default .select2-selection--single .select2-selection__clear:hover {
  color: var(--zw-text);
}

/* Multi-selección (filtro de tags, ITEM-011): mismo criterio que --single arriba, pero acá el
   "valor elegido" es una lista de chips (.select2-selection__choice), no un texto plano. */
.zw-app .select2-container--default .select2-selection--multiple {
  min-height: calc(1.5em + 0.75rem + 2px);
  border: var(--bs-border-width) solid var(--zw-border-md);
  border-radius: var(--bs-border-radius);
  background-color: var(--zw-elevated);
}

.zw-app .select2-container--default.select2-container--focus .select2-selection--multiple,
.zw-app .select2-container--default.select2-container--open .select2-selection--multiple {
  border-color: var(--zw-accent);
  box-shadow: 0 0 0 0.25rem var(--zw-accent-bg);
}

.zw-app .select2-container--default .select2-selection--multiple .select2-selection__rendered {
  padding: 0.25rem 0.5rem;
  gap: 0.25rem;
}

.zw-app .select2-container--default .select2-selection--multiple .select2-selection__choice {
  background-color: var(--zw-accent-bg);
  border: var(--bs-border-width) solid var(--zw-accent-border);
  border-radius: var(--bs-border-radius-sm);
  color: var(--zw-text);
  margin: 0;
  padding: 0.125rem 0.5rem;
}

.zw-app .select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
  color: var(--zw-text-muted);
  border-right: none;
  margin-right: 0.375rem;
}

.zw-app .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
  color: var(--zw-text);
  background-color: transparent;
}

.zw-app .select2-container--default .select2-selection--multiple .select2-search__field {
  color: var(--zw-text);
}

/* Área táctil bajo 992px (UI-004/UX-009): mismo mínimo de 44px que se aplica a .form-select en
   components.css §13, hasta el mismo límite de 991.98px, para que el select de activo o broker no
   quede más bajo que el campo de moneda que tiene al lado. Los tres valores tienen que moverse
   juntos —caja, línea de texto y flecha— porque el tema default de Select2 los define por separado. */
@media (max-width: 991.98px) {
  .zw-app .select2-container--default .select2-selection--single {
    height: 44px;
  }

  .zw-app .select2-container--default .select2-selection--single .select2-selection__rendered {
    line-height: 42px;
  }

  .zw-app .select2-container--default .select2-selection--single .select2-selection__arrow {
    height: 42px;
  }

  /* El campo de búsqueda del desplegable también se toca con el dedo. */
  .zw-app .select2-container--default .select2-search--dropdown .select2-search__field {
    min-height: 44px;
  }

  .zw-app .select2-container--default .select2-selection--multiple {
    min-height: 44px;
  }
}

/* Shell de la aplicación (UI-002): topbar, sidebar, área de contenido y footer.

   Se carga entre theme.css y site.css. Todo el color sale de los tokens --zw-* de UI-001: en este
   archivo no hay un solo valor de color literal, así que cambiar la paleta sigue siendo un cambio
   de un único archivo.

   Estructura:
     1. Estructura general (body en columna, shell en fila)
     2. Skip link
     3. Topbar
     4. Sidebar y navegación
     5. Contenido
     6. Footer
     7. Íconos y botones del shell */

/* ============================================================================
   1. ESTRUCTURA GENERAL
   ============================================================================
   El footer queda al final por layout y no por position:absolute (como hacía el scaffold): con
   min-height 100vh y el shell tomando el sobrante, una página corta lo empuja al pie de la ventana
   y una larga lo deja después del contenido, sin necesidad de reservar altura en el body. */

.zw-app {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.zw-shell {
  display: flex;
  flex: 1 0 auto;
  align-items: stretch;
  /* min-width en el shell y en el contenido: sin esto un descendiente ancho (una tabla, el canvas
     del dashboard) infla la columna flexible y desborda la página horizontalmente. */
  min-width: 0;
}

/* ============================================================================
   2. SKIP LINK
   ============================================================================ */

.zw-skip-link {
  position: absolute;
  top: 0;
  left: -9999px;
  z-index: 1080;
  padding: 0.5rem 0.875rem;
  border: 1px solid var(--zw-accent);
  border-radius: var(--bs-border-radius);
  background-color: var(--zw-elevated);
  color: var(--zw-text);
  text-decoration: none;
}

.zw-skip-link:focus {
  top: 0.5rem;
  left: 0.5rem;
}

/* ============================================================================
   3. TOPBAR
   ============================================================================ */

.zw-topbar {
  position: sticky;
  top: 0;
  /* 1030 = el z-index que Bootstrap usa para navbars fijos; queda por debajo del backdrop del
     offcanvas (1040) y de los modales. */
  z-index: 1030;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  height: 56px;
  padding: 0 1rem;
  border-bottom: 1px solid var(--zw-border);
  background-color: var(--zw-surface);
}

/* En un teléfono angosto el padding lateral compite con el email del menú de usuario, que ya se
   recorta con puntos suspensivos: se recuperan 8px para el contenido (UI-004). */
@media (max-width: 575.98px) {
  .zw-topbar {
    padding: 0 0.75rem;
  }
}

.zw-topbar-start,
.zw-topbar-end {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-width: 0;
}

.zw-brand {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-width: 0;
  color: var(--zw-text);
  font-weight: 600;
  text-decoration: none;
}

a.zw-brand:hover {
  color: var(--zw-accent);
}

.zw-brand-mark {
  width: 1.25rem;
  height: 1.25rem;
  color: var(--zw-accent);
}

.zw-brand-text {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* ============================================================================
   4. SIDEBAR Y NAVEGACIÓN
   ============================================================================
   El elemento es un .offcanvas-lg de Bootstrap: por debajo de 992px es un panel deslizante y por
   encima un bloque normal, que acá se fija como columna. */

.zw-sidebar {
  /* Variables del propio componente offcanvas: así el panel de mobile toma la paleta del tema sin
     reescribir sus reglas.

     El ancho es un min() y no 260px fijos (UI-004): en un teléfono de 320px el panel dejaba 60px de
     backdrop, y cerrarlo tocando afuera —que es el gesto natural— era casi imposible. */
  --bs-offcanvas-width: min(260px, 82vw);
  --bs-offcanvas-bg: var(--zw-surface);
  --bs-offcanvas-border-color: var(--zw-border);
  --bs-offcanvas-color: var(--zw-text);
  background-color: var(--zw-surface);
}

.zw-sidebar .zw-sidebar-body {
  padding: 1rem 0.75rem;
}

@media (min-width: 992px) {
  .zw-sidebar {
    position: sticky;
    /* Arranca donde termina el topbar y ocupa exactamente el resto de la ventana: la navegación
       queda visible aunque el contenido scrollee. */
    top: 56px;
    flex: 0 0 240px;
    width: 240px;
    height: calc(100vh - 56px);
    overflow-y: auto;
    border-right: 1px solid var(--zw-border);
    /* !important porque a partir de este breakpoint Bootstrap fuerza
       "background-color: transparent !important" sobre .offcanvas-lg y su body: es la única forma
       de recuperar la superficie del sidebar sin dejar de usar el componente. */
    background-color: var(--zw-surface) !important;
  }

  /* Mismo caso: Bootstrap pasa el body del offcanvas a display:flex y padding 0 en desktop, lo que
     acostaría las secciones de la navegación en una fila. */
  .zw-sidebar .zw-sidebar-body {
    display: block;
    padding: 1rem 0.75rem;
    background-color: transparent;
  }
}

.zw-nav-section {
  margin: 0 0 0.375rem;
  padding: 0 0.625rem;
  color: var(--zw-text-dim);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.zw-nav {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 0 0 1.25rem;
  padding: 0;
  list-style: none;
}

.zw-nav:last-child {
  margin-bottom: 0;
}

.zw-nav-link {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.5rem 0.625rem;
  /* El borde transparente está también en el estado normal para que marcar el ítem activo no
     corra el texto dos píxeles. */
  border-left: 2px solid transparent;
  border-radius: var(--bs-border-radius);
  color: var(--zw-text-muted);
  font-size: 0.8125rem;
  line-height: 1.25rem;
  text-decoration: none;
}

.zw-nav-link:hover {
  background-color: var(--zw-hover);
  color: var(--zw-text);
}

.zw-nav-link.active {
  border-left-color: var(--zw-accent);
  background-color: var(--zw-accent-bg);
  color: var(--zw-accent);
}

/* Por debajo de 992px la navegación vive en el panel deslizante y se toca con el dedo, no con el
   mouse. Con el root en 14px (ver site.css) el ítem mide 36px de alto y los once entradas quedan
   pegadas una a otra (UI-004). */
@media (max-width: 991.98px) {
  .zw-nav-link {
    min-height: 44px;
  }
}

/* ============================================================================
   5. CONTENIDO
   ============================================================================ */

.zw-content {
  flex: 1 1 auto;
  min-width: 0;
  padding: 1.25rem 1rem;
  /* El skip link enfoca #zw-main, que es tabindex="-1": sin margen de scroll el topbar sticky
     taparía el arranque del contenido justo después del salto. */
  scroll-margin-top: 56px;
}

/* El foco de #zw-main viene siempre de ese salto programático, nunca de tabular: dibujar el anillo
   ahí marcaría media pantalla sin aportar nada. */
.zw-content:focus {
  outline: none;
}

/* Escalón intermedio (UI-004): entre el teléfono y el desktop hay un tramo de 768 a 991px —tablet en
   portrait, ventana a media pantalla— donde 1rem deja el contenido pegado al borde y 2rem le come
   demasiado ancho a las tablas, que son lo que más sufre en ese rango. */
@media (min-width: 768px) {
  .zw-content {
    padding: 1.5rem;
  }
}

@media (min-width: 992px) {
  .zw-content {
    padding: 1.75rem 2rem;
  }
}

/* ============================================================================
   6. FOOTER
   ============================================================================ */

.zw-footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.375rem;
  padding: 0.875rem 1rem;
  border-top: 1px solid var(--zw-border);
  background-color: var(--zw-surface);
  color: var(--zw-text-muted);
  font-size: 0.75rem;
}

.zw-footer a {
  color: var(--zw-text-muted);
  text-decoration: none;
}

.zw-footer a:hover {
  color: var(--zw-accent);
  text-decoration: underline;
}

/* Empuja el contacto a la derecha aunque sea el único hijo restante (mismo patrón que
   .zw-toolbar-end en components.css). */
.zw-footer-end {
  margin-left: auto;
}

/* Cuando el footer se parte en dos líneas ya no hay nada a la izquierda de este bloque, y el
   margin-left:auto lo deja solo contra el borde derecho. Apilado, alinea a la izquierda como el
   resto del footer (UI-004). */
@media (max-width: 575.98px) {
  .zw-footer-end {
    margin-left: 0;
  }
}

/* ============================================================================
   7. ÍCONOS Y BOTONES DEL SHELL
   ============================================================================ */

/* El sprite de _Icons.cshtml: define los símbolos, no dibuja nada. */
.zw-icon-sprite {
  display: none;
}

.zw-icon {
  flex: 0 0 auto;
  width: 1rem;
  height: 1rem;
}

/* Botón cuadrado solo con ícono (el ☰ del topbar). */
.zw-icon-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 0;
  border-radius: var(--bs-border-radius);
  background-color: transparent;
  color: var(--zw-text-muted);
}

.zw-icon-button:hover {
  background-color: var(--zw-hover);
  color: var(--zw-text);
}

/* El ☰ solo existe por debajo de 992px, y ahí es el único acceso a la navegación entera: 36px es
   chico para el dedo (UI-004). No se toca el ícono, solo el área que lo rodea. */
@media (max-width: 991.98px) {
  .zw-icon-button {
    width: 44px;
    height: 44px;
  }
}

.zw-user-button {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  max-width: 260px;
  padding: 0.375rem 0.625rem;
  border: 1px solid transparent;
  border-radius: var(--bs-border-radius);
  background-color: transparent;
  color: var(--zw-text-muted);
  font-size: 0.8125rem;
}

.zw-user-button:hover {
  border-color: var(--zw-border);
  background-color: var(--zw-hover);
  color: var(--zw-text);
}

/* Un email largo no puede empujar el topbar: se recorta con puntos suspensivos. */
.zw-user-name {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.zw-user-caption {
  color: var(--zw-text-muted);
  font-size: 0.8125rem;
}

.zw-user-logout {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

/* Componentes de página (UI-003).

   Se carga entre layout.css y site.css. Es el vocabulario que comparten las vistas: encabezado,
   secciones, tablas, estados vacíos, métricas y el shell de las pantallas de sesión.

   Por qué existe este archivo y no se resuelve con utilidades de Bootstrap en cada .cshtml: hasta
   UI-002 cada vista armaba lo mismo de forma distinta (tres variantes de encabezado, dos tamaños de
   valor para la misma métrica, "table table-striped align-middle" copiado en cinco tablas). Con las
   reglas acá, UI-004 toca los breakpoints en un solo lugar.

   Misma regla que layout.css: ni un color literal. Todo sale de los tokens --zw-* de UI-001.

   Estructura:
     1. Encabezado de página y títulos
     2. Toolbar
     3. Tablas
     4. Números
     5. Estados vacíos
     6. Métricas (stat cards)
     7. Formularios
     8. Paginación
     9. Badges
    10. Bloques monoespaciados y QR
    11. Listas de detalle
    12. Shell de las pantallas de sesión
    13. Área táctil en pantallas chicas
    14. Árbol de carpetas (Vault)
    15. Tabs de configuración de cuenta
    16. Filtro (popover)

   Los breakpoints de UI-004 están junto al componente que modifican y no agrupados al final: la
   excepción es la §13, que es una sola regla transversal a los controles de Bootstrap. */

/* ============================================================================
   1. ENCABEZADO DE PÁGINA Y TÍTULOS
   ============================================================================
   El <h1> de Bootstrap mide 2.5rem, pensado para una landing. Acá compite con el contenido: la
   aplicación es un tablero operativo y el título es una referencia, no el protagonista. */

.zw-page-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 1.25rem;
}

.zw-page-title {
  margin: 0;
  font-size: 1.375rem;
  font-weight: 600;
  line-height: 1.3;
}

/* Columna de lectura centrada para páginas de contenido largo (Privacy, Terms): el bloque se
   centra horizontalmente, el texto adentro queda alineado a la izquierda como un artículo. */
.zw-prose {
  max-width: 720px;
  margin-inline: auto;
}

/* Las acciones de la página (exportar, ir al historial) van a la derecha del título y bajan solas
   cuando no entran. */
.zw-page-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}

/* Título de una sección suelta sobre la página. El margen superior es parte del componente: sin él
   cada vista lo resolvía con un mt-4 propio. */
.zw-section-title {
  margin: 1.75rem 0 0.75rem;
  font-size: 0.9375rem;
  font-weight: 600;
  line-height: 1.4;
}

/* Título de un bloque dentro de una card (filtros, formulario de alta). Va en label chico y no en
   heading grande: la card ya delimita el bloque, el texto solo lo nombra. */
.zw-panel-title {
  margin: 0 0 1rem;
  color: var(--zw-text-muted);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  line-height: 1.4;
  text-transform: uppercase;
}

/* ============================================================================
   2. TOOLBAR
   ============================================================================
   Fila de controles arriba de una tabla: a la izquierda lo que filtra o cambia la vista (el selector
   de moneda de Assets/List), a la derecha lo que actúa sobre el resultado (exportar). */

.zw-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 0.75rem;
}

/* Empuja el bloque a la derecha aunque sea el único hijo del toolbar. */
.zw-toolbar-end {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-left: auto;
}

/* Cuando el toolbar se parte en dos líneas ya no hay nada a la izquierda de este bloque, y el
   margin-left:auto lo deja solo contra el borde derecho, desalineado del selector de moneda que le
   quedó arriba. Apilado, alinea a la izquierda como el resto de la página (UI-004). */
@media (max-width: 575.98px) {
  .zw-toolbar-end {
    margin-left: 0;
  }
}

.zw-toolbar-label {
  display: block;
  margin: 0 0 0.375rem;
  color: var(--zw-text-muted);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* ============================================================================
   3. TABLAS
   ============================================================================
   .zw-table se usa junto a .table de Bootstrap: hereda de ahí el striping y el hover (cuyos colores
   ya define theme.css) y agrega la densidad y el encabezado. */

/* El wrapper y no .table-responsive de Bootstrap: aquel fuerza overflow siempre, lo que recorta el
   foco de los controles dentro de la tabla incluso cuando entra entera. Acá el scroll aparece solo
   si hace falta.

   Sombra de scroll (UI-004): cuatro gradientes con background-attachment mixto. Los dos primeros son
   "tapas" del color de la superficie ancladas al contenido (local), los dos últimos son la sombra
   anclada al recuadro visible (scroll). Mientras hay contenido por ver de un lado, la tapa de ese
   lado está fuera de cuadro y la sombra queda expuesta; al llegar al extremo, la tapa la cubre. Es
   decir: la sombra aparece exactamente del lado hacia el que todavía se puede desplazar, sin JS y
   sin elementos extra. --zw-bg hace de sombra por ser la superficie más oscura de la paleta.

   El anillo de foco cuando el contenedor es enfocable (ver site.js) lo aporta la regla global
   :focus-visible de theme.css; no hace falta repetirlo acá. */
.zw-table-wrap {
  overflow-x: auto;
  border: 1px solid var(--zw-border);
  border-radius: var(--bs-border-radius);
  background-color: var(--zw-surface);
  background-image:
    linear-gradient(to right, var(--zw-surface), transparent),
    linear-gradient(to left, var(--zw-surface), transparent),
    linear-gradient(to right, var(--zw-bg), transparent),
    linear-gradient(to left, var(--zw-bg), transparent);
  background-position: left center, right center, left center, right center;
  background-repeat: no-repeat;
  background-size: 20px 100%, 20px 100%, 12px 100%, 12px 100%;
  background-attachment: local, local, scroll, scroll;
}

.zw-table {
  margin-bottom: 0;
  font-size: 0.8125rem;
  vertical-align: middle;
}

/* Los encabezados como label y no como texto: en una tabla densa el nombre de la columna es
   metadato, y en mayúsculas chicas deja de competir con los datos. */
.zw-table > thead > tr > th {
  padding: 0.625rem 0.75rem;
  border-bottom: 1px solid var(--zw-border-md);
  color: var(--zw-text-muted);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
}

.zw-table > tbody > tr > td {
  padding: 0.5625rem 0.75rem;
}

/* Columna de acciones de una tabla angosta (nombre + opciones, como Vault/Folders y Vault/Tags):
   sin esto el layout automático de <table> le da a esta columna el mismo ancho que a la del
   nombre y deja un hueco vacío a la derecha de los botones. */
.zw-table-col-actions {
  width: 1%;
  white-space: nowrap;
}

/* La última fila no dibuja su borde: ya lo aporta el borde del wrapper. */
.zw-table > tbody > tr:last-child > td {
  border-bottom: 0;
}

/* En pantalla chica cada píxel de ancho es una columna menos que hay que ir a buscar con scroll: el
   historial de movimientos tiene diez columnas (cuatro de ellas —Descripción, Comprobante, Broker y
   PrecioUnitario— ocultas por debajo de lg), y recortando el padding lateral entran casi dos más
   antes de necesitar desplazarse (UI-004). El padding vertical no baja tanto porque define el alto
   de fila, que es lo que se toca con el dedo. */
@media (max-width: 767.98px) {
  .zw-table > thead > tr > th,
  .zw-table > tbody > tr > td {
    padding-right: 0.5rem;
    padding-left: 0.5rem;
  }
}

/* ============================================================================
   4. NÚMEROS
   ============================================================================
   Los dígitos de DM Sans son proporcionales: en una columna de montos el "1" ocupa menos que el "8"
   y las cifras no alinean por posición decimal. tabular-nums las lleva a ancho fijo. */

.zw-num {
  font-variant-numeric: tabular-nums;
}

/* ============================================================================
   5. ESTADOS VACÍOS
   ============================================================================
   El borde punteado marca "acá va a haber algo" sin fingir un contenedor con contenido. */

.zw-empty {
  padding: 1.75rem 1.25rem;
  border: 1px dashed var(--zw-border-md);
  border-radius: var(--bs-border-radius);
  color: var(--zw-text-muted);
  font-size: 0.8125rem;
  text-align: center;
}

.zw-empty p {
  margin-bottom: 0;
}

.zw-empty p + p,
.zw-empty p + a {
  margin-top: 0.5rem;
}

/* Un estado vacío ofrece a lo sumo una acción, y como es lo único accionable del bloque se muestra
   como botón y no como link suelto. */
.zw-empty-action {
  display: inline-block;
  margin-top: 0.75rem;
}

/* ============================================================================
   6. MÉTRICAS
   ============================================================================
   .zw-stat se usa sobre .card: aporta el ritmo interno (label chico, valor grande, nota) que antes
   cada bloque resolvía por su cuenta —de ahí que el dashboard tuviera un h3 en la fila de valores y
   un h4 en la de actividad para métricas del mismo rango. */

.zw-stat {
  height: 100%;
  padding: 1rem 1.125rem;
}

.zw-stat-label {
  margin: 0 0 0.5rem;
  color: var(--zw-text-muted);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* Sin @media propio a propósito (UX-008/UX-020): las dos stat cards del dashboard viven en
   col-sm-6, que por el width:100% mobile-first de Bootstrap ya ocupan el ancho completo del
   contenedor bajo 576px (no están comprimidas a mitad de pantalla), y el 1.5rem ya baja de 24px a
   21px bajo 768px porque site.css escala toda la interfaz bajando el font-size del html — el mismo
   mecanismo que evita reglas de tamaño repetidas en cada componente. Con esos dos ~260px de ancho
   útil y 21px de fuente, un valor extremo tipo "AR$ 99.999.999,99" entra sin cortar línea. */
.zw-stat-value {
  margin: 0;
  font-size: 1.5rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  line-height: 1.2;
}

/* Cuando no hay dato el hueco se llena con texto en el tono secundario, no con el tamaño de un
   valor: "todavía no hay" no es una cifra. */
.zw-stat-value--empty {
  color: var(--zw-text-muted);
  font-size: 0.8125rem;
  font-weight: 400;
  line-height: 1.5;
}

.zw-stat-note {
  margin: 0.625rem 0 0;
  font-size: 0.75rem;
  line-height: 1.4;
}

/* ============================================================================
   7. FORMULARIOS
   ============================================================================ */

/* Pie del formulario. El borde separa los campos de la acción que los envía, que si no queda como
   un control más de la grilla. */
.zw-form-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.5rem;
  padding-top: 1rem;
  border-top: 1px solid var(--zw-border);
}

/* En teléfono los campos ocupan el ancho completo y un submit de 90px al pie se lee como un control
   secundario más. Repartido, cierra el formulario con el mismo peso que tiene (UI-004).

   Selector de hijo directo y no descendiente: en ConnectDrive los hijos del bloque son dos <form>
   (reconectar / desconectar) y sus botones no son flex items, así que la regla no los alcanzaría
   igual. Son acciones secundarias y quedan bien con su ancho natural. */
@media (max-width: 575.98px) {
  .zw-form-actions > .btn {
    flex: 1 1 auto;
  }
}

/* Enmascara un textarea multilínea para campos sensibles de tipo LongText (ITEM-007): un
   input[type=password] no admite saltos de línea, así que esto es el equivalente para algo como
   "Recovery codes". vault-item-form.js la agrega/quita al togglear la visibilidad. Degrada a texto
   visible en navegadores sin soporte para -webkit-text-security (Firefox); el botón de
   mostrar/ocultar sigue funcionando igual. */
.zw-masked {
  -webkit-text-security: disc;
}

/* Panel de opciones del generador de contraseñas (PWDGEN-002): sin min-width el dropdown de
   Bootstrap se angosta al ancho del botón trigger y las tres opciones + el input de longitud
   quedan amontonados. */
.zw-generate-password-menu {
  min-width: 220px;
  max-width: min(280px, 90vw);
}

/* Asterisco de campo obligatorio (junto al label) + texto de la leyenda del formulario que lo
   explica. Solo color: no es un badge ni necesita fondo/borde como los tokens semánticos -bg/-border. */
.zw-required-mark {
  color: var(--zw-danger);
  margin-left: 0.125rem;
}

/* Ícono de ayuda junto a un label, con tooltip de Bootstrap (primer uso en el proyecto). Es un
   <button> y no un <span> para que sea alcanzable por teclado; visualmente no parece un botón para
   no competir con las acciones reales del formulario. */
.zw-label-with-info {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  margin-bottom: 0.25rem;
}

.zw-info-trigger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: none;
  background: none;
  color: var(--zw-text-dim);
  cursor: help;
}

.zw-info-trigger:hover,
.zw-info-trigger:focus-visible {
  color: var(--zw-accent);
}

.zw-info-trigger .zw-icon {
  width: 14px;
  height: 14px;
}

/* Mismo mínimo táctil que el resto de los controles interactivos (§13): un ícono de 14px es
   imposible de acertar con el dedo sin agrandar su área de toque. */
@media (max-width: 767.98px) {
  .zw-info-trigger {
    min-width: 44px;
    min-height: 44px;
  }
}

/* ============================================================================
   8. PAGINACIÓN
   ============================================================================ */

.zw-pager {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-top: 1rem;
}

.zw-pager-status {
  color: var(--zw-text-muted);
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
}

/* ============================================================================
   9. BADGES
   ============================================================================
   Variante suave en vez del .badge sólido de Bootstrap: sobre fondo oscuro un rectángulo esmeralda
   o rojo pleno pesa más que el dato de la fila que está calificando. */

.zw-badge {
  display: inline-flex;
  align-items: center;
  padding: 0.1875rem 0.5rem;
  border: 1px solid transparent;
  border-radius: var(--bs-border-radius-sm);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  line-height: 1.4;
  white-space: nowrap;
}

.zw-badge-success {
  border-color: var(--zw-success-border);
  background-color: var(--zw-success-bg);
  color: var(--zw-accent-hover);
}

.zw-badge-danger {
  border-color: var(--zw-danger-border);
  background-color: var(--zw-danger-bg);
  color: var(--zw-danger);
}

/* Variante neutral: no es ni éxito ni error, solo informativa (ej. origen Sistema de un
   recordatorio, UIREM-009). */
.zw-badge-info {
  border-color: var(--zw-info-border);
  background-color: var(--zw-info-bg);
  color: var(--zw-info);
}

/* Prioridad Media de un ticket (UIPROJ-001) — Alta reusa zw-badge-danger, Baja reusa zw-badge-success. */
.zw-badge-warning {
  border-color: var(--zw-warning-border);
  background-color: var(--zw-warning-bg);
  color: var(--zw-warning);
}

/* Reorden por drag & drop de una lista de cards (columnas del tablero en Projects/{id}/Settings,
   KANBAN-004, y estados de una plantilla/alta manual de proyecto): drag & drop nativo por manija,
   nunca sobre la card entera, porque la card tiene inputs (checkbox, radio, WIP limit) que
   necesitan poder clickearse sin iniciar un arrastre. Usado por Settings.cshtml,
   Templates.cshtml y Create.cshtml. */
.zw-column-reorder-handle {
  cursor: grab;
  color: var(--zw-text-muted);
  display: flex;
  align-items: center;
}

.zw-column-reorder-item--dragging {
  opacity: 0.5;
}

.zw-column-reorder-item--drag-over {
  outline: 2px dashed var(--zw-accent);
  outline-offset: -2px;
  border-radius: var(--bs-border-radius-sm);
}

/* ============================================================================
   10. BLOQUES MONOESPACIADOS Y QR
   ============================================================================ */

/* Texto que el usuario tiene que leer carácter por carácter o copiar tal cual: la clave manual del
   TOTP, los recovery codes, el Request ID de la página de error. Monoespaciado para que 0/O y 1/l se
   distingan, y white-space: pre-wrap para respetar los saltos de línea de una lista de códigos. */
.zw-key {
  margin: 0;
  padding: 0.75rem 0.875rem;
  overflow-x: auto;
  border: 1px solid var(--zw-border);
  border-radius: var(--bs-border-radius);
  background-color: var(--zw-elevated);
  color: var(--zw-accent-hover);
  font-family: var(--bs-font-monospace);
  font-size: 0.8125rem;
  line-height: 1.7;
  white-space: pre-wrap;
  word-break: break-all;
}

/* El QR se genera en negro sobre transparente: sobre el fondo del tema queda negro sobre negro y no
   lo lee ninguna cámara. Es el único blanco de la aplicación, y es funcional. */
.zw-qr {
  display: inline-block;
  padding: 0.75rem;
  border-radius: var(--bs-border-radius);
  background-color: #ffffff;
}

.zw-qr img {
  display: block;
  width: 220px;
  max-width: 100%;
  height: auto;
}

/* ============================================================================
   11. LISTAS DE DETALLE
   ============================================================================
   Pares etiqueta/valor (el estado de la conexión con Drive). El <dl class="row"> de Bootstrap deja
   ambos lados con el mismo peso y hay que leer cuál es cuál. */

.zw-detail-list {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.5rem 1.25rem;
  margin: 0;
}

.zw-detail-list dt {
  margin: 0;
  color: var(--zw-text-muted);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  line-height: 1.6;
  text-transform: uppercase;
}

.zw-detail-list dd {
  margin: 0;
  font-size: 0.8125rem;
  line-height: 1.6;
}

/* En teléfono la columna "auto" de la etiqueta se lleva media pantalla y al valor —una cuenta de
   Google, que es largo— le queda un canal angosto donde parte cada dos palabras. Apilado se lee
   mejor, con la etiqueta arriba en tono secundario (UI-004). */
@media (max-width: 575.98px) {
  .zw-detail-list {
    grid-template-columns: 1fr;
    gap: 0.125rem;
  }

  .zw-detail-list dd + dt {
    margin-top: 0.75rem;
  }
}

/* ============================================================================
   12. SHELL DE LAS PANTALLAS DE SESIÓN
   ============================================================================
   Login, activación, recuperación de contraseña y 2FA del login. Lo usa _AuthLayout.cshtml.

   Estas páginas no tienen sidebar (no hay a dónde navegar sin sesión), así que el contenido quedaba
   suelto en la esquina superior izquierda de una pantalla vacía. */

.zw-auth {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* El alto disponible es la ventana menos el topbar (56px), su padding y el del contenido; con
     min-height la card queda centrada en pantallas altas y el bloque crece si el formulario es más
     largo que el viewport. */
  min-height: calc(100vh - 12rem);
  /* dvh es el alto real de la ventana, descontando la barra de URL del navegador móvil; con 100vh
     el bloque se reserva el alto de la ventana SIN esa barra y aparece scroll en una pantalla que
     entraba. La declaración anterior queda como fallback para navegadores sin dvh (UI-004). */
  min-height: calc(100dvh - 12rem);
  padding: 1rem 0;
}

.zw-auth-card {
  width: 100%;
  max-width: 420px;
  padding: 1.75rem;
  border: 1px solid var(--zw-border);
  border-radius: var(--bs-border-radius-lg);
  background-color: var(--zw-surface);
}

/* A 320px el padding de la card más el del contenido dejan el campo en 240px (UI-004). */
@media (max-width: 575.98px) {
  .zw-auth-card {
    padding: 1.25rem;
  }
}

.zw-auth-brand {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  margin-bottom: 1.5rem;
  color: var(--zw-text);
  font-size: 1.0625rem;
  font-weight: 600;
}

.zw-auth-brand .zw-icon {
  width: 1.375rem;
  height: 1.375rem;
  color: var(--zw-accent);
}

.zw-auth-title {
  margin: 0 0 1.25rem;
  font-size: 1.0625rem;
  font-weight: 600;
  text-align: center;
}

/* Texto explicativo entre el título y el formulario (las instrucciones del código 2FA). */
.zw-auth-intro {
  margin: -0.75rem 0 1.25rem;
  color: var(--zw-text-muted);
  font-size: 0.8125rem;
  line-height: 1.5;
  text-align: center;
}

/* Links de pie de la card (recuperar contraseña, volver al login). */
.zw-auth-footer {
  margin: 1.25rem 0 0;
  font-size: 0.8125rem;
  text-align: center;
}

/* ============================================================================
   13. ÁREA TÁCTIL EN PANTALLAS CHICAS Y MEDIANAS
   ============================================================================
   Por debajo de 768px site.css baja el root a 14px, y como todo el dimensionado de Bootstrap es
   relativo, los controles se achican con él: un .btn-sm queda en 26px de alto y un .form-control en
   31px. Con el mouse eso es densidad; con el dedo es fallar el objetivo. Los 44px son el mínimo
   recomendado por las guías de iOS y Android y el criterio 2.5.5 de WCAG.

   El problema no desaparece a partir de 768px: ahí el root sube a 16px, pero con los valores por
   defecto de Bootstrap 5.3 (sin overrides de tamaño en theme.css, solo de color) un .form-control
   mide `calc(1.5em + 0.75rem + border*2)` = 38px y un .btn 38px — los dos siguen bajo el mínimo. Y
   el ancho de pantalla hasta 991.98px sigue siendo táctil: es el mismo rango en el que el sidebar es
   el offcanvas deslizante (.zw-nav-link y .zw-icon-button en layout.css, con el mismo límite de
   991.98px). Recién en 992px, cuando el sidebar deja de ser offcanvas, el dispositivo es
   mayoritariamente de mouse.

   Se ajusta el alto y no la tipografía: agrandar la letra reflotaría todas las tablas.

   El equivalente para Select2 vive en theme.css §5, junto a la definición del alto base del control:
   son el mismo ajuste y separarlos dejaría dos lugares donde tocar lo mismo. */

@media (max-width: 991.98px) {
  /* inline-flex además del min-height: .btn es inline-block y con un alto mínimo mayor al natural
     el texto se apoyaría arriba en vez de quedar centrado. */
  .btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
  }

  .form-control,
  .form-select {
    min-height: 44px;
  }

  /* El casillero de Bootstrap mide 1em: crece con el root (14px o 16px según el rango). El margen
     compensa el alto extra para que siga alineado con la primera línea de su etiqueta. */
  .form-check-input {
    width: 1.25em;
    height: 1.25em;
    margin-top: 0.15em;
  }

  .form-check {
    padding-left: 1.85em;
  }

  .form-check .form-check-input {
    margin-left: -1.85em;
  }
}

/* ============================================================================
   14. ÁRBOL DE CARPETAS (VAULT Y WIKI)
   ============================================================================
   Barra lateral de Vault/Items/Index y Wiki/Pages/Index (dentro de un .card, como el resto de los
   paneles de la app), y tabla de Vault/Folders y Wiki/Folders (ORG-009, ORGWIKI-003). Reusa
   .zw-nav-link tal cual para el link de cada nodo — el
   único agregado es la sangría por profundidad, que no puede ser una clase fija porque el árbol
   admite subcarpetas de cualquier nivel: cada <li> declara su propio --zw-folder-depth inline (no
   el <a>, porque también lo necesita la guía de más abajo) y las reglas de acá lo traducen a
   indentación y a la posición de las líneas. Sin ícono de expandir/colapsar ni JS: un vault
   personal no tiene volumen para justificarlo (mismo criterio "no realtime" del proyecto); por la
   misma razón no hay chevrons acá — insinuarían una interacción que no existe. */

.zw-folder-tree-list {
  position: relative;
  list-style: none;
  margin: 0.125rem 0 0;
  padding: 0;
}

/* min(…, 8) capa la profundidad visual: no hay límite de anidamiento en el dominio
   (VaultFolderService/WikiFolderTree no lo validan), y sin tope la sangría por sí sola puede
   agotar el ancho de la card de col-lg-3 que contiene el árbol. Los tres usos de
   --zw-folder-depth en esta sección comparten el mismo cap para que el tronco y la rama sigan
   alineados con el ícono del nodo más allá del nivel 8. */
.zw-folder-tree .zw-nav-link {
  padding-left: calc(0.625rem + min(var(--zw-folder-depth, 0), 8) * 1rem);
}

/* Nombre de la carpeta: recorta con puntos suspensivos en vez de desbordar la card, mismo patrón
   que .zw-user-name (layout.css). Al ser hijo de un flex container, overflow: hidden ya le da
   minimum-size 0 y le permite achicarse sin necesitar min-width: 0 explícito. */
.zw-folder-tree-label {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* Fila "Todas las carpetas": es la raíz del árbol, no una carpeta más. El borde inferior la separa
   del resto de la lista para que se lea como encabezado del panel. */
.zw-folder-tree-root {
  margin-bottom: 0.375rem;
  padding-bottom: 0.625rem;
  border-bottom: 1px solid var(--zw-border);
  font-weight: 600;
}

/* Tronco vertical de cada grupo de subcarpetas: un pseudo-elemento absoluto sobre la propia lista
   (no un border-left, que movería la caja y duplicaría la sangría que ya pone .zw-nav-link arriba).
   Se ancla a la altura del ícono de la carpeta padre — 0.625rem de padding base + medio ícono
   (0.5rem, el ícono mide 1rem) — leyendo el --zw-folder-depth heredado del <li> que contiene la
   lista. */
.zw-folder-tree li > .zw-folder-tree-list::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(1.125rem + min(var(--zw-folder-depth, 0), 8) * 1rem);
  width: 1px;
  background-color: var(--zw-border-md);
}

/* Rama horizontal: conecta el tronco del padre con el ícono de cada subcarpeta. Mismo cálculo que
   el tronco pero leyendo el --zw-folder-depth del propio <li> (un nivel más profundo), así que el
   tramo mide siempre 1rem sin importar la profundidad. */
.zw-folder-tree li > .zw-folder-tree-list > li {
  position: relative;
}

.zw-folder-tree li > .zw-folder-tree-list > li::before {
  content: "";
  position: absolute;
  top: 1.125rem;
  left: calc(0.125rem + min(var(--zw-folder-depth, 0), 8) * 1rem);
  width: 1rem;
  height: 1px;
  background-color: var(--zw-border-md);
}

.zw-folder-tree-cell {
  display: inline-block;
  padding-left: calc(var(--zw-folder-depth, 0) * 1.25rem);
}

/* ============================================================================
   15. TABS DE CONFIGURACIÓN DE CUENTA
   ============================================================================
   _AccountSettingsNav.cshtml: Profile, NotificationChannels y ConnectDrive comparten este
   selector para verse como una sola pantalla con tabs, aunque cada una siga siendo una página y una
   ruta separadas. El .nav-tabs de Bootstrap ya sale con la paleta correcta por el remapeo de
   theme.css, pero el tab activo quedaba distinguido solo por fondo/borde, casi invisible sobre
   fondo oscuro: acá se lo marca además con un borde inferior del acento, mismo lenguaje que el
   ítem activo del sidebar (.zw-nav-link.active). */

.zw-tabs {
  margin-bottom: 1.25rem;
  border-bottom-color: var(--zw-border);
}

.zw-tabs .nav-link {
  color: var(--zw-text-muted);
  border: none;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  padding-inline: 0.25rem;
  margin-inline-end: 1.25rem;
}

.zw-tabs .nav-link:hover {
  color: var(--zw-text);
  border-bottom-color: var(--zw-border-lg);
}

/* ============================================================================
   16. FILTRO (POPOVER)
   ============================================================================
   Reemplaza la card de filtros que antes quedaba siempre visible arriba de cada listado. El único
   nodo del panel (FilterPopoverTagHelper) se relocaliza entre dos modos vía filter-popover.js: en
   desktop es el menú de un Dropdown de Bootstrap (ancla al trigger, Popper resuelve la posición y el
   flip si se saldría de la pantalla), en mobile pasa a ser un Offcanvas inferior. Por eso .zw-filter-
   panel no fija su propio color: ya lo hereda de .dropdown-menu (theme.css §3) en el primer modo y de
   .offcanvas (idem) en el segundo. */

.zw-filter-popover {
  position: relative;
  display: inline-block;
}

.zw-filter-trigger {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
}

/* Contador circular, distinto de .zw-badge (§9): aquella es una pastilla de estado, esto es un
   número. [hidden] y no d-none: así un solo atributo nativo alcanza para "sin filtros → sin badge". */
.zw-filter-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.125rem;
  height: 1.125rem;
  padding: 0 0.3125rem;
  border-radius: 999px;
  background-color: var(--zw-accent);
  color: var(--zw-on-accent);
  font-size: 0.6875rem;
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.zw-filter-count[hidden] {
  display: none;
}

.zw-filter-panel {
  padding: 1rem;
  /* visible y no el overflow:auto que trae .dropdown-menu por defecto: el filtro de tags (Select2)
     vive adentro y pinta su propia lista como hijo del panel (dropdownParent), que quedaría recortada
     si el panel clipeara su contenido. */
  overflow: visible;
}

/* Ancho acotado solo en modo dropdown: en modo offcanvas (mobile) el ancho lo define el propio
   offcanvas-bottom, que ya es 100% del viewport. */
.zw-filter-panel.dropdown-menu {
  min-width: 280px;
  max-width: min(360px, 90vw);
}

.zw-filter-panel.offcanvas-bottom {
  --bs-offcanvas-height: 60vh;
  padding-bottom: max(1rem, env(safe-area-inset-bottom));
}

.zw-filter-panel-header {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.75rem;
}

/* El botón de cerrar es mobile-only (d-lg-none en el markup) pero la regla vale para los dos modos:
   con título, lo empuja a la derecha; sin título, es el único hijo y esto no cambia nada. */
.zw-filter-panel-header .btn-close {
  margin-inline-start: auto;
}

.zw-filter-panel-footer {
  margin-top: 0.75rem;
}

.zw-tabs .nav-link.active {
  color: var(--zw-text);
  background-color: transparent;
  border-bottom-color: var(--zw-accent);
}

/* Mismo mínimo táctil y mismo rango que el resto de los controles interactivos (§13): un link de
   tab angosto es tan fácil de fallar con el dedo como un botón chico, y el rango táctil real llega
   hasta 991.98px —donde el sidebar deja de ser offcanvas—, no hasta 767.98px. */
@media (max-width: 991.98px) {
  .zw-tabs .nav-link {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
}

/* ============================================================================
   17. EDITOR DE MARKDOWN (PESTAÑAS)
   ============================================================================
   _MarkdownEditor.cshtml: un solo panel visible a la vez —"Editar" (textarea) o "Vista previa"
   (render)—, alternados con pestañas al estilo GitHub y sin split-view: dos columnas compitiendo
   por ancho es lo que causaba que una creciera a costa de la otra con contenido largo sin
   espacios. El textarea usa la monoespaciada de Bootstrap (igual que .zw-key) porque es texto que
   se edita carácter por carácter. El panel de preview queda con el mismo borde/superficie que
   .zw-table-wrap (§4) para leerse como "el mismo tipo de contenedor" que el resto de la app. Las
   pestañas son el componente `nav nav-tabs` de Bootstrap tal cual, ya temado por theme.css. */

.zw-md-editor {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

/* Modo lectura (VERSIONS-002): oculta el panel de código fuente entero (label + textarea) y deja
   el preview a ancho completo. El textarea sigue en el DOM —solo oculto— porque es de ahí que
   markdown-editor.js toma el contenido para el render inicial. */
.zw-md-editor--readonly .zw-md-editor-pane:not(.zw-md-editor-pane--preview) {
  display: none;
}

.zw-md-editor-pane {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.zw-md-editor-textarea {
  min-height: 60vh;
  resize: vertical;
  font-family: var(--bs-font-monospace);
  font-size: 0.8125rem;
}

.zw-md-editor-preview-body {
  min-height: 60vh;
  overflow-y: auto;
  padding: 1rem;
  border: 1px solid var(--zw-border);
  border-radius: var(--bs-border-radius);
  background-color: var(--zw-surface);
}

/* Tipografía del contenido renderizado: markdown-it emite HTML crudo (h1-h6, code, pre,
   blockquote, table, a) que no pasa por ninguna clase zw-*, así que hay que alinearlo a los
   tokens acá para que no se vea con los defaults de Bootstrap. */
.zw-md-editor-preview-body h1,
.zw-md-editor-preview-body h2,
.zw-md-editor-preview-body h3,
.zw-md-editor-preview-body h4,
.zw-md-editor-preview-body h5,
.zw-md-editor-preview-body h6 {
  color: var(--zw-text);
  font-weight: 600;
}

.zw-md-editor-preview-body a {
  color: var(--zw-accent);
}

/* Link roto (LINKS-003): el título no matchea ninguna WikiPage. Sigue siendo clickeable — navega
   a Wiki/Pages/Create con el título precargado — así que el estilo solo tiene que diferenciarlo,
   no deshabilitarlo. */
.zw-md-editor-preview-body a.zw-wiki-link--broken {
  color: var(--zw-danger);
  text-decoration-style: dashed;
}

.zw-md-editor-preview-body code {
  background-color: var(--zw-elevated);
  border: 1px solid var(--zw-border);
  border-radius: var(--bs-border-radius-sm);
  padding: 0.125em 0.375em;
  font-size: 0.875em;
}

.zw-md-editor-preview-body pre {
  background-color: var(--zw-elevated);
  border: 1px solid var(--zw-border);
  border-radius: var(--bs-border-radius);
  padding: 0.75rem;
  overflow-x: auto;
}

.zw-md-editor-preview-body pre code {
  background-color: transparent;
  border: none;
  padding: 0;
}

.zw-md-editor-preview-body blockquote {
  border-left: 3px solid var(--zw-border-lg);
  margin-inline-start: 0;
  padding-inline-start: 1rem;
  color: var(--zw-text-muted);
}

.zw-md-editor-preview-body table {
  display: block;
  width: max-content;
  max-width: 100%;
  overflow-x: auto;
  border-color: var(--zw-border);
}

.zw-md-editor-preview-body th,
.zw-md-editor-preview-body td {
  border: 1px solid var(--zw-border);
  padding: 0.375rem 0.5rem;
}

/* Iframe de ejecución de una herramienta de Zero.Tools (SECURITY-004): ocupa el ancho disponible
   y una altura generosa fija, ya que el contenido de la herramienta define su propio scroll
   interno. Usado por _ToolExecutionFrame.cshtml, consumido desde Tools/{slug} (SECURITY-005) y
   Tools/{slug}/preview/{version} (VERSION-002). */
.zw-tool-frame {
  width: 100%;
  min-height: 70vh;
  border: 0;
  border-radius: var(--bs-border-radius);
}

/* Ajustes específicos de la aplicación. La paleta y el tema oscuro viven en theme.css (UI-001) y
   la estructura del shell en layout.css (UI-002); ambos se cargan antes que este archivo. */

html {
  font-size: 14px;
}

@media (min-width: 768px) {
  html {
    font-size: 16px;
  }
}

/* El "html position:relative + body margin-bottom:60px" del scaffold se quitó en UI-002: existía
   para sostener un footer en position:absolute, que ahora queda al pie por el flex del shell. */

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
  color: var(--bs-secondary-color);
  text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
  text-align: start;
}

/* Gráfico de distribución (DASH-003).
   Alto fijo en el contenedor y maintainAspectRatio:false en el chart: sin una altura de referencia,
   un canvas responsive dentro de una card crece en cada resize hasta desbordar la página. */
.zw-distribucion-canvas {
  position: relative;
  height: 280px;
}

@media (min-width: 768px) {
  .zw-distribucion-canvas {
    height: 320px;
  }
}

/* Los estilos de Select2 se mudaron a theme.css: eran mayormente color, y separarlos del tema
   dejaba dos lugares donde tocar lo mismo. */

/* Muestra de color de un estado de ticket (LIB-008). El color en sí es dato del usuario y se aplica
   inline vía background-color en el .cshtml, no acá: esta regla solo define la forma. */
.zw-state-swatch {
  display: inline-block;
  width: 0.875rem;
  height: 0.875rem;
  border-radius: var(--bs-border-radius-sm);
  border: 1px solid var(--zw-border-md);
  vertical-align: middle;
  margin-inline-end: 0.375rem;
}

/* Tablero de un proyecto (KANBAN-001). Sin precedente de layout en columnas en el resto de la app:
   fila con scroll horizontal (mismo mecanismo que .zw-table-wrap) de columnas de ancho fijo, cada
   una con su propio scroll vertical para no estirar el tablero entero por una columna larga. */
.zw-board {
  display: flex;
  gap: 1rem;
  overflow-x: auto;
  padding-bottom: 0.5rem;
}

.zw-board-column {
  flex: 0 0 auto;
  width: 18rem;
  background-color: var(--zw-surface);
  border: 1px solid var(--zw-border);
  border-radius: var(--bs-border-radius);
  padding: 0.75rem;
}

.zw-board-column-header {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.75rem;
}

.zw-board-column-header .zw-panel-title {
  flex: 1 1 auto;
}

.zw-board-column-body {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  max-height: 32rem;
  overflow-y: auto;
}

.zw-board-card {
  background-color: var(--zw-elevated);
  position: relative;
}

/* Deja lugar a .zw-board-card-details y .zw-board-card-edit en la esquina para que el título no
   pase por debajo. */
.zw-board-card .card-body {
  padding-right: 4rem;
}

/* Afordance de detalle (COMMENT-003) y edición (TICKET-009) de un ticket: dos links en la esquina
   de la card, no la card entera envuelta en <a>, para no interferir con el dragstart nativo de
   .zw-board-card[draggable]. */
.zw-board-card-edit,
.zw-board-card-details {
  position: absolute;
  top: 0.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: var(--bs-border-radius-sm);
  color: var(--zw-text-muted);
}

.zw-board-card-edit {
  right: 0.5rem;
}

.zw-board-card-details {
  right: 2.25rem;
}

.zw-board-card-edit:hover,
.zw-board-card-edit:focus-visible,
.zw-board-card-details:hover,
.zw-board-card-details:focus-visible {
  color: var(--zw-text);
  background-color: var(--zw-hover);
}

/* Drag & drop de tickets (KANBAN-002), API nativa de HTML5. */
.zw-board-card[draggable="true"] {
  cursor: grab;
}

.zw-board-card--dragging {
  opacity: 0.5;
}

.zw-board-column-body--drop-target {
  outline: 2px dashed var(--zw-accent);
  outline-offset: -2px;
  border-radius: var(--bs-border-radius-sm);
}

/* Selector de ícono de tipo de ticket (LIB-006): grilla de botones en vez de <select> para que el
   ícono elegido se vea. Mismo tamaño/mínimo táctil que .zw-icon-button (layout.css), pero vive acá
   porque es específico de esta pantalla y necesita un estado "elegido" que .zw-icon-button no
   tiene. */
.zw-icon-picker {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
}

.zw-icon-picker-option {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 1px solid var(--zw-border);
  border-radius: var(--bs-border-radius);
  background-color: var(--zw-surface);
  color: var(--zw-text-muted);
}

.zw-icon-picker-option:hover {
  background-color: var(--zw-hover);
  color: var(--zw-text);
  border-color: var(--zw-border-md);
}

/* El estado elegido se engancha directo a aria-pressed, no a una clase aparte, para que estado
   ARIA y estilo no puedan desincronizarse. */
.zw-icon-picker-option[aria-pressed="true"] {
  background-color: var(--zw-accent-bg);
  border-color: var(--zw-accent-border);
  color: var(--zw-accent);
}

@media (max-width: 767.98px) {
  .zw-icon-picker-option {
    width: 44px;
    height: 44px;
  }
}

/* Previsualización de un comprobante imagen en la bandeja "Sin clasificar" (UIREC-004). */
.zw-receipt-preview-image {
  display: block;
  max-width: 100%;
  max-height: 480px;
  border-radius: var(--bs-border-radius);
  border: 1px solid var(--zw-border);
  background-color: var(--zw-elevated);
  object-fit: contain;
}

/* Previsualización de un comprobante PDF en la bandeja "Sin clasificar" (UIREC-005). */
.zw-receipt-preview-pdf {
  display: block;
  width: 100%;
  height: 600px;
  border-radius: var(--bs-border-radius);
  border: 1px solid var(--zw-border);
  background-color: var(--zw-elevated);
}
