/* ============================================================================
   CLAYMORPHISM — FacturaO
   Capa de rediseño visual. Se carga DESPUÉS de base/tailwind/dashboard/modules,
   por lo que sobrescribe sin tocar esos archivos. Revertir = quitar el <link>.

   Estructura:
     1. Tokens (paleta clay + radios + sombras) — tema claro y oscuro
     2. Scrollbar
     3. Primitivas (botones, paneles, KPIs, tabs, inputs, badges, tablas)
     4. Chrome (sidebar, topbar)
     5. Paleta de acentos (categorías/datos)

   Intensidad MEDIDA: arcilla plena en cards/KPIs/botones/nav; contenida en
   tablas e inputs. El morado de marca se conserva.
   ============================================================================ */

/* ============ 1. TOKENS — TEMA CLARO ============ */
:root {
  /* Suelo lavanda-gris de tono medio (que el relieve se lea) + superficies */
  --color-background: #e4deef;
  --color-surface: #f4f1fc;
  --color-surface-container-lowest: #f7f4fd;
  --color-surface-container-low: #efeaf8;
  --color-surface-container: #ebe5f4;
  --color-surface-container-high: #e6e0f1;
  --color-surface-container-highest: #e0d9ec;
  --color-surface-bright: #f8f5fd;
  --color-surface-dim: #d8d1e6;

  /* Radios generosos y graduados */
  --radius-sm: 12px;
  --radius-md: 16px;
  --radius-lg: 22px;
  --radius-xl: 28px;

  /* Ingredientes de sombra (tintados, nunca negros) */
  --clay-dark: 183,173,204;
  --clay-light: 255,255,255;
  --clay-hi-a: .75;
  --clay-sh-a: .5;

  /* ─── SISTEMA DE TALLAS DE INPUT (por tipo de contenido) ───
     Un solo sitio para todas las anchuras de campo. "texto" y "texto-lg"
     son TOPES: crecen hasta ahí y no más. */
  --clay-w-cod:     5.5rem;   /* código / nº corto (3-5 dígitos) */
  --clay-w-num:     7.5rem;   /* número (importes, cantidades, %) */
  --clay-w-date:    10.5rem;  /* fecha */
  --clay-w-select:  13rem;    /* desplegable */
  --clay-w-text:    22rem;    /* texto normal (nombre, población…) — TOPE */
  --clay-w-text-lg: 36rem;    /* texto largo (domicilio, email…) — TOPE */

  /* Escala de radios clay (uso directo) */
  --clay-r-sm: 14px;
  --clay-r-md: 20px;
  --clay-r-lg: 26px;
  --clay-r-xl: 34px;
  --clay-r-pill: 999px;

  /* Sombras clay */
  --clay-raised:
     6px 6px 14px rgba(var(--clay-dark), var(--clay-sh-a)),
    -6px -6px 11px rgba(var(--clay-light), var(--clay-hi-a));
  --clay-raised-sm:
     3px 3px 8px rgba(var(--clay-dark), var(--clay-sh-a)),
    -3px -3px 7px rgba(var(--clay-light), var(--clay-hi-a));
  --clay-raised-hover:
     9px 9px 19px rgba(var(--clay-dark), var(--clay-sh-a)),
    -8px -8px 15px rgba(var(--clay-light), var(--clay-hi-a));
  --clay-inset:
    inset 3px 3px 7px rgba(var(--clay-dark), var(--clay-sh-a)),
    inset -3px -3px 7px rgba(var(--clay-light), var(--clay-hi-a));
  --clay-flat:
     2px 2px 6px rgba(var(--clay-dark), var(--clay-sh-a)),
    -2px -2px 5px rgba(var(--clay-light), var(--clay-hi-a));
  --clay-primary-glow:
     5px 5px 13px rgba(130,49,167,.30),
    -5px -5px 10px rgba(var(--clay-light), .5);

  /* Tokens de sombra que la app ya referencia (estaban indefinidos → planos) */
  --shadow-1: var(--clay-raised);
  --shadow-2: var(--clay-raised-hover);

  --clay-line: rgba(130,49,167,.12);

  /* Acentos (ver bloque 5) */
  --c-amber:#d98a12; --c-amber-bg:rgba(217,138,18,.15);
  --c-green:#2e9e5b; --c-green-bg:rgba(46,158,91,.15);
  --c-blue:#3f6fe3;  --c-blue-bg:rgba(63,111,227,.15);
  --c-teal:#12968a;  --c-teal-bg:rgba(18,150,138,.15);
  --c-pink:#d54a8c;  --c-pink-bg:rgba(213,74,140,.15);

  /* Blobs decorativos del fondo (formas suaves tras las tarjetas) */
  --clay-blob-a: rgba(130,49,167,.16);
  --clay-blob-b: rgba(18,150,138,.13);
  --clay-blob-c: rgba(213,74,140,.13);
  --clay-blob-d: rgba(217,138,18,.10);
}

/* ============ TOKENS — TEMA OSCURO ============ */
/* La app fija data-theme="dark" en <html> (app/functions.php). Definimos aquí
   una paleta oscura completa (antes estaba incompleta). */
:root[data-theme="dark"] {
  --color-background: #1b1826;
  --color-surface: #241f31;
  --color-surface-container-lowest: #201c2c;
  --color-surface-container-low: #232030;
  --color-surface-container: #2a2439;
  --color-surface-container-high: #2f2840;
  --color-surface-container-highest: #362e49;
  --color-surface-bright: #2c2640;
  --color-surface-dim: #16131f;

  --color-on-surface: #ece8f6;
  --color-on-surface-variant: #b6adca;
  --color-on-background: #ece8f6;
  --color-outline: #8f86a6;
  --color-outline-variant: #3c3552;

  --color-primary: #b46fd6;
  --color-primary-container: #9d4ec4;
  --color-on-primary: #ffffff;
  --color-on-primary-fixed-variant: #eab2ff;
  --color-primary-fixed-dim: #6a4780;

  --clay-dark: 9,7,14;
  --clay-light: 255,255,255;
  --clay-hi-a: .05;
  --clay-sh-a: .55;
  --clay-primary-glow:
     5px 5px 14px rgba(0,0,0,.5),
    -5px -5px 11px rgba(var(--clay-light), .05);
  --clay-line: rgba(234,178,255,.14);

  --clay-blob-a: rgba(180,111,214,.17);
  --clay-blob-b: rgba(18,150,138,.13);
  --clay-blob-c: rgba(213,74,140,.12);
  --clay-blob-d: rgba(217,138,18,.09);
}

/* Fallback por preferencia del SO cuando el usuario no ha elegido tema */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --color-background: #1b1826;
    --color-surface: #241f31;
    --color-surface-container-lowest: #201c2c;
    --color-surface-container-low: #232030;
    --color-surface-container: #2a2439;
    --color-surface-container-high: #2f2840;
    --color-surface-container-highest: #362e49;
    --color-on-surface: #ece8f6;
    --color-on-surface-variant: #b6adca;
    --color-outline: #8f86a6;
    --color-outline-variant: #3c3552;
    --color-primary: #b46fd6;
    --color-primary-container: #9d4ec4;
    --clay-dark: 9,7,14; --clay-light: 255,255,255; --clay-hi-a: .05; --clay-sh-a: .55;
    --clay-primary-glow: 5px 5px 14px rgba(0,0,0,.5), -5px -5px 11px rgba(var(--clay-light), .05);
    --clay-line: rgba(234,178,255,.14);
    --clay-blob-a: rgba(180,111,214,.17);
    --clay-blob-b: rgba(18,150,138,.13);
    --clay-blob-c: rgba(213,74,140,.12);
    --clay-blob-d: rgba(217,138,18,.09);
  }
}

/* Sin anclaje de scroll en el lienzo: al recargar, el navegador restauraba el
   scroll y el anclaje compensaba el crecimiento tardío del contenido
   (textareas auto-alto, fuentes…) sumando desplazamiento — la página
   aparecía cada vez más abajo con cada recarga. */
.dash-canvas { overflow-anchor: none; }

/* El lienzo usa el SUELO (más oscuro) para que las superficies elevadas resalten,
   con blobs radiales suaves para que el fondo no sea un color plano. */
body,
.dash-canvas {
  background:
    radial-gradient(52rem 44rem at 8% -10%, var(--clay-blob-a), transparent 60%),
    radial-gradient(40rem 36rem at 104% 15%, var(--clay-blob-b), transparent 62%),
    radial-gradient(44rem 40rem at 60% 115%, var(--clay-blob-c), transparent 60%),
    radial-gradient(26rem 26rem at 88% 78%, var(--clay-blob-d), transparent 65%),
    radial-gradient(20rem 20rem at 35% 45%, var(--clay-blob-a), transparent 70%),
    radial-gradient(16rem 16rem at -4% 70%, var(--clay-blob-b), transparent 68%),
    var(--color-background);
}

/* ============ 2. SCROLLBAR CLAYMORPHISM ============ */
* { scrollbar-width: thin; scrollbar-color: var(--color-primary) transparent; }
::-webkit-scrollbar { width: 12px; height: 12px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  border-radius: var(--clay-r-pill);
  border: 3px solid var(--color-background);
  background: linear-gradient(145deg, var(--color-primary-container), var(--color-primary));
  box-shadow: var(--clay-raised-sm);
}
::-webkit-scrollbar-thumb:hover { filter: brightness(1.08); }
::-webkit-scrollbar-corner { background: transparent; }

/* ============ 3. PRIMITIVAS ============ */

/* Botones */
.btn-primary {
  border-radius: var(--clay-r-md);
  background: linear-gradient(145deg, var(--color-primary-container), var(--color-primary));
  box-shadow: var(--clay-primary-glow);
  transition: box-shadow .15s ease, transform .1s ease, filter .15s ease;
}
.btn-primary:hover { transform: translateY(-1px); opacity: 1; filter: brightness(1.07); box-shadow: var(--clay-raised-hover); }
.btn-primary:active { transform: translateY(1px); box-shadow: var(--clay-inset); }

/* Emitir factura: mismo acabado de arcilla pero en azul, para que no se confunda con
   Guardar (morado) ni con Anular (rojo). Antes iba en rojo por un style en línea. */
.btn-primary.btn-emitir {
  background: linear-gradient(145deg,
    color-mix(in srgb, var(--c-blue) 62%, white),
    var(--c-blue));
  color: #fff;
  box-shadow:
     5px 5px 13px color-mix(in srgb, var(--c-blue) 34%, transparent),
    -5px -5px 10px rgba(var(--clay-light), .5);
}
.btn-primary.btn-emitir:hover { background: linear-gradient(145deg, color-mix(in srgb, var(--c-blue) 62%, white), var(--c-blue)); }

.btn-secondary {
  border-radius: var(--clay-r-md);
  background: var(--color-surface);
  color: var(--color-primary);
  box-shadow: var(--clay-raised-sm);
  transition: box-shadow .15s ease, transform .1s ease;
}
.btn-secondary:hover { transform: translateY(-1px); background: var(--color-surface); box-shadow: var(--clay-raised-hover); }
.btn-secondary:active { transform: translateY(1px); box-shadow: var(--clay-inset); }

