:root {
    --signo-navy: #002855; /* PALETTE P2/P4 (v43): UI y docs PDF (.oc-doc/.mov-doc/#fwd/#costeo) unificados al navy V4 #002855. COMPLETO — la tabla on-screen del Costeo también quedó unificada (COSTEO-ONSCREEN-PALETTE). Verificado 2026-07-15: cero #0B2545 en fuentes. El design system hi-fi (#11151C ink / #0E1626 sidebar) coexiste POR DISEÑO (handoffs Claude Design); los PDFs van pinneados a literal, aislados de esta var a propósito. */
    --signo-blue: #13315C;
    --signo-red:  #C9182B;
    --signo-gold: #E8B547;
    --signo-bg:   #F5F7FB;
    /* D1.6 · Design system v1 · escala navy completa derivada de #002855 (V4 canónico).
       Para uso en CSS scoped fuera de Tailwind (CSS scoped del modal de OT). Las clases
       Tailwind bg-signo-800 / text-signo-400 etc. apuntan a estos mismos valores vía
       tailwind.config.js. Coexisten con --signo-navy: signo-800 ≡ --signo-navy. */
    --signo-50:  #F0F4FA;
    --signo-100: #DDE5F1;
    --signo-200: #B7C8E0;
    --signo-300: #84A0C9;
    --signo-400: #4A6FAA;
    --signo-500: #2A4F8B;
    --signo-600: #1C3A72;
    --signo-700: #14305A;
    --signo-800: #002855;
    --signo-900: #001A3D;
    --signo-950: #000D24;

    /* ============================================================
       D19.1 · Tokens del design system v1.1 (UX System Refresh SIGNO).
       Variables CSS centralizadas usables por componentes nuevos
       (SignoStatusPill, SignoButton, SignoEmptyState, SignoTextField,
       SignoInlineAlert, etc.) y por CSS scoped. Las clases Tailwind
       existentes NO cambian · estas vars son aditivas.
       Ver docs/d19-ux-audit.md §2.1 + §5 backlog.
       ============================================================ */

    /* Spacing scale · base 4px (matching Tailwind's spacing semantics).
       Uso recomendado: gaps internos de componentes nuevos, paddings,
       márgenes. Componentes existentes que usan Tailwind utility classes
       (`p-2.5`, `gap-3`, etc.) NO cambian. */
    --space-1:  0.25rem;  /*  4px · tight (icon gap, badge padding x) */
    --space-2:  0.5rem;   /*  8px · default inline */
    --space-3:  0.75rem;  /* 12px · group separator */
    --space-4:  1rem;     /* 16px · card padding base */
    --space-5:  1.25rem;  /* 20px · card padding comfortable */
    --space-6:  1.5rem;   /* 24px · section padding */
    --space-8:  2rem;     /* 32px · large gap (between cards) */
    --space-12: 3rem;     /* 48px · hero / empty-state padding */

    /* Radius scale · diseño Swiss Modernism: bordes finos, radius bajo.
       SIGNO tiende a 4-6px (.ot-card=4px, button rounded=6px). */
    --radius-xs:  2px;   /* badges micro */
    --radius-sm:  4px;   /* .ot-card actual · inputs · select · default */
    --radius-md:  6px;   /* modales · cards prominentes · .signo-modal */
    --radius-lg:  10px;  /* dialogs grandes · panels destacados */
    --radius-full: 9999px; /* pills, avatares circulares */

    /* Transition durations · microinteracciones discretas (HubSpot-style:
       rápidas, sin bouncing). Cubre hover/focus/active/expand. */
    --transition-fast:  100ms;  /* feedback inmediato · click feedback */
    --transition-base:  150ms;  /* hover/focus/border-color default */
    --transition-slow:  250ms;  /* expand/collapse · panel transitions */

    /* Easing curves · ease-out por defecto (entrada rápida + salida suave).
       NO usar ease-in-out con curva pronunciada · se siente lento. */
    --ease-out:        cubic-bezier(0.16, 1, 0.3, 1);     /* default · ux nice */
    --ease-in-out:     cubic-bezier(0.4, 0, 0.2, 1);      /* modal open/close */
    --ease-in:         cubic-bezier(0.4, 0, 1, 1);        /* salidas (rare) */

    /* Shadows · usar sparingly. Modales/dropdowns ya están en Tailwind
       config (shadow-modal, shadow-dropdown). Estos son complementarios
       para superficies que no merecen shadow-modal pero quieren elevación. */
    --shadow-xs: 0 1px 2px rgba(0, 40, 85, 0.06);
    --shadow-sm: 0 2px 4px rgba(0, 40, 85, 0.08), 0 1px 2px rgba(0, 40, 85, 0.04);
    --shadow-md: 0 4px 8px -2px rgba(0, 40, 85, 0.10), 0 2px 4px -2px rgba(0, 40, 85, 0.06);
    --shadow-lg: 0 8px 16px -4px rgba(0, 40, 85, 0.12), 0 4px 8px -4px rgba(0, 40, 85, 0.08);

    /* Borders · grosor consistente. SIGNO usa borders 1px en superficies
       y border-l 4px en alerts/banner critical. */
    --border-thin:    1px;
    --border-base:    1px;  /* alias semántico para "borde por defecto" */
    --border-accent:  2px;  /* outline buttons, focused inputs */
    --border-banner:  4px;  /* alerts P1 critical, border-l banner */

    /* Touch targets · mínimo accesible 36px (WCAG AA · alineado con
       constraint v43 documentado). Botones icon-only deben respetarlo. */
    --touch-target-min: 36px;
    --touch-target-md:  40px;  /* botones primarios */
    --touch-target-lg:  44px;  /* CTA hero mobile */

    /* Z-index scale · evita el chaos de z-50/z-40/z-30 inconsistente.
       Solo declarativo · componentes nuevos lo usan. */
    --z-base:      0;
    --z-dropdown:  20;
    --z-sticky:    30;
    --z-modal:     50;
    --z-toast:     60;
    --z-tooltip:   70;
  }
  /* APP-HORIZONTAL-SCROLL-FIX (v43): el scroll horizontal debe vivir SOLO dentro de
     tablas/preview específicos (que conservan su overflow-x-auto), nunca en todo el
     body. El preview off-screen del editor (.ed-preview[data-active=false] a
     left:-99999px) extendía el ancho scrolleable global → la app quedaba corrida.
     overflow-x: hidden a nivel raíz lo encapsula. No afecta sticky (los headers
     sticky viven en contenedores con overflow propio, no a nivel body). */
  html { overflow-x: hidden; }
  body { background: var(--signo-bg); font-family: 'Inter', system-ui, -apple-system, sans-serif; overflow-x: hidden; }
  #root { overflow-x: hidden; }
  /* MOBILE-MODULE-FULL-VIEWPORT — los módulos full-screen ocultan la navegación
     global móvil y administran su propia navegación inferior. No reservar los
     56px del bottom-bar global: esa franja dejaba ver la pantalla base y recortaba
     el CTA local en navegadores móviles con viewport dinámico. */
  @media (max-width: 767px) {
    .mobile-module { bottom: 0 !important; min-height: 100dvh; }
  }
  .signo-navy { background-color: var(--signo-navy); color: #fff; }
  .signo-red  { background-color: var(--signo-red);  color: #fff; }
  .text-signo-navy { color: var(--signo-navy); }
  .text-signo-red  { color: var(--signo-red);  }
  .border-signo    { border-color: var(--signo-navy); }
  /* UI-1 (v43): revivir clases utilitarias muertas. Tailwind CDN no compila
     clases custom, así que estas se usaban (bg-/border-signo-*) pero no existían
     → renderizaban sin color. Se definen mapeadas a las vars legacy. Las clases
     bg-* solo fijan background-color (sin forzar color de texto) para respetar
     el text-white que ya acompaña a cada elemento. PALETTE P4: el navy de los
     docs PDF quedó unificado al V4 #002855 (ver más abajo). */
  .bg-signo-navy     { background-color: var(--signo-navy); }
  .bg-signo-red      { background-color: var(--signo-red);  }
  .border-signo-navy { border-color: var(--signo-navy); }
  .border-signo-red  { border-color: var(--signo-red);  }
  .ring-signo:focus { outline: none; box-shadow: 0 0 0 2px rgba(0,40,85,0.25); }
  /* FASE_5_UX — Headers del catálogo con estilo navy + sticky */
  .cat-th { background-color: var(--signo-navy); color: #fff; position: sticky; top: 0; z-index: 10; font-weight: 600; letter-spacing: 0.025em; text-transform: uppercase; font-size: 11px; border: 1px solid #163a6b; padding: 8px 8px; }
  .cat-th-sort { cursor: pointer; user-select: none; transition: background-color 120ms; }
  .cat-th-sort:hover { background-color: #163a6b; }
  .cat-th-active { background-color: #1a4480; }

  /* PDF preview look */
  .oc-doc {
    font-family: 'Helvetica Neue', Arial, sans-serif;
    color: #111;
    background: #fff;
    width: 8.5in;
    min-height: 11in;
    padding: 0.5in;
    box-sizing: border-box;
    box-shadow: 0 4px 20px rgba(0,0,0,0.08);
    font-size: 10pt;
  }
  .oc-doc table { border-collapse: collapse; width: 100%; }
  .oc-doc th, .oc-doc td { border: 1px solid #2a2a2a; padding: 4px 6px; vertical-align: top; }
  /* PALETTE P1/P4 (v43): docs PDF pinneados a literal #002855 (navy V4), aislados
     del var --signo-navy a propósito. P4 unificó el navy legacy #0B2545 → #002855
     en estas superficies PDF. No cambiar sin smoke PDF. */
  .oc-doc th { background: #002855; color: #fff; font-size: 9pt; text-align: left; }
  .oc-doc .label { background: #f1f3f7; font-weight: 600; }
  .oc-doc .header-band { background: #002855; color: #fff; padding: 8px 12px; }
  .oc-doc .red-band { background: var(--signo-red); height: 6px; }

  /* INV-OPS-D2d-1 — Comprobante de movimiento (salida/retorno D/P/RMA). Estilos
     PROPIOS, independientes de .oc-doc. Se renderiza off-screen en #mov-print-target
     y se exporta con html2pdf (letter portrait). No afecta el PDF de la OC. */
  .mov-doc {
    font-family: 'Helvetica Neue', Arial, sans-serif;
    color: #111; background: #fff; width: 8.5in; min-height: 11in;
    padding: 0.5in; box-sizing: border-box; font-size: 10pt;
  }
  .mov-doc .mov-band { background: #002855; color: #fff; padding: 12px 16px; display: flex; align-items: center; justify-content: space-between; }
  .mov-doc .mov-band img { height: 40px; }
  .mov-doc .mov-red { background: var(--signo-red); height: 6px; }
  .mov-doc .mov-title { font-size: 13pt; font-weight: 700; letter-spacing: 0.02em; }
  .mov-doc .mov-codigo { font-family: 'Courier New', monospace; font-size: 12pt; font-weight: 700; }
  .mov-doc table { border-collapse: collapse; width: 100%; }
  .mov-doc th, .mov-doc td { border: 1px solid #2a2a2a; padding: 4px 6px; vertical-align: top; }
  .mov-doc th { background: #002855; color: #fff; font-size: 9pt; text-align: left; }
  .mov-doc .meta { width: 100%; margin: 14px 0; }
  .mov-doc .meta td { border: none; padding: 2px 6px; font-size: 9.5pt; }
  .mov-doc .meta .k { color: #555; width: 130px; }
  .mov-doc .meta .v { font-weight: 600; }
  .mov-doc .firma-box { border-top: 1px solid #111; padding-top: 4px; text-align: center; font-size: 9pt; }

  /* RECIBOS-PDF — Recibo de Caja imprimible. Estilos INDEPENDIENTES de
     .oc-doc/.mov-doc/.ot-doc. Letter portrait · banda navy #002855 + franja roja. */
  .recibo-doc { width: 816px; box-sizing: border-box; font-family: Arial, Helvetica, sans-serif; color: #111; background: #fff; position: relative; }
  .recibo-doc .rc-band { background: #002855; color: #fff; padding: 14px 22px; display: flex; align-items: center; justify-content: space-between; }
  .recibo-doc .rc-band img { height: 42px; }
  .recibo-doc .rc-title { font-size: 15pt; font-weight: 700; letter-spacing: 0.04em; }
  .recibo-doc .rc-serie { font-family: 'Courier New', monospace; font-size: 12pt; font-weight: 700; margin-top: 2px; }
  .recibo-doc .rc-red { background: #C9182B; height: 6px; }
  .recibo-doc .rc-body { padding: 20px 28px 26px; }
  .recibo-doc table.rc-meta { width: 100%; border-collapse: collapse; margin: 4px 0 12px; }
  .recibo-doc table.rc-meta td { padding: 4px 6px; font-size: 10pt; vertical-align: top; border-bottom: 1px solid #f0f0f0; }
  .recibo-doc table.rc-meta .k { color: #555; width: 140px; white-space: nowrap; }
  .recibo-doc table.rc-meta .v { font-weight: 600; }
  .recibo-doc .rc-concepto { font-size: 10pt; white-space: pre-line; border: 1px solid #ddd; border-radius: 4px; padding: 8px 10px; margin: 10px 0; }
  .recibo-doc .rc-monto-box { border: 2px solid #002855; border-radius: 6px; padding: 12px 16px; margin: 12px 0; display: flex; align-items: center; justify-content: space-between; gap: 16px; }
  .recibo-doc .rc-monto-lbl { font-size: 9pt; color: #555; text-transform: uppercase; letter-spacing: 0.05em; }
  .recibo-doc .rc-letras { font-size: 10pt; font-style: italic; color: #333; margin-top: 4px; }
  .recibo-doc .rc-monto { font-size: 20pt; font-weight: 800; font-family: 'Courier New', monospace; white-space: nowrap; }
  .recibo-doc .rc-notas { font-size: 9pt; color: #333; margin-top: 8px; }
  .recibo-doc .rc-firma { margin-top: 52px; text-align: center; }
  .recibo-doc .rc-firma .rc-line { border-top: 1px solid #111; width: 58%; margin: 0 auto; padding-top: 5px; font-size: 9pt; color: #333; }
  .recibo-doc .rc-footer { font-size: 8pt; color: #777; margin-top: 14px; border-top: 1px solid #eee; padding-top: 6px; }
  .recibo-doc .rc-watermark { position: absolute; top: 42%; left: 0; right: 0; text-align: center; font-size: 64pt; font-weight: 800; color: rgba(201,24,43,0.16); transform: rotate(-18deg); pointer-events: none; letter-spacing: 0.1em; }

  /* F4E.1 — PDF Acta de Servicio (Orden de Trabajo). Estilos INDEPENDIENTES
     de .oc-doc y .mov-doc · cualquier cambio futuro a OC/Mov PDFs NO afecta
     OT PDF, y viceversa. Letter portrait · 0.5in padding · navy #002855 +
     red Signo banding consistente con los otros PDFs Signo. Decisión usuario
     (F4E pre-codeo): español V1, máx 4 evidencias-imagen en grid, firmas
     siempre con page-break-inside: avoid, caja ámbar para justificadas. */
  /* F4E.12 · Refactor a wrappers .ot-page con altura forzada · alineado con
     el patrón de OC PDF (.oc-doc) que NO sufre este problema.
     · .ot-doc · solo contenedor visual · sin padding/min-height
     · .ot-page · cada "página lógica" del PDF (página 1 + opcional anexo)
       - min-height: 11in (letter portrait · MISMA altura que OC PDF)
       - display: flex; flex-direction: column · permite footer flotante abajo
       - padding interno · el .ot-doc ya no lo tiene
     · Resuelve: footer flotando entre páginas (capturas usuario F4E.11) ·
       el footer ahora SIEMPRE se ancla al fondo de su .ot-page con margin-top:
       auto · idéntico al comportamiento de OC PDF. */
  /* A6 · CSS del PDF de Acta de Entrega · INDEPENDIENTE de .ot-doc / .oc-doc.
     El doc fluye en alto natural (ancho 8.5in); handleExportActaPDF rasteriza
     y corta en páginas letter. NO tocar .ot-doc ni .oc-doc. */
  .acta-doc {
    font-family: 'Helvetica Neue', Arial, sans-serif;
    color: #111; background: #fff;
    width: 8.5in; box-sizing: border-box; font-size: 8.25pt; line-height: 1.28;
    padding: 0.3in 0.34in;
  }
  .acta-doc .acta-band {
    background: #002855; color: #fff; padding: 10px 14px;
    display: grid; grid-template-columns: 1fr 1fr 1fr; align-items: center; gap: 12px;
  }
  .acta-doc .acta-band img { height: 34px; justify-self: start; }
  .acta-doc .acta-band .acta-title { font-size: 13pt; font-weight: 700; letter-spacing: 0.03em; text-align: center; justify-self: center; }
  .acta-doc .acta-band .acta-numero { font-family: 'Courier New', monospace; font-size: 10pt; font-weight: 700; text-align: right; justify-self: end; }
  .acta-doc .acta-band .acta-pais { font-size: 8pt; opacity: 0.85; display: block; }
  .acta-doc .acta-red-band { background: #C9182B; height: 6px; margin-bottom: 8px; }
  .acta-doc .acta-meta { width: 100%; margin: 6px 0 3px; border-collapse: collapse; }
  .acta-doc .acta-meta td { border: none; padding: 2px 5px; font-size: 8pt; vertical-align: top; line-height: 1.32; }
  .acta-doc .acta-meta .k { color: #555; width: 104px; }
  .acta-doc .acta-meta .v { font-weight: 600; }
  .acta-doc .acta-declaration { margin: 7px 0 6px; border: 1px solid #cbd5e1; padding: 6px 8px; break-inside: avoid; }
  .acta-doc .acta-declaration-title { color: #002855; font-size: 8pt; font-weight: 800; text-align: center; letter-spacing: 0.025em; margin-bottom: 3px; }
  .acta-doc .acta-declaration p { margin: 0; font-size: 7.5pt; line-height: 1.32; text-align: justify; }
  .acta-doc .acta-sec { background: #eef2f7; color: #002855; font-weight: 700; font-size: 8pt; padding: 3px 7px; margin: 7px 0 3px; border-left: 3px solid #C9182B; }
  .acta-doc .acta-table { width: 100%; border-collapse: collapse; margin: 2px 0 6px; }
  .acta-doc .acta-table th { background: #f1f5f9; color: #334155; font-size: 6.5pt; text-transform: uppercase; letter-spacing: 0.02em; text-align: left; padding: 3px 4px; border: 1px solid #b8c5d6; }
  .acta-doc .acta-table td { font-size: 7.25pt; padding: 3px 4px; border: 1px solid #d7dee8; vertical-align: top; }
  .acta-doc .acta-table .acta-group td { background: #f8fafc; color: #002855; border-color: #c3cfdd; font-size: 6.5pt; font-weight: 700; text-transform: uppercase; letter-spacing: 0.02em; padding: 2px 4px; }
  .acta-doc .acta-col-qty { width: 5%; }
  .acta-doc .acta-col-brand { width: 10%; }
  .acta-doc .acta-col-model { width: 12%; }
  .acta-doc .acta-col-serial { width: 24%; }
  .acta-doc .acta-col-description { width: 37%; }
  .acta-doc .acta-col-status { width: 12%; }
  .acta-doc .acta-status { font-size: 6.5pt; line-height: 1.18; }
  .acta-doc .acta-acceptance-close { margin: 9px 0 3px; font-size: 7.5pt; line-height: 1.32; text-align: justify; break-inside: avoid; }
  .acta-doc .acta-firmas { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-top: 14px; padding-bottom: 9px; }
  .acta-doc .acta-firma { text-align: center; break-inside: avoid; }
  .acta-doc .acta-firma-head { color: #002855; font-size: 9pt; font-weight: 800; margin-bottom: 2px; }
  .acta-doc .acta-firma .sig-img { height: 56px; object-fit: contain; margin: 0 auto 2px; display: block; }
  .acta-doc .acta-firma .sig-line { border-top: 1px solid #333; margin-top: 26px; padding-top: 3px; font-size: 7.5pt; }
  .acta-doc .acta-firma .sig-field { min-height: 15px; text-align: left; border-bottom: 1px solid #cbd5e1; padding: 2px 3px; }
  .acta-doc .acta-firma .sig-field span { color: #555; font-size: 7.5pt; font-weight: 700; }
  .acta-doc .acta-firma .sig-role { color: #555; font-size: 7.5pt; }
  .acta-doc .acta-firma .sig-label { color: #555; font-size: 7pt; line-height: 1.35; margin-top: 12px; padding-bottom: 2px; }
  .acta-doc .acta-foot { margin-top: 10px; border-top: 1px solid #cbd5e1; padding-top: 4px; font-size: 6.5pt; color: #777; text-align: center; display: grid; gap: 2px; }
  .acta-doc .acta-corp { color: #002855; font-size: 7.5pt; font-weight: 700; letter-spacing: 0.025em; }
  .acta-doc .acta-address { color: #64748b; font-size: 7pt; line-height: 1.25; }

  /* Actas · editor compacto: dos niveles en desktop, apilado legible en móvil. */
  .acta-equipment-primary {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: end;
    gap: 8px;
  }
  .acta-equipment-kind { display: inline-flex; align-items: center; gap: 6px; align-self: center; }
  .acta-equipment-section { min-width: 0; }
  .acta-equipment-description { grid-column: 1 / span 2; min-width: 0; }
  .acta-equipment-quantity { grid-column: 3; width: 100px; }
  .acta-equipment-actions { justify-self: end; align-self: center; }
  .acta-equipment-details { display: block; }
  .acta-equipment-tech { margin-top: 8px; display: grid; grid-template-columns: 1fr; gap: 8px; }
  @media (min-width: 1024px) {
    .acta-equipment-primary {
      grid-template-columns: auto minmax(180px, .72fr) minmax(320px, 1.55fr) 90px auto;
    }
    .acta-equipment-description, .acta-equipment-quantity { grid-column: auto; }
    .acta-equipment-details {
      display: grid;
      grid-template-columns: 190px minmax(0, 1fr);
      align-items: end;
      gap: 8px;
    }
    .acta-equipment-details > summary { align-self: center; }
    .acta-equipment-tech {
      margin-top: 0;
      grid-template-columns: repeat(5, minmax(0, 1fr));
    }
  }

  .ot-doc {
    font-family: 'Helvetica Neue', Arial, sans-serif;
    color: #111;
    background: #fff;
    width: 8.5in;
    box-sizing: border-box;
    font-size: 9.5pt;
  }
  .ot-doc .ot-page {
    width: 8.5in;
    /* F4G.5 · CAMBIO CRÍTICO · height fijo en vez de min-height.
       min-height permitía que .ot-page creciera > 11in cuando el contenido
       era extenso · el footer (margin-top:auto) terminaba más allá del corte
       de 11in que hace html2pdf y rebotaba a página 2 (encima del anexo).
       Ahora cada .ot-page es exactamente 1 página letter portrait.
       margin: 0 defensivo · evita gaps por colapso de margin entre páginas.
       overflow: hidden defensivo · si por algún caso edge un contenido excede
       11in, se clipea ANTES de derramar a la siguiente PDF page. Las
       compactaciones F4G.4 garantizan que el caso real cabe. */
    height: 11in;
    margin: 0;
    overflow: hidden;
    /* F4G.4/12/13 · padding evolución: 0.25/0.4/0.15 → 0.25/0.4/0.22 → 0.25/0.4/0.35
       F4G.15 · padding SIMÉTRICO arriba/abajo (0.35/0.4/0.35) para mejor
       balance visual del documento. Top antes era 0.25in (apretado) ahora
       0.35in dándole respiración igual al footer. Sides 0.4in conservados.
       Content area total: 11 - 0.35 - 0.35 = 10.3in (más que suficiente
       para nuestro contenido compactado F4G.4 + F4G.14). */
    padding: 0.35in 0.4in 0.35in;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
  }
  /* F4G.5 · Salto de página explícito entre .ot-page consecutivos.
     Combinado con height:11in fijo asegura que html2pdf rasterice y pagine
     LIMPIO · page 1 = primer .ot-page entero · page 2 = anexo entero.
     F4G.6 · agregado .ot-page-anexo como selector adicional · más explícito
     para html2pdf pagebreak.before (ver F4E_HTML2PDF_OPTS). */
  .ot-doc .ot-page + .ot-page,
  .ot-doc .ot-page-anexo {
    page-break-before: always;
    break-before: page;
  }
  /* F4G.6 · Wrapper .ot-page-body con flex 1 · absorbe TODO el espacio entre
     header y footer dentro del .ot-page (height 11in fijo). Resultado:
     · header SIEMPRE arriba del .ot-page (sin gap dependiente del contenido)
     · footer SIEMPRE pegado al borde inferior (sin rebotar a la pág siguiente)
     · contenido fluye normal dentro de body
     · min-height: 0 evita que el body inflate más allá del contenedor cuando
       el contenido excede (defensive · combina con overflow:hidden de ot-page) */
  .ot-doc .ot-page-body {
    flex: 1 1 auto;
    min-height: 0;
    display: block;
  }
  /* Footer · flex-shrink: 0 garantiza que NUNCA se comprima por presión del
     body. Sin esto, en flex column un footer "compresible" se aplasta si el
     body crece · acá lo blindamos. margin-top: auto queda redundante con
     flex:1 del body pero lo dejamos por compat con código previo. */
  .ot-doc .ot-page .ot-footer {
    margin-top: auto;
    flex: 0 0 auto;
  }
  /* Banda navy header · logo izq + título centro + número derecha.
     F4G.15 · CSS grid 3 columnas iguales (1fr 1fr 1fr) garantiza que el
     título quede EN EL CENTRO ABSOLUTO de la página, independiente de los
     anchos del logo (left) y del bloque número (right). Antes con flex
     justify-content space-between + flex:1 en title, el centrado dependía
     del balance logo↔numero · si pesaban distinto, el título se veía corrido. */
  .ot-doc .ot-band {
    background: #002855;
    color: #fff;
    padding: 10px 14px;
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    align-items: center;
    gap: 12px;
  }
  /* F4E.5 · El logo ya viene en blanco como PNG generado programáticamente
     en handleExportOTPDF (f4eLogoToWhite). Quitamos el filter CSS de F4E.4
     porque html2canvas no lo respetaba en producción. */
  .ot-doc .ot-band img { height: 38px; justify-self: start; }
  .ot-doc .ot-band .ot-title {
    font-size: 14pt; font-weight: 700; letter-spacing: 0.03em;
    text-align: center; justify-self: center;
  }
  .ot-doc .ot-band .ot-numero {
    font-family: 'Courier New', monospace; font-size: 11pt; font-weight: 700;
    text-align: right; justify-self: end;
  }
  .ot-doc .ot-band .ot-pais { font-size: 8pt; opacity: 0.85; display: block; }
  /* Placeholder cuando no hay logo · ocupa la columna izquierda igual */
  .ot-doc .ot-band > span:empty { justify-self: start; }
  /* Banda roja 6px decorativa */
  .ot-doc .ot-red-band { background: var(--signo-red); height: 6px; }

  /* Tabla de metadatos · 2 cols sin border · label gris / value bold.
     F4E.4 · márgenes reducidos para mejor paginación.
     F4G.4 · padding 1.5→1, margin 8/4→6/3 (ahorra ~16px verticales).
     F4G.12 · padding 1→3px vertical · line-height 1.4 explícito
     F4G.14 · padding 3→4px vertical · line-height 1.4→1.5 · resuelve definitivamente
     el solape del Impacto sobre la línea separadora (valores largos de Impacto
     que ocupan 2 líneas tienen ahora aire cómodo). */
  .ot-doc .ot-meta { width: 100%; margin: 6px 0 3px; border-collapse: collapse; }
  .ot-doc .ot-meta td {
    border: none;
    padding: 4px 6px;
    font-size: 9pt;
    vertical-align: top;
    line-height: 1.5;
  }
  .ot-doc .ot-meta .k { color: #555; width: 110px; }
  .ot-doc .ot-meta .v { font-weight: 600; }

  /* Encabezados de sección · banda gris claro.
     F4E.4 · margen superior reducido (12 → 8) y padding (4 → 3) para compacidad.
     F4G.4 · margin 8/3→6/2, padding 3→2.
     F4G.16 · centrado vertical · min-height 22px + flex align-items center +
     line-height 1.2 explícito. El título de la sección queda perfectamente
     centrado dentro de la banda gris sin rozar bordes superior/inferior. */
  .ot-doc h2.ot-section {
    background: #f1f3f7;
    color: #002855;
    padding: 4px 10px;
    font-size: 10pt;
    font-weight: 600;
    margin: 6px 0 3px;
    border-left: 3px solid #002855;
    min-height: 22px;
    display: flex;
    align-items: center;
    line-height: 1.2;
  }

  /* Tablas internas (contactos, equipos, líneas)
     F4G.4 · padding 4/6→3/5, mb 6→4
     F4G.12 · padding 3/5→4/6 + line-height 1.3
     F4G.13 · padding 4/6→6/8 + line-height 1.3→1.4 + word-break/wrap normal
     F4G.14 · padding 6/8→8/10 + line-height 1.4→1.5 · respiración cómoda
     en descripciones de 2 líneas. Preferimos whitespace sobre crowding. */
  .ot-doc table.ot-table { border-collapse: collapse; width: 100%; margin-bottom: 4px; }
  .ot-doc table.ot-table th,
  .ot-doc table.ot-table td {
    border: 1px solid #2a2a2a;
    padding: 8px 10px;
    vertical-align: top;
    font-size: 9pt;
    line-height: 1.5;
    word-break: normal;
    overflow-wrap: break-word;
  }
  .ot-doc table.ot-table th {
    background: #002855;
    color: #fff;
    font-size: 8.5pt;
    text-align: left;
    font-weight: 600;
  }

  /* Bloques de texto multilínea (servicio_solicitado, diagnostico, trabajos_*).
     F4E.4 · padding y min-height reducidos para compacidad.
     F4G.4 · padding 4→3, min-height 22→18, line-height 1.3→1.25, mb 4→3.
     F4G.16 · centrado vertical · padding 3/8→6/10, min-height 18→24,
     line-height 1.25→1.4, display flex align-items center.
     Texto se centra ópticamente en la caja gris sin rozar bordes.
     Para multilínea (\n en el value), flex centra el bloque entero · el
     pre-wrap conserva los saltos · sin romper layout. */
  .ot-doc .ot-multiline {
    white-space: pre-wrap;
    padding: 6px 10px;
    border: 1px solid #ddd;
    background: #fafafa;
    min-height: 24px;
    font-size: 9pt;
    line-height: 1.4;
    margin-bottom: 4px;
    display: flex;
    align-items: center;
  }
  .ot-doc .ot-multiline.empty {
    color: #999;
    font-style: italic;
    background: #fff;
  }
  /* F4G.4 · Permite que html2pdf corte LIMPIO entre secciones cuando una
     sección de texto larga obliga a paginar (raro, pero defensivo). Cada
     h2.ot-section + su .ot-multiline siguiente forman un bloque atómico que
     no se corta a la mitad · si no cabe, salta entero. Esto evita títulos
     huérfanos al final de página 1. */
  .ot-doc h2.ot-section,
  .ot-doc .ot-multiline {
    page-break-inside: avoid;
    break-inside: avoid;
  }

  /* Grid de evidencias · F4E.5 · FORZADO a 2 columnas (imágenes siempre en
     pares lado a lado). Altura reducida 2.4in → 1.6in para que entren 2 filas
     en menos espacio vertical · favorece paginación ≤2 páginas. */
  .ot-doc .ot-evidencias-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 6px;
    margin-bottom: 6px;
  }
  .ot-doc .ot-evidencia-cell {
    border: 1px solid #ddd;
    padding: 3px;
    page-break-inside: avoid;
    background: #fff;
  }
  .ot-doc .ot-evidencia-cell img {
    width: 100%;
    height: 1.6in;
    object-fit: cover;
    display: block;
  }
  .ot-doc .ot-evidencia-cell .caption {
    font-size: 7.5pt;
    color: #555;
    padding: 2px 4px 0;
    line-height: 1.2;
  }
  .ot-doc .ot-evidencias-nota {
    font-size: 8pt;
    color: #555;
    font-style: italic;
    margin: 4px 0 6px;
  }
  /* Lista textual de adjuntos no-imagen (PDF/video/log) */
  .ot-doc .ot-adjuntos-list {
    list-style: disc inside;
    font-size: 9pt;
    margin: 4px 0;
    padding-left: 4px;
  }

  /* F4E.12 / F4G.5 · .ot-anexo es solo una variante semántica de .ot-page.
     El page-break ahora vive en `.ot-page + .ot-page` (selector arriba) ·
     siempre disparado para cualquier secuencia de .ot-page. El padding,
     height, flex column vienen heredados de .ot-page.
     · .ot-cierre-block ya no se usa (eliminado en F4E.12 · footer ahora
       se ancla al fondo del .ot-page con margin-top: auto, no en wrapper). */
  .ot-doc .ot-anexo .ot-anexo-content {
    padding-top: 4px;
  }
  .ot-doc .ot-anexo h2.ot-section {
    margin-top: 8px;
  }

  /* Sección Conformidad · firmas · SIEMPRE protegida de saltos.
     F4E.5 · compactada: margin-top 18 → 10, padding 10 → 6, height 1.1in →
     0.85in · evita que el bloque de firmas + footer se salten a página vacía.
     F4G.4 · margin-top 10→6, padding 6/8→4/6, height 0.85→0.75in, img max-height
     0.75→0.65in, label padding-top 6→4, line-height 1.3→1.25 (ahorra ~25px). */
  .ot-doc .ot-firmas {
    width: 100%;
    margin-top: 6px;
    page-break-inside: avoid;
    border-collapse: collapse;
  }
  .ot-doc .ot-firmas td {
    width: 50%;
    text-align: center;
    border: none;
    padding: 4px 6px;
    vertical-align: top;
  }
  .ot-doc .ot-firma-box {
    border-bottom: 1px solid #111;
    height: 0.75in;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    padding: 3px;
    background: #fff;
  }
  .ot-doc .ot-firma-box img {
    max-height: 0.65in;
    max-width: 100%;
    object-fit: contain;
  }
  .ot-doc .ot-firma-label {
    font-size: 8.5pt;
    padding-top: 4px;
    line-height: 1.25;
  }
  .ot-doc .ot-firma-label .ot-firma-nombre  { font-weight: 700; color: #111; display: block; }
  .ot-doc .ot-firma-label .ot-firma-cargo   { color: #555; display: block; }
  .ot-doc .ot-firma-label .ot-firma-fecha   { color: #777; font-family: 'Courier New', monospace; font-size: 7.5pt; display: block; margin-top: 2px; }
  .ot-doc .ot-firma-label .ot-firma-by      { color: #777; font-size: 7.5pt; display: block; }
  /* Caja ámbar para "Servicio sin firma física" · explícita para el cliente */
  .ot-doc .ot-firma-justif {
    border: 1.5px solid #d97706;
    background: #fef3c7;
    color: #92400e;
    padding: 8px 10px;
    height: 1.1in;
    font-size: 8.5pt;
    line-height: 1.3;
    text-align: left;
    display: flex;
    flex-direction: column;
    justify-content: center;
    box-sizing: border-box;
  }
  .ot-doc .ot-firma-justif .ot-justif-title { font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; font-size: 8pt; margin-bottom: 3px; }
  .ot-doc .ot-firma-justif .ot-justif-motivo { font-style: italic; }

  /* Indicadores de cierre · tabla compacta · 2 cols · solo respondidos */
  .ot-doc .ot-indicadores {
    width: 100%;
    border-collapse: collapse;
    margin-bottom: 6px;
  }
  .ot-doc .ot-indicadores td {
    border: 1px solid #ddd;
    padding: 4px 6px;
    font-size: 9pt;
    width: 50%;
    vertical-align: top;
  }
  .ot-doc .ot-indicadores .k { color: #555; font-weight: normal; }
  .ot-doc .ot-indicadores .v { font-weight: 600; }
  .ot-doc .ot-indicadores .v.si { color: #047857; }
  .ot-doc .ot-indicadores .v.no { color: #b45309; }

  /* F4E.4/F4E.11/F4G.11 · Footer corporativo compacto · 3 líneas centradas
     (tagline + URL + países) + audit con 3 spans (Generado / Página / OT).
     F4G.11 · más respiración vertical + separación del audit:
       · padding-top 4→6, margin-top 8→10
       · tagline mb 1→3 · URL mb 1→2 · países mb 2→6 (más aire entre líneas)
       · audit border-top eliminado · usa solo padding/margin-top para separar
       · audit padding-top 2→6 · margin-top 2→6 · font 6.5→7pt (más legible)
       · audit padding-bottom 2 nuevo · ancla el bloque al borde inferior
     Esto separa visualmente el bloque corporativo (azul/rojo/gris) de la línea
     de auditoría (gris pequeña) sin restar identidad. */
  .ot-doc .ot-footer {
    border-top: 1.5px solid #002855;
    padding-top: 6px;
    padding-bottom: 2px;
    margin-top: 10px;
    text-align: center;
  }
  .ot-doc .ot-footer .corp-tagline {
    font-size: 8pt;
    font-weight: 700;
    color: #002855;
    letter-spacing: 0.02em;
    margin: 0 0 3px 0;
  }
  .ot-doc .ot-footer .corp-url {
    font-size: 8pt;
    color: #C9182B;
    font-weight: 600;
    margin: 0 0 2px 0;
  }
  .ot-doc .ot-footer .corp-paises {
    font-size: 7pt;
    color: #555;
    margin: 0 0 6px 0;
    letter-spacing: 0.01em;
  }
  /* F4G.15 · audit line con CSS grid 3-col equal · garantiza que "Página N de M"
     quede en el centro absoluto del documento (mismo eje vertical que el
     título de la banda navy). Antes con flex justify-content space-between,
     el span central podía aparecer corrido si los spans laterales tenían
     anchos asimétricos (Generado fecha vs OT-XXX número). */
  .ot-doc .ot-footer .audit {
    font-size: 7pt;
    color: #888;
    padding-top: 6px;
    margin-top: 6px;
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    align-items: center;
    gap: 12px;
    line-height: 1.3;
  }
  .ot-doc .ot-footer .audit > :nth-child(1) { justify-self: start; }
  .ot-doc .ot-footer .audit > :nth-child(2) { justify-self: center; text-align: center; }
  .ot-doc .ot-footer .audit > :nth-child(3) { justify-self: end; text-align: right; }

  /* D21.2 · Animaciones de drawer · slide-in from right + fade. */
  @keyframes signo-drawer-slide-in {
    from { transform: translateX(100%); opacity: 0.5; }
    to   { transform: translateX(0);    opacity: 1; }
  }
  .signo-drawer-enter {
    animation: signo-drawer-slide-in 240ms var(--ease-out, cubic-bezier(0.16, 1, 0.3, 1));
  }

  /* Scroll containers */
  .pane { max-height: calc(100vh - 170px); overflow: auto; }
  .preview-wrap { transform-origin: top left; }

  /* UI-2a (v43): en <lg el editor alterna form/preview con un toggle. El pane de
     preview se mantiene MONTADO y medible (html2pdf lee #print-target); cuando
     está inactivo en móvil se posiciona fuera de pantalla en vez de display:none,
     así el export sigue funcionando aun en modo "Editar". En ≥1024px la media
     query no aplica → el split 50/50 queda idéntico y el toggle no se ve. */
  @media (max-width: 1023px) {
    .ed-pane[data-active="false"]    { display: none; }
    .ed-preview[data-active="false"] { position: absolute; left: -99999px; top: 0; width: 860px; }
    /* UI-2c: en móvil/tablet la tabla de Líneas no se comprime hasta volverse
       inusable; mantiene un ancho mínimo y el pane (overflow:auto) hace scroll
       horizontal. En ≥1024px no aplica → tabla w-full como hoy. */
    .lineas-table { min-width: 680px; }
  }

  /* OC-PREVIEW-TOGGLE — en escritorio oculto conserva #print-target montado
     fuera del viewport, mientras el formulario ocupa la única columna. */
  @media (min-width: 1024px) {
    .ed-preview[data-desktop-visible="false"] { position: absolute; left: -99999px; top: 0; width: 860px; }
  }

  /* Number input clean */
  input[type=number]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

  /* Autocomplete */
  .ac-list { position: absolute; top: 100%; left: 0; right: 0; background: #fff; border: 1px solid #ccc; max-height: 480px; overflow: auto; z-index: 50; }
  .ac-item { padding: 8px 10px; cursor: pointer; font-size: 13px; }
  .ac-item:hover, .ac-item.active { background: #eef2f7; }

  @media print {
    body * { visibility: hidden; }
    #print-target, #print-target * { visibility: visible; }
    #print-target { position: absolute; left: 0; top: 0; box-shadow: none; }
  }

  /* ===========================================================================
     D1.1 — UX Density scoped al modal de OT (data-density="compact").
     Selectores anidados con [data-density="compact"] como ancla.
     NO afecta OC, Inventario, Catálogo, Proyectos, ni ningún otro modal.
     Reduce padding/font/gap solo dentro del modal de Órdenes de Trabajo.
     Tap targets mínimos en mobile (36px) garantizados.
     =========================================================================== */

  /* Inputs / selects / textareas dentro del modal OT */
  [data-density="compact"] input[type="text"],
  [data-density="compact"] input[type="date"],
  [data-density="compact"] input[type="time"],
  [data-density="compact"] input[type="email"],
  [data-density="compact"] input[type="tel"],
  [data-density="compact"] input[type="number"],
  [data-density="compact"] input[type="search"],
  [data-density="compact"] input:not([type]),
  [data-density="compact"] select,
  [data-density="compact"] textarea {
    padding-top: 0.25rem;
    padding-bottom: 0.25rem;
    font-size: 13px;
    line-height: 1.35;
  }

  /* Labels */
  [data-density="compact"] label {
    margin-bottom: 2px;
    font-size: 10.5px;
  }

  /* Sub-textos descriptivos (hints, tooltips inline) */
  [data-density="compact"] .text-\[10px\],
  [data-density="compact"] .text-\[11px\] {
    line-height: 1.25;
  }

  /* Grids: gaps internos del form */
  [data-density="compact"] .grid.gap-3 {
    gap: 0.5rem;
  }
  [data-density="compact"] .grid.gap-2 {
    gap: 0.375rem;
  }

  /* Espaciado vertical de cards · más compacto sin perder respiración.
     D1.2 — ajustado un poco más (0.5→0.375, 0.375→0.25) para reducir
     el aire muerto entre cards en tabs Cierre, Programación y Trabajo
     realizado, que es donde el usuario reportó demasiado scroll. */
  [data-density="compact"] .space-y-3 > :not([hidden]) ~ :not([hidden]) {
    margin-top: 0.375rem;
  }
  [data-density="compact"] .space-y-2 > :not([hidden]) ~ :not([hidden]) {
    margin-top: 0.25rem;
  }

  /* D1.2 — Cards internos del modal OT · padding p-2.5 → p-2 para
     compactar el chrome de cada card sin tocar Tailwind del JSX. */
  [data-density="compact"] .p-2\.5 {
    padding: 0.5rem;
  }

  /* Tap targets mínimos en mobile (concesión usabilidad táctil · Apple HIG) */
  @media (max-width: 640px) {
    [data-density="compact"] input,
    [data-density="compact"] select,
    [data-density="compact"] textarea {
      min-height: 36px;
      font-size: 14px;
    }
  }

  /* Excepciones: checkboxes y radios no se compactan */
  [data-density="compact"] input[type="checkbox"],
  [data-density="compact"] input[type="radio"] {
    padding: 0;
    font-size: inherit;
    min-height: auto;
  }

  /* D1.3 — textareas auto-grow.
     · field-sizing:content (Chrome 123+, Safari 17.4+): textarea crece con su contenido.
     · max-height + overflow-y para que en navegadores antiguos no haya regresión.
     · max-height en 50vh para que un textarea largo no empuje el footer fuera del modal. */
  [data-density="compact"] textarea.ot-autosize {
    field-sizing: content;
    max-height: 50vh;
    overflow-y: auto;
  }

  /* ===========================================================================
     D1.6 — Batch 2 · Forms · estados refinados de inputs/select/textarea.
     Design system v1 (Swiss Modernism enterprise).
     Color tokens: --signo-100/200/300/800.
     Aplicado solo dentro de [data-density="compact"] → no afecta otros módulos.
     =========================================================================== */

  /* Default border + color · más sutil que slate-300 (signo-200 vs hex equivalente).
     Hover: border-color sube a signo-300 (sin layout shift).
     Tipografía body alineada con design system (14px / 1.5).
     Font-family hereda Inter (body). */
  [data-density="compact"] input[type="text"],
  [data-density="compact"] input[type="date"],
  [data-density="compact"] input[type="time"],
  [data-density="compact"] input[type="email"],
  [data-density="compact"] input[type="tel"],
  [data-density="compact"] input[type="number"],
  [data-density="compact"] input[type="search"],
  [data-density="compact"] input:not([type]),
  [data-density="compact"] select,
  [data-density="compact"] textarea {
    border-color: var(--signo-200);
    color: var(--signo-900);
    background-color: #FFFFFF;
    transition: border-color 150ms ease-out, box-shadow 100ms ease-out, background-color 150ms ease-out;
  }
  [data-density="compact"] input[type="text"]:hover:not(:focus):not(:disabled):not([readonly]),
  [data-density="compact"] input[type="email"]:hover:not(:focus):not(:disabled):not([readonly]),
  [data-density="compact"] input[type="tel"]:hover:not(:focus):not(:disabled):not([readonly]),
  [data-density="compact"] input[type="number"]:hover:not(:focus):not(:disabled):not([readonly]),
  [data-density="compact"] input[type="search"]:hover:not(:focus):not(:disabled):not([readonly]),
  [data-density="compact"] input[type="date"]:hover:not(:focus):not(:disabled):not([readonly]),
  [data-density="compact"] input[type="time"]:hover:not(:focus):not(:disabled):not([readonly]),
  [data-density="compact"] input:not([type]):hover:not(:focus):not(:disabled):not([readonly]),
  [data-density="compact"] select:hover:not(:focus):not(:disabled),
  [data-density="compact"] textarea:hover:not(:focus):not(:disabled):not([readonly]) {
    border-color: var(--signo-300);
  }
  /* Focus state · border signo-800 + ring signo-100 (subtle navy halo). */
  [data-density="compact"] input:focus,
  [data-density="compact"] select:focus,
  [data-density="compact"] textarea:focus {
    outline: none;
    border-color: var(--signo-800);
    box-shadow: 0 0 0 3px rgba(0, 40, 85, 0.10);
  }
  /* Disabled state · text muted + slate-50 background. */
  [data-density="compact"] input:disabled,
  [data-density="compact"] select:disabled,
  [data-density="compact"] textarea:disabled,
  [data-density="compact"] fieldset:disabled input,
  [data-density="compact"] fieldset:disabled select,
  [data-density="compact"] fieldset:disabled textarea {
    background-color: #F8FAFC; /* slate-50 */
    color: var(--signo-400);
    cursor: not-allowed;
    border-color: var(--signo-100);
  }
  /* Error state · activado vía aria-invalid="true" (a11y) o .field-error (clase manual).
     No agrega border-color por sí solo si el input está :focus (focus prevalece). */
  [data-density="compact"] input[aria-invalid="true"]:not(:focus),
  [data-density="compact"] select[aria-invalid="true"]:not(:focus),
  [data-density="compact"] textarea[aria-invalid="true"]:not(:focus),
  [data-density="compact"] .field-error:not(:focus) {
    border-color: #DC2626; /* red-600 */
  }
  [data-density="compact"] input[aria-invalid="true"]:focus,
  [data-density="compact"] select[aria-invalid="true"]:focus,
  [data-density="compact"] textarea[aria-invalid="true"]:focus,
  [data-density="compact"] .field-error:focus {
    border-color: #DC2626;
    box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.12); /* red-600 con alpha */
  }
  /* Placeholder · más sutil. */
  [data-density="compact"] input::placeholder,
  [data-density="compact"] textarea::placeholder {
    color: var(--signo-300);
    opacity: 1;
  }
  /* Select arrow · custom chevron navy en lugar del default del navegador. */
  [data-density="compact"] select {
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%234A6FAA' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'/%3e%3c/svg%3e");
    background-repeat: no-repeat;
    background-position: right 0.5rem center;
    background-size: 14px;
    padding-right: 1.75rem;
  }
  /* Select disabled · chevron más claro. */
  [data-density="compact"] select:disabled {
    background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2384A0C9' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'/%3e%3c/svg%3e");
  }
  /* Inputs mono (codigos, fechas legacy, IDs) · tabular-nums. */
  [data-density="compact"] input.font-mono,
  [data-density="compact"] input[type="date"],
  [data-density="compact"] input[type="time"],
  [data-density="compact"] input[type="number"] {
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum";
  }
  /* Numeración 1.x.x en encabezados de cards · tabular-nums + tracking ajustado. */
  [data-density="compact"] .font-mono {
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum";
  }

  /* Cards refinadas · clase utilitaria `ot-card` aplicable en JSX en lugar de
     `bg-white border border-slate-200 rounded p-2.5`. Encapsula el pattern Swiss
     Modernism enterprise sin tocar utility classes existentes. Se aplica en JSX
     en Batch 2 paulatinamente (no es CSS catch-all). */
  [data-density="compact"] .ot-card {
    background-color: #FFFFFF;
    border: 1px solid var(--signo-100);
    border-radius: 4px;
    padding: 0.625rem; /* 10px · density compact */
    transition: border-color 150ms ease-out;
  }
  [data-density="compact"] .ot-card > * + * {
    margin-top: 0.5rem;
  }
  [data-density="compact"] .ot-card-header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    color: var(--signo-700);
    margin-bottom: 0.25rem;
  }
  [data-density="compact"] .ot-card-header .ot-card-num {
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    font-variant-numeric: tabular-nums;
    font-size: 11px;
    color: var(--signo-400);
    font-weight: 500;
  }
  [data-density="compact"] .ot-card-header .ot-card-title {
    font-family: 'Lexend', system-ui, sans-serif;
    font-size: 13px;
    font-weight: 600;
    color: var(--signo-800);
    letter-spacing: -0.005em;
  }
  [data-density="compact"] .ot-card-header .ot-card-icon {
    color: var(--signo-400);
    flex-shrink: 0;
  }