.btn-sm { border-radius: var(--clay-r-sm); box-shadow: var(--clay-raised-sm); }
.btn-sm:active { box-shadow: var(--clay-inset); }

/* Paneles / cards — con un velo diagonal de marca que les da vida */
.pre-panel {
  border: none;
  border-radius: var(--clay-r-lg);
  background:
    linear-gradient(160deg, color-mix(in srgb, var(--color-primary) 5%, transparent), transparent 45%),
    var(--color-surface);
  box-shadow: var(--clay-raised);
}
/* El mismo velo en las tarjetas de pestaña de las fichas antiguas */
.cli-tab-panel:has(> .cli-form-grid) {
  background:
    linear-gradient(160deg, color-mix(in srgb, var(--color-primary) 5%, transparent), transparent 45%),
    var(--color-surface);
}

/* KPI cards del dashboard */
.dash-kpi-card { border-radius: var(--clay-r-lg); box-shadow: var(--clay-raised); border: none; }
.dash-kpi-card:hover { box-shadow: var(--clay-raised-hover); }
.dash-kpi-card--default {
  background:
    linear-gradient(160deg, color-mix(in srgb, var(--color-primary) 5%, transparent), transparent 45%),
    var(--color-surface);
  border: none;
  box-shadow: var(--clay-raised);
}
.dash-kpi-card--hero {
  background: linear-gradient(150deg, var(--color-primary-container), var(--color-primary));
  box-shadow: var(--clay-primary-glow);
}
.dash-kpi-card--hero, .dash-kpi-card--hero .dash-kpi-card__value,
.dash-kpi-card--hero .dash-kpi-card__label, .dash-kpi-card--hero .dash-kpi-card__delta,
.dash-kpi-card--hero .hi { color: var(--color-on-primary); }

.dash-table-container { border-radius: var(--clay-r-lg); background: var(--color-surface); box-shadow: var(--clay-raised); border: none; }

/* Tabs → canal hundido con píldoras (como el preview aprobado) */
.cli-tabs {
  display: inline-flex;
  border-bottom: none;
  gap: .3rem;
  padding: .35rem;
  border-radius: var(--clay-r-pill);
  background: var(--color-background);
  box-shadow: var(--clay-inset);
  max-width: 100%;
}
.cli-tab { border-bottom: none; border-radius: var(--clay-r-pill); padding: .55rem 1.1rem; color: var(--color-on-surface-variant); }
.cli-tab:hover { background: var(--color-surface); box-shadow: var(--clay-raised-sm); }
.cli-tab.active { border-bottom-color: transparent; color: var(--color-primary); background: var(--color-surface); box-shadow: var(--clay-raised-sm); }

/* Píldora deslizante (creada por base.js): el fondo de la activa se desliza */
.cli-tabs { position: relative; }
.cli-tab-pill {
  position: absolute;
  left: 0; top: 0;
  border-radius: var(--clay-r-pill);
  background: var(--color-surface);
  box-shadow: var(--clay-raised-sm);
  opacity: 0;
  pointer-events: none;
  transform-origin: center;
  transition:
    left .28s cubic-bezier(.25, 1.2, .35, 1),
    width .28s cubic-bezier(.25, 1.2, .35, 1),
    top .28s ease, height .28s ease,
    transform .18s ease, opacity .15s ease;
}
/* Amago en hover: la píldora se estira hacia la pestaña apuntada y se
   aplasta un pelín, "como que quiere ir"; respuesta rápida, sin rebote */
.cli-tab-pill.is-tease {
  transform: scaleY(.93);
  transition:
    left .18s ease, width .18s ease,
    top .18s ease, height .18s ease,
    transform .18s ease, opacity .15s ease;
}
.cli-tabs.has-pill .cli-tab { position: relative; z-index: 1; }
/* Con píldora, ni la activa ni el hover pintan fondo propio:
   el fondito deslizante ES el hover (sigue al cursor y vuelve a la activa) */
.cli-tabs.has-pill .cli-tab.active,
.cli-tabs.has-pill .cli-tab:hover {
  background: transparent;
  box-shadow: none;
}
.cli-tabs.has-pill .cli-tab:hover { color: var(--color-primary); }

/* Inputs → hueco hundido (arcilla contenida) */
.pre-input,
.pre-form-group input:not([type="checkbox"]):not([type="radio"]),
.pre-form-group select,
.pre-form-group textarea,
.pre-form-grid input:not([type="checkbox"]):not([type="radio"]),
.pre-form-grid select,
.pre-form-grid textarea,
.cli-dialog__content input:not([type="checkbox"]):not([type="radio"]),
.cli-dialog__content select,
.cli-dialog__content textarea {
  border: none;
  border-radius: var(--clay-r-sm);
  box-shadow: var(--clay-inset);
}
.pre-input:hover { border: none; }
.pre-input:focus,
.pre-form-group input:focus,
.pre-form-group select:focus,
.pre-form-group textarea:focus,
.pre-form-grid input:focus,
.pre-form-grid select:focus,
.pre-form-grid textarea:focus,
/* hover = misma animación de anillo que el focus (salvo readonly/disabled) */
.pre-input:hover:not([readonly]):not(:disabled),
.pre-form-group input:hover:not([readonly]):not(:disabled),
.pre-form-group select:hover:not(:disabled),
.pre-form-group textarea:hover:not([readonly]):not(:disabled),
.pre-form-grid input:hover:not([readonly]):not(:disabled),
.pre-form-grid select:hover:not(:disabled),
.pre-form-grid textarea:hover:not([readonly]):not(:disabled) {
  border: none;
  box-shadow: var(--clay-inset), 0 0 0 2px var(--color-primary);
}
/* Textarea que crece con el contenido, sin JS (fallback: atributo rows) */
.pre-form-group textarea, .pre-form-grid textarea, .cli-dialog__content textarea {
  field-sizing: content;
  min-height: 2.7rem;
  max-height: 12rem;
}

/* REFUERZO: la regla universal de modules.css (especificidad ~0,9,1) pisa mi
   border/border-radius, dejando los inputs con un borde de caja de 1px y radio
   8px. Con !important, TODOS los inputs (formulario Y líneas de detalle) quedan
   con el hueco de arcilla completo: sin borde, radio clay, mismo componente. */
.pre-input,
.pre-form-group input:not([type="checkbox"]):not([type="radio"]),
.pre-form-group select, .pre-form-group textarea,
.pre-form-grid input:not([type="checkbox"]):not([type="radio"]),
.pre-form-grid select, .pre-form-grid textarea,
.cli-form-group input:not([type="checkbox"]):not([type="radio"]),
.cli-form-group select, .cli-form-group textarea,
.cli-dialog__content input:not([type="checkbox"]):not([type="radio"]),
.cli-dialog__content select, .cli-dialog__content textarea {
  border: none !important;
  border-radius: var(--clay-r-sm) !important;
  background-color: var(--color-surface-container-lowest) !important;
}
/* Inputs de las líneas de detalle: radio algo menor por la densidad de la tabla
   (pre-lineas-tbody lo comparten presupuesto, pedido y albarán) */
#pre-lineas-tbody .pre-input,
#fac-lineas-tbody .pre-input {
  border-radius: 10px !important;
}
/* Descuentos de línea (D1/D2/D3%): eran demasiado estrechos (49px) y cortaban
   el "0.00". Se les da tamaño de número como Cantidad/Precio/Total. */
#pre-lineas-tbody .pre-input-dto, #pre-lineas-tbody .pre-input-dto2, #pre-lineas-tbody .pre-input-dto3,
#fac-lineas-tbody .pre-input-dto, #fac-lineas-tbody .pre-input-dto2, #fac-lineas-tbody .pre-input-dto3 {
  min-width: 4.5rem;
}

/* Referencia (cabecera): más estrecha para que quepan más campos en la fila
   (p. ej. Transportista en factura). */
.pre-form-group:has(> input[id^="field-REF"]) {
  flex: 0 1 12rem;
  max-width: 12rem;
}

/* Badges de estado → píldora con relieve suave + punto de color (preview) */
.badge-status {
  border-radius: var(--clay-r-pill);
  box-shadow: var(--clay-flat);
  font-weight: 700;
  padding: 0.3rem 0.75rem;
  gap: 0.35rem;
}
.badge-status::before {
  content: "";
  width: .45rem;
  height: .45rem;
  border-radius: 50%;
  background: currentColor;
  flex: 0 0 auto;
}

/* Iconos de KPI → chip de arcilla con degradado del color del icono */
.dash-kpi-card__icon {
  width: 44px;
  height: 44px;
  padding: 10px;
  opacity: 1;
  border-radius: var(--clay-r-sm);
  background: linear-gradient(145deg,
    color-mix(in srgb, currentColor 18%, var(--color-surface)),
    color-mix(in srgb, currentColor 6%, var(--color-surface)));
  box-shadow: var(--clay-flat);
}
.dash-kpi-card--hero .dash-kpi-card__icon {
  background: rgba(255,255,255,.18);
  box-shadow: inset 2px 2px 5px rgba(0,0,0,.15), inset -2px -2px 5px rgba(255,255,255,.15);
}

/* Icono de título de sección → chip de arcilla con degradado suave */
.pre-form-section-title > .hi {
  width: 38px;
  height: 38px;
  padding: 8px;
  flex: 0 0 auto;
  border-radius: 12px;
  color: var(--color-primary);
  background: linear-gradient(145deg,
    color-mix(in srgb, var(--color-primary) 18%, var(--color-surface)),
    color-mix(in srgb, var(--color-primary) 6%, var(--color-surface)));
  box-shadow: var(--clay-flat);
}

/* Tarjeta de totales → arcilla (preview) */
.pre-totales-grid {
  border: 1px solid color-mix(in srgb, var(--color-outline) 35%, transparent);
  border-radius: var(--clay-r-lg);
  background: var(--color-surface);
  box-shadow: var(--clay-raised);
}

/* TODOS los selects = MISMO componente: apariencia customizable (opciones con
   arcilla) + UNA sola flecha. `background-image:none` mata el triángulo que
   modules.css pinta en .cli-form-group/.cli-filters select (causaba 2 flechas).
   El :not(.no-bg) respeta los que se excluyen a propósito. */
select:not(.no-bg) {
  appearance: base-select;
  background-image: none !important;
  padding-right: 2.2rem;
  /* Texto largo (p. ej. "2026-A — Por defecto"): recorte con … en vez de salto de línea */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Con base-select lo que se pinta es <selectedcontent>: el recorte va ahí */
select:not(.no-bg) selectedcontent {
  display: block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
select:not(.no-bg)::picker-icon {
  color: var(--color-on-surface-variant);
  transition: transform .2s ease;
}
select:not(.no-bg):open::picker-icon {
  color: var(--color-primary);
  transform: rotate(180deg);
}

/* Popup de opciones con estilo claymorphism */
::picker(select) {
  appearance: base-select;
  border: none;
  background: var(--color-surface);
  box-shadow: var(--clay-raised);
  border-radius: var(--clay-r-md);
  padding: .35rem;
  margin-top: .4rem;
}
::picker(select) option {
  border-radius: var(--clay-r-sm);
  padding: .5rem .8rem;
  color: var(--color-on-surface);
  transition: background .12s ease;
  cursor: pointer;
}
::picker(select) option:hover,
::picker(select) option:focus {
  background: color-mix(in srgb, var(--color-primary) 12%, transparent);
  outline: none;
}
::picker(select) option:checked {
  color: var(--color-primary);
  font-weight: 700;
  background: color-mix(in srgb, var(--color-primary) 8%, transparent);
}
::picker(select) option::checkmark {
  color: var(--color-primary);
  order: 1;
  margin-left: auto;
}

/* ============ 4. CHROME (sidebar / topbar) ============ */
/* El velo morado (transparente a la izquierda, morado a la derecha) vive en el
   PANEL, no en todo el sidebar: el rail lleva su propio tinte para que la
   lengüeta del departamento abierto tenga con qué contrastar al pegarse.
   El velo arranca transparente justo en la junta, así que ahí el panel es
   exactamente --dash-panel-bg y la lengüeta funde sin costura.
   Base y velo van en la misma propiedad: el gradiente translúcido necesita algo
   debajo que teñir. */
.dash-sidebar {
  background: var(--color-surface-container-lowest);
  border-right: none;
  box-shadow: var(--clay-flat);
}
.dash-panel {
  background:
    linear-gradient(90deg,
      transparent 0%,
      color-mix(in srgb, var(--color-primary) 7%, transparent) 45%,
      color-mix(in srgb, var(--color-primary) 20%, transparent) 100%),
    var(--dash-panel-bg);
}
.dash-nav-link { border-radius: var(--clay-r-sm); }
.dash-nav-link:hover { background: var(--color-surface); box-shadow: var(--clay-raised-sm); }
.dash-nav-link.active {
  background: linear-gradient(145deg, var(--color-primary-container), var(--color-primary));
  color: var(--color-on-primary);
  border-right: none;
  box-shadow: var(--clay-primary-glow);
}
.dash-nav-link.active .hi { color: var(--color-on-primary); }

/* Rail de departamentos. El tinte morado suave lo separa del panel (más claro):
   ese contraste es lo que hace legible que la lengüeta activa se despega del
   rail y se pega al panel. */
:root {
  --dash-rail-bg: color-mix(in srgb, var(--color-primary) 9%, var(--color-surface-container-lowest));
}
.dash-rail { border-right: none; }
.dash-rail__btn:hover { background-color: color-mix(in srgb, var(--color-surface) 70%, transparent); }

/* Departamento abierto: la lengüeta es una prolongación del panel, así que NO
   lleva sombra de arcilla propia — una pieza pegada no proyecta sombra contra
   aquello a lo que está pegada. Solo el icono y el texto se tiñen de morado. */
body:not(.sidebar-collapsed) .dash-rail__btn.active {
  box-shadow: none;
  color: var(--color-primary);
}

/* Contraído no hay panel: el departamento de la página actual vuelve a ser una
   pastilla morada suelta */
/* El borde derecho transparente ya lo separa del borde; no hace falta margen */
body.sidebar-collapsed .dash-rail__btn.aqui {
  background-image: linear-gradient(145deg, var(--color-primary-container), var(--color-primary));
  color: var(--color-on-primary);
  box-shadow: var(--clay-primary-glow);
  border-radius: var(--clay-r-md);
}
.dash-panel { border-right: none; }
.dash-rail__flyout {
  border: none;
  border-radius: var(--clay-r-lg);
  background: var(--color-surface);
  box-shadow: var(--clay-raised);
}

.dash-topbar {
  background: color-mix(in srgb, var(--color-background) 82%, transparent);
  border-bottom: 1px solid var(--clay-line);
}
.dash-topbar__search input {
  border: none;
  border-radius: var(--clay-r-pill);
  background: var(--color-surface-container-lowest);
  box-shadow: var(--clay-inset);
}

/* ============ 5. ACENTOS (categorías / datos) ============ */
/* Disponibles como utilidades para iconos de tarjeta, avatares, etc. */
.clay-ic--amber { background: var(--c-amber-bg); color: var(--c-amber); }
.clay-ic--green { background: var(--c-green-bg); color: var(--c-green); }
.clay-ic--blue  { background: var(--c-blue-bg);  color: var(--c-blue); }
.clay-ic--teal  { background: var(--c-teal-bg);  color: var(--c-teal); }
.clay-ic--pink  { background: var(--c-pink-bg);  color: var(--c-pink); }

/* ============ 6. MODALES / DIÁLOGOS ============ */
.cli-dialog-overlay { background: rgba(20, 10, 32, .45); }
.cli-dialog {
  background: var(--color-surface);
  border-radius: var(--clay-r-xl);
  box-shadow: var(--clay-raised);
}
.cli-dialog__header { border-bottom: 1px solid var(--clay-line); }
.cli-dialog__icon { box-shadow: var(--clay-inset); }
.cli-dialog__btn-danger {
  border-radius: var(--clay-r-md);
  background: linear-gradient(145deg, #d64545, var(--color-error));
  box-shadow: 5px 5px 13px rgba(186,26,26,.30), -5px -5px 10px rgba(var(--clay-light), var(--clay-hi-a));
  transition: box-shadow .15s ease, transform .1s ease, filter .15s ease;
}
.cli-dialog__btn-danger:hover { transform: translateY(-1px); filter: brightness(1.06); background: linear-gradient(145deg, #d64545, var(--color-error)); box-shadow: 7px 7px 16px rgba(186,26,26,.36), -6px -6px 12px rgba(var(--clay-light), var(--clay-hi-a)); }
.cli-dialog__btn-danger:active { transform: translateY(1px); box-shadow: var(--clay-inset); }

/* ============ 7. TOPBAR (botones / perfil / avatar) ============ */
.dash-topbar__icon-btn {
  width: 42px; height: 42px; padding: 0; opacity: 1;
  border-radius: var(--clay-r-md);
  background: var(--color-surface);
  box-shadow: var(--clay-raised-sm);
  display: grid; place-items: center;
  transition: box-shadow .15s ease, transform .1s ease, color .15s ease;
}
.dash-topbar__icon-btn:hover { transform: translateY(-1px); color: var(--color-primary); box-shadow: var(--clay-raised); }
.dash-topbar__icon-btn:active { transform: translateY(1px); box-shadow: var(--clay-inset); }
.dash-topbar__profile {
  border-left: none;
  background: var(--color-surface);
  box-shadow: var(--clay-raised-sm);
  border-radius: var(--clay-r-pill);
  padding: .3rem .45rem .3rem 1rem;
  transition: box-shadow .2s ease, transform .2s ease;
}
/* Es un enlace a "Mi Perfil": se comporta como el resto de piezas de arcilla pulsables */
a.dash-topbar__profile { text-decoration: none; color: inherit; }
a.dash-topbar__profile:hover { transform: translateY(-1px); box-shadow: var(--clay-raised); }
a.dash-topbar__profile:active { transform: translateY(1px); box-shadow: var(--clay-inset); }
a.dash-topbar__profile.active { box-shadow: var(--clay-inset); }
a.dash-topbar__profile:hover .dash-topbar__profile-name { color: var(--color-primary); }
.dash-topbar__avatar {
  border: none;
  background: linear-gradient(145deg, var(--color-primary-container), var(--color-primary));
  box-shadow: var(--clay-primary-glow);
}

/* ============ 8. SIDEBAR (buscador / toggle) ============ */
/* Eclipse: un halo difuso que orbita despacio detrás del buscador.
   - `overflow:hidden` + el radio de píldora lo recortan a la forma del campo: al rotar, un
     rectángulo ancho barre un área del tamaño de su diagonal y el halo invadía el menú.
   - El pseudo es cuadrado (aspect-ratio 1) para que su caja no crezca al girar.
   - `isolation` mantiene el z-index:-1 dentro del buscador; si no, se colaría tras el sidebar.
   El input es semitransparente, así que el halo se translucе como una aurora bajo el cristal. */
.dash-sidebar__search {
  isolation: isolate;
  overflow: hidden;
  border-radius: var(--clay-r-pill);
}

.dash-sidebar__search::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 118%;
  aspect-ratio: 1;
  translate: -50% -50%;
  z-index: -1;
  /* Dos focos opuestos que orbitan el centro. Un conic-gradient no valía: de él solo se ve la
     banda central —donde convergen todos los tonos— y al girar apenas hay movimiento.
     Con focos desplazados, cada uno cruza el campo y se oculta por arriba y abajo: el eclipse. */
  background:
    radial-gradient(circle at 50% 20%, color-mix(in srgb, var(--color-primary) 95%, transparent) 0 4%, transparent 40%),
    radial-gradient(circle at 50% 80%, color-mix(in srgb, var(--c-teal) 85%, transparent) 0 4%, transparent 40%),
    radial-gradient(circle at 18% 50%, color-mix(in srgb, var(--c-pink) 70%, transparent) 0 3%, transparent 34%);
  filter: blur(11px);
  opacity: .55;
  pointer-events: none;
  animation: eclipseOrbita 22s linear infinite;
  transition: opacity .35s ease;
}

/* Al escribir o enfocar, el halo se aviva un poco */
.dash-sidebar__search:focus-within::before,
.dash-sidebar__search.has-text::before {
  opacity: .62;
}

/* `rotate` como propiedad independiente: no pisa el `translate` del centrado */
@keyframes eclipseOrbita {
  to { rotate: 360deg; }
}

/* El input lleva la clase 'no-bg', que lo saca de la regla universal de inputs de
   modules.css (su especificidad (0,9,1) aplastaba a este selector (0,2,0) aunque
   clay cargue después). Por eso aquí ya no hace falta ningún !important. */
.dash-sidebar__search input {
  border: none;
  border-radius: var(--clay-r-pill);
  box-shadow: var(--clay-inset);
  /* Semitransparente para que el eclipse se translucza. */
  background: color-mix(in srgb, var(--color-surface) 62%, transparent);
}

/* El foco se marca por dentro: el buscador recorta a su forma con overflow:hidden
   y el input lo llena entero, así que un anillo por fuera quedaría cortado. */
.dash-sidebar__search input:focus {
  background: color-mix(in srgb, var(--color-surface) 72%, transparent);
  box-shadow: var(--clay-inset), inset 0 0 0 2px var(--color-primary);
}
.dash-sidebar__toggle {
  border: none;
  background: var(--color-surface);
  box-shadow: var(--clay-raised-sm);
}
.dash-sidebar__toggle:hover { box-shadow: var(--clay-raised); }
.dash-sidebar__search-kbd { box-shadow: var(--clay-flat); border-radius: 8px; }

/* Menú pegado arriba: ambas columnas (riel de iconos y panel) a la vez para
   que iconos y logo queden alineados */
.dash-rail { padding-top: .2rem; }
.dash-panel { padding-top: .2rem; }

/* Logo sobre el buscador. Los PNG son cuadrados con la marca en la banda
   central: el contenedor de altura fija recorta el lienzo sobrante
   (flex centra la imagen y overflow:hidden corta arriba/abajo). */
.dash-panel__logo {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 62px;
  overflow: hidden;
  margin: .5rem .75rem .25rem;
  border-radius: var(--clay-r-sm);
  flex: 0 0 auto;
}
/* ojo: sin display aquí — un display:block (0,1,1) ganaría al display:none
   de .dash-panel__logo-oscuro (0,1,0) y se verían los dos logos a la vez */
.dash-panel__logo img { width: 100%; }
.dash-panel__logo-oscuro { display: none; }
:root[data-theme="dark"] .dash-panel__logo-claro { display: none; }
:root[data-theme="dark"] .dash-panel__logo-oscuro { display: block; }

/* ============ 9. TABLAS DE LISTADOS ============ */
/* Botones de acciones SIEMPRE en fila: la celda no parte línea aunque sea
   estrecha, y el grupo flex no envuelve */
.dash-table td[data-col="acciones"],
.dash-table th[data-col="acciones"] { white-space: nowrap; }
.cli-row-actions { flex-wrap: nowrap; }

/* Compactas + zebra: fuera las spacer-row (siguen en el DOM, por eso el
   zebra usa nth-child(even of .data-row) para contar solo filas de datos) */
.dash-table thead th { padding: .55rem 1rem; }
.dash-table tbody td { padding: .45rem 1rem; }
.dash-table .spacer-row { display: none; }
.dash-table tbody tr:nth-child(even of .data-row) {
  background: color-mix(in srgb, var(--color-on-surface) 4%, transparent);
}
.dash-table__client-avatar { border-radius: var(--clay-r-sm); box-shadow: var(--clay-flat); }
.dash-table__more { border-radius: var(--clay-r-sm); }
.dash-table__more:hover { background: var(--color-surface-container); box-shadow: var(--clay-inset); }

/* Paginación */
.cli-pag-btn {
  border: none;
  border-radius: var(--clay-r-sm);
  background: var(--color-surface);
  box-shadow: var(--clay-raised-sm);
  transition: box-shadow .15s ease, transform .1s ease;
}
.cli-pag-btn:hover:not(:disabled) { transform: translateY(-1px); box-shadow: var(--clay-raised); }
.cli-pag-btn:active:not(:disabled) { box-shadow: var(--clay-inset); }
.cli-pag-btn:disabled { opacity: .5; }

/* ============ 10. TABLAS DE LÍNEAS (documentos) ============ */
.pre-table-container { border: none; border-radius: var(--clay-r-lg); box-shadow: var(--clay-flat); }
.pre-table th { background: var(--color-surface-container-low); padding: .5rem .6rem; }
.pre-table td { padding: .3rem .5rem; }
.pre-table tbody tr:nth-child(even) {
  background: color-mix(in srgb, var(--color-on-surface) 4%, transparent);
}

/* ============ 11. AJUSTES / TARJETAS ENLACE ============ */
.ajuste-card {
  border: none;
  border-radius: var(--clay-r-lg);
  background: var(--color-surface);
  box-shadow: var(--clay-raised);
  transition: box-shadow .15s ease, transform .12s ease;
}
.ajuste-card:hover { transform: translateY(-2px); box-shadow: var(--clay-raised-hover); }

/* ============ 12. TOASTS / NOTIFICACIONES ============ */
#notificacion {
  border: none;
  border-radius: var(--clay-r-md);
  box-shadow: var(--clay-raised);
}

/* ============ 12b. TRANSICIONES ENTRE PÁGINAS ============
   La app ya emitía `@view-transition { navigation: none }` cuando el perfil activa "reducir
   efectos de movimiento", pero nunca llegó a declarar la transición: el ajuste apagaba algo que
   no existía. Aquí se declara; el <style> inline de crear_head() la anula cuando toca.
   Solo navegaciones del mismo origen y solo en navegadores que lo soporten (mejora progresiva). */
@view-transition { navigation: auto; }

@keyframes vtSale { to { opacity: 0; transform: translateY(-8px); } }
@keyframes vtEntra { from { opacity: 0; transform: translateY(10px); } }

::view-transition-old(root) {
  animation: vtSale .18s cubic-bezier(.4, 0, 1, 1) both;
}

::view-transition-new(root) {
  animation: vtEntra .3s cubic-bezier(.22, 1, .36, 1) both;
}

/* El menú y la barra superior no se mueven con la página: se quedan fijos entre navegaciones */
.dash-sidebar { view-transition-name: sidebar; }
.dash-topbar { view-transition-name: topbar; }
::view-transition-group(sidebar),
::view-transition-group(topbar) { animation: none; }
::view-transition-old(sidebar),
::view-transition-new(sidebar),
::view-transition-old(topbar),
::view-transition-new(topbar) { animation: none; mix-blend-mode: normal; }

@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
}

/* ============ 13. ENTRADA DE PRESENTACIÓN (al cargar página) ============ */
@keyframes clayInUp { 0% { opacity: 0; transform: translateY(16px); } 100% { opacity: 1; transform: none; } }
@keyframes clayPuffIn { 0% { opacity: 0; transform: scale(.9); } 100% { opacity: 1; transform: scale(1); } }
@keyframes clayFadeIn { 0% { opacity: 0; } 100% { opacity: 1; } }
@media (prefers-reduced-motion: no-preference) {
  /* El header anima SOLO opacidad: contiene el FAB fijo de Guardar, y un
     ancestro con transform lo captura (aparecía arriba y saltaba abajo). */
  .dash-page-header { animation: clayFadeIn .5s ease both .05s; }
  .dash-kpi-card { animation: clayPuffIn .5s cubic-bezier(.22,1,.36,1) both; }
  .dash-kpi-card:nth-child(1) { animation-delay: .12s; }
  .dash-kpi-card:nth-child(2) { animation-delay: .20s; }
  .dash-kpi-card:nth-child(3) { animation-delay: .28s; }
  .dash-table-container, .pre-panel { animation: clayInUp .55s ease both .22s; }
  /* Fichas de documento: pestañas y paneles entran también */
  .cli-tabs { animation: clayInUp .5s ease both .08s; }
  .cli-form-section-title { animation: clayFadeIn .5s ease both .3s; }
}
body.clay-anim-done .cli-tabs,
body.clay-anim-done .cli-form-section-title { animation: none; }
/* Tras el arranque (base.js marca el body), estas animaciones NO se
   re-disparan al cambiar de pestaña — evita el efecto "recarga". */
body.clay-anim-done .dash-page-header,
body.clay-anim-done .dash-kpi-card,
body.clay-anim-done .dash-table-container,
body.clay-anim-done .pre-panel { animation: none; }

/* Cambio de panel de pestañas: el contenido se mantiene quieto (sin fundidos
   ni re-entradas — cualquier animación aquí lee como "refresco"); el único
   movimiento es la píldora deslizándose entre pestañas. */
body.clay-anim-done .cli-tab-panel { animation: none; }

/* ============ 15. ICONO DE TEMA (luna en claro / sol en oscuro) ============ */
#btn-tema .ico-sol { display: none; }
:root[data-theme="dark"] #btn-tema .ico-luna { display: none; }
:root[data-theme="dark"] #btn-tema .ico-sol { display: block; }

/* ============ 16. MENÚ MÓVIL (drawer) ============ */
.dash-topbar__hamburger { display: none; }
@media (max-width: 768px) {
  .dash-topbar__hamburger { display: grid; flex: 0 0 auto; }
  /* dashboard.css oculta el sidebar en móvil; lo convertimos en drawer off-canvas */
  .dash-sidebar {
    display: flex;
    position: fixed;
    left: 0; top: 0;
    transform: translateX(-110%);
    transition: transform .25s cubic-bezier(.22,1,.36,1);
    z-index: 80;
    box-shadow: var(--clay-raised);
  }
  body.menu-movil-abierto .dash-sidebar { transform: translateX(0); }
  /* En móvil el drawer siempre abre con rail + panel, aunque el usuario
     tuviera el menú contraído a solo rail en escritorio */
  body.sidebar-collapsed { --dash-panel-w: 13.75rem; }
  body.sidebar-collapsed .dash-panel { display: flex; }
  body.sidebar-collapsed .dash-rail { border-right: 1px solid var(--clay-line); }
  /* Overlay oscuro tras el drawer */
  body.menu-movil-abierto::before {
    content: "";
    position: fixed; inset: 0;
    background: rgba(20, 10, 32, .45);
    z-index: 70;
  }
}
@media (prefers-reduced-motion: reduce) {
  .dash-sidebar { transition: none; }
}

/* ============ 17. LOGIN ============ */
/* El login define <style> propio DESPUÉS de los <link>; usamos html + selector
   para ganar en especificidad sin !important. */
html .login-card {
  border: none;
  border-radius: var(--clay-r-xl);
  background: var(--color-surface);
  box-shadow: var(--clay-raised);
}
html .login-form .form-input {
  border: none;
  border-radius: var(--clay-r-sm);
  background: var(--color-surface-container-lowest);
  box-shadow: var(--clay-inset);
}
html .login-form .form-input:focus {
  box-shadow: var(--clay-inset), 0 0 0 2px var(--color-primary);
}
html .login-card .submit-btn {
  border-radius: var(--clay-r-md);
  background: linear-gradient(145deg, var(--color-primary-container), var(--color-primary));
  box-shadow: var(--clay-primary-glow);
}
html .login-card .submit-btn:hover { transform: translateY(-1px); filter: brightness(1.07); }
html .login-card .submit-btn:active { transform: translateY(1px); box-shadow: var(--clay-inset); }
html .login-card .error-alert {
  border-left: none;
  border-radius: var(--clay-r-md);
  box-shadow: var(--clay-flat);
}

/* ============ 22. BOTÓN GUARDAR FLOTANTE (FAB) ============ */
/* Solo los "Guardar" de página (en el header de las fichas); los de los
   modales no se ven afectados. */
.dash-page-header__actions .btn-primary[id^="btn-guardar-"] {
  position: fixed;
  right: 1.5rem;
  bottom: 1.5rem;
  z-index: 90;
  padding: .95rem 1.6rem;
  font-size: .95rem;
  border-radius: var(--clay-r-pill);
  box-shadow:
    6px 6px 16px rgba(130,49,167,.35),
    -4px -4px 12px rgba(var(--clay-light), var(--clay-hi-a)),
    0 8px 28px rgba(0,0,0,.16);
}
.dash-page-header__actions .btn-primary[id^="btn-guardar-"]:hover { transform: translateY(-2px); }
.dash-page-header__actions .btn-primary[id^="btn-guardar-"]:active { transform: translateY(1px); box-shadow: var(--clay-inset); }
/* Hueco al final de la página para que el FAB no tape contenido */
.dash-canvas:has(.dash-page-header__actions .btn-primary[id^="btn-guardar-"]) {
  padding-bottom: 7rem;
}
@media (max-width: 768px) {
  .dash-page-header__actions .btn-primary[id^="btn-guardar-"] { right: 1rem; bottom: 1rem; }
}

/* ============ TARJETA DE TOTALES — STICKY CONSISTENTE ============ */
/* Antes: position:sticky dentro de #panel-lineas → su posición dependía del
   alto de la cabecera/tabla de cada ficha (factura 2 filas vs presupuesto 1),
   por eso no cuadraban. Ahora: fija a una esquina del viewport (MISMA posición
   en factura/presupuesto/pedido/albarán) pero SOLO visible mientras la tabla de
   líneas está a la vista (base.js la muestra/oculta con IntersectionObserver).
   Resultado: se comporta como sticky (pegada abajo, ligada a las líneas) pero
   consistente entre fichas, y ya no tapa las columnas. */
.pre-totales-wrapper {
  position: fixed;
  right: 16rem;          /* a la izquierda del botón Guardar (misma línea) */
  bottom: 1.5rem;        /* alineado abajo con el botón Guardar */
  margin: 0;
  width: auto;
  min-height: 0;
  z-index: 45;
}
/* Sin JS: el total está dentro del panel de la pestaña de líneas; al cambiar de
   pestaña ese panel pasa a display:none y oculta también este elemento fixed.
   Así aparece fijo desde la carga y se oculta solo fuera de las líneas. */
.pre-totales-grid { width: 300px; }
/* El total es position:fixed. Cualquier ancestro con `transform` lo posiciona
   respecto a ese ancestro en vez del viewport → aparecería en el centro y
   saltaría a la esquina al acabar la animación. Los ancestros que animan con
   transform (el panel de líneas y su tab-panel, con fadeSlideUp) se desactivan
   para que el total salga YA posicionado desde el primer frame. */
/* El panel/tab-panel de líneas NO puede usar transform (rompe el total fixed),
   pero SÍ puede entrar con un fade (opacity) — así anima sin descolocar el total. */
#panel-lineas { animation: none !important; }
.cli-tab-panel:has(.pre-totales-wrapper) {
  transform: none !important;
  animation: clayFadeIn .5s ease both .2s !important;
  /* Colchón inferior: la tarjeta de totales es fixed y sin esto tapa las últimas
     líneas de detalle al llegar al final del scroll (visible sobre todo en
     facturas emitidas, donde el contenido acaba antes) */
  padding-bottom: 9rem;
}
body.clay-anim-done .cli-tab-panel:has(.pre-totales-wrapper) { animation: none !important; }
@media (max-width: 768px) {
  .pre-totales-wrapper { right: 1rem; bottom: 5.5rem; }
  .pre-totales-grid { width: min(300px, calc(100vw - 2rem)); }
}

/* ============ 20. SIN MIGAS DE PAN ============ */
/* La navegación va por el sidebar; las migas sobran en esta app. */
.cli-ficha-breadcrumb { display: none; }

/* ============ 21. INPUTS EN MODO OSCURO ============ */
/* base.css fuerza fondo claro (#fbfbfd) con un selector muy específico, y el
   override oscuro de modules.css está anidado en @media (prefers-color-scheme)
   → solo aplicaba si el SO estaba en oscuro. Aquí manda data-theme. */
:root[data-theme="dark"] input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):not([type="submit"]):not([type="button"]):not([type="file"]):not([type="image"]):not([type="reset"]):not(.no-bg),
:root[data-theme="dark"] textarea:not(.no-bg),
:root[data-theme="dark"] select:not(.no-bg) {
  background-color: var(--color-surface-container-lowest);
  color: var(--color-on-surface);
}
:root[data-theme="dark"] input::placeholder,
:root[data-theme="dark"] textarea::placeholder {
  color: var(--color-on-surface-variant);
  opacity: .7;
}

/* ============ 19. CAMPOS CON BUSCADOR EN COLUMNA ============ */
/* Los campos con buscador (Cliente, Forma de Pago, Agente, Almacén,
   Transportista, Banco…) venían como fila (label+lupa y "Cód." en línea),
   gastando ancho. Se pasan a columna como el resto de campos.
   El wrapper lleva estilo inline (align-items/gap), de ahí los !important. */
/* Generalizado: CUALQUIER envoltorio fila (label + input en línea) dentro de
   un grupo pasa a columna — buscadores, Tarifa, Tipo de Cliente, etc. */
.pre-form-group > div:has(> label):has(> input),
.cli-form-group > div:has(> label):has(> input) {
  display: flex;
  flex-direction: column;
  align-items: stretch !important;
  gap: .25rem !important; /* mismo gap label↔input que .pre-form-group */
}
.pre-form-group > div:has(> label):has(> input) > input,
.cli-form-group > div:has(> label):has(> input) > input {
  width: var(--clay-w-cod) !important;   /* pisa anchos inline (60px…) */
  text-align: left !important;
  padding: .35rem .55rem !important;     /* pisa el padding estrecho inline */
  align-self: flex-start;
}
.pre-form-group > div:has(> label[id^="btn-search-"]) > input,
.cli-form-group > div:has(> label[id^="btn-search-"]) > input {
  width: var(--clay-w-cod) !important;     /* !important: pisa anchos inline (p. ej. 60px en cliente) */
  max-width: var(--clay-w-cod) !important; /* y el tope 4rem de input-narrow-xs (Agente) */
  align-self: flex-start;
  text-align: left !important;
}
/* Estándar de códigos: todas las variantes estrechas al mismo ancho */
.input-narrow, input.input-narrow,
.input-narrow-xs, input.input-narrow-xs {
  width: var(--clay-w-cod);
  max-width: var(--clay-w-cod);
}
/* El grupo se ciñe a su contenido (label o input, el más ancho) en vez de
   reservar el mínimo de --sm (7.5rem) que dejaba huecos vacíos alrededor
   de códigos cortos como el de Agente. */
.pre-form-group:has(> div > label[id^="btn-search-"]) {
  min-width: 0;
  flex: 0 1 auto;
}
/* Ídem para grupos cuyo input es estrecho (Número, códigos, CP…): sin el
   mínimo de 7.5rem desaparece el aire muerto entre campos (p. ej. Número→Fecha). */
.pre-form-group:has(> .input-narrow),
.pre-form-group:has(> .input-narrow-xs) {
  min-width: 0;
  flex: 0 1 auto;
}
/* .hi fuerza 24px pisando el atributo width/height de los SVG, y los iconos
   pequeños de los labels (lupa 14, candado 12…) agrandaban el label y
   descolgaban su input ~4px. Con width/height:auto el SVG recupera el tamaño
   declarado en sus atributos. Aplica a todos los labels de formulario. */
.pre-form-group label[id^="btn-search-"],
.cli-form-group label[id^="btn-search-"] { line-height: 1.5; }
.pre-form-group label .hi,
.cli-form-group label .hi {
  width: auto;
  height: auto;
}

/* ============ 23. FORMULARIOS cli-* IGUALADOS A FACTURAS ============ */
/* Cliente, agente, forma de pago y remesa usan el sistema cli-form-* (grid
   rígido de columnas iguales, tope 64rem). Se convierte al MISMO layout que
   facturas: flex fluido donde cada campo ocupa lo que su contenido pide. */
.cli-form-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1rem;
  align-items: flex-start;
  max-width: none;
}
/* Mapeo de variantes al comportamiento de pre-form-group */
.cli-form-group { gap: 0.25rem; flex: 1 1 200px; min-width: 0; justify-content: flex-start; }
.cli-form-group--sm  { flex: 0 1 auto; min-width: 7.5rem; max-width: none; }
.cli-form-group--xs  { flex: 0 1 auto; min-width: 5rem;  max-width: none; }
.cli-form-group--xxs { flex: 0 0 auto; max-width: none; }
.cli-form-group--xxs input { width: var(--clay-w-cod); }
.cli-form-group--code { flex: 0 0 auto; max-width: none; }
.cli-form-group--code input { width: 9rem; }
.cli-form-group--lg  { flex: 1 1 320px; }
.cli-form-group--xl  { flex: 1 1 480px; }
.cli-form-group--full { flex: 1 1 100%; }
.cli-form-group label {
  font-size: 0.8125rem;
  text-transform: none;
  letter-spacing: normal;
}
.cli-required { color: var(--color-error); }
.cli-form-group input:not([type="checkbox"]):not([type="radio"]),
.cli-form-group select,
.cli-form-group textarea {
  border: none;
  border-radius: var(--clay-r-sm);
  box-shadow: var(--clay-inset);
}
.cli-form-group input:not([type="checkbox"]):not([type="radio"]):focus,
.cli-form-group select:focus,
.cli-form-group textarea:focus,
.cli-form-group input:not([type="checkbox"]):not([type="radio"]):hover:not([readonly]):not(:disabled),
.cli-form-group select:hover:not(:disabled),
.cli-form-group textarea:hover:not([readonly]):not(:disabled) {
  border: none;
  box-shadow: var(--clay-inset), 0 0 0 2px var(--color-primary);
}
.cli-form-group textarea {
  field-sizing: content;
  min-height: 2.7rem;
  max-height: 12rem;
}

/* Panel de arcilla: en cliente (y fichas antiguas) el contenido cuelga
   directamente del panel de pestaña, sin la tarjeta que facturas monta con
   .pre-panel. Se la damos al panel que contenga una rejilla cli- directa
   (los de facturas contienen .pre-panel, no rejillas → no les afecta). */
.cli-tab-panel:has(> .cli-form-grid) {
  background: var(--color-surface);
  border-radius: var(--clay-r-lg);
  box-shadow: var(--clay-raised);
  padding: 1.5rem;
}

/* Fila de Dirección SIEMPRE en una línea con repartos propios:
   Domicilio crece sin imponer los 480px de --xl (que expulsaba al resto),
   CP fijo corto, Población/Provincia medianos y País compacto. */
.cli-form-grid--dir { flex-wrap: nowrap; }
.cli-form-grid--dir > .cli-form-group { min-width: 0; } /* pueden encoger */
.cli-form-grid--dir > .cli-form-group--xl { flex: 2.2 1 10rem; }   /* Domicilio */
.cli-form-grid--dir > .cli-form-group--xs { flex: 0 0 6.5rem; }    /* Código Postal */
.cli-form-grid--dir > .cli-form-group:nth-child(n+3) { flex: 1 1 7rem; } /* Población / Provincia */
.cli-form-grid--dir > .cli-form-group:last-child { flex: .7 1 6rem; }    /* País */
@media (max-width: 900px) {
  .cli-form-grid--dir { flex-wrap: wrap; } /* en móvil sí puede envolver */
}

/* Rejillas --inline (descuentos, IVA…): etiqueta ENCIMA del input, como en
   facturas (el CSS antiguo las ponía en fila etiqueta|input). */
.cli-form-grid--inline .cli-form-group {
  flex-direction: column;
  align-items: flex-start;
  gap: .25rem;
}
.cli-form-grid--inline .cli-form-group input,
.cli-form-grid--inline .cli-form-group select {
  width: var(--clay-w-cod);
  text-align: left;
  padding: .35rem .55rem; /* padding estándar (el inline lo estrechaba) */
}

/* Fila C.C.C. (Entidad · Oficina · DC · Nº de Cuenta): tallas propias con
   separación normal (antes DC tenía un max-width inline que apretaba). */
.cli-form-grid--ccc > .cli-form-group { flex: 0 0 auto; }
.cli-form-grid--ccc .cli-form-group--cuenta { flex: 0 1 auto; }
.cli-form-grid--ccc .cli-form-group--cuenta > input { width: var(--clay-w-num) !important; max-width: var(--clay-w-num) !important; }

/* Datos bancarios: Banco e IBAN ajustados a su contenido real (llevan --lg,
   que es la talla grande de 36rem — demasiado para un nombre de banco o IBAN). */
.cli-form-group:has(> #field-BANCLI) { flex: 0 1 15rem; max-width: 15rem; }
.cli-form-group:has(> #field-IBACLI) { flex: 0 1 17rem; max-width: 17rem; }

/* Desplegables de cliente IDÉNTICOS a los de facturas (refuerzo explícito:
   modules.css define .cli-form-group select con triángulo gris y borde
   antiguos; esta regla, más específica, los iguala al pre-*). */
.cli-tab-panel .cli-form-group select,
.cli-form-grid .cli-form-group select {
  appearance: base-select;
  border: none;
  border-radius: var(--clay-r-sm);
  background-color: var(--color-surface-container-lowest);
  box-shadow: var(--clay-inset);
  padding: .5rem 2.2rem .5rem .7rem;
  cursor: pointer;
}
.cli-tab-panel .cli-form-group select:hover,
.cli-tab-panel .cli-form-group select:focus {
  border: none;
  box-shadow: var(--clay-inset), 0 0 0 2px var(--color-primary);
}

/* ── Componentes antiguos del sistema cli-* ── */

/* Sub-pestañas (Direcciones/Contactos/…) → canal hundido con píldoras */
.cli-subtabs {
  background: var(--color-background);
  border-radius: var(--clay-r-pill);
  padding: .35rem;
  box-shadow: var(--clay-inset);
}
.cli-subtab { border-radius: var(--clay-r-pill); }
.cli-subtab.active { background: var(--color-surface); box-shadow: var(--clay-raised-sm); }

/* Tarjetas de sublistas (direcciones, contactos, recurrentes…) */
.cli-sublist-card {
  border: none;
  border-radius: var(--clay-r-md);
  box-shadow: var(--clay-raised-sm);
}
.cli-sublist-card:hover { border: none; box-shadow: var(--clay-raised); }

/* Formulario inline de alta rápida (mantiene el punteado de "zona editable") */
.cli-inline-form { border-radius: var(--clay-r-md); }

/* Chips de estadísticas */
.cli-stat-chip { background: var(--color-surface); box-shadow: var(--clay-flat); }

/* Botones de icono (imprimir, editar, eliminar en tarjetas…) */
.btn-icon {
  border: none;
  border-radius: var(--clay-r-sm);
  background: var(--color-surface);
  box-shadow: var(--clay-raised-sm);
  transition: box-shadow .15s ease, transform .1s ease, color .15s ease;
}
.btn-icon:hover {
  border: none;
  background: var(--color-surface);
  transform: translateY(-1px);
  box-shadow: var(--clay-raised);
}
.btn-icon:active { transform: translateY(1px); box-shadow: var(--clay-inset); }

/* Estado vacío ("no hay direcciones…") → hueco hundido */
.cli-empty-state-inline {
  border-radius: var(--clay-r-md);
  background: var(--color-background);
  box-shadow: var(--clay-inset);
}

/* Buscador de filtros de las sublistas */
.cli-filters__search input {
  border: none;
  border-radius: var(--clay-r-pill);
  box-shadow: var(--clay-inset);
}
.cli-filters__search input:focus {
  box-shadow: var(--clay-inset), 0 0 0 2px var(--color-primary);
}

/* Títulos de sección de cliente igualados a los de facturas
   (tamaño 1.125rem, color primario, icono en chip de arcilla) */
.cli-form-section-title {
  font-size: 1.125rem;
  gap: 0.5rem;
  color: var(--color-primary);
}
.cli-form-section-title .hi {
  width: 38px;
  height: 38px;
  padding: 8px;
  flex: 0 0 auto;
  border-radius: 12px;
  color: var(--color-primary);
  background: linear-gradient(145deg,
    color-mix(in srgb, var(--color-primary) 18%, var(--color-surface)),
    color-mix(in srgb, var(--color-primary) 6%, var(--color-surface)));
  box-shadow: var(--clay-flat);
}
/* Alineación por ARRIBA en las rejillas de formulario: todos los labels a la
   misma altura y los inputs alineados. Los grupos con líneas extra debajo
   (nombre del cliente, "Personalizar") cuelgan sin desalinear a los vecinos.
   (Antes: align-items center → el grupo más alto descentraba su input.) */
.pre-form-grid { align-items: flex-start; }
.pre-form-group { justify-content: flex-start; }

/* ============ 25. SISTEMA DE TALLAS DE INPUT (por tipo) ============ */
/* Regla: cada GRUPO se dimensiona según el TIPO de su campo, con topes fijos.
   El input llena su grupo (width:100%) salvo los códigos, que van a ancho fijo.
   Orden de la cascada (de genérico a específico): texto → select/fecha/número
   → código. Los más específicos ganan. */

/* 1) Base: TEXTO. Crece hasta el tope --clay-w-text y NO más. */
.pre-form-group,
.cli-form-group { flex: 1 1 var(--clay-w-text); max-width: var(--clay-w-text); min-width: 0; }
/* Texto largo (variantes grandes) → tope mayor; full → ancho completo */
.pre-form-group--lg, .pre-form-group--xl,
.cli-form-group--lg, .cli-form-group--xl { flex: 1 1 var(--clay-w-text-lg); max-width: var(--clay-w-text-lg); }
.pre-form-group--full, .cli-form-group--full { flex: 1 1 100%; max-width: none; }

/* 2) SELECT → se ajusta a su contenido (base-select), entre un mínimo y el
   tope de talla select. "No/Sí" quedan pequeños; opciones largas hasta 13rem. */
.pre-form-group:has(> select),
.cli-form-group:has(> select) { flex: 0 0 auto; max-width: var(--clay-w-select); min-width: 0; }
.pre-form-group:has(> select) > select,
.cli-form-group:has(> select) > select {
  width: auto;
  min-width: 6.5rem;
  max-width: var(--clay-w-select);
}

/* 3) FECHA → talla fecha */
.pre-form-group:has(> input[type="date"]),
.cli-form-group:has(> input[type="date"]) { flex: 0 1 var(--clay-w-date); max-width: var(--clay-w-date); }

/* 4) NÚMERO genérico (importes, cantidades, %) → talla número */
.pre-form-group:has(> input[type="number"]),
.cli-form-group:has(> input[type="number"]) { flex: 0 1 var(--clay-w-num); max-width: var(--clay-w-num); }

/* 5) CÓDIGO (gana sobre número/texto): input a ancho fijo, grupo ceñido.
   Cubre field-COD*, input-narrow y maxlength 1-5. */
.pre-form-group > input[id^="field-COD"],
.cli-form-group > input[id^="field-COD"],
.input-narrow, .input-narrow-xs,
input[maxlength="1"]:not(.no-bg), input[maxlength="2"]:not(.no-bg),
input[maxlength="3"]:not(.no-bg), input[maxlength="4"]:not(.no-bg),
input[maxlength="5"]:not(.no-bg) { width: var(--clay-w-cod) !important; max-width: var(--clay-w-cod) !important; }
.pre-form-group:has(> input[id^="field-COD"]),
.cli-form-group:has(> input[id^="field-COD"]),
.pre-form-group:has(> .input-narrow), .pre-form-group:has(> .input-narrow-xs),
.cli-form-group:has(> .input-narrow), .cli-form-group:has(> .input-narrow-xs),
.pre-form-group:has(> input[maxlength="1"]), .pre-form-group:has(> input[maxlength="2"]),
.pre-form-group:has(> input[maxlength="3"]), .pre-form-group:has(> input[maxlength="4"]),
.pre-form-group:has(> input[maxlength="5"]),
.cli-form-group:has(> input[maxlength="1"]), .cli-form-group:has(> input[maxlength="2"]),
.cli-form-group:has(> input[maxlength="3"]), .cli-form-group:has(> input[maxlength="4"]),
.cli-form-group:has(> input[maxlength="5"]) { flex: 0 0 auto; max-width: none; }

/* ============ 13a. TOGGLE DEL RESUMEN (KPIs) ============
   Botón que acompaña al subtítulo de la página; pieza pequeña de arcilla. */
.dash-resumen-toggle {
  border: none;
  background: var(--color-surface);
  box-shadow: var(--clay-flat);
  border-radius: var(--clay-r-pill);
  padding: .3rem .8rem;
  transition: box-shadow .18s ease, color .18s ease;
}

.dash-resumen-toggle:hover {
  background: var(--color-surface);
  border-color: transparent;
  box-shadow: var(--clay-raised-sm);
  color: var(--color-primary);
}

.dash-resumen-toggle:active { box-shadow: var(--clay-inset); }
.dash-resumen-toggle[aria-expanded="false"] { box-shadow: var(--clay-inset); color: var(--color-primary); }

/* ============ 13b. OPCIONES DE PANTALLA ============
   Panel desplegable de los listados. La lengüeta cuelga del panel como una pieza continua
   (sin hueco entre ambos) y al abrirse queda hundida para leerse como la misma arcilla.
   Los chips se ajustan a su texto: con ~20 columnas una rejilla de celdas fijas dejaba
   demasiado aire muerto. */
.cli-screen-options-panel {
  background: var(--color-surface);
  border: none;
  /* Esquina inferior derecha recta: de ahí cuelga la lengüeta */
  border-radius: var(--clay-r-lg) var(--clay-r-lg) 0 var(--clay-r-lg);
  box-shadow: var(--clay-raised);
  padding: 0 1.5rem;
}

/* La altura la calcula screen-options.js (scrollHeight); aquí solo el ritmo de la animación.
   Salida rápida y entrada con rebote suave: `all .4s` animaba también sombras y colores,
   y hacía el cierre pastoso. */
.cli-screen-options-panel {
  transition:
    max-height .32s cubic-bezier(.4, 0, .2, 1),
    padding .32s cubic-bezier(.4, 0, .2, 1),
    opacity .22s ease;
  will-change: max-height;
}

.cli-screen-options-panel.open {
  padding: 1.5rem;
  /* El hueco que despegaba la lengüeta del panel (modules.css la separaba 1.5rem) */
  margin-bottom: 0;
  transition:
    max-height .4s cubic-bezier(.22, 1, .36, 1),
    padding .4s cubic-bezier(.22, 1, .36, 1),
    opacity .28s ease;
}

/* Los chips entran escalonados al abrir; al cerrar se van con el panel sin animación propia */
@media (prefers-reduced-motion: no-preference) {
  .cli-screen-options-panel.open .cli-screen-options-cols label {
    animation: clayPuffIn .32s cubic-bezier(.22, 1, .36, 1) both;
  }
  .cli-screen-options-panel.open .cli-screen-options-cols label:nth-child(n+6) { animation-delay: .04s; }
  .cli-screen-options-panel.open .cli-screen-options-cols label:nth-child(n+12) { animation-delay: .08s; }
  .cli-screen-options-panel.open .cli-screen-options-group:nth-child(2) { animation: clayFadeIn .4s ease both .1s; }
}

/* Las columnas mandan; la paginación solo ocupa lo que necesita */
.cli-screen-options-content {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 1.5rem 2.5rem;
  align-items: start;
}

.cli-screen-options-group { min-width: 0; }

.cli-screen-options-group h5 {
  display: flex;
  align-items: center;
  gap: .75rem;
  color: var(--color-on-surface-variant);
  letter-spacing: .09em;
  font-size: .6875rem;
  margin-bottom: .85rem;
  padding-bottom: .5rem;
  border-bottom: 1px solid var(--clay-line);
}

/* Atajos "Todas / Ninguna" (los inyecta screen-options.js) */
.cli-screen-options-acciones {
  display: inline-flex;
  gap: .35rem;
  margin-left: auto;
}

.cli-screen-options-acciones button {
  border: none;
  background: transparent;
  padding: .1rem .45rem;
  border-radius: var(--clay-r-pill);
  color: var(--color-primary);
  font-family: 'Inter', sans-serif;
  font-size: .6875rem;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background .15s ease, box-shadow .15s ease;
}

.cli-screen-options-acciones button:hover {
  background: var(--color-surface-container-low);
  box-shadow: var(--clay-flat);
}

/* Chips que se ajustan a su texto, no celdas de ancho fijo */
.cli-screen-options-cols {
  display: flex;
  flex-wrap: wrap;
  gap: .45rem;
}

/* Cada opción es un chip de arcilla; marcado, se hunde y toma el morado de marca */
.cli-screen-options-cols label {
  background: var(--color-surface-container-low);
  border-radius: var(--clay-r-pill);
  box-shadow: var(--clay-flat);
  padding: .35rem .8rem .35rem .5rem;
  gap: .45rem;
  font-size: .8125rem;
  line-height: 1.3;
  white-space: nowrap;
  transition: box-shadow .18s ease, color .18s ease, background .18s ease;
  user-select: none;
}

.cli-screen-options-cols label:hover {
  box-shadow: var(--clay-raised-sm);
  color: var(--color-on-surface);
}

.cli-screen-options-cols label:has(> input:checked) {
  background: color-mix(in srgb, var(--color-primary) 10%, var(--color-surface-container-low));
  box-shadow: var(--clay-inset);
  color: var(--color-primary);
  font-weight: 600;
}

/* Casilla propia: un disco de arcilla con el check dibujado en ::after */
.cli-screen-options-cols input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  flex: 0 0 auto;
  width: 1.05rem;
  height: 1.05rem;
  margin: 0;
  border: none;
  border-radius: 7px;
  background: var(--color-surface);
  box-shadow: var(--clay-flat);
  cursor: pointer;
  position: relative;
  transition: background .18s ease, box-shadow .18s ease;
}

.cli-screen-options-cols input[type="checkbox"]:checked {
  background: linear-gradient(145deg, var(--color-primary-container), var(--color-primary));
  box-shadow: var(--clay-primary-glow);
}

.cli-screen-options-cols input[type="checkbox"]:checked::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 46%;
  width: .3rem;
  height: .55rem;
  border: solid var(--color-on-primary);
  border-width: 0 2px 2px 0;
  transform: translate(-50%, -50%) rotate(45deg);
}

.cli-screen-options-cols input[type="checkbox"]:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* Selector de paginación: hueco excavado, coherente con los inputs clay */
.cli-screen-options-pag label { gap: .6rem; font-size: .8125rem; }

.cli-input-sm {
  border: none !important;
  border-radius: var(--clay-r-sm);
  background: var(--color-surface-container-low);
  box-shadow: var(--clay-inset);
  color: var(--color-on-surface);
  padding: .4rem .7rem !important;
  font-family: 'Inter', sans-serif;
  outline: none;
}

/* Lengüeta: cuelga del panel, sin separación ni desalineación con su borde derecho */
.cli-screen-options-tab-container {
  margin-right: 0;
  justify-content: flex-end;
}

.cli-screen-options-tab {
  background: var(--color-surface);
  border: none;
  border-radius: 0 0 var(--clay-r-md) var(--clay-r-md);
  box-shadow: var(--clay-raised-sm);
  padding: .45rem 1rem;
  font-weight: 600;
  transition: box-shadow .2s ease, color .2s ease, background .2s ease;
}

.cli-screen-options-tab:hover {
  background: var(--color-surface);
  box-shadow: var(--clay-raised-hover);
  color: var(--color-primary);
}

/* Abierta: se solapa hacia arriba para tapar la sombra que el panel proyecta sobre ella;
   si no, esa franja oscura se lee como un hueco aunque estén pegados (hueco real = 0).
   La sombra propia se limita a los lados y abajo para no re-dibujar esa línea. */
.cli-screen-options-tab.open,
.cli-screen-options-tab.open:hover {
  margin-top: -10px;
  padding-top: calc(.45rem + 10px);
  border-top-color: transparent;
  border-radius: 0 0 var(--clay-r-md) var(--clay-r-md);
  box-shadow:
     4px 6px 10px -2px rgba(var(--clay-dark), var(--clay-sh-a)),
    -4px 2px 8px -2px rgba(var(--clay-light), var(--clay-hi-a));
  color: var(--color-primary);
  z-index: 3;
}

/* La lengüeta cerrada se redondea entera: no cuelga de nada */
.cli-screen-options-tab:not(.open) {
  border-radius: var(--clay-r-md);
}

/* ============ 14. RESPONSIVE / MÓVIL ============ */
@media (max-width: 768px) {
  /* Los flex-items no pueden encoger por debajo de su contenido (min-width:auto):
     los botones del page-header forzaban ~460px y cortaban toda la página. */
  .dash-main, .dash-canvas { min-width: 0; }
  .dash-page-header__actions { flex-wrap: wrap; }
  .dash-page-header h2 { font-size: 1.4rem; }
  .dash-canvas { padding: 1.25rem 1rem 2rem; }
  .dash-topbar { gap: .5rem; padding: 0 .75rem; }
  .dash-topbar__search { width: auto; flex: 1 1 auto; min-width: 0; }
  .cli-screen-options-cols { grid-template-columns: 1fr; }
  .cli-screen-options-panel.open { padding: 1.25rem 1rem; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* ============ Ilustraciones del menú lateral (Favoritos / Búsqueda) ============
   Últimas hijas de .dash-panel, FUERA del scroll de #sidebar-nav: dentro del
   scroll no pueden pegarse al borde real del panel. Cada una se ve solo cuando
   su sección está a la vista. */
.dash-fav-ilustracion, .dash-buscar-ilustracion, .dash-ventas-ilustracion { display: none; }
.dash-panel:has(.dash-panel__section[data-dept="dept-busqueda"]:not([hidden])) > .dash-buscar-ilustracion,
.dash-panel:has(.dash-panel__section[data-dept="dept-favoritos"]:not([hidden])) > .dash-fav-ilustracion,
.dash-panel:has(.dash-panel__section[data-dept="dept-ventas"]:not([hidden])) > .dash-ventas-ilustracion {
  display: block;
  flex: 0 0 auto;
  /* Ancho completo del panel, de borde a borde: el ancho suma los dos paddings
     laterales (0.75rem) que los márgenes negativos se comen.
     max-width:none anula el img{max-width:100%} del reset de tailwind.css,
     que capaba el calc() y dejaba aire a los lados. */
  width: calc(100% + 1.5rem);
  max-width: none;
  margin: 0 -0.75rem -1rem;
  padding-top: 0.5rem;
  pointer-events: none;
  user-select: none;
  /* El PNG trae margen transparente alrededor del dibujo: se escala desde la base
     para que el DIBUJO (no el fichero) llegue a los bordes. El sobrante lo recorta
     el overflow:hidden del panel. */
  transform-origin: bottom center;
}
/* Escala calculada para que el DIBUJO (los PNG traen aire transparente distinto
   cada uno) quede al ancho interior del panel, con el mismo margen a ambos lados */
.dash-fav-ilustracion { transform: scale(0.98); }
.dash-buscar-ilustracion { transform: scale(0.82); }
.dash-ventas-ilustracion { transform: scale(1); } /* su PNG no trae aire alrededor */

/* ============ MODO OSCURO: readonly y focus de inputs ============
   modules.css fija fondos CLAROS a pelo (#f3f3f6 !important en readonly, #ffffff
   en focus) y sus overrides oscuros viven dentro de @media (prefers-color-scheme),
   así que con el tema oscuro elegido a mano sobre un SO claro no se aplicaban:
   el Total de cada línea (readonly) y cualquier campo enfocado salían blancos. */
:root[data-theme="dark"] input[readonly]:not(.no-bg),
:root[data-theme="dark"] textarea[readonly]:not(.no-bg) {
  background-color: rgba(255, 255, 255, 0.06) !important;
  color: var(--color-on-surface);
}
:root[data-theme="dark"] input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):not(.no-bg):focus,
:root[data-theme="dark"] textarea:not(.no-bg):focus,
:root[data-theme="dark"] select:not(.no-bg):focus {
  background-color: rgba(255, 255, 255, 0.08);
}
/* Mismo arreglo cuando el oscuro viene del SO (sin tema elegido a mano) */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) input[readonly]:not(.no-bg),
  :root:not([data-theme="light"]) textarea[readonly]:not(.no-bg) {
    background-color: rgba(255, 255, 255, 0.06) !important;
    color: var(--color-on-surface);
  }
  :root:not([data-theme="light"]) input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):not(.no-bg):focus,
  :root:not([data-theme="light"]) textarea:not(.no-bg):focus,
  :root:not([data-theme="light"]) select:not(.no-bg):focus {
    background-color: rgba(255, 255, 255, 0.08);
  }
}

/* Los rótulos de info bajo los campos con buscador (desc-FOP, desc-AGE,
   desc-ALM, desc-TRA, desc-BAN, desc-FPACLI: descripción de la forma de
   pago, nombre del agente, "No encontrado"…) llevaban width:max-content +
   nowrap inline y estiraban la columna del formulario. Ahora FLOTAN bajo su
   campo (absolute): no ocupan sitio en el grid y el texto largo salta de
   línea en una tarjetita. Vacíos no se pintan (:empty). El bloque de
   cliente (desc-CLI…) se excluye: tiene varias líneas + botón Personalizar
   y sí forma parte del layout. OJO: nada de secuencias asterisco-barra
   dentro de este comentario — cierran el comentario y rompen la regla. */
/* Ancla universal: valga el contenedor que valga (pre-form-group, cli-form-group
   o cualquier otro en remesas/cliente/forma de pago), el padre directo del rótulo
   se vuelve el marco de referencia del flotante. Incluye el bloque de cliente
   (desc-CLI...): el botón Personalizar queda en el flujo y la tarjeta flota debajo. */
:not(body):not(html):has(> [id^="desc-"]) {
  position: relative;
}
/* Receta clay de tooltip (referencia de diseño del usuario): superficie pastel
   saturada, radio generoso, brillo interior en el borde superior y sombra de
   caída exterior. Reutilizable en otros flotantes vía estas dos variables. */
:root {
  --clay-tooltip-bg: color-mix(in srgb, var(--color-primary) 9%, var(--color-surface));
  --clay-tooltip-shadow:
    inset 0 2px 3px rgba(var(--clay-light), .75),   /* inset top highlight */
    0 10px 22px rgba(var(--clay-dark), .16),        /* outer drop shadow */
    0 3px 8px rgba(var(--clay-dark), .10);
}
[id^="desc-"] {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 5;
  margin-top: .3rem !important;
  width: max-content !important;
  max-width: 15rem;
  white-space: normal !important;
  font-size: .72rem !important;
  line-height: 1.35 !important;
  background: var(--clay-tooltip-bg);
  box-shadow: var(--clay-tooltip-shadow);
  border-radius: var(--clay-r-md);
  padding: .5rem .75rem;
}
[id^="desc-"]:empty { display: none; }
/* La burbuja de cliente nunca está :empty (lleva un sub-div de contenido para
   alojar también el botón Personalizar): se oculta por clase */
[id^="desc-"].sin-contenido { display: none; }

/* Botón Personalizar DENTRO de la burbuja de cliente: icono redondo arriba a
   la derecha, sin texto (font-size:0 esconde el rótulo, el SVG conserva su
   tamaño por atributos width/height) */
[id^="desc-CLI"] { padding-right: 2.3rem; } /* hueco para el icono (la burbuja ya es absolute: ancla a sus hijos) */
[id^="desc-CLI"] > [id^="btn-ovr-"] {
  position: absolute;
  top: .3rem;
  right: .3rem;
  font-size: 0 !important;
  line-height: 0;
  padding: .3rem !important;
  border-radius: 50%;
  box-shadow: var(--clay-raised-sm);
}
[id^="desc-CLI"] > [id^="btn-ovr-"] .hi { width: 12px; height: 12px; }

/* ============ SIN MOSTAZA: tertiary → gris suave ============
   El "tertiary" de la paleta original es un mostaza (#725c07) que tiñe de
   amarillo textos secundarios, hints, el badge "esporádico" y un icono KPI
   por toda la app. Se alias al gris del tema: al resolverse en el uso,
   sigue automáticamente al modo claro/oscuro. */
:root {
  --color-tertiary: var(--color-on-surface-variant);
}

/* ============ COMPENSACIÓN ÓPTICA EN OSCURO ============
   El texto claro sobre fondo oscuro "sangra" luz (halación) y engorda
   visualmente. Solo se ajusta el suavizado (escala de grises, evita el
   engorde del subpixel rendering); los pesos NO se tocan para que cambiar
   de tema no cambie la letra de verdad. */
:root[data-theme="dark"] body {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) body {
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
  }
}

/* ============ CLAY DATEPICKER ============
   Popup de calendario propio (assets/js/clay-datepicker.js): tarjeta clay con
   superficie pastel, brillo superior y sombra de caída (mismas variables que
   los tooltips). El input nativo esconde su icono de calendario. */
input[type="date"].clay-dp-input::-webkit-calendar-picker-indicator { display: none; }
input[type="date"].clay-dp-input { cursor: pointer; }

.clay-dp {
  position: absolute;
  z-index: 10000;
  width: 284px;
  padding: .75rem;
  border-radius: var(--clay-r-md);
  background: var(--clay-tooltip-bg);
  box-shadow: var(--clay-tooltip-shadow);
  user-select: none;
  /* Paleta pastel del calendario (guía claymorphism); en color-mix con la
     superficie para que respiren igual en tema claro y oscuro */
  --dp-mint:  #7DD4A8;
  --dp-sky:   #9EC9F0;
  --dp-lemon: #F5D77A;
  --dp-peach: #FFB59E;
  --dp-pink:  #F5B8D0;
  --dp-coral: #FF7A6B;
}
.clay-dp[hidden] { display: none; }

.clay-dp__cab {
  display: flex;
  align-items: center;
  gap: .25rem;
  margin-bottom: .5rem;
}
.clay-dp__mes {
  flex: 1;
  display: flex;
  justify-content: center;
  gap: .3rem;
  text-align: center;
  font-weight: 700;
  color: var(--color-on-surface);
  text-transform: capitalize;
}
/* Mes y año son BOTONES: clic en el mes → rejilla de meses; en el año → años */
.clay-dp__titulo {
  border: none;
  background: transparent;
  font: inherit;
  font-weight: 700;
  color: var(--color-on-surface);
  cursor: pointer;
  padding: .1rem .35rem;
  border-radius: 8px;
  transition: background .12s ease, color .12s ease;
}
.clay-dp__titulo:hover {
  color: var(--color-primary);
  background: color-mix(in srgb, var(--color-primary) 10%, transparent);
}

/* Rejilla de meses/años: 3 columnas, celdas más altas */
.clay-dp__grid--meses { grid-template-columns: repeat(3, 1fr); gap: 6px; }
.clay-dp__grid--meses .clay-dp__mes-btn { height: 44px; font-size: .8rem; text-transform: capitalize; }
.clay-dp__nav {
  width: 30px; height: 30px;
  border: none;
  border-radius: 10px;
  background: var(--color-surface);
  box-shadow: var(--clay-raised-sm);
  color: var(--color-on-surface-variant);
  font-size: 1rem;
  cursor: pointer;
  transition: transform .1s ease, box-shadow .15s ease;
}
.clay-dp__nav:hover { color: var(--color-primary); }
.clay-dp__nav:active { transform: scale(.94); box-shadow: var(--clay-inset); }

.clay-dp__semana {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  margin-bottom: .25rem;
}
.clay-dp__semana span {
  text-align: center;
  font-size: .68rem;
  font-weight: 700;
  color: var(--color-on-surface-variant);
}
/* Fin de semana con su propio tono (S azul cielo, D coral suave) */
.clay-dp__semana span:nth-child(6) { color: color-mix(in srgb, var(--dp-sky) 70%, var(--color-on-surface)); }
.clay-dp__semana span:nth-child(7) { color: color-mix(in srgb, var(--dp-coral) 70%, var(--color-on-surface)); }
.clay-dp__grid:not(.clay-dp__grid--meses) .clay-dp__dia:nth-child(7n+6):not(.clay-dp__dia--sel) {
  background: color-mix(in srgb, var(--dp-sky) 14%, transparent);
}
.clay-dp__grid:not(.clay-dp__grid--meses) .clay-dp__dia:nth-child(7n):not(.clay-dp__dia--sel) {
  background: color-mix(in srgb, var(--dp-coral) 12%, transparent);
}

.clay-dp__grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
}
.clay-dp__dia {
  height: 32px;
  border: none;
  border-radius: 10px;
  background: transparent;
  color: var(--color-on-surface);
  font-size: .8rem;
  cursor: pointer;
  transition: background .12s ease, transform .1s ease;
}
.clay-dp__dia:hover { background: color-mix(in srgb, var(--color-primary) 12%, transparent); }
.clay-dp__dia:active { transform: scale(.92); }
.clay-dp__dia--otro { color: color-mix(in srgb, var(--color-on-surface-variant) 45%, transparent); }
/* Hoy: anillo verde menta (destaca sin competir con el morado de selección) */
.clay-dp__dia--hoy {
  box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--dp-mint) 85%, var(--color-on-surface));
  font-weight: 700;
}
.clay-dp__dia--sel {
  background: var(--color-primary);
  color: var(--color-on-primary, #fff);
  font-weight: 700;
  box-shadow: var(--clay-raised-sm);
}

.clay-dp__atajos {
  display: flex;
  gap: .4rem;
  margin-top: .6rem;
  padding-top: .6rem;
  border-top: 1px solid color-mix(in srgb, var(--color-outline) 25%, transparent);
}
.clay-dp__atajos button {
  flex: 1;
  border: none;
  border-radius: var(--clay-r-pill);
  padding: .35rem .4rem;
  font-size: .7rem;
  font-weight: 600;
  background: var(--color-surface);
  box-shadow: var(--clay-raised-sm);
  color: var(--color-on-surface);
  cursor: pointer;
  transition: transform .1s ease, filter .12s ease;
}
.clay-dp__atajos button:hover { filter: brightness(1.05); }
.clay-dp__atajos button:active { transform: scale(.95); box-shadow: var(--clay-inset); }
/* Cada atajo con su pastilla pastel (paleta de la guía) */
.clay-dp__atajos [data-atajo="hoy"]       { background: color-mix(in srgb, var(--dp-mint) 32%, var(--color-surface)); }
.clay-dp__atajos [data-atajo="ayer"]      { background: color-mix(in srgb, var(--dp-sky) 32%, var(--color-surface)); }
.clay-dp__atajos [data-atajo="iniciomes"] { background: color-mix(in srgb, var(--dp-lemon) 36%, var(--color-surface)); }
.clay-dp__atajos [data-atajo="finmes"]    { background: color-mix(in srgb, var(--dp-peach) 36%, var(--color-surface)); }
.clay-dp__atajos [data-atajo="borrar"]    { background: color-mix(in srgb, var(--dp-pink) 32%, var(--color-surface)); }

/* ============ MODO RENDIMIENTO (reducir efectos) ============
   Activado desde Ajustes (localStorage 'reducirEfectos', por equipo).
   Mata animaciones y transiciones en toda la app; el JS no depende de
   animationend/transitionend, así que nada se queda colgado. */
:root[data-efectos="reducidos"] *,
:root[data-efectos="reducidos"] *::before,
:root[data-efectos="reducidos"] *::after {
  animation: none !important;
  transition: none !important;
}
:root[data-efectos="reducidos"] {
  scroll-behavior: auto !important;
}
/* Los skeletons sin su pulso parecen contenido roto: se atenúan como carga estática */
:root[data-efectos="reducidos"] .cli-skeleton { opacity: .5; }
