/* =========================================================================
   SKIN CARE CLINIC — DESIGN SYSTEM v2 "AURA"
   ──────────────────────────────────────────────────────────────────────────
   Foundations:
     • Chrome neutro estilo ElevenLabs: blancos, bordes hairline 1px,
       botones primarios grafito, sombras suaves en capas (no pesadas).
     • COLOR VIVE EN EL CONTENIDO, no en el chrome: paleta de 8 acentos
       (blue/cyan/teal/green/amber/orange/rose/violet) para avatares,
       icon-tiles, chips, badges, barras y estados.
     • Estados semánticos saturados-pero-refinados (no Bootstrap-neón,
       no sage apagado).
     • Geist (UI/headings) + Geist Mono (números, totales, IDs, tickets).
     • Mucho aire: paddings generosos, radios amplios, line-height alto.
     • Reskin de Tabler/Bootstrap vía CSS variables (sin tocar EJS).
   ========================================================================= */

/* -------------------------------------------------------------------------
   1. Tokens
   ------------------------------------------------------------------------- */
:root {
    /* Root = 13px so 1rem IS the body baseline. Single source of truth
       for the design system's rem cascade. Body uses 1rem; running-text
       surfaces (.table tbody td, .modal-body, .panel-item) also use 1rem.
       The interactive control layer (.btn, .form-control, .form-select,
       .dropdown-*, .ts-control, .nav-tabs.new-tabs) instead reads from
       --ds-control-font (a touch under 1rem) so controls feel tighter
       than prose while every input matches button height via --ds-control-h.
       Headings and labels scale relative to this 13px unit.
       REGLA DURA: la tipografía SIEMPRE en rem (nunca px → no escala con
       este baseline) y NUNCA por debajo de 0.72rem (piso de metadata:
       overlines, thead, nav-tabs). Texto legible ≥ 0.8rem. */
    font-size: 13px;

    /* Surfaces */
    --ds-bg:             #ffffff;          /* fondo de página */
    --ds-surface:        #ffffff;          /* cards, modales, dropdowns */
    --ds-surface-muted:  #fafafa;          /* hovers, table headers, sidebar */
    --ds-surface-soft:   #f4f4f5;          /* badges suaves, chips */
    --ds-surface-active: #ededed;          /* selected, pressed */

    /* Ink */
    --ds-ink:            #0a0a0a;          /* texto principal / acento */
    --ds-ink-2:          #262626;
    --ds-ink-3:          #525252;          /* texto secundario */
    --ds-ink-4:          #737373;          /* muted */
    --ds-ink-5:          #a3a3a3;          /* placeholders */

    /* Borders */
    --ds-border:         #ececec;          /* bordes principales */
    --ds-border-strong:  #d4d4d4;          /* inputs, focus */
    --ds-border-soft:    #f1f1f1;          /* divisores internos */

    /* Estados semánticos — entonados a la paleta Apollo (tierra/menta),
       manteniendo contraste AA del texto sobre su pastel. */
    --ds-success:        #3e7b46;
    --ds-success-bg:     #e8f3e8;
    --ds-warning:        #a16207;
    --ds-warning-bg:     #f7efd8;
    --ds-danger:         #d14034;
    --ds-danger-bg:      #fbe9e7;
    --ds-info:           #4353c5;
    --ds-info-bg:        #e7eafc;

    /* ───── ACCENT PALETTE (Apollo) ──────────────────────────────────────
       SOLO colores Apollo: negro + lime héroe + los pasteles de su
       sistema (periwinkle, lavanda, beige, rosa, oliva). Los NOMBRES de
       los tokens se conservan (blue/teal/violet/…) para que todo el CSS
       y JS que los referencia siga funcionando — solo cambia el valor. */
    --ds-accent-blue:       #4353c5;   /* periwinkle */
    --ds-accent-blue-bg:    #e7eafc;
    --ds-accent-cyan:       #4a6286;   /* slate */
    --ds-accent-cyan-bg:    #e9eff7;
    --ds-accent-teal:       #6b7a00;   /* oliva-lime */
    --ds-accent-teal-bg:    #f4fbd7;
    --ds-accent-green:      #3e7b46;   /* menta */
    --ds-accent-green-bg:   #e8f3e8;
    --ds-accent-amber:      #95652a;   /* beige/tan */
    --ds-accent-amber-bg:   #f4ebdc;
    --ds-accent-orange:     #b05c13;
    --ds-accent-orange-bg:  #f8eadd;
    --ds-accent-rose:       #b13693;   /* rosa Apollo */
    --ds-accent-rose-bg:    #f9e5f5;
    --ds-accent-violet:     #6552d0;   /* lavanda */
    --ds-accent-violet-bg:  #ebe7fd;

    /* Lime héroe Apollo — reservado para EL CTA de la pantalla
       (Start/Upgrade en Apollo). Texto siempre oscuro encima. */
    --ds-lime:           #dfff54;
    --ds-lime-hover:     #d2f53e;
    --ds-lime-ink:       #1f2502;

    /* Radius — contenidos, auditados contra Handle: cards ~10px, arte
       mesh ~12px, controles ~8px. Menos agresivo que la etapa ElevenLabs
       (14/20 se sentía inflado junto a la tipografía editorial). */
    --ds-radius-sm:      6px;
    --ds-radius-md:      8px;
    --ds-radius-lg:      10px;
    --ds-radius-xl:      12px;

    /* Sombras en capas — muy suaves, tinte slate (16,24,40) en vez de
       negro puro para que no ensucien los pasteles. */
    --ds-shadow-xs: 0 1px 2px rgba(16, 24, 40, 0.04);
    --ds-shadow-sm: 0 1px 3px rgba(16, 24, 40, 0.06), 0 1px 2px rgba(16, 24, 40, 0.04);
    --ds-shadow-md: 0 6px 24px rgba(16, 24, 40, 0.07), 0 2px 6px rgba(16, 24, 40, 0.04);
    --ds-shadow-lg: 0 12px 40px rgba(16, 24, 40, 0.1), 0 4px 12px rgba(16, 24, 40, 0.05);

    /* Spacing scale (4px base) */
    --ds-space-1: 0.25rem;
    --ds-space-2: 0.5rem;
    --ds-space-3: 0.75rem;
    --ds-space-4: 1rem;
    --ds-space-5: 1.5rem;
    --ds-space-6: 2rem;
    --ds-space-7: 3rem;

    /* Altura compartida de page-header, rail-brand, panel-header y
       mobile-topbar. Una sola fuente de verdad para la línea Y=0. */
    --ds-header-h: 3.5rem;

    /* Interactive controls — single source of truth for the font size and
       the height shared by EVERY clickable/typeable control: buttons,
       dropdowns, .form-control, .form-select, .input-group-text and the
       Tom-Select wrapper. --ds-control-font is a touch smaller than the
       1rem body baseline so the control layer reads tighter than running
       text; --ds-control-h is set comfortably above the natural content
       height of all of them so min-height dominates and every input ends
       up exactly as tall as a button. Change these two numbers to retune
       the whole control layer at once. */
    --ds-control-font: 0.9rem;
    --ds-control-h: 2.4rem;

    /* Anillo de foco accesible — un solo token para checks/radios/switch.
       Se re-mapea en dark mode para seguir siendo visible sobre fondo oscuro. */
    --ds-focus-ring: 0 0 0 3px rgba(10, 10, 10, 0.10);

    /* Single source of truth for lateral content padding — used by cards,
       card-headers/body/footers, modals, tabs, and table edge cells.
       Change this number once and the whole UI re-aligns. */
    --ds-content-padding-x: 1.4rem;
    --ds-content-padding-y: 1rem;

    /* Typography */
    --ds-font-sans:
        'Geist', ui-sans-serif, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    --ds-font-mono:
        'Geist Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

    /* Tabler/Bootstrap overrides (heredan en cascada) */
    --tblr-font-sans-serif: var(--ds-font-sans);
    --tblr-font-monospace:  var(--ds-font-mono);
    --tblr-headings-font-family: var(--ds-font-sans);
    --tblr-body-font-family: var(--ds-font-sans);

    --tblr-body-bg:        var(--ds-bg);
    --tblr-bg-surface:     var(--ds-surface);
    --tblr-bg-surface-secondary: var(--ds-surface-muted);
    --tblr-bg-surface-tertiary:  var(--ds-surface-soft);

    --tblr-body-color:     var(--ds-ink);
    --tblr-secondary-color: var(--ds-ink-3);
    --tblr-muted:          var(--ds-ink-4);

    --tblr-border-color:           var(--ds-border);
    --tblr-border-color-translucent: var(--ds-border);
    --tblr-border-radius:           var(--ds-radius-md);
    --tblr-border-radius-sm:        var(--ds-radius-sm);
    --tblr-border-radius-lg:        var(--ds-radius-lg);
    --tblr-border-radius-xl:        var(--ds-radius-xl);

    --tblr-primary:        var(--ds-ink);
    --tblr-primary-rgb:    10, 10, 10;
    --tblr-primary-fg:     #ffffff;
    --tblr-link-color:     var(--ds-ink);
    --tblr-link-hover-color: var(--ds-ink-2);

    /* Bootstrap mirror */
    --bs-body-bg:          var(--ds-bg);
    --bs-body-color:       var(--ds-ink);
    --bs-body-font-family: var(--ds-font-sans);
    --bs-secondary-color:  var(--ds-ink-3);
    --bs-border-color:     var(--ds-border);
    --bs-primary:          var(--ds-ink);
    --bs-primary-rgb:      10, 10, 10;

    /* ── Alias de compatibilidad ──────────────────────────────────────────
       Algunas vistas usan nombres NO canónicos (`--ds-line`, `--ds-surface-2`,
       `--ds-ink-1`, `--ds-accent`…) con fallback hex CLARO hardcodeado, que no
       adaptaba a dark. Apuntándolos al token real, adaptan solos (y dejan de
       depender del hex). El canon sigue siendo el token real; esto es un puente. */
    --ds-line:         var(--ds-border);
    --ds-surface-2:    var(--ds-surface-muted);
    --ds-ink-1:        var(--ds-ink);
    --ds-accent:       var(--ds-accent-violet);
    --ds-accent-soft:  var(--ds-accent-violet-bg);

    /* Icono del empty state canónico (inbox de línea). Mask → toma el color
       del token y adapta a dark. Una sola fuente para listas/tablas/charts. */
    --ds-empty-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 13h3l3 3h4l3 -3h3'/%3E%3Cpath d='M5 5h14a1 1 0 0 1 1 1v12a1 1 0 0 1 -1 1h-14a1 1 0 0 1 -1 -1v-12a1 1 0 0 1 1 -1z'/%3E%3C/svg%3E");
}

/* =========================================================================
   DARK MODE — base (Fase 1). Solo remapea los tokens --ds-*; como TODO el
   sistema (chrome incluido) consume var(--ds-*), la mayoría se adapta sola.
   Los stragglers con hex hardcodeado se barren por vista en la Fase 2.
   Se activa con <html data-theme="dark"> (toggle en la topbar + localStorage).
   ========================================================================= */

/* Brand logo — el isotipo de Circadis vive sobre superficies que siguen el
   tema (--ds-surface). Por defecto se usa la variante AZUL (_light) para fondos
   claros; en modo oscuro se intercambia al trazo BLANCO. Un solo punto de
   control: todo <img> que apunte al _light.svg se swappea vía `content`. */
:root[data-theme="dark"] img[src*="circadis_min_logo_light.svg"] {
    content: url("/public/static/logo/circadis_min_logo.svg");
}

:root[data-theme="dark"] {
    color-scheme: dark;

    /* Anillo de foco visible sobre fondo oscuro (el gris de light casi no se ve). */
    --ds-focus-ring: 0 0 0 3px rgba(255, 255, 255, 0.16);

    /* Surfaces — negro NEUTRO (grises puros R=G=B, sin tinte azul), jerarquía
       por elevación al estilo Vercel/Linear. */
    --ds-bg:             #0a0a0a;   /* fondo de página */
    --ds-surface:        #161616;   /* cards, modales, sidebar, topbar */
    --ds-surface-muted:  #1f1f1f;   /* hovers, table headers */
    --ds-surface-soft:   #262626;   /* chips, badges suaves */
    --ds-surface-active: #2f2f2f;   /* selected, pressed */

    /* Ink — gris neutro, sin blanco puro (#fff cansa sobre negro) */
    --ds-ink:            #f5f5f5;
    --ds-ink-2:          #d6d6d6;
    --ds-ink-3:          #a8a8a8;
    --ds-ink-4:          #808080;
    --ds-ink-5:          #5c5c5c;

    /* Borders — grises neutros sólidos */
    --ds-border:         #2a2a2a;
    --ds-border-strong:  #3a3a3a;
    --ds-border-soft:    #1e1e1e;

    /* Semánticos — texto más brillante, pastel → tinte oscuro del tono */
    --ds-success:        #6fce8a;   --ds-success-bg:     #16271b;
    --ds-warning:        #e0b65f;   --ds-warning-bg:     #2a2310;
    --ds-danger:         #ec7a70;   --ds-danger-bg:      #2c1714;
    --ds-info:           #8ea2ff;   --ds-info-bg:        #181d33;

    /* Acentos Apollo — mismo nombre, valor adaptado a fondo oscuro */
    --ds-accent-blue:    #8ea2ff;   --ds-accent-blue-bg:    #181d33;
    --ds-accent-cyan:    #93b2d8;   --ds-accent-cyan-bg:    #161f2a;
    --ds-accent-teal:    #c3d65a;   --ds-accent-teal-bg:    #20240e;
    --ds-accent-green:   #6fce8a;   --ds-accent-green-bg:   #16271b;
    --ds-accent-amber:   #d9aa6a;   --ds-accent-amber-bg:   #271d10;
    --ds-accent-orange:  #e09a5d;   --ds-accent-orange-bg:  #2a1c10;
    --ds-accent-rose:    #e589cb;   --ds-accent-rose-bg:    #2a1426;
    --ds-accent-violet:  #b3a5f2;   --ds-accent-violet-bg:  #1e1a33;

    /* Lime héroe se conserva (el CTA debe seguir saltando), texto oscuro encima */

    /* Sombras — negro real y más profundas (sobre oscuro el tinte slate no lee) */
    --ds-shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.40);
    --ds-shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.50), 0 1px 2px rgba(0, 0, 0, 0.40);
    --ds-shadow-md: 0 6px 24px rgba(0, 0, 0, 0.50), 0 2px 6px rgba(0, 0, 0, 0.40);
    --ds-shadow-lg: 0 12px 40px rgba(0, 0, 0, 0.60), 0 4px 12px rgba(0, 0, 0, 0.50);

    /* Tabler/Bootstrap derivados que NO cuelgan de --ds-* directamente */
    --tblr-dark: #f5f5f5;
    --tblr-light: #1f1f1f;
    --tblr-body-color: var(--ds-ink);
    --tblr-border-color: var(--ds-border);
    --bs-body-color: var(--ds-ink);
    --bs-border-color: var(--ds-border);
}

/* -------------------------------------------------------------------------
   2. Base — refined, tighter, world-class densidad
   ------------------------------------------------------------------------- */
html, body {
    background-color: var(--ds-bg) !important;
    color: var(--ds-ink);
    font-family: var(--ds-font-sans) !important;
    font-feature-settings: 'ss01', 'cv11';
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
    line-height: 1.55;
}

body {
    letter-spacing: -0.005em;
    font-size: 1rem;
}

p { margin-bottom: 0.65rem; }
small, .small { font-size: 0.85rem; }

h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
    font-family: var(--ds-font-sans) !important;
    color: var(--ds-ink);
    font-weight: 600;
    letter-spacing: -0.02em;
    line-height: 1.25;
    margin-bottom: 0.5rem;
}

.text-muted,
.text-secondary {
    color: var(--ds-ink-4) !important;
}

/* =========================================================================
   GEIST MONO — used wherever data has a fixed shape (numbers, IDs, dates,
   currencies, durations, hashes, codes, percentages, keystrokes, units).
   This is the visual signature of the design system. */
code, kbd, samp, pre, var, output, tt,
.font-mono, .text-mono, .font-monospace, .text-monospace,
.amount, .price, .total, .subtotal, .balance,
.ticket-id, .invoice-number, .order-number,
.id, .identifier, .sku, .upc, .barcode, .folio,
.code, .hash, .uuid, .reference,
.timestamp, .date, .datetime, .hour, .time,
.duration, .elapsed, .ago,
.percentage, .percent, .pct,
.qty, .quantity, .count, .stock,
[data-mono],
.page-link, .dt-paginate-button,
.dataTables_info,
.flatpickr-day, .flatpickr-time input {
    font-family: var(--ds-font-mono) !important;
    font-feature-settings: 'tnum', 'zero';
    letter-spacing: -0.01em;
}

/* Auto-mono in data contexts:
   - numeric cells in tables (right-aligned, .text-end, .text-right, .numeric)
   - currency / number form inputs
   - badges that contain only digits (counts) */
.table td.text-end,
.table td.text-right,
.table td.numeric,
.table td.amount,
.table td.price,
.table td.total,
.table td.qty,
.table td.id,
.table td.sku,
.table td.code,
.table td.date,
.table td.datetime,
input[type='number'],
input[type='tel'],
input[inputmode='numeric'],
input[inputmode='decimal'],
input.amount, input.price, input.numeric,
.form-control.numeric, .form-control.amount,
.flatpickr-input,
.form-control[type='number'] {
    font-family: var(--ds-font-mono) !important;
    font-feature-settings: 'tnum';
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
}

/* Tabular numerals on every numeric-looking column */
.table td, .table th { font-variant-numeric: tabular-nums; }

kbd {
    background-color: var(--ds-surface-soft);
    border: 1px solid var(--ds-border);
    border-bottom-width: 2px;
    border-radius: var(--ds-radius-sm);
    color: var(--ds-ink-2);
    font-size: 0.85rem;
    padding: 0.1rem 0.35rem;
}

/* Links sin subrayado SIEMPRE (decisión de diseño — ElevenLabs-style):
   el hover comunica con color, no con underline. */
a {
    color: var(--ds-ink);
    text-decoration: none;
}
a:hover {
    color: var(--ds-ink-2);
    text-decoration: none;
}

hr, .dropdown-divider {
    border-color: var(--ds-border) !important;
    opacity: 1;
}

::selection { background: #f0ffb3; color: var(--ds-ink); }

/* Scrollbars finos y neutros — parte del "aire" del sistema */
* { scrollbar-width: thin; scrollbar-color: #d4d4d4 transparent; }
*::-webkit-scrollbar { width: 8px; height: 8px; }
*::-webkit-scrollbar-thumb {
    background: #d4d4d4;
    border-radius: 99px;
}
*::-webkit-scrollbar-thumb:hover { background: #a3a3a3; }
*::-webkit-scrollbar-track { background: transparent; }

/* -------------------------------------------------------------------------
   3. Page shell / sidebar / navbar
   ------------------------------------------------------------------------- */
.page,
.page-wrapper,
.page-body,
.page-header {
    background-color: var(--ds-bg) !important;
}

/* Homologated page-header: every section gets the same shape.
   Covers all 3 markup patterns found in the codebase:
     A) .page-header > .d-flex[height:3rem] > .container-fluid > .d-flex (Inicio)
     B) .page-header > .container-xl > .row.align-items-center > .col + .col-auto (listings)
     C) .page-header > .container-xl > .row > .col-12.d-flex.justify-content-between (detail/edit)
   - Fixed bar of 3rem (grows only if the right-side action group wraps).
   - Single source of truth for the divider (border-bottom).
   - Content always vertically centered regardless of inner markup. */
.page-header,
.page-header.d-print-none,
.page-header.position-sticky {
    min-height: var(--ds-header-h) !important;
    height: auto !important;
    box-sizing: border-box !important;     /* border-bottom counted INSIDE the 3rem */
    display: flex !important;
    align-items: center !important;
    padding: 0 !important;
    margin: 0 !important;
    background-color: var(--ds-surface) !important;
    border-bottom: 1px solid var(--ds-border-soft) !important;
    position: relative;
}
/* Remove redundant vertical padding from inner rows so the bar stays at 3rem */
.page-header .py-1, .page-header .py-2, .page-header .py-3 {
    padding-top: 0 !important;
    padding-bottom: 0 !important;
}
/* Preserve sticky behaviour where markup requests it — pegado bajo la
   topbar fija (misma altura --ds-header-h en desktop y móvil). */
.page-header.position-sticky,
.page-header[style*='sticky'] {
    position: sticky !important;
    top: var(--ds-header-h) !important;
    z-index: 3 !important;
}
.page-header > * {
    width: 100%;
    align-self: center;
}
.page-header > .container,
.page-header > .container-fluid,
.page-header > .container-xl {
    padding-top: 0 !important;
    padding-bottom: 0 !important;
}
/* Inner d-flex wrappers (Pattern A) inherit the bar height cleanly.
   Don't force min-height here — the page-header's own height drives layout.
   Forcing min-height: 3rem on the inner div would push total beyond 3rem. */
.page-header > .d-flex {
    height: auto !important;
    min-height: 0 !important;
    align-items: center !important;
    flex: 1 1 auto;
}
/* Inner row vertically centered (Patterns B + C) */
.page-header .row {
    width: 100%;
    align-items: center !important;
}
/* Kill any inner divider — only the page-header's own border-bottom shows */
.page-header .border-bottom {
    border-bottom: 0 !important;
}
/* Action button group on the right: consistent gap between actions */
.page-header .col-auto > .btn + .btn,
.page-header .col-auto > .btn + a.btn,
.page-header .col-auto > a.btn + .btn,
.page-header .col-auto > a.btn + a.btn,
.page-header .col-12 > .d-flex > .btn + .btn,
.page-header .col-12 > .d-flex > .btn + a.btn,
.page-header .col-12 > .d-flex > a.btn + .btn {
    margin-left: 0.4rem;
}
.page-pretitle {
    color: var(--ds-ink-4) !important;
    font-size: 0.85rem;
    font-weight: 500;
    letter-spacing: -0.005em;
    text-transform: none !important;
    margin-bottom: 0.1rem;
}
/* Single source of truth for page-header titles.
   Applies to ANY heading tag inside .page-header (h1/h2/h3) and to the
   explicit .page-title class — all 46 page templates render at the same
   size regardless of which tag the author used.
   Hierarchy below: modal (0.95rem) < page (1.125rem) < card (0.875rem) etc. */
.page-title,
.page-header h1,
.page-header h2,
.page-header h3 {
    font-size: 1rem;
    font-weight: 550;
    letter-spacing: -0.015em;
    color: var(--ds-ink);
    line-height: 1.2;
    margin-bottom: 0;
}
.page-subtitle {
    color: var(--ds-ink-4);
    font-size: 0.85rem;
    font-weight: 400;
    margin-top: 0.2rem;
}
/* Breadcrumb-style category prefix used in 44 listing/detail headers:
   <h2><span style="font-weight:300">Clientes /</span> Editar</h2>.
   Normalize the inline style into a class so it stays consistent. */
.page-header h1 > span:first-child[style*='font-weight'],
.page-header h2 > span:first-child[style*='font-weight'],
.page-header h3 > span:first-child[style*='font-weight'],
.page-title-prefix {
    color: var(--ds-ink-4);
    font-weight: 400 !important;
    margin-right: 0.15rem;
}

/* Tabler .subheader (stat-card overlines, section labels) */
.subheader {
    font-family: var(--ds-font-sans) !important;
    font-size: 0.85rem !important;
    font-weight: 500 !important;
    letter-spacing: -0.005em !important;
    text-transform: none !important;
    color: var(--ds-ink-4) !important;
}

/* Headings: refined hierarchy, finer scale */
h1, .h1 { font-size: 1.4rem;  font-weight: 600; letter-spacing: -0.028em; }
h2, .h2 { font-size: 1.125rem; font-weight: 600; letter-spacing: -0.022em; }
h3, .h3 { font-size: 0.95rem;  font-weight: 600; letter-spacing: -0.018em; }
h4, .h4 { font-size: 0.85rem;  font-weight: 600; letter-spacing: -0.012em; }
h5, .h5 { font-size: 0.85rem;  font-weight: 600; letter-spacing: -0.005em; }
h6, .h6 { font-size: 0.85rem;  font-weight: 600; letter-spacing: 0; text-transform: none; }

/* Stat card big numbers — Geist Mono, hairline weight.
   OJO: nunca seleccionar `.card .h2` a secas — los títulos de texto dentro
   de cards (ej. el "Bienvenido" del login) se volvían mono. Los números
   reales ya quedan cubiertos por los selectores de forma de la sección 14
   ([id*='total'], .amount, …) y por los fw-* de abajo. */
.h1.font-weight-medium,
.h2.font-weight-medium,
.h1.fw-medium,
.h2.fw-medium,
.h1.fw-bold,
.h2.fw-bold,
[class*='card-stamp'] + * .h1,
[class*='stat-'] .h1, [class*='stat-'] .h2 {
    font-family: var(--ds-font-mono) !important;
    font-feature-settings: 'tnum', 'zero';
    letter-spacing: -0.04em;
    font-weight: 500;
}

/* Sidebar (Tabler navbar-vertical) */
.navbar-vertical {
    background-color: var(--ds-surface) !important;
    border-right: 1px solid var(--ds-border);
    box-shadow: none !important;
}
.navbar-vertical .nav-link {
    color: var(--ds-ink-3) !important;
    border-radius: var(--ds-radius-md);
    padding: 0.4rem 0.65rem;
    font-weight: 500;
    font-size: 1rem;
    transition: background-color 0.12s ease, color 0.12s ease;
}
.navbar-vertical .nav-link:hover {
    background-color: var(--ds-surface-muted);
    color: var(--ds-ink) !important;
}
.navbar-vertical .nav-link.active,
.navbar-vertical .nav-link.current {
    color: var(--ds-ink) !important;
    background-color: var(--ds-surface-active);
}
.navbar-vertical .nav-link .nav-link-icon,
.navbar-vertical .nav-link i {
    color: currentColor !important;
}

/* Reemplazar fondo azul claro de .nav-link.current::before del layout inline */
.nav-link.current::before {
    background: transparent !important;
}
.navbar-vertical .nav-link.current {
    background-color: var(--ds-surface-active) !important;
}

ul.new-tabs[data-bs-toggle='tabs'] .nav-link.active::before {
    background: var(--ds-surface-active) !important;
}

/* =========================================================================
   .new-tabs — segmented-control style. Responsive: equal-width on wide
   screens, horizontal scroll on narrow ones, never wraps to two rows.
   ========================================================================= */
.nav-tabs.new-tabs {
    display: flex !important;
    flex-wrap: nowrap !important;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
    border: 1px solid var(--ds-border) !important;
    background-color: var(--ds-surface);
    padding: 0.25rem !important;
    border-radius: var(--ds-radius-md) !important;
    gap: 0.15rem;
    /* Segmented box: separa del contenido. La regla global `.nav-tabs {
       margin: 0 !important }` anula los utilities `mb-*` del markup, así que
       el aire inferior se fija aquí. */
    margin-bottom: 1rem !important;
}
.nav-tabs.new-tabs::-webkit-scrollbar { display: none; }

.nav-tabs.new-tabs .nav-item {
    flex: 1 1 0 !important;          /* equal width by default */
    min-width: max-content;          /* but never squash below content size */
    width: auto !important;          /* defeats inline style="width: 25%" */
}

.nav-tabs.new-tabs .nav-link {
    width: 100%;
    padding: 0.4rem 0.75rem !important;
    font-family: var(--ds-font-sans) !important;   /* selector de vista: sans, no mono */
    font-size: var(--ds-control-font) !important;
    font-weight: 500;
    letter-spacing: -0.005em;
    text-transform: none;
    color: var(--ds-ink-3) !important;
    border: 0 !important;
    border-radius: var(--ds-radius-sm) !important;
    background: transparent !important;
    margin: 0 !important;
    white-space: nowrap;
    transition: background-color 0.12s ease, color 0.12s ease;
}
.nav-tabs.new-tabs .nav-link:hover:not(.active) {
    background-color: var(--ds-surface-muted) !important;
    color: var(--ds-ink) !important;
}
.nav-tabs.new-tabs .nav-link.active {
    color: var(--ds-ink) !important;
    background-color: var(--ds-surface-active) !important;
    border-bottom: 0 !important;
}
/* Active pill is now provided by the bg above, kill the legacy ::before */
.nav-tabs.new-tabs .nav-link.active::before {
    display: none !important;
}

/* Label with controlled truncation when really tight */
.nav-tabs.new-tabs .nav-tab-label {
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

/* Inline badge inside a tab — mono if numeric, sized small */
.nav-tabs.new-tabs .nav-link .badge {
    font-family: var(--ds-font-mono);
    font-size: 0.85rem;
    padding: 0.15rem 0.4rem;
    font-feature-settings: 'tnum';
    line-height: 1.3;
    flex-shrink: 0;
}

/* Tab icons match the new font scale */
.nav-tabs.new-tabs .nav-link .ti {
    font-size: 1.05rem !important;
    flex-shrink: 0;
}

.navbar-brand,
.navbar-brand-autodark {
    color: var(--ds-ink) !important;
}
.navbar-brand .card,
.navbar-brand-autodark .card {
    border: 1px solid var(--ds-border);
    background-color: var(--ds-surface);
    box-shadow: none;
}

/* Top navbar */
.navbar:not(.navbar-vertical) {
    background-color: var(--ds-surface) !important;
    border-bottom: 1px solid var(--ds-border);
    box-shadow: none !important;
}

/* -------------------------------------------------------------------------
   4. Cards
   ------------------------------------------------------------------------- */
.card {
    background-color: var(--ds-surface) !important;
    border: 1px solid var(--ds-border) !important;
    border-radius: var(--ds-radius-lg) !important;
    box-shadow: var(--ds-shadow-xs) !important;
    /* Clip any edge-to-edge children (table rows, list items, hover bgs)
       to the card's rounded corners. Without this, hover/selected
       backgrounds bleed past the rounded corners. */
    overflow: hidden;
}
/* Modal content reuses .card-content but should NOT clip its dropdowns */
.modal-content { overflow: visible; }
.card-header {
    background-color: var(--ds-surface) !important;
    border-bottom: 1px solid var(--ds-border-soft) !important;
    padding: var(--ds-content-padding-y) var(--ds-content-padding-x);
    min-height: auto;
    /* Force vertical stacking of card title + description so the small
       muted text below the title never inlines next to it. Cards that
       need a horizontal layout in the header (e.g. title + button on the
       right) opt into it explicitly with .d-flex / .flex-row. */
    display: flex;
    flex-direction: column;
    align-items: flex-start; /* every child snaps to the left edge */
    gap: 0.2rem;
    text-align: left;
}
.card-header > * { text-align: left; }
/* Allow opt-in horizontal headers (title + side button etc.) to override
   the column default cleanly. */
.card-header.d-flex,
.card-header.flex-row {
    flex-direction: row !important;
    align-items: center;
    gap: 0.5rem;
}
/* .card-title applies regardless of tag (h1..h6, div, p). The fallback rule
   on .card-header > h* covers cards whose author forgot the .card-title class.
   Uses align-items: baseline + flex (block-level) so when the title text
   wraps in narrow cards, the icon stays aligned to the first line cap-height
   instead of floating to the vertical centre of the wrapped block. */
.card-title,
.card-header > h1:not([class*='page-']),
.card-header > h2:not([class*='page-']),
.card-header > h3:not([class*='page-']),
.card-header > h4:not([class*='page-']),
.card-header > h5:not([class*='page-']) {
    display: flex;
    align-items: baseline;
    gap: 0.35rem;
    font-weight: 600;
    color: var(--ds-ink);
    font-size: 0.875rem;
    letter-spacing: -0.012em;
    margin-bottom: 0;
    line-height: 1.25;
    flex-wrap: wrap;
}
.card-title .ti {
    color: var(--ds-ink-3);
    font-size: 0.95rem !important;
    flex-shrink: 0;
}
.card-subtitle {
    color: var(--ds-ink-4);
    font-size: 0.85rem;
}
.card-body {
    padding: var(--ds-content-padding-x);
}
.card-footer {
    background-color: var(--ds-surface) !important;
    border-top: 1px solid var(--ds-border-soft) !important;
    padding: var(--ds-content-padding-y) var(--ds-content-padding-x);
}

/* Hover sutil opcional para cards clicables */
.card.card-link:hover,
.card[role="button"]:hover {
    border-color: var(--ds-border-strong) !important;
    background-color: var(--ds-surface-muted) !important;
}

/* -------------------------------------------------------------------------
   5. Buttons
   ------------------------------------------------------------------------- */
/* =========================================================================
   BUTTON SYSTEM — categorized hierarchy, single source of truth
   --------------------------------------------------------------------------
   Categories (by visual prominence):
     PRIMARY    Solid grafito ink. ONE per screen. Save / Submit / Crear / Confirmar.
                Classes: .btn-primary, .btn-dark, .btn-github, .bg-github
     SECONDARY  Outline neutral. Cancel / Cerrar / Atrás / Filtrar.
                Classes: .btn-secondary, .btn-light, .btn-white, .btn-outline-secondary, bare .btn
     SOFT       Subtle filled (surface-muted). Less common alt actions.
                Classes: .btn-github-lt, .bg-github-lt, .bg-secondary-lt, .bg-primary-lt
     OUTLINE-PRIMARY  Outline grafito. Strong alt action. .btn-outline-primary, .btn-outline-dark
     GHOST      Transparent. Toolbar / inline actions. .btn-ghost-*, .btn-transparent, bare hover-only
     LINK       Text-only with underline on hover. .btn-link
     ICON       Square ghost icon. In tables/headers. .btn-icon
   Semantic colors:
     SUCCESS    Green sage. .btn-success, .btn-green   (.bg-success-lt = soft variant)
     WARNING    Amber muted. .btn-warning, .btn-yellow (.bg-warning-lt, .bg-orange-lt)
     DANGER     Red coral. .btn-danger, .btn-red       (.bg-danger-lt = soft variant)
     INFO       Blue muted (rare). .btn-info, .btn-blue (.bg-info-lt, .bg-azure-lt, .bg-blue-lt)
   Sizes:
     .btn-sm    0.28rem 0.65rem padding, 0.85rem font
     .btn       0.4rem 0.85rem  padding, 1rem font       (default = body baseline 13.5px)
     .btn-lg    0.55rem 1.2rem  padding, 1.05rem font
   ========================================================================= */

.btn {
    font-family: var(--ds-font-sans);
    font-weight: 500;
    font-size: var(--ds-control-font);
    border-radius: var(--ds-radius-md) !important;
    padding: 0.4rem 0.95rem;
    min-height: var(--ds-control-h);
    border: 1px solid transparent;
    box-shadow: none !important;
    cursor: pointer;
    transition: background-color 0.12s ease, border-color 0.12s ease, color 0.12s ease;
    letter-spacing: -0.005em;
    line-height: 1.4;
    -webkit-user-select: none;
    user-select: none;
    white-space: nowrap;
    /* Centrado real de icono + texto: flex, no vertical-align. El gap
       sustituye los espacios/márgenes manuales entre icono y label. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.35rem;
}
.btn-sm  { padding: 0.2rem 0.6rem;  font-size: 0.8rem;  min-height: 1.9rem; }
.btn-lg  { padding: 0.5rem 1.2rem;   font-size: 0.95rem; min-height: 2.7rem; }
/* Square icon buttons stay exactly as tall as their text siblings (shared
   --ds-control-h) so toolbars line up; width matches height to keep square. */
.btn-icon { padding: 0.4rem; min-width: var(--ds-control-h); min-height: var(--ds-control-h); }
.btn-icon.btn-sm { padding: 0.25rem; min-width: 1.9rem; min-height: 1.9rem; }
.btn-icon.btn-lg { padding: 0.55rem; min-width: 2.7rem; min-height: 2.7rem; }
.btn:disabled,
.btn.disabled {
    opacity: 0.5;
    pointer-events: none;
    cursor: not-allowed;
}
.btn:focus-visible {
    outline: 2px solid var(--ds-ink) !important;
    outline-offset: 2px !important;
}

/* Bare .btn (no variant) → secondary outline (Bootstrap leaves it invisible by default) */
.btn:not([class*='btn-']):not([class*='bg-']),
.btn.btn-default {
    background-color: var(--ds-surface) !important;
    border-color: var(--ds-border-strong) !important;
    color: var(--ds-ink) !important;
}
.btn:not([class*='btn-']):not([class*='bg-']):hover,
.btn.btn-default:hover {
    background-color: var(--ds-surface-muted) !important;
    color: var(--ds-ink) !important;
}
.btn:not([class*='btn-']):not([class*='bg-']).show,
.btn:not([class*='btn-']):not([class*='bg-']):active,
.btn:not([class*='btn-']):not([class*='bg-']).active,
.btn.btn-default.show,
.btn.btn-default:active,
.btn.btn-default.active {
    background-color: var(--ds-surface-muted) !important;
    border-color: var(--ds-border-strong) !important;
    color: var(--ds-ink) !important;
    box-shadow: none !important;
}

/* ─── PRIMARY ───────────────────────────────────────────────────────── */
.btn-primary,
.btn-dark,
.btn-github,
.bg-github {
    background-color: var(--ds-ink) !important;
    border-color: var(--ds-ink) !important;
    color: var(--ds-bg) !important;
}
.btn-primary:hover,
.btn-dark:hover,
.btn-github:hover,
.bg-github:hover {
    background-color: var(--ds-ink-2) !important;
    border-color: var(--ds-ink-2) !important;
    color: #ffffff !important;
}
.btn-primary:active,
.btn-dark:active,
.btn-github:active,
.bg-github:active {
    background-color: #000 !important;
    border-color: #000 !important;
}

/* ─── SECONDARY (outline neutral) ───────────────────────────────────── */
.btn-secondary,
.btn-outline-secondary,
.btn-light,
.btn-white {
    background-color: var(--ds-surface) !important;
    border-color: var(--ds-border-strong) !important;
    color: var(--ds-ink) !important;
}
.btn-secondary:hover,
.btn-outline-secondary:hover,
.btn-light:hover,
.btn-white:hover {
    background-color: var(--ds-surface-muted) !important;
    border-color: var(--ds-border-strong) !important;
    color: var(--ds-ink) !important;
}

/* ─── SOFT (subtle filled, less prominent than secondary) ───────────── */
.btn-github-lt,
.bg-github-lt,
.bg-secondary-lt,
.bg-primary-lt,
.btn-secondary-lt,
.btn-primary-lt {
    background-color: var(--ds-surface-active) !important;
    border-color: transparent !important;
    color: var(--ds-ink) !important;
}
.btn-github-lt:hover,
.bg-github-lt:hover,
.bg-secondary-lt:hover,
.bg-primary-lt:hover,
.btn-secondary-lt:hover,
.btn-primary-lt:hover {
    background-color: var(--ds-border-strong) !important;
    color: var(--ds-ink) !important;
}

/* ─── OUTLINE PRIMARY (strong alt action) ───────────────────────────── */
.btn-outline-primary,
.btn-outline-dark {
    background-color: transparent !important;
    border-color: var(--ds-ink) !important;
    color: var(--ds-ink) !important;
}
.btn-outline-primary:hover,
.btn-outline-dark:hover {
    background-color: var(--ds-ink) !important;
    color: var(--ds-bg) !important;
}

/* ─── GHOST / TRANSPARENT (toolbar inline actions) ──────────────────── */
.btn-ghost,
.btn-ghost-secondary,
.btn-ghost-primary,
.btn-ghost-dark,
.btn-transparent {
    background-color: transparent !important;
    border-color: transparent !important;
    color: var(--ds-ink-2) !important;
    box-shadow: none !important;
}
.btn-ghost:hover,
.btn-ghost-secondary:hover,
.btn-ghost-primary:hover,
.btn-ghost-dark:hover,
.btn-transparent:hover {
    background-color: var(--ds-surface-muted) !important;
    color: var(--ds-ink) !important;
}

/* ─── LOADING STATE ─────────────────────────────────────────────────────
   Restore Tabler's transparent text during .btn-loading. Variant rules
   in this file (.btn-github, .btn-primary, …) re-set color with
   !important, so we use compound .btn.btn-loading (specificity 0,2,0)
   to beat any single-class variant regardless of source order. */
.btn.btn-loading {
    color: transparent !important;
}

/* ─── BACK BUTTONS ──────────────────────────────────────────────────────
   Homologated style for the 27 back/return buttons across detail/edit views.
   Pattern: <a class="btn btn-transparent px-0|px-2" href="/parent">
              <i class="ti ti-arrow-left ti-sm"></i>
            </a>
   - All variants (px-0 / px-2) collapse to the same padding & icon size
   - Cleaner square hit-target instead of zero/asymmetric padding
   - Always anchor-based (href to parent route) — no history.back() surprises
   - Behavior is preserved: navigation goes to the explicit href so the user
     lands on a known page even if they entered via deep-link.                */
.page-header .btn-transparent:has(> .ti-arrow-left),
.page-header a.btn:has(> .ti-arrow-left) {
    padding: 0.4rem 0.5rem !important;
    margin-right: 0.15rem;
    border-radius: var(--ds-radius-md);
}
.page-header .ti-arrow-left {
    font-size: 1rem !important;
    color: var(--ds-ink-2);
}
.page-header .btn-transparent:has(> .ti-arrow-left):hover .ti-arrow-left,
.page-header a.btn:has(> .ti-arrow-left):hover .ti-arrow-left {
    color: var(--ds-ink);
}

/* ─── LINK (text only, no fill) ─────────────────────────────────────── */
.btn-link,
.link-button,
.link-secondary,
.btn.btn-link.link-secondary {
    background: transparent !important;
    border-color: transparent !important;
    color: var(--ds-ink-2) !important;
    text-decoration: none !important;
    font-weight: 500;
    padding: 0.4rem 0.5rem !important;
}
.btn-link:hover,
.link-button:hover,
.link-secondary:hover {
    color: var(--ds-ink) !important;
    text-decoration: none !important;
    background: var(--ds-surface-muted) !important;
    border-radius: var(--ds-radius-md);
}

/* ─── SEMANTIC: SUCCESS ─────────────────────────────────────────────── */
.btn-success,
.btn-green {
    background-color: var(--ds-success) !important;
    border-color: var(--ds-success) !important;
    color: #fff !important;
}
.btn-success:hover, .btn-green:hover {
    background-color: #116232 !important;
    border-color: #116232 !important;
}
.btn-success-lt,
.bg-success-lt,
.bg-green-lt {
    background-color: var(--ds-success-bg) !important;
    border-color: transparent !important;
    color: var(--ds-success) !important;
}
.btn-success-lt:hover,
.bg-success-lt:hover,
.bg-green-lt:hover {
    background-color: color-mix(in srgb, var(--ds-success-bg), var(--ds-success) 8%) !important;
    color: var(--ds-success) !important;
}

/* ─── SEMANTIC: WARNING ─────────────────────────────────────────────── */
.btn-warning,
.btn-yellow {
    background-color: var(--ds-warning) !important;
    border-color: var(--ds-warning) !important;
    color: #fff !important;
}
.btn-warning:hover, .btn-yellow:hover {
    background-color: #92400e !important;
    border-color: #92400e !important;
}
.btn-warning-lt,
.bg-warning-lt,
.bg-yellow-lt,
.bg-orange-lt {
    background-color: var(--ds-warning-bg) !important;
    border-color: transparent !important;
    color: var(--ds-warning) !important;
}
.btn-warning-lt:hover,
.bg-warning-lt:hover,
.bg-yellow-lt:hover,
.bg-orange-lt:hover {
    background-color: color-mix(in srgb, var(--ds-warning-bg), var(--ds-warning) 8%) !important;
    color: var(--ds-warning) !important;
}

/* ─── SEMANTIC: DANGER ──────────────────────────────────────────────── */
.btn-danger,
.btn-red {
    background-color: var(--ds-danger) !important;
    border-color: var(--ds-danger) !important;
    color: #fff !important;
}
.btn-danger:hover, .btn-red:hover {
    background-color: #b42318 !important;
    border-color: #b42318 !important;
}
.btn-outline-danger {
    background-color: transparent !important;
    border-color: var(--ds-danger) !important;
    color: var(--ds-danger) !important;
}
.btn-outline-danger:hover {
    background-color: var(--ds-danger) !important;
    color: #fff !important;
}
.btn-danger-lt,
.bg-danger-lt,
.bg-red-lt {
    background-color: var(--ds-danger-bg) !important;
    border-color: transparent !important;
    color: var(--ds-danger) !important;
}
.btn-danger-lt:hover,
.bg-danger-lt:hover,
.bg-red-lt:hover {
    background-color: color-mix(in srgb, var(--ds-danger-bg), var(--ds-danger) 8%) !important;
    color: var(--ds-danger) !important;
}

/* ─── SEMANTIC: INFO ────────────────────────────────────────────────── */
.btn-info,
.btn-blue,
.btn-azure {
    background-color: var(--ds-info) !important;
    border-color: var(--ds-info) !important;
    color: #fff !important;
}
.btn-info:hover, .btn-blue:hover, .btn-azure:hover {
    background-color: #1d4ed8 !important;
    border-color: #1d4ed8 !important;
}
.btn-info-lt,
.bg-info-lt,
.bg-blue-lt,
.bg-azure-lt {
    background-color: var(--ds-info-bg) !important;
    border-color: transparent !important;
    color: var(--ds-info) !important;
}
.btn-info-lt:hover,
.bg-info-lt:hover,
.bg-blue-lt:hover,
.bg-azure-lt:hover {
    background-color: color-mix(in srgb, var(--ds-info-bg), var(--ds-info) 8%) !important;
    color: var(--ds-info) !important;
}

/* ─── ICON ALIGNMENT WITHIN BUTTONS ───────────────────────────────────
   Tamaño normalizado: el icono apenas mayor que el texto (1.1em), nunca
   el 1.3em de .ti-sm — dentro de un botón el icono acompaña, no domina.
   El centrado vertical lo hace el flex del .btn. */
.btn .ti,
.btn i,
.btn .ti-sm,
.btn .ti-xs {
    font-size: 1.1em !important;
    line-height: 1;
    flex-shrink: 0;
}
.btn-icon .ti,
.btn-icon i {
    font-size: 1.15em !important;
    margin: 0 !important;
}

/* -------------------------------------------------------------------------
   6. Forms
   ------------------------------------------------------------------------- */
.form-label {
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--ds-ink-2);
    margin-bottom: 0.3rem;
    letter-spacing: -0.005em;
}

.form-control,
.form-select,
.input-group-text {
    background-color: var(--ds-surface) !important;
    border: 1px solid var(--ds-border-strong) !important;
    color: var(--ds-ink) !important;
    border-radius: var(--ds-radius-md) !important;
    padding: 0.4rem 0.75rem !important;
    min-height: var(--ds-control-h);
    font-size: var(--ds-control-font) !important;
    line-height: 1.4 !important;
    box-shadow: none !important;
    transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
/* Multi-line fields grow from the shared control height but aren't pinned
   to it — let the rows define the box. */
textarea.form-control { min-height: calc(var(--ds-control-h) * 1.6); }
/* The .sm / .lg modifiers tighten padding for compact UI rows but the
   FONT-SIZE stays at the base 1rem (= 13.5px) so text doesn't shrink to an
   unreadable size. This matches the user's preference: "don't make the
   inputs smaller, just keep a normal input size". */
.form-control-sm,
.form-select-sm,
.input-group-sm > .form-control,
.input-group-sm > .form-select,
.input-group-sm > .input-group-text {
    font-size: 0.8rem !important;
    padding: 0.2rem 0.55rem !important;
    min-height: 1.9rem;
    line-height: 1.4 !important;
}
.form-control-lg,
.form-select-lg,
.input-group-lg > .form-control,
.input-group-lg > .form-select,
.input-group-lg > .input-group-text {
    font-size: 0.95rem !important;
    padding: 0.5rem 0.85rem !important;
    min-height: 2.7rem;
    line-height: 1.4 !important;
}
.form-control::placeholder { color: var(--ds-ink-5); }
.form-control:focus,
.form-select:focus {
    border-color: var(--ds-ink) !important;
    outline: none !important;
    box-shadow: 0 0 0 3px rgba(10, 10, 10, 0.07) !important;
}
.form-control:disabled,
.form-select:disabled {
    background-color: var(--ds-surface-soft) !important;
    color: var(--ds-ink-4) !important;
    cursor: not-allowed;
}
.input-group-text {
    background-color: var(--ds-surface-muted) !important;
    color: var(--ds-ink-3) !important;
}

/* ─── Choice cards — radios/checkbox como tarjetas grandes seleccionables ───
   Reutilizable en formularios: <label class="choice-card"><input type="radio">
   <span class="choice-card-icon">…</span><span class="choice-card-body">…</span>
   <i class="ti ti-check choice-card-check"></i></label>. El estado seleccionado
   usa :has() sobre el input nativo (sin JS). */
.choice-cards { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.choice-card {
    position: relative; flex: 1 1 0; min-width: 9.5rem; margin: 0; cursor: pointer;
    display: flex; align-items: center; gap: 0.75rem;
    padding: 0.8rem 0.95rem;
    border: 1px solid var(--ds-border); border-radius: var(--ds-radius-md);
    background: var(--ds-surface);
    transition: border-color 0.12s ease, background-color 0.12s ease, box-shadow 0.12s ease;
}
.choice-card:hover { border-color: var(--ds-border-strong); background: var(--ds-surface-muted); }
.choice-card > input { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; margin: 0; }
.choice-card-icon {
    width: 2.25rem; height: 2.25rem; flex: 0 0 auto; border-radius: var(--ds-radius-sm);
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--ds-surface-soft); color: var(--ds-ink-3);
    transition: background-color 0.12s ease, color 0.12s ease;
}
.choice-card-icon .ti { font-size: 1.25rem !important; }
.choice-card-body { display: flex; flex-direction: column; min-width: 0; }
.choice-card-label { font-size: 0.95rem; font-weight: 600; color: var(--ds-ink); line-height: 1.25; }
.choice-card-hint { font-size: 0.8rem; color: var(--ds-ink-4); line-height: 1.3; }
/* El check explícito se sentía tosco — la selección se comunica con borde
   grafito + icono invertido. El check queda oculto (markup inerte). */
.choice-card-check { display: none; }
/* Seleccionado — borde grafito limpio (1px, sin doble borde) + icono invertido */
.choice-card.is-selected { border-color: var(--ds-ink); }
.choice-card.is-selected .choice-card-icon { background: var(--ds-ink); color: var(--ds-bg); }
.choice-card:has(> input:checked) { border-color: var(--ds-ink); }
.choice-card:has(> input:checked) .choice-card-icon { background: var(--ds-ink); color: var(--ds-bg); }
/* Foco por teclado (el input nativo está oculto) */
.choice-card:has(> input:focus-visible) { box-shadow: 0 0 0 3px rgba(10, 10, 10, 0.07); border-color: var(--ds-ink); }
.choice-card:has(> input:disabled) { opacity: 0.55; cursor: not-allowed; }

/* Uploader de evidencia — dos vías de subida igual de visibles (equipo / celular).
   Reutilizable: notas de evolución y modales de evidencia de citas (agenda/servicios).
   La tarjeta "equipo" lleva un <input type=file> transparente encima → habilita clic
   y arrastrar-soltar nativo. La tarjeta "celular" es un botón que muestra el QR inline. */
.ev-evidence-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 0.75rem; }
.ev-drop {
    position: relative; display: flex; align-items: center; gap: 0.85rem; margin: 0; width: 100%;
    padding: 1rem 1.1rem; text-align: left; cursor: pointer;
    border: 1px dashed var(--ds-border-strong); border-radius: var(--ds-radius-md); background: var(--ds-surface);
    transition: border-color 0.12s ease, background-color 0.12s ease, box-shadow 0.12s ease;
}
.ev-drop:hover { border-color: var(--ds-ink); background: var(--ds-surface-muted); }
.ev-drop.is-dragover { border-color: var(--ds-ink); border-style: solid; background: var(--ds-surface-muted); box-shadow: inset 0 0 0 2px var(--ds-border-strong); }
.ev-drop-input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; }
.ev-drop--mobile { border-style: solid; }
.ev-drop--mobile.is-active { border-color: var(--ds-ink); background: var(--ds-surface-muted); }
.ev-drop-ic {
    flex: 0 0 auto; width: 2.6rem; height: 2.6rem; border-radius: var(--ds-radius-sm);
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--ds-surface-soft); color: var(--ds-ink-3);
}
.ev-drop--mobile .ev-drop-ic { background: var(--ds-accent-violet-bg); color: var(--ds-accent-violet); }
.ev-drop-ic .ti { font-size: 1.35rem !important; }
.ev-drop-body { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }
.ev-drop-title { font-size: 0.9rem; font-weight: 600; color: var(--ds-ink); }
.ev-drop-hint { font-size: 0.78rem; line-height: 1.3; color: var(--ds-ink-4); }
.ev-drop-qr { margin-left: auto; flex: 0 0 auto; color: var(--ds-ink-4); font-size: 1.15rem !important; }
.ev-qr-steps { display: inline-block; text-align: left; margin: 0 auto 0.75rem; padding-left: 1.1rem; color: var(--ds-ink-3); font-size: 0.85rem; line-height: 1.5; }
/* QR inline (modales de cita): se revela al activar "Subir desde tu celular" */
.ev-qr-inline { display: flex; flex-direction: column; align-items: center; gap: 0.25rem; margin-top: 0.85rem; padding-top: 0.85rem; border-top: 1px solid var(--ds-border-soft); }
.ev-qr-inline .small { color: var(--ds-ink-4); }

/* Input-group radius surgery: only the OUTER edges get rounded so the
   input + addon read as one continuous control. Bootstrap does this by
   default but my .form-control/.form-select/.input-group-text rules
   force full radius — restore the segmentation here. */
.input-group {
    flex-wrap: nowrap;
}
.input-group > .form-control,
.input-group > .form-select,
.input-group > .form-floating,
.input-group > .input-group-text,
.input-group > .btn {
    border-radius: 0 !important;
}
.input-group > :first-child,
.input-group > :first-child > .form-control,
.input-group > :first-child > .form-select {
    border-top-left-radius: var(--ds-radius-md) !important;
    border-bottom-left-radius: var(--ds-radius-md) !important;
}
.input-group > :last-child,
.input-group > :last-child > .form-control,
.input-group > :last-child > .form-select {
    border-top-right-radius: var(--ds-radius-md) !important;
    border-bottom-right-radius: var(--ds-radius-md) !important;
}
/* Avoid double border at the seam */
.input-group > :not(:first-child) {
    margin-left: -1px;
}
/* Focused element on top so its focus ring isn't clipped by the addon */
.input-group > .form-control:focus,
.input-group > .form-select:focus {
    z-index: 2;
}

/* ══ Checkbox + Radio ad-hoc del DS ═══════════════════════════════════════════
   Control grafito con glyph blanco (palomita / punto / guion), aplicado de forma
   GLOBAL vía .form-check-input (300+ usos). El switch conserva su forma y thumb
   más abajo (+ guard de background-size). Estados: hover, checked, indeterminate,
   focus-visible y disabled. Dark mode: hereda tokens + --ds-focus-ring. */
.form-check-input {
    -webkit-appearance: none;
    appearance: none;
    background-repeat: no-repeat;
    background-position: center;
    border: 1.5px solid var(--ds-border-strong);
    border-radius: var(--ds-radius-sm);
    transition: background-color 0.13s ease, border-color 0.13s ease, box-shadow 0.13s ease;
    cursor: pointer;
}
/* Tamaño con presencia — solo checkbox y radio (el switch se auto-dimensiona).
   El border-radius va aquí (type-scoped, 0,1,1) para ganarle a la regla de Tabler
   `.form-check-input[type=checkbox]{border-radius:var(--tblr-border-radius)}`, que
   deja el checkbox como círculo (8px sobre 16px). Radio se re-fija a 50% abajo. */
.form-check-input[type="checkbox"],
.form-check-input[type="radio"] {
    width: 1.15rem;
    height: 1.15rem;
    margin-top: 0.14em;
    background-color: var(--ds-surface);
    border-radius: var(--ds-radius-sm) !important;
}
.form-check-input[type="radio"] { border-radius: 50% !important; }

/* Hover (no marcado): borde más presente. */
.form-check-input:hover:not(:disabled):not(:checked):not(:indeterminate) {
    border-color: var(--ds-ink-3);
    background-color: var(--ds-surface-muted);
}

/* Marcado: relleno grafito + glyph blanco. */
.form-check-input[type="checkbox"]:checked {
    background-color: var(--ds-ink) !important;
    border-color: var(--ds-ink) !important;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath fill='none' stroke='%23fff' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round' d='M5 10.5l3.4 3.4L15 6.4'/%3E%3C/svg%3E");
    background-size: 0.72em;
}
.form-check-input[type="checkbox"]:indeterminate {
    background-color: var(--ds-ink) !important;
    border-color: var(--ds-ink) !important;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath stroke='%23fff' stroke-width='2.6' stroke-linecap='round' d='M5.5 10h9'/%3E%3C/svg%3E");
    background-size: 0.72em;
}
.form-check-input[type="radio"]:checked {
    background-color: var(--ds-ink) !important;
    border-color: var(--ds-ink) !important;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Ccircle cx='10' cy='10' r='3.6' fill='%23fff'/%3E%3C/svg%3E");
    background-size: 1em;
}

/* Foco accesible (token, dark-aware). */
.form-check-input:focus,
.form-check-input:focus-visible {
    box-shadow: var(--ds-focus-ring) !important;
    border-color: var(--ds-ink);
    outline: none;
}
/* Deshabilitado. */
.form-check-input:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}
.form-check-input:disabled ~ .form-check-label {
    opacity: 0.6;
    cursor: not-allowed;
}

/* Dark mode: el relleno marcado es --ds-ink (claro, #f5f5f5); el glyph blanco
   quedaría invisible. Se cambia a glyph OSCURO para conservar el contraste. */
:root[data-theme="dark"] .form-check-input[type="checkbox"]:checked {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath fill='none' stroke='%230a0a0a' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round' d='M5 10.5l3.4 3.4L15 6.4'/%3E%3C/svg%3E");
}
:root[data-theme="dark"] .form-check-input[type="checkbox"]:indeterminate {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath stroke='%230a0a0a' stroke-width='2.6' stroke-linecap='round' d='M5.5 10h9'/%3E%3C/svg%3E");
}
:root[data-theme="dark"] .form-check-input[type="radio"]:checked {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Ccircle cx='10' cy='10' r='3.6' fill='%230a0a0a'/%3E%3C/svg%3E");
}

/* Form-switch must keep Bootstrap's pill shape (2em radius) — the rule above
   on .form-check-input overrides Tabler's default and would render the
   switch as a square. Restore the pill radius and the explicit dimensions
   so the thumb SVG positions correctly. */
/* Switch estilo Apollo: más alto y con presencia — un toggle es una
   decisión, no un checkbox disfrazado. El contenedor es flex para que
   el label viva SIEMPRE al lado (el padding/float de Bootstrap rompía
   la línea con el switch grande). */
.form-switch {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding-left: 0 !important;
    min-height: 0;
}
.form-switch .form-check-input {
    border-radius: 2em !important;
    width: 2.7em !important;
    height: 1.5em !important;
    flex-shrink: 0;
    float: none !important;
    margin-left: 0 !important;
    margin-top: 0 !important;
    cursor: pointer;
    transition: background-color 0.15s ease, border-color 0.15s ease;
    /* El checkbox ad-hoc fija background-size en :checked; el switch debe
       conservar su thumb a tamaño completo (contain), no la palomita compacta. */
    background-size: contain;
}
.form-switch .form-check-label {
    white-space: nowrap;
    cursor: pointer;
}
.form-switch .form-check-input:checked {
    background-color: var(--ds-ink) !important;
    border-color: var(--ds-ink) !important;
}

.form-hint, .form-text {
    color: var(--ds-ink-4);
    font-size: 0.85rem;
}

/* =========================================================================
   Tom-Select — wrapper IS the visible field
   --------------------------------------------------------------------------
   Single source of truth: the .ts-wrapper carries the border, background
   and radius. The .ts-control inside is just a transparent inner padding
   box. This eliminates two failure modes:
     1) DOUBLE BORDER — happened when both .ts-wrapper (via inherited
        .form-select / .form-control rules) and .ts-control rendered their
        own border at the same time.
     2) GREY/SEE-THROUGH SURFACE — a transparent wrapper meant the parent's
        background bled through the rounded corners and the ts-control's
        white box never reached the visible edge, so the field looked
        "blocked/disabled" when sitting inside a coloured container
        (.form-selectgroup-label, .alert, recessed cards, modals, etc.).
   ========================================================================= */
.ts-wrapper,
.ts-wrapper.single,
.ts-wrapper.multi,
.ts-wrapper.form-select,
.ts-wrapper.form-control,
.form-select.ts-wrapper,
.form-control.ts-wrapper {
    background-color: var(--ds-surface) !important;
    background-image: none !important;
    border: 1px solid var(--ds-border-strong) !important;
    border-radius: var(--ds-radius-md) !important;
    padding: 0 !important;
    box-shadow: none !important;
    min-height: var(--ds-control-h) !important;
    height: auto !important;
    color: var(--ds-ink) !important;
    display: flex;
    align-items: stretch;
    transition: border-color 0.12s ease, box-shadow 0.12s ease;
}

/* The control is now just a transparent inner pad — no border, no bg,
   no radius (inherits from wrapper), just padding + flex layout. */
.ts-wrapper > .ts-control,
.ts-wrapper.single > .ts-control,
.ts-wrapper.multi > .ts-control,
.ts-wrapper.form-select > .ts-control,
.ts-wrapper.form-control > .ts-control,
.ts-control {
    background: transparent !important;
    background-image: none !important;
    border: 0 !important;
    border-radius: inherit !important;
    box-shadow: none !important;
    padding: 0.4rem 0.75rem !important;
    font-size: var(--ds-control-font) !important;
    min-height: 0 !important;
    color: var(--ds-ink) !important;
    width: 100%;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    cursor: pointer;
}

/* Selected single-mode item: plain text, no chip styling. */
.ts-wrapper.single > .ts-control > .item {
    background: transparent !important;
    border: 0 !important;
    padding: 0 !important;
    margin: 0 !important;
    color: var(--ds-ink) !important;
    line-height: inherit;
}

/* True disabled state — applied to the wrapper so the whole surface reads
   as locked, mirroring .form-control:disabled. */
.ts-wrapper.disabled,
.ts-wrapper.disabled > .ts-control,
.ts-wrapper.disabled > .ts-control * {
    background-color: var(--ds-surface-soft) !important;
    color: var(--ds-ink-4) !important;
    cursor: not-allowed !important;
}

/* Compact (.form-select-sm / .form-control-sm / .input-group-sm) — only
   the inner padding tightens. Font-size stays at the base 1rem. */
.ts-wrapper.form-select-sm > .ts-control,
.ts-wrapper.form-control-sm > .ts-control,
.input-group-sm .ts-wrapper > .ts-control {
    font-size: 0.8rem !important;
    padding: 0.2rem 0.55rem !important;
}

/* Inline input inside .ts-control inherits the field's size and never
   introduces its own height (otherwise the field grows with the input). */
.ts-wrapper.form-select-sm,
.ts-wrapper.form-control-sm,
.input-group-sm .ts-wrapper { min-height: 1.9rem !important; }
.ts-control > input {
    min-height: 0 !important;
    line-height: 1.4 !important;
    font-size: var(--ds-control-font) !important;
    color: inherit;
}

/* Focus ring lives on the wrapper (since the wrapper carries the border).
   Suppress any focus border on the inner .ts-control. */
.ts-wrapper.focus,
.ts-wrapper.focus.single,
.ts-wrapper.focus.multi {
    border-color: var(--ds-ink) !important;
    box-shadow: 0 0 0 3px rgba(10, 10, 10, 0.07) !important;
}
.ts-wrapper.focus > .ts-control {
    border-color: transparent !important;
    box-shadow: none !important;
}
.ts-dropdown {
    background-color: var(--ds-surface) !important;
    border: 1px solid var(--ds-border) !important;
    border-radius: var(--ds-radius-md) !important;
    box-shadow: var(--ds-shadow-md) !important;
    margin-top: 4px !important;
    overflow: hidden;
}
.ts-dropdown,
.ts-dropdown .option,
.ts-dropdown .optgroup-header,
.ts-dropdown .no-results {
    /* Match the .form-control / .ts-control font-size so the open dropdown
       reads at the same density as the input — without this they inherit
       Tabler's default ~1rem and feel oversized. */
    font-size: var(--ds-control-font) !important;
}
.ts-dropdown .option {
    padding: 0.45rem 0.7rem;
    color: var(--ds-ink-2);
    border-radius: 0;
}
.ts-dropdown .option:hover,
.ts-dropdown .active {
    background-color: var(--ds-surface-muted) !important;
    color: var(--ds-ink) !important;
}
.ts-dropdown .selected {
    background-color: var(--ds-surface-active) !important;
    color: var(--ds-ink) !important;
}
/* TomSelect renderiza su dropdown como hijo del .ts-wrapper (no en <body>), así
   que un ancestro con overflow:hidden (típicamente .card / .card-body) CORTA las
   opciones que sobresalen. Mientras el dropdown está abierto (.dropdown-active),
   dejamos que el contenedor desborde para que se vean completas; al cerrarse
   vuelve a recortar. Fix global: aplica a cualquier card con un TomSelect activo. */
.card:has(.ts-wrapper.dropdown-active),
.card-body:has(.ts-wrapper.dropdown-active),
.modal-body:has(.ts-wrapper.dropdown-active) {
    overflow: visible !important;
}
/* El dropdown debe flotar por encima de las tarjetas siguientes al desbordar. */
.ts-dropdown { z-index: 60 !important; }
.ts-wrapper.multi .ts-control > div {
    background-color: var(--ds-surface-soft) !important;
    border: 1px solid var(--ds-border) !important;
    border-radius: var(--ds-radius-sm) !important;
    color: var(--ds-ink) !important;
    font-size: 0.85rem !important;
    padding: 0.05rem 0.5rem 0.05rem 0.45rem !important;
    line-height: 1.5 !important;
}

/* -------------------------------------------------------------------------
   7. Tables
   ------------------------------------------------------------------------- */
.table {
    --tblr-table-bg: var(--ds-surface);
    --tblr-table-color: var(--ds-ink);
    --tblr-table-border-color: var(--ds-border-soft);
    --tblr-table-hover-bg: var(--ds-surface-muted);
    --tblr-table-striped-bg: var(--ds-surface-muted);
    color: var(--ds-ink);
    border-color: var(--ds-border-soft);
}
.table > :not(caption) > * > * {
    background-color: transparent;
}
/* Headers de tabla en mono uppercase (lenguaje Handle): la cabecera es
   metadata, no contenido — overline quieto que deja brillar las filas.
   Aplica a TODA tabla del sistema. */
.table thead th {
    background-color: var(--ds-surface) !important;
    color: var(--ds-ink-4) !important;
    /* Cabecera = metadata, pero en SANS: el acento lo dan mayúsculas +
       letter-spacing, sin el peso "terminal" del mono (el mono se reserva
       para números/tnum y overlines). */
    font-family: var(--ds-font-sans) !important;
    font-weight: 600 !important;
    font-size: 0.72rem !important;
    letter-spacing: 0.06em !important;
    text-transform: uppercase !important;
    border-bottom: 1px solid var(--ds-border-soft) !important;
    border-top: 0 !important;
    padding: 0.75rem 1rem !important;
    white-space: nowrap;
}
/* Bootstrap's default rule `.table > :not(caption) > * + *` adds a 2nd
   border-top to the first body row that compounds with thead's border-bottom
   = visible darker line. Force it to a single soft separator. */
.table > :not(caption) > * + *,
.table > :not(caption) > * > * {
    border-top-color: var(--ds-border-soft) !important;
}
/* Filas con aire Handle: ~52px de alto, hover con transición */
.table tbody td {
    padding: 0.85rem 1rem !important;
    border-color: var(--ds-border-soft) !important;
    font-size: 1rem;
    vertical-align: middle;
    color: var(--ds-ink-2);
}
.table tbody tr { transition: background-color 0.1s ease; }

/* ─── Chevron de drill-down (primera celda, patrón Handle) ───────────
   Afordancia de "esta fila abre algo": gris fantasma que se asoma al
   hover de la fila. <td class="row-chevron"><i class="ti ti-chevron-right"></i></td> */
.table td.row-chevron,
.table th.row-chevron {
    width: 2.2rem !important;
    padding-right: 0 !important;
    text-align: center;
}
.table td.row-chevron .ti {
    font-size: 0.9rem !important;
    color: var(--ds-ink-5);
    transition: color 0.12s ease, transform 0.12s ease;
}
.table tbody tr:hover td.row-chevron .ti {
    color: var(--ds-ink-2);
    transform: translateX(2px);
}

/* ─── Count badge (el "1" junto al nombre en Handle) ───────────────── */
.count-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: var(--ds-radius-sm);
    background: var(--ds-surface-soft);
    border: 1px solid var(--ds-border-soft);
    color: var(--ds-ink-3);
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-size: 0.7rem;
    font-weight: 600;
    line-height: 1;
    flex-shrink: 0;
}

/* Edge cells share the system's content padding token. Applies to ALL
   tables — inside cards, tab-panes, raw containers, .card-table from
   Tabler — so the leftmost data column always lines up with the leftmost
   tab, card-header text, modal-header text, and card-body content. */
.table thead th:first-child,
.table tbody td:first-child,
.table tfoot td:first-child {
    padding-left: var(--ds-content-padding-x) !important;
}
.table thead th:last-child,
.table tbody td:last-child,
.table tfoot td:last-child {
    padding-right: var(--ds-content-padding-x) !important;
}
.table tbody tr:hover {
    background-color: var(--ds-surface-muted) !important;
}
.table-card .table {
    margin-bottom: 0;
}

/* DataTables */
.dataTables_wrapper {
    color: var(--ds-ink);
}
.dataTables_filter input,
.dataTables_length select {
    background-color: var(--ds-surface) !important;
    border: 1px solid var(--ds-border-strong) !important;
    border-radius: var(--ds-radius-md) !important;
    color: var(--ds-ink);
    padding: 0.4rem 0.6rem;
}
.dataTables_paginate .pagination {
    margin-bottom: 0;
}
.page-link {
    background-color: transparent !important;
    border-color: transparent !important;
    color: var(--ds-ink-3) !important;
    border-radius: var(--ds-radius-md) !important;
    margin: 0 1px;
    padding: 0.35rem 0.65rem;
    font-size: 0.85rem;
}
.page-link:hover {
    background-color: var(--ds-surface-muted) !important;
    color: var(--ds-ink) !important;
}
.page-item.active .page-link,
.page-link.active,
.active > .page-link {
    background-color: var(--ds-ink) !important;
    border-color: var(--ds-ink) !important;
    color: var(--ds-bg) !important;
}
.page-item.disabled .page-link {
    color: var(--ds-ink-5) !important;
    background: transparent !important;
}

#products-table > thead > tr > th {
    background-color: var(--ds-surface) !important;
}

/* -------------------------------------------------------------------------
   8. Modals
   ------------------------------------------------------------------------- */
.modal-content {
    background-color: var(--ds-surface) !important;
    border: 1px solid var(--ds-border) !important;
    border-radius: var(--ds-radius-lg) !important;
    box-shadow: var(--ds-shadow-lg) !important;
    overflow: hidden;
}
.modal-header {
    padding: 1rem var(--ds-content-padding-x) 0.75rem;
    border-bottom: 1px solid var(--ds-border-soft) !important;
    background: var(--ds-surface);
}
/* .modal-title applies regardless of tag (the codebase has h5, h1 and even
   div instances historically). Fallback on bare h* inside .modal-header
   keeps modals consistent if the author forgets the .modal-title class. */
.modal-title,
.modal-header > h1:not([class*='page-']),
.modal-header > h2:not([class*='page-']),
.modal-header > h3:not([class*='page-']),
.modal-header > h4:not([class*='page-']),
.modal-header > h5:not([class*='page-']),
.modal-header > h6:not([class*='page-']) {
    font-weight: 600;
    color: var(--ds-ink);
    font-size: 1rem;
    letter-spacing: -0.018em;
    margin-bottom: 0;
    line-height: 1.25;
}
/* Subtítulo de modal — UNA línea de contexto bajo el título. Recipe slim
   compartido por todos los modales (sin breadcrumb overline: el modal ya
   se abre desde un contexto conocido). */
.modal-subtitle {
    margin: 0.2rem 0 0;
    font-size: 0.85rem;
    line-height: 1.45;
    color: var(--ds-ink-4);
    max-width: 64ch;
}
.modal-body {
    padding: var(--ds-content-padding-x);
    color: var(--ds-ink-2);
    line-height: 1.55;
    font-size: 1rem;
}
.modal-footer {
    padding: var(--ds-content-padding-y) var(--ds-content-padding-x);
    border-top: 1px solid var(--ds-border-soft) !important;
    background: var(--ds-surface);
    gap: 0.5rem;
}
.modal-backdrop {
    background-color: rgba(10, 10, 10, 0.35);
}
.modal-backdrop.show {
    opacity: 1;
}
.btn-close {
    opacity: 0.5;
    filter: none;
}
.btn-close:hover { opacity: 1; }
/* Dark mode: invert the black close glyph so the X stays visible on dark surfaces */
:root[data-theme="dark"] .btn-close {
    filter: invert(1) grayscale(100%) brightness(200%);
}

/* -------------------------------------------------------------------------
   9. Dropdowns
   ------------------------------------------------------------------------- */
.dropdown-menu {
    background-color: var(--ds-surface) !important;
    border: 1px solid var(--ds-border) !important;
    border-radius: var(--ds-radius-md) !important;
    box-shadow: var(--ds-shadow-md) !important;
    padding: 0.35rem !important;
    font-size: var(--ds-control-font) !important;
    color: var(--ds-ink);
    min-width: 200px;
}
.dropdown-item {
    color: var(--ds-ink-2) !important;
    padding: 0.4rem 0.6rem;
    border-radius: var(--ds-radius-sm);
    font-weight: 400;
    font-size: var(--ds-control-font);
    transition: background-color 0.1s ease;
}
.dropdown-item:hover,
.dropdown-item:focus {
    background-color: var(--ds-surface-muted) !important;
    color: var(--ds-ink) !important;
}
.dropdown-item.active,
.dropdown-item:active {
    background-color: var(--ds-surface-active) !important;
    color: var(--ds-ink) !important;
}
.dropdown-item.text-danger { color: var(--ds-danger) !important; }
.dropdown-item.text-danger:hover { background-color: var(--ds-danger-bg) !important; color: var(--ds-danger) !important; }
.dropdown-divider { margin: 0.35rem 0 !important; border-color: var(--ds-border-soft) !important; }
.dropdown-header {
    color: var(--ds-ink-4);
    font-size: 0.85rem;
    font-weight: 500;
    letter-spacing: -0.005em;
    text-transform: none;
    padding: 0.5rem 0.7rem 0.25rem;
}

/* -------------------------------------------------------------------------
   10. Badges, alerts, toasts
   ------------------------------------------------------------------------- */
.badge {
    font-family: var(--ds-font-sans);
    font-weight: 500;
    font-size: 0.9rem;
    padding: 0.24rem 0.5rem;
    border-radius: var(--ds-radius-sm);
    border: 1px solid transparent;
    letter-spacing: -0.003em;
    line-height: 1.3;
}
/* Numeric badges (counts, IDs) get mono — auto-detected by content shape */
.badge[data-count],
.badge.count,
.badge.numeric,
.badge.mono {
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-weight: 500;
    letter-spacing: -0.01em;
}
.badge.bg-primary,
.badge.bg-dark {
    background-color: var(--ds-ink) !important;
    color: var(--ds-bg) !important;
}
.badge.bg-secondary {
    background-color: var(--ds-surface-soft) !important;
    color: var(--ds-ink-2) !important;
    border-color: var(--ds-border) !important;
}
.badge.bg-success, .badge.bg-green,
.badge.bg-success-lt, .badge.bg-green-lt {
    background-color: var(--ds-success-bg) !important;
    color: var(--ds-success) !important;
    border-color: transparent !important;
}
.badge.bg-warning, .badge.bg-yellow,
.badge.bg-warning-lt, .badge.bg-yellow-lt {
    background-color: var(--ds-warning-bg) !important;
    color: var(--ds-warning) !important;
}
.badge.bg-danger, .badge.bg-red,
.badge.bg-danger-lt, .badge.bg-red-lt {
    background-color: var(--ds-danger-bg) !important;
    color: var(--ds-danger) !important;
}
.badge.bg-info, .badge.bg-blue,
.badge.bg-info-lt, .badge.bg-blue-lt,
.badge.bg-azure, .badge.bg-azure-lt {
    background-color: var(--ds-info-bg) !important;
    color: var(--ds-info) !important;
}
/* Familia completa de tonos Tabler → paleta de acentos del sistema.
   Cualquier vista puede usar bg-purple-lt, bg-teal-lt, etc. y obtiene
   un chip pastel coherente en vez del color crudo de Tabler. */
.badge.bg-purple, .badge.bg-purple-lt,
.badge.bg-indigo, .badge.bg-indigo-lt,
.badge.bg-violet, .badge.bg-violet-lt {
    background-color: var(--ds-accent-violet-bg) !important;
    color: var(--ds-accent-violet) !important;
    border-color: transparent !important;
}
.badge.bg-pink, .badge.bg-pink-lt {
    background-color: var(--ds-accent-rose-bg) !important;
    color: var(--ds-accent-rose) !important;
    border-color: transparent !important;
}
.badge.bg-cyan, .badge.bg-cyan-lt {
    background-color: var(--ds-accent-cyan-bg) !important;
    color: var(--ds-accent-cyan) !important;
    border-color: transparent !important;
}
.badge.bg-teal, .badge.bg-teal-lt {
    background-color: var(--ds-accent-teal-bg) !important;
    color: var(--ds-accent-teal) !important;
    border-color: transparent !important;
}
.badge.bg-orange, .badge.bg-orange-lt {
    background-color: var(--ds-accent-orange-bg) !important;
    color: var(--ds-accent-orange) !important;
    border-color: transparent !important;
}
.badge.bg-lime, .badge.bg-lime-lt {
    background-color: var(--ds-accent-green-bg) !important;
    color: var(--ds-accent-green) !important;
    border-color: transparent !important;
}

/* Alerts */
.alert {
    border: 1px solid var(--ds-border) !important;
    border-radius: var(--ds-radius-md);
    background-color: var(--ds-surface) !important;
    color: var(--ds-ink-2);
    padding: var(--ds-space-4);
    box-shadow: none !important;
}
.alert-success { background-color: var(--ds-success-bg) !important; border-color: transparent !important; color: var(--ds-success) !important; }
.alert-warning { background-color: var(--ds-warning-bg) !important; border-color: transparent !important; color: var(--ds-warning) !important; }
.alert-danger  { background-color: var(--ds-danger-bg)  !important; border-color: transparent !important; color: var(--ds-danger)  !important; }
.alert-info    { background-color: var(--ds-info-bg)    !important; border-color: transparent !important; color: var(--ds-info)    !important; }

/* =========================================================================
   Toasts (ds-toast) — motor propio del DS (public/scripts/ds-toast.js) con la
   API de toastr. Chrome neutro; el color vive en el icon-tile (tint semántico)
   y en el acento lateral por `inset box-shadow` (regla dura #3 — nunca
   border-left). Overline mono como etiqueta de estado, mensaje en sans.
   ========================================================================= */
#ds-toast-container {
    position: fixed;
    z-index: 2000;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    padding: 0.85rem;
    max-width: 100vw;
    pointer-events: none; /* solo los toasts capturan eventos */
}
#ds-toast-container.toast-top-right { top: calc(var(--ds-header-h, 3.5rem) + 0.25rem); right: 0; align-items: flex-end; }
#ds-toast-container.toast-top-left { top: calc(var(--ds-header-h, 3.5rem) + 0.25rem); left: 0; align-items: flex-start; }
#ds-toast-container.toast-bottom-right { bottom: 0; right: 0; align-items: flex-end; }
#ds-toast-container.toast-bottom-left { bottom: 0; left: 0; align-items: flex-start; }
#ds-toast-container.toast-top-center { top: calc(var(--ds-header-h, 3.5rem) + 0.25rem); left: 50%; transform: translateX(-50%); align-items: center; }
#ds-toast-container.toast-bottom-center { bottom: 0; left: 50%; transform: translateX(-50%); align-items: center; }

.ds-toast {
    pointer-events: auto;
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: 0.9rem;
    width: 24rem;
    max-width: calc(100vw - 1.7rem);
    padding: 1.05rem 1.15rem;
    background: var(--ds-surface);
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-lg);
    box-shadow: var(--ds-shadow-lg);
    overflow: hidden;
    cursor: default;
    opacity: 0;
    transform: translateX(14px);
    transition: opacity 0.22s ease, transform 0.24s cubic-bezier(0.16, 1, 0.3, 1);
}
.ds-toast--in { opacity: 1; transform: none; }
.ds-toast--out { opacity: 0; transform: translateX(14px); }
/* Contenedores a la izquierda: la animación entra/sale por ese lado. */
#ds-toast-container.toast-top-left .ds-toast,
#ds-toast-container.toast-bottom-left .ds-toast { transform: translateX(-14px); }
#ds-toast-container.toast-top-left .ds-toast--in,
#ds-toast-container.toast-bottom-left .ds-toast--in { transform: none; }
#ds-toast-container.toast-top-left .ds-toast--out,
#ds-toast-container.toast-bottom-left .ds-toast--out { transform: translateX(-14px); }

.ds-toast-content { flex: 1 1 auto; min-width: 0; }
/* Estado = status-chip: ■ + overline mono con color semántico (sin caja ni barra). */
.ds-toast-label {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0 0 0.4rem;
    font-family: var(--ds-font-mono);
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}
.ds-toast-label::before {
    content: '';
    width: 9px;
    height: 9px;
    background: currentColor;
    flex-shrink: 0;
}
.ds-toast--success .ds-toast-label { color: var(--ds-success); }
.ds-toast--warning .ds-toast-label { color: var(--ds-warning); }
.ds-toast--error .ds-toast-label { color: var(--ds-danger); }
.ds-toast--info .ds-toast-label { color: var(--ds-info); }
.ds-toast-message {
    margin: 0;
    font-family: var(--ds-font-sans);
    font-size: 0.95rem;
    font-weight: 450;
    line-height: 1.45;
    color: var(--ds-ink);
    overflow-wrap: anywhere;
}

.ds-toast-close {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    margin: -0.2rem -0.25rem 0 0;
    padding: 0;
    border: 0;
    background: transparent;
    border-radius: var(--ds-radius-sm);
    color: var(--ds-ink-4);
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease;
}
.ds-toast-close:hover { background: var(--ds-surface-muted); color: var(--ds-ink-2); }
.ds-toast-close .ti { font-size: 1.05rem !important; }

.ds-toast-progress {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 2px;
    background: transparent;
}
.ds-toast-progress-bar {
    display: block;
    width: 100%;
    height: 100%;
    border-radius: 0 2px 2px 0;
    opacity: 0.55;
}
.ds-toast--success .ds-toast-progress-bar { background: var(--ds-success); }
.ds-toast--warning .ds-toast-progress-bar { background: var(--ds-warning); }
.ds-toast--error .ds-toast-progress-bar { background: var(--ds-danger); }
.ds-toast--info .ds-toast-progress-bar { background: var(--ds-info); }

@media (max-width: 480px) {
    #ds-toast-container { left: 0; right: 0; align-items: stretch; }
    #ds-toast-container.toast-top-center,
    #ds-toast-container.toast-bottom-center { transform: none; }
    .ds-toast { width: 100%; }
}
@media (prefers-reduced-motion: reduce) {
    .ds-toast { transition: opacity 0.18s ease; transform: none; }
    .ds-toast--out { transform: none; }
}

/* -------------------------------------------------------------------------
   11. Tabs
   ------------------------------------------------------------------------- */
/* =========================================================================
   Tabs — Linear/Vercel style: text tabs with a 1.5px ink underline on active,
   subtle muted state otherwise, no flashy hover borders, badges go neutral.
   ========================================================================= */
.nav-tabs {
    border-bottom: 1px solid var(--ds-border) !important;
    background: transparent !important;
    gap: 0;
    margin: 0 !important;
    padding: 0;
    flex-wrap: nowrap;
}
.nav-tabs .nav-item { margin: 0; }

/* Tabs en mono uppercase (lenguaje Handle) — GLOBAL: toda .nav-tabs de la
   app (expedientes, productos, agentes…). Los .new-tabs (segmented
   control) y .nav-pills (filtros) conservan sans: son selectores de
   vista, no navegación de documento. */
.nav-tabs .nav-link {
    border: 0 !important;
    border-bottom: 1.5px solid transparent !important;
    background: transparent !important;
    color: var(--ds-ink-4) !important;
    font-family: var(--ds-font-mono) !important;
    font-weight: 600;
    font-size: 0.8rem !important;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    padding: 0.6rem 0.85rem !important;
    margin: 0 0 -1px 0 !important;
    border-radius: 0 !important;
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    line-height: 1.4;
    white-space: nowrap;
    transition: color 0.12s ease, border-color 0.12s ease;
}
.nav-tabs .nav-link:hover:not(.active) {
    color: var(--ds-ink-2) !important;
    background: transparent !important;
    border-bottom-color: transparent !important;  /* no border flash */
}
.nav-tabs .nav-link.active {
    color: var(--ds-ink) !important;
    background: transparent !important;
    border-bottom-color: var(--ds-ink) !important;
}
.nav-tabs .nav-link .ti,
.nav-tabs .nav-link i.ti {
    font-size: 0.95rem !important;
    color: currentColor;
    margin: 0 !important;
}

/* Badge inside a tab — neutral, mono, muted. Counts not alarms. */
.nav-tabs .nav-link .badge {
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-size: 0.85rem;
    font-weight: 500;
    line-height: 1.3;
    padding: 0.12rem 0.4rem;
    background-color: var(--ds-surface-soft) !important;
    color: var(--ds-ink-3) !important;
    border: 0 !important;
    margin-left: 0.15rem;
}
.nav-tabs .nav-link.active .badge {
    background-color: var(--ds-surface-active) !important;
    color: var(--ds-ink) !important;
}

/* ─── Tabs de documento deslizables en móvil (<992px) ────────────────────
   La .nav-tabs de record trae `flex-wrap: nowrap` pero sin overflow, así que
   con 6 tabs en móvil se recortaban contra el borde (sin scroll). Aquí el
   contenedor pasa a scroll horizontal con scrollbar oculto y snap. El JS del
   layout (main.ejs) hornea auto-scroll de la tab activa a la vista y toggle de
   las clases .tabs-fade-* para el degradado de affordance en los bordes. */
@media (max-width: 991.98px) {
    .nav-tabs:not(.new-tabs):not(.card-header-tabs) {
        overflow-x: auto;
        overflow-y: hidden;
        scrollbar-width: none;
        -webkit-overflow-scrolling: touch;
        scroll-snap-type: x proximity;
    }
    .nav-tabs:not(.new-tabs):not(.card-header-tabs)::-webkit-scrollbar { display: none; }
    .nav-tabs:not(.new-tabs):not(.card-header-tabs) .nav-item { scroll-snap-align: start; }
    /* Degradado de borde: se desvanece el lado donde hay más tabs ocultas.
       El mask se aplica al viewport del scroller (no scrollea con el contenido),
       por eso el fade queda pegado al borde. Las clases las pone el JS según la
       posición de scroll — sin fade cuando no hay overflow. */
    .nav-tabs.tabs-fade-end {
        -webkit-mask-image: linear-gradient(to right, #000 84%, transparent);
                mask-image: linear-gradient(to right, #000 84%, transparent);
    }
    .nav-tabs.tabs-fade-start {
        -webkit-mask-image: linear-gradient(to right, transparent, #000 12%);
                mask-image: linear-gradient(to right, transparent, #000 12%);
    }
    .nav-tabs.tabs-fade-start.tabs-fade-end {
        -webkit-mask-image: linear-gradient(to right, transparent, #000 12%, #000 84%, transparent);
                mask-image: linear-gradient(to right, transparent, #000 12%, #000 84%, transparent);
    }
}

/* Espacio uniforme entre una nav-tabs de navegación de documento (record) y su
   primer bloque de contenido. Reemplaza los `margin-bottom` inline dispares
   (1 / 1.2 / 1.4rem) que cada vista traía. Excluye .new-tabs (segmented control)
   y .card-header-tabs (van flush dentro del card). */
.nav-tabs:not(.new-tabs):not(.card-header-tabs) + .tab-content,
.nav-tabs:not(.new-tabs):not(.card-header-tabs) + .money-cells,
.nav-tabs:not(.new-tabs):not(.card-header-tabs) + .stat-strip {
    margin-top: 1.2rem;
}

/* `.card-header-tabs` (Tabler) inherits the same look */
.card-header-tabs {
    margin: 0 !important;
}
.card-header-tabs .nav-link {
    border-bottom: 1.5px solid transparent !important;
}
.card-header-tabs .nav-link.active {
    background-color: transparent !important;
    border-bottom-color: var(--ds-ink) !important;
}
.card-header-tabs .nav-link:hover:not(.active) {
    background-color: transparent !important;
    border-bottom-color: transparent !important;
}

/* When a card-header is used solely as a tab strip, collapse all its
   padding so the tabs sit flush against the card edges. The first tab's
   own padding-left then provides the visual indent that aligns with the
   first table cell below. No `px-0` needed in markup. */
.card-header:has(> .nav-tabs),
.card-header:has(> .card-header-tabs),
.card-header.border-bottom:has(.nav-tabs) {
    padding: 0 !important;
    background: var(--ds-surface) !important;
    border-bottom: 0 !important;  /* nav-tabs draws its own border */
}

/* Remove inner padding from the nav-tabs container too */
.card-header > .nav-tabs,
.card-header > .nav-tabs.px-0,
.card-header > .card-header-tabs {
    padding-left: 0 !important;
    padding-right: 0 !important;
    margin: 0 !important;
}

/* First tab's content aligns with the first table cell's content via the
   shared --ds-content-padding-x token. */
.card-header > .nav-tabs > .nav-item:first-child > .nav-link,
.card-header > .card-header-tabs > .nav-item:first-child > .nav-link,
.flex-grow-0.card-header > .nav-tabs > .nav-item:first-child > .nav-link {
    padding-left: var(--ds-content-padding-x) !important;
}
/* Last tab gets matching right padding for symmetry on the trailing edge */
.card-header > .nav-tabs > .nav-item:last-child > .nav-link,
.card-header > .card-header-tabs > .nav-item:last-child > .nav-link {
    padding-right: var(--ds-content-padding-x) !important;
}

/* Pills */
.nav-pills .nav-link {
    color: var(--ds-ink-3);
    background: transparent;
    border-radius: var(--ds-radius-md);
}
.nav-pills .nav-link:hover { background: var(--ds-surface-muted); }
.nav-pills .nav-link.active {
    background-color: var(--ds-surface-active) !important;
    color: var(--ds-ink) !important;
}

/* -------------------------------------------------------------------------
   12. Datepicker (flatpickr) — refined clinical look
   ------------------------------------------------------------------------- */

/* Calendar container.
   Popover (default): subtle card so it stands out from the page.
   Inline: completely flat — embeds naturally in whatever parent holds it. */
.flatpickr-calendar {
    background-color: var(--ds-surface) !important;
    border: 1px solid var(--ds-border) !important;
    border-radius: var(--ds-radius-lg) !important;
    box-shadow: var(--ds-shadow-md) !important;
    padding: 0.5rem !important;
    font-family: var(--ds-font-sans) !important;
    color: var(--ds-ink) !important;
    z-index: 9999 !important;
}
.flatpickr-calendar.inline {
    background: transparent !important;
    border: 0 !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    padding: 0 !important;
    width: 100% !important;
}
.flatpickr-calendar.arrowTop::before,
.flatpickr-calendar.arrowTop::after,
.flatpickr-calendar.arrowBottom::before,
.flatpickr-calendar.arrowBottom::after {
    border-bottom-color: var(--ds-border) !important;
}
.flatpickr-calendar.arrowBottom::before,
.flatpickr-calendar.arrowBottom::after {
    border-top-color: var(--ds-border) !important;
}

/* ── Month / year navigation ──
   Tabler's flatpickr.css positions each piece with hardcoded absolute
   offsets (current-month at top:1.15rem, arrows at top:0.75rem) that don't
   line up vertically. We override that to a single flex row so the prev/next
   arrows and the "Month Year" label are all centered on the same baseline,
   regardless of font size or locale. */
.flatpickr-months {
    display: flex !important;
    align-items: center !important;
    justify-content: space-between !important;
    gap: 0.25rem;
    padding: 0.25rem 0.25rem 0.5rem !important;
}
.flatpickr-months .flatpickr-month {
    color: var(--ds-ink) !important;
    background: transparent !important;
    fill: var(--ds-ink) !important;
    position: static !important;
    flex: 1 1 auto !important;
    height: auto !important;
    overflow: visible !important;
}
.flatpickr-current-month {
    position: static !important;
    left: auto !important;
    top: auto !important;
    width: 100% !important;
    justify-content: center !important;
    padding: 0 !important;
    transform: none !important;
}
.flatpickr-months .flatpickr-prev-month,
.flatpickr-months .flatpickr-next-month {
    position: static !important;
    top: auto !important;
    right: auto !important;
    left: auto !important;
    flex: 0 0 auto !important;
    /* ink-2 (no ink-3): las flechas a ink-3 casi no se ven en dark. */
    color: var(--ds-ink-2) !important;
    fill: var(--ds-ink-2) !important;
    border-radius: var(--ds-radius-sm);
    transition: background-color 0.12s ease, color 0.12s ease;
}
.flatpickr-months .flatpickr-prev-month:hover,
.flatpickr-months .flatpickr-next-month:hover {
    color: var(--ds-ink) !important;
    fill: var(--ds-ink) !important;
    background: var(--ds-surface-muted) !important;
}

/* ── FullCalendar — tema GLOBAL (todos los calendarios) ──────────────────────
   Mapea las variables internas de FC a tokens DS para que CUALQUIER instancia
   (.fc) adapte al dark mode: agenda, agenda quirúrgica, consultorios, salas de
   cirugía, calendarios en ficha de cliente, etc. Sin esto FC usa sus defaults
   claros (#ddd/#fff) que no cambian con el tema. (Antes vivía scoped en
   Agenda.ejs; movido aquí para que aplique a todos.) */
.fc {
    --fc-border-color: var(--ds-border-soft);
    --fc-page-bg-color: var(--ds-surface);
    --fc-neutral-bg-color: var(--ds-surface-muted);
    --fc-neutral-text-color: var(--ds-ink-3);
    --fc-today-bg-color: var(--ds-surface-muted);
    --fc-now-indicator-color: var(--ds-danger);
    --fc-event-bg-color: var(--ds-surface-muted);
    --fc-event-border-color: var(--ds-border);
    --fc-event-text-color: var(--ds-ink);
    --fc-list-event-hover-bg-color: var(--ds-surface-muted);
    --fc-highlight-color: var(--ds-surface-active);
    --fc-non-business-color: var(--ds-surface-soft);
}
.flatpickr-months .flatpickr-prev-month svg,
.flatpickr-months .flatpickr-next-month svg {
    fill: currentColor !important;
}
.flatpickr-months .flatpickr-prev-month svg path,
.flatpickr-months .flatpickr-next-month svg path {
    fill: currentColor !important;
}
.flatpickr-current-month .flatpickr-monthDropdown-months,
.flatpickr-current-month input.cur-year {
    color: var(--ds-ink) !important;
    font-family: var(--ds-font-sans) !important;
    font-weight: 600 !important;
    background: transparent !important;
}
.flatpickr-current-month input.cur-year {
    font-family: var(--ds-font-mono) !important;
    font-feature-settings: 'tnum';
}
.flatpickr-current-month .arrowUp,
.flatpickr-current-month .arrowDown {
    border-color: var(--ds-ink-3) !important;
}
.flatpickr-current-month .arrowUp::after { border-bottom-color: var(--ds-ink-3) !important; }
.flatpickr-current-month .arrowDown::after { border-top-color: var(--ds-ink-3) !important; }

/* ── Weekdays header ── */
.flatpickr-weekdays { background-color: transparent !important; height: 2rem; }
.flatpickr-weekdaycontainer { padding: 0 !important; }
span.flatpickr-weekday {
    color: var(--ds-ink-4) !important;
    font-family: var(--ds-font-sans) !important;
    font-weight: 500 !important;
    font-size: 0.85rem !important;
    text-transform: none !important;
    letter-spacing: -0.005em !important;
    background: transparent !important;
}

/* ── Day cells ──
   Width / height left to Flatpickr defaults so the calendar can be inline
   (full-width) or popover. We only style colors, fonts, and transitions. */
.flatpickr-days { padding: 0 !important; }
.dayContainer { padding: 0 !important; }
.flatpickr-day {
    border-radius: var(--ds-radius-sm) !important;
    color: var(--ds-ink-2) !important;
    font-family: var(--ds-font-mono) !important;
    font-feature-settings: 'tnum';
    font-size: 0.85rem !important;
    font-weight: 500 !important;
    border: 1px solid transparent !important;
    transition: background-color 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}
.flatpickr-day:hover:not(.flatpickr-disabled):not(.selected):not(.startRange):not(.endRange) {
    background-color: var(--ds-surface-muted) !important;
    border-color: transparent !important;
    color: var(--ds-ink) !important;
}

/* Today: subtle ring underneath, not solid black */
.flatpickr-day.today,
.flatpickr-calendar .dayContainer .today {
    background-color: transparent !important;
    color: var(--ds-ink) !important;
    border-color: var(--ds-ink) !important;
    font-weight: 600 !important;
}
.flatpickr-day.today:hover {
    background-color: var(--ds-surface-muted) !important;
    color: var(--ds-ink) !important;
    border-color: var(--ds-ink) !important;
}
/* When today is also selected, fill it solid */
.flatpickr-day.today.selected,
.flatpickr-day.today.startRange,
.flatpickr-day.today.endRange {
    background-color: var(--ds-ink) !important;
    color: var(--ds-bg) !important;
    border-color: var(--ds-ink) !important;
}

/* Selected (single date or range endpoints) */
.flatpickr-day.selected,
.flatpickr-day.startRange,
.flatpickr-day.endRange,
.flatpickr-calendar .selected {
    background-color: var(--ds-ink) !important;
    color: var(--ds-bg) !important;
    border-color: var(--ds-ink) !important;
    font-weight: 600 !important;
}
.flatpickr-day.selected:hover,
.flatpickr-day.startRange:hover,
.flatpickr-day.endRange:hover {
    background-color: var(--ds-ink-2) !important;
    border-color: var(--ds-ink-2) !important;
}
.flatpickr-day.startRange { border-radius: var(--ds-radius-sm) 0 0 var(--ds-radius-sm) !important; }
.flatpickr-day.endRange   { border-radius: 0 var(--ds-radius-sm) var(--ds-radius-sm) 0 !important; }
.flatpickr-day.startRange.endRange { border-radius: var(--ds-radius-sm) !important; }

/* ── Week selection (agenda mini-calendar, weekSelect plugin) ──
   weekSelect tags every day of the chosen week with `.week.selected` and the
   week under the cursor with `.inRange`. Each renders as ONE continuous band
   (rounded ends, no per-cell gaps), with a clear hierarchy between states:
     · selected week       → solid dark band
     · hover preview week   → soft gray band
     · hover over selected  → dark band lifted one step (intentional feedback) */

/* Selected week: dark continuous band */
.flatpickr-day.week.selected {
    background-color: var(--ds-ink) !important;
    color: var(--ds-bg) !important;
    border-color: transparent !important;
    border-radius: 0 !important;
    box-shadow: -5px 0 0 var(--ds-ink), 5px 0 0 var(--ds-ink) !important;
}
.flatpickr-day.week.selected:nth-child(7n + 1) {
    border-radius: var(--ds-radius-sm) 0 0 var(--ds-radius-sm) !important;
    box-shadow: 5px 0 0 var(--ds-ink) !important;
}
.flatpickr-day.week.selected:nth-child(7n) {
    border-radius: 0 var(--ds-radius-sm) var(--ds-radius-sm) 0 !important;
    box-shadow: -5px 0 0 var(--ds-ink) !important;
}

/* Hover preview week (not the selected one): soft gray continuous band */
.flatpickr-day.inRange,
.flatpickr-calendar .inRange {
    background-color: var(--ds-surface-active) !important;
    color: var(--ds-ink) !important;
    border-color: transparent !important;
    border-radius: 0 !important;
    box-shadow: -5px 0 0 var(--ds-surface-active), 5px 0 0 var(--ds-surface-active) !important;
}
.flatpickr-day.inRange:nth-child(7n + 1) {
    border-radius: var(--ds-radius-sm) 0 0 var(--ds-radius-sm) !important;
    box-shadow: 5px 0 0 var(--ds-surface-active) !important;
}
.flatpickr-day.inRange:nth-child(7n) {
    border-radius: 0 var(--ds-radius-sm) var(--ds-radius-sm) 0 !important;
    box-shadow: -5px 0 0 var(--ds-surface-active) !important;
}

/* Hover OVER the already-selected week: keep it dark, lift one step so the
   hover reads as deliberate feedback instead of muddying the selected band. */
.flatpickr-day.week.selected.inRange {
    background-color: var(--ds-ink-2) !important;
    color: #fff !important;
    box-shadow: -5px 0 0 var(--ds-ink-2), 5px 0 0 var(--ds-ink-2) !important;
}
.flatpickr-day.week.selected.inRange:nth-child(7n + 1) {
    box-shadow: 5px 0 0 var(--ds-ink-2) !important;
}
.flatpickr-day.week.selected.inRange:nth-child(7n) {
    box-shadow: -5px 0 0 var(--ds-ink-2) !important;
}

/* Disabled / outside current month */
.flatpickr-day.flatpickr-disabled,
.flatpickr-day.flatpickr-disabled:hover,
.flatpickr-disabled {
    color: var(--ds-ink-5) !important;
    background: transparent !important;
    cursor: not-allowed !important;
}
.flatpickr-day.prevMonthDay,
.flatpickr-day.nextMonthDay {
    color: var(--ds-ink-5) !important;
}

/* ── Time input (when enableTime: true) ── */
.flatpickr-time {
    border-top: 1px solid var(--ds-border-soft) !important;
    margin-top: 0.4rem;
    padding-top: 0.5rem;
}
.flatpickr-time input {
    color: var(--ds-ink) !important;
    font-family: var(--ds-font-mono) !important;
    font-feature-settings: 'tnum';
    font-weight: 600 !important;
    font-size: 0.875rem !important;
    background: var(--ds-surface-soft) !important;
    border-radius: var(--ds-radius-sm) !important;
}
.flatpickr-time input:hover,
.flatpickr-time input:focus {
    background: var(--ds-surface-muted) !important;
}
.flatpickr-time .flatpickr-time-separator,
.flatpickr-time .flatpickr-am-pm {
    color: var(--ds-ink-3) !important;
    font-family: var(--ds-font-mono) !important;
}

/* ── Week numbers (if enableWeekNumbers: true) ── */
.flatpickr-weeks {
    border-right: 1px solid var(--ds-border-soft) !important;
    padding: 0 0.4rem !important;
}
.flatpickr-weekwrapper .flatpickr-weeks span.flatpickr-day {
    color: var(--ds-ink-4) !important;
    font-size: 0.85rem !important;
    font-weight: 500 !important;
}

/* ── Month dropdown options (browser-rendered <option>) ── */
.flatpickr-monthDropdown-month {
    background: var(--ds-surface) !important;
    color: var(--ds-ink) !important;
}

/* -------------------------------------------------------------------------
   13. Misc utilities (kept from previous global.css)
   ------------------------------------------------------------------------- */
.navbar-nav { font-weight: 500; }

.progressbg { padding: 0.15rem 0.5rem !important; }

tr:hover { cursor: pointer; }

#selected-images {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: 10px;
    width: 100%;
}
@media (max-width: 767.98px) {
    #selected-images { grid-template-columns: repeat(3, 1fr); }
}
.img-added-dpz,
.add-file-element {
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
    font-size: 1.5rem;
    position: relative;
    aspect-ratio: 1;
}
.img-added-dpz img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: var(--ds-radius-md);
    background-color: var(--ds-surface-soft);
}
.dz-preview { display: none; }
#selected-images .img-added-dpz:nth-child(1) {
    grid-column: span 2;
    grid-row: span 2;
}

.file-item {
    width: 100px;
    height: 100px;
    object-fit: contain;
    background-color: var(--ds-surface);
    border-radius: var(--ds-radius-md);
    border: 1px solid var(--ds-border);
}

.add-file-element {
    background-color: var(--ds-surface-muted);
    border-radius: var(--ds-radius-md);
    border: 1px dashed var(--ds-border-strong);
    cursor: pointer;
}

/* ─── ADD TILE: dashed full-width "agregar" affordance (empty states) ─── */
.add-tile {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    width: 100%;
    padding: 0.9rem 1.25rem;
    border: 1px dashed var(--ds-border-strong);
    border-radius: var(--ds-radius-lg);
    background-color: var(--ds-surface-muted);
    color: var(--ds-ink-3);
    font-weight: 500;
    cursor: pointer;
    transition: border-color .15s ease, color .15s ease, background-color .15s ease;
}
.add-tile:hover {
    border-color: var(--ds-ink-4);
    background-color: var(--ds-surface);
    color: var(--ds-ink);
}
.add-tile i { color: var(--ds-ink-4); }
.add-tile:hover i { color: var(--ds-ink); }

.select-categories-item:hover {
    background-color: var(--ds-surface-muted);
    cursor: pointer;
}
.selected-category { background-color: var(--ds-surface-active); }
#product-category-ts-dropdown > .selected.active,
#product-category-ts-dropdown > .active { background-color: var(--ds-surface-muted); }
#product-category-ts-dropdown > .selected { background-color: var(--ds-surface-active); }
.dp-header-categories:hover { background-color: var(--ds-surface-muted); cursor: pointer; }

.horizontal-divider {
    width: 1px;
    height: 1.5rem;
    background-color: var(--ds-border);
}

.link-button {
    background-color: transparent;
    border: none;
    color: var(--ds-ink);
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 3.5px;
}
.link-button:hover .link-text { color: var(--ds-ink); }
.link-button i { font-size: 19px; } /* icono: escala propia, exento del piso rem (DS §3) */

.dropzone {
    border: 1px dashed var(--ds-border-strong) !important;
    border-radius: var(--ds-radius-lg) !important;
    color: var(--ds-ink-4);
    padding: 1.25rem;
    background-color: var(--ds-surface-muted);
}
.dropzone-60, .dropzone-50, .dropzone-40, .dropzone-30, .dropzone-20 {
    border: 1px dashed var(--ds-border-strong);
    background-color: var(--ds-surface-muted);
}
.dropzone-60 { height: 60px; width: 60px; }
.dropzone-50 { height: 50px; width: 50px; }
.dropzone-40 { height: 40px; width: 40px; }
.dropzone-30 { height: 30px; width: 30px; }
.dropzone-20 { height: 20px; width: 20px; }
.dropzone-60:hover, .dropzone-50:hover, .dropzone-40:hover,
.dropzone-30:hover, .dropzone-20:hover {
    background-color: var(--ds-surface-active);
    cursor: pointer;
}

/* Google Places autocomplete */
.pac-icon { display: none; }
.pac-item {
    border: 0;
    border-radius: var(--ds-radius-md);
    cursor: pointer;
    padding: 0.4rem 0.6rem;
    font-family: var(--ds-font-sans);
}
.pac-item:hover, .pac-item-selected {
    background-color: var(--ds-surface-muted);
}
.pac-container {
    background-color: var(--ds-surface);
    border-radius: var(--ds-radius-md);
    border: 1px solid var(--ds-border);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.04);
    padding: 5px;
    margin-top: 5px;
    z-index: 9999;
    position: fixed;
    display: inline-block;
}

.iti { width: 100%; }

/* Responsive borders helpers */
.border-bottom-sm { border-bottom: 1px solid var(--ds-border); }
@media (min-width: 768px) {
    .border-bottom-sm { border-bottom: 0; }
}
.border-bottom-md { border-bottom: 0; }
@media (min-width: 768px) {
    .border-bottom-md { border-bottom: 1px solid var(--ds-border); }
}
.border-end-sm { border-right: 1px solid var(--ds-border); }
@media (min-width: 768px) {
    .border-end-sm { border-right: 0; }
}
.border-end-md { border-right: 0; }
@media (min-width: 768px) {
    .border-end-md { border-right: 1px solid var(--ds-border); }
}

.dropdown-toggle:after { margin-top: -0.3em !important; }

/* Scroll containers */
div.dts div.dt-scroll-body,
div.dts div.dataTables_scrollBody { background: none !important; }
div.dts div.dt-scroll-body table,
div.dts div.dataTables_scrollBody table { background-color: transparent !important; }

td {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.lb-outerContainer { border-radius: var(--ds-radius-lg) !important; overflow: hidden; }
.lb-image { border: 0 !important; }

.sys-notification {
    display: flex;
    align-items: center;
    padding: 14px 16px;
    border-bottom: 1px solid var(--ds-border-soft);
    font-family: var(--ds-font-sans);
    background-color: var(--ds-surface);
    transition: background-color 0.1s ease;
}
.sys-notification:hover { background-color: var(--ds-surface-muted); }

/* =========================================================================
   .badge-button — status filter pills (Todas / Activos / Borrador /
   Archivados, etc). Used in 18 views (Productos, Giftcards, Servicios,
   Clientes, Ventas, Compras, Terminal, Users, Devices, Branches…).
   Works as <span>, <a>, or <button> — the browser-default <button> chrome
   is fully reset so the visual is consistent regardless of element.
   ========================================================================= */
.badge-button {
    display: inline-flex !important;
    align-items: center;
    background: transparent !important;
    color: var(--ds-ink-4) !important;
    cursor: pointer;
    padding: 0.35rem 0.75rem !important;
    border-radius: var(--ds-radius-md) !important;
    font-family: var(--ds-font-sans) !important;
    font-size: 0.85rem !important;
    font-weight: 500 !important;
    border: 1px solid transparent !important;
    line-height: 1.3 !important;
    letter-spacing: -0.005em;
    transition: background-color 0.12s ease, color 0.12s ease, border-color 0.12s ease;
    -webkit-user-select: none;
    user-select: none;
    /* Reset native <button> chrome (background, border, outline) so the
       element doesn't appear "highlighted" just because the browser
       focused it on page-load or after a click. */
    appearance: none;
    -webkit-appearance: none;
    text-decoration: none;
    text-align: center;
    box-shadow: none !important;
    outline: none !important;
}
.badge-button:hover:not(.active) {
    /* No background on hover — only color change. This prevents
       inactive pills from looking like the active one. */
    background: transparent !important;
    color: var(--ds-ink) !important;
    border-color: transparent !important;
}
.badge-button:focus,
.badge-button:focus:not(:focus-visible),
.badge-button:active {
    outline: none !important;
    box-shadow: none !important;
    background: transparent !important;
    border-color: transparent !important;
}
/* Focus only retains background when the pill is also .active */
.badge-button.active:focus,
.badge-button.active:focus:not(:focus-visible) {
    background-color: var(--ds-surface-active) !important;
    border-color: var(--ds-border) !important;
}
.badge-button:focus-visible {
    outline: 2px solid var(--ds-ink-4) !important;
    outline-offset: 2px !important;
}
.badge-button.active {
    background-color: var(--ds-surface-active) !important;
    color: var(--ds-ink) !important;
    border-color: var(--ds-border) !important;
    font-weight: 600 !important;
}

/* Sibling spacing — they appear in markup as bare inline <span>s without
   a container, so we space them via adjacent selector. */
.badge-button + .badge-button {
    margin-left: 0.2rem;
}

/* Counter badge nested inside a .badge-button (e.g. "Sin agendar 1410"
   where 1410 is a <span class="badge"> inside the pill). The :not()
   prevents it from matching pills that ARE .badge-button themselves. */
.badge-button > .badge:not(.badge-button) {
    font-family: var(--ds-font-mono);
    font-size: 0.85rem;
    font-feature-settings: 'tnum';
    margin-left: 0.3rem;
    padding: 0.12rem 0.35rem;
    background: var(--ds-surface-soft) !important;
    color: var(--ds-ink-3) !important;
    border: 0;
}

.delete-products:hover { background-color: var(--ds-danger-bg); }

.user-name-ellipsis {
    max-width: 100%;
    display: inline-block;
    vertical-align: middle;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
    flex: 1 1 0%;
}

/* Footer */
.footer {
    background-color: var(--ds-bg) !important;
    border-top: 1px solid var(--ds-border-soft);
    color: var(--ds-ink-4);
    font-size: 0.85rem;
}

/* Print */
@media print {
    body { background: #fff !important; }
    .card { border: 1px solid #ddd !important; }
}

/* =========================================================================
   18. APP SIDEBAR — Rail (icons) + Panel (subitems)
   --------------------------------------------------------------------------
   Two-column sidebar: a 56px icon rail on the left and a 220px contextual
   panel on its right that shows the subitems of the active section.
   ========================================================================= */
:root {
    --ds-rail-width: 46px;
    --ds-panel-width: 208px;
    --ds-sidebar-width: calc(var(--ds-rail-width) + var(--ds-panel-width));
}

.app-sidebar {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    z-index: 1030;
    width: var(--ds-sidebar-width);
    display: flex;
    align-items: stretch;
    background: var(--ds-surface);
    border-right: 1px solid var(--ds-border);
    transition: width 0.2s ease;
}
.app-sidebar.panel-collapsed {
    width: var(--ds-rail-width);
}
.app-sidebar.panel-collapsed .app-panel {
    display: none;
}

/* Push page content to the right of the sidebar and below the topbar */
.page-wrapper {
    margin-left: var(--ds-sidebar-width);
    padding-top: var(--ds-header-h);
    min-height: 100vh;
    transition: margin-left 0.2s ease;
}
.app-sidebar.panel-collapsed ~ .page-wrapper {
    margin-left: var(--ds-rail-width);
}

/* ─── RAIL ─────────────────────────────────────────────────────────── */
.app-rail {
    width: var(--ds-rail-width);
    flex: 0 0 var(--ds-rail-width);
    display: flex;
    flex-direction: column;
    align-items: stretch;
    padding: 0;                 /* brand sits flush at the top, aligning Y=0 with page-header */
    /* Superficie unificada con el panel — una sola pieza, no dos columnas
       de distinto gris (look ElevenLabs). El hairline separa, no el fondo. */
    background: var(--ds-surface);
    border-right: 1px solid var(--ds-border-soft);
}
/* Brand area aligns with the page-header (3rem) so the first rail icon
   sits flush below the top divider line of the page-header. */
.rail-brand {
    height: var(--ds-header-h);
    flex: 0 0 var(--ds-header-h);
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: center;
    border-bottom: 1px solid var(--ds-border-soft);
    background: var(--ds-surface);
}
.rail-brand img {
    width: 26px;
    height: 26px;
    object-fit: contain;
}

.rail-items {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    padding: 0.5rem 0.3rem;     /* ritmo tight, mismo gutter que el footer */
    flex: 1 1 auto;
}

/* Divisor entre grupos cognitivos del rail (chunking visual) */
.rail-divider {
    display: block;
    width: 20px;
    height: 1px;
    margin: 0.3rem auto;
    background: var(--ds-border-soft);
}

.rail-footer {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    padding: 0.5rem 0.3rem;
    border-top: 1px solid var(--ds-border-soft);
    margin-top: auto;
}

.rail-item {
    width: 36px;
    height: 36px;
    margin: 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--ds-ink-4);
    background: transparent;
    border: 0;
    border-radius: var(--ds-radius-md);
    text-decoration: none;
    cursor: pointer;
    position: relative;
    transition: background-color 0.12s ease, color 0.12s ease;
}
.rail-item .ti {
    font-size: 1.2rem !important;
    color: currentColor;
}

/* Hover tooltip: cápsula compacta, peso ligero, sombra del sistema */
.rail-item .rail-tooltip {
    position: absolute;
    left: calc(100% + 0.6rem);
    top: 50%;
    transform: translateY(-50%) translateX(-4px);
    background: var(--ds-ink);
    color: var(--ds-bg);
    padding: 0.28rem 0.6rem;
    border-radius: var(--ds-radius-sm);
    font-size: 0.8rem;
    font-weight: 450;
    letter-spacing: -0.01em;
    line-height: 1.2;
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.12s ease, transform 0.12s ease, visibility 0s linear 0.12s;
    z-index: 1100;
    box-shadow: var(--ds-shadow-md);
}
.rail-item:hover .rail-tooltip,
.rail-item:focus-visible .rail-tooltip {
    opacity: 1;
    visibility: visible;
    transform: translateY(-50%) translateX(0);
    transition-delay: 0.25s, 0.25s, 0s;
}
.rail-item:hover {
    background: var(--ds-surface-muted);
    color: var(--ds-ink);
}
.rail-item.current,
.rail-item[aria-expanded='true'] {
    background: var(--ds-surface-active);
    color: var(--ds-ink);
    box-shadow: none;
}
/* El item activo viste el color de identidad de su módulo — los mismos
   tintes que los quick-tiles del dashboard. Un solo punto de color en
   una sidebar que se mantiene neutra. */
.rail-item.current[data-section='agenda'],
.rail-item[aria-expanded='true'][data-section='agenda'] {
    background: var(--ds-accent-violet-bg);
    color: var(--ds-accent-violet);
}
.rail-item.current[data-section='caja'],
.rail-item[aria-expanded='true'][data-section='caja'] {
    background: var(--ds-accent-green-bg);
    color: var(--ds-accent-green);
}
.rail-item.current[data-section='expedientes'],
.rail-item[aria-expanded='true'][data-section='expedientes'] {
    background: var(--ds-accent-blue-bg);
    color: var(--ds-accent-blue);
}
.rail-item.current[data-section='cirugia'],
.rail-item[aria-expanded='true'][data-section='cirugia'] {
    background: var(--ds-accent-cyan-bg);
    color: var(--ds-accent-cyan);
}
.rail-item.current[data-section='analiticas'],
.rail-item[aria-expanded='true'][data-section='analiticas'] {
    background: var(--ds-accent-teal-bg);
    color: var(--ds-accent-teal);
}
.rail-item.current[data-section='productos'],
.rail-item[aria-expanded='true'][data-section='productos'] {
    background: var(--ds-accent-amber-bg);
    color: var(--ds-accent-amber);
}
.rail-item.current[data-section='inventario'],
.rail-item[aria-expanded='true'][data-section='inventario'] {
    background: var(--ds-accent-rose-bg);
    color: var(--ds-accent-rose);
}
.rail-item.current[data-section='finanzas'],
.rail-item[aria-expanded='true'][data-section='finanzas'] {
    background: var(--ds-accent-orange-bg);
    color: var(--ds-accent-orange);
}
.rail-item.current[data-section='clientes'],
.rail-item[aria-expanded='true'][data-section='clientes'] {
    background: var(--ds-accent-violet-bg);
    color: var(--ds-accent-violet);
}
.rail-item.current[data-section='administracion'],
.rail-item[aria-expanded='true'][data-section='administracion'] {
    background: var(--ds-accent-rose-bg);
    color: var(--ds-accent-rose);
}
.rail-item.current[data-section='configuracion'],
.rail-item[aria-expanded='true'][data-section='configuracion'] {
    background: var(--ds-accent-violet-bg);
    color: var(--ds-accent-violet);
}
.rail-item.current[data-section='agentes'],
.rail-item[aria-expanded='true'][data-section='agentes'] {
    background: var(--ds-accent-teal-bg);
    color: var(--ds-accent-teal);
}
.rail-item.current[data-section='inbox'],
.rail-item[aria-expanded='true'][data-section='inbox'] {
    background: var(--ds-accent-orange-bg);
    color: var(--ds-accent-orange);
}

.rail-avatar {
    width: 24px;
    height: 24px;
    border-radius: 50%;
    object-fit: cover;
    /* When used as a <span> wrapping a ti-user icon, render as a circular
       chip so it doesn't conflict with the brand logo on the top-left. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--ds-accent-blue-bg);
    color: var(--ds-accent-blue);
    line-height: 1;
}
.rail-avatar .ti { line-height: 1; }

/* ─── Badges operativos ──────────────────────────────────────────────
   En el rail: contador superpuesto arriba-derecha del icono (citas de
   hoy, pre-compras pendientes). En el panel: chip al final del item. */
.rail-item .rail-badge {
    position: absolute;
    top: 1px;
    right: 1px;
    min-width: 15px;
    height: 15px;
    padding: 0 4px;
    border-radius: 99px;
    background: var(--ds-ink);
    color: var(--ds-bg);
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-size: 0.72rem;
    font-weight: 600;
    line-height: 15px;
    text-align: center;
    box-shadow: 0 0 0 2px var(--ds-surface);
    pointer-events: none;
}
.panel-item .rail-badge {
    margin-left: auto;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 99px;
    background: var(--ds-surface-soft);
    color: var(--ds-ink-2);
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-size: 0.72rem;
    font-weight: 600;
    line-height: 18px;
    text-align: center;
}

/* User dropdown opens to the right of the rail */
.rail-user-wrap .dropdown-menu {
    margin-left: 0.5rem !important;
    min-width: 220px;
}
.rail-user-card {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    padding: 0.65rem 0.7rem;
}
.rail-user-card-avatar {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--ds-accent-blue-bg);
    color: var(--ds-accent-blue);
    flex-shrink: 0;
}
.rail-user-card-avatar .ti { line-height: 1; }
.rail-user-name {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--ds-ink);
    line-height: 1.2;
}
.rail-user-branch {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    margin-top: 0.4rem;
    font-size: 0.8rem;
    color: var(--ds-ink-4);
}
.rail-user-branch .ti {
    font-size: 0.85rem !important;
    color: var(--ds-ink-5);
}
.rail-user-role-badge {
    display: inline-flex;
    align-items: center;
    margin-top: 4px;
    padding: 1px 8px;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--ds-ink-3);
    background: var(--ds-surface-soft);
    border: 1px solid var(--ds-border);
    border-radius: 999px;
    text-transform: capitalize;
    line-height: 1.4;
    letter-spacing: 0.02em;
}

/* ─── PANEL ────────────────────────────────────────────────────────── */
.app-panel {
    width: var(--ds-panel-width);
    flex: 0 0 var(--ds-panel-width);
    display: flex;
    flex-direction: column;
    background: var(--ds-surface);
    border-right: 1px solid var(--ds-border);   /* explicit right divider */
    overflow-y: auto;
    overflow-x: hidden;
}
.panel-section[hidden] { display: none !important; }
.panel-section {
    display: flex;
    flex-direction: column;
    height: 100%;
}
/* Panel header height = 3rem, matches page-header so the line under the
   panel title sits exactly at the same Y as the page-header divider. */
.panel-header {
    height: var(--ds-header-h);
    flex: 0 0 var(--ds-header-h);
    box-sizing: border-box;
    padding: 0 1rem;
    border-bottom: 1px solid var(--ds-border-soft);
    background: var(--ds-surface);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    position: sticky;
    top: 0;
    z-index: 1;
}
/* Ícono tintado + nombre del área, espejo de la sección activa de la topbar. */
.panel-header-title {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
}
.panel-header h2 {
    /* Homologado con la sección activa de la topbar (.topbar-area-label, 0.95rem):
       header del panel = ÁREA, topbar = módulo, ambos al mismo tamaño. */
    font-size: 0.95rem;
    font-weight: 550;
    letter-spacing: -0.015em;
    color: var(--ds-ink);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Collapse / Expand buttons */
.panel-collapse-btn,
.panel-expand-btn {
    width: 1.85rem;
    height: 1.85rem;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 0;
    border-radius: var(--ds-radius-sm);
    color: var(--ds-ink-5);
    cursor: pointer;
    transition: background-color 0.12s ease, color 0.12s ease;
}
.panel-collapse-btn:hover,
.panel-expand-btn:hover {
    background: var(--ds-surface-muted);
    color: var(--ds-ink);
}
.panel-collapse-btn .ti,
.panel-expand-btn .ti {
    font-size: 1rem !important;
}

/* Floating expand button — appears on the rail when panel is collapsed.
   Se centra verticalmente con el logo del brand (que ocupa toda la altura
   del header), no anclado al borde superior, para que ambos compartan eje Y. */
.panel-expand-btn {
    position: absolute;
    top: calc((var(--ds-header-h) - 1.7rem) / 2);
    right: -0.85rem;
    width: 1.7rem;
    height: 1.7rem;
    background: var(--ds-surface);
    border: 1px solid var(--ds-border);
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.04);
    z-index: 1031;
    color: var(--ds-ink-3);
}
.app-sidebar:not(.panel-collapsed) .panel-expand-btn {
    display: none;
}

.panel-nav {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    padding: 0.65rem 0.6rem 1rem;
}
/* Overline que clasifica los submenús dentro del panel (operación /
   consulta / configuración…). Mismo lenguaje de overline del sistema:
   mayúsculas, mono-quiet, ink-5 — metadata, no contenido. */
.panel-group-label {
    margin: 0.55rem 0.75rem 0.15rem;
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ds-ink-5);
    user-select: none;
}
/* El primer overline no necesita el respiro superior. */
.panel-nav > .panel-group-label:first-child { margin-top: 0.1rem; }
.panel-item {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    padding: 0.52rem 0.75rem;
    color: var(--ds-ink-3);
    text-decoration: none !important;
    border-radius: var(--ds-radius-md);
    font-size: 1rem;
    font-weight: 450;
    line-height: 1.4;
    transition: background-color 0.12s ease, color 0.12s ease;
}
.panel-item .ti {
    font-size: 1.05rem !important;
    color: var(--ds-ink-4);
    flex-shrink: 0;
    transition: color 0.12s ease;
}
.panel-item:hover {
    background: var(--ds-surface-muted);
    color: var(--ds-ink);
    text-decoration: none;
}
.panel-item:hover .ti { color: var(--ds-ink-3); }
.panel-item.current {
    background: var(--ds-surface-active);
    color: var(--ds-ink);
    font-weight: 550;
}
.panel-item.current .ti { color: var(--ds-ink); }
/* El icono del item activo hereda el color de identidad del módulo padre */
.panel-section[data-section='agenda'] .panel-item.current .ti     { color: var(--ds-accent-violet); }
.panel-section[data-section='caja'] .panel-item.current .ti       { color: var(--ds-accent-green); }
.panel-section[data-section='expedientes'] .panel-item.current .ti { color: var(--ds-accent-blue); }
.panel-section[data-section='cirugia'] .panel-item.current .ti { color: var(--ds-accent-cyan); }
.panel-section[data-section='analiticas'] .panel-item.current .ti { color: var(--ds-accent-teal); }
.panel-section[data-section='productos'] .panel-item.current .ti  { color: var(--ds-accent-amber); }
.panel-section[data-section='admin'] .panel-item.current .ti      { color: var(--ds-accent-rose); }
.panel-section[data-section='administracion'] .panel-item.current .ti { color: var(--ds-accent-rose); }
.panel-section[data-section='configuracion'] .panel-item.current .ti  { color: var(--ds-accent-violet); }
.panel-item.disabled {
    opacity: 0.5;
    pointer-events: none;
}

/* Hide Tabler's old `.navbar-vertical` overrides since we replaced it */
.app-sidebar.navbar-vertical { display: flex; }

/* ─── APP TOPBAR (desktop) — barra fija global estilo Apollo ────────
   Búsqueda rápida de secciones (⌘K), CTA lime y usuario. Vive a la
   derecha de la sidebar; en móvil se oculta (mobile-topbar manda). */
.app-topbar {
    position: fixed;
    top: 0;
    left: var(--ds-sidebar-width);
    right: 0;
    height: var(--ds-header-h);
    z-index: 1029;
    background: var(--ds-surface);
    border-bottom: 1px solid var(--ds-border-soft);
    transition: left 0.2s ease;
}
/* El contenido de la topbar comparte el MISMO contenedor que el body de
   su página (container-xl o fluid, decidido por ruta en main.ejs) —
   una sola retícula vertical en toda la pantalla. */
.app-topbar .topbar-container {
    display: grid;
    grid-template-columns: 1fr auto 1fr;   /* área · centro (search+CTA) · acciones */
    align-items: center;
    gap: 0.85rem;
    height: 100%;
}
/* Zona izquierda: el área activa (icono tintado + nombre). */
.topbar-area {
    justify-self: start;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;                          /* permite truncar el label */
}
/* Oculta el chip pero CONSERVA su columna del grid (1fr · auto · 1fr): si se
   quitara del grid (display:none), el centro se descuadraría a la izquierda en
   páginas sin área activa (p. ej. Mi cuenta). */
.topbar-area[hidden] { visibility: hidden; }
.topbar-area-label {
    font-size: 0.95rem;
    font-weight: 550;
    color: var(--ds-ink);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Zona central: search + "Nuevo", centrados en la topbar. */
.topbar-center {
    justify-self: center;
    display: flex;
    align-items: center;
    gap: 0.85rem;
    width: clamp(360px, 44vw, 620px);
}
.topbar-center .topbar-search { max-width: none; }

/* Páginas sin topbar (POS: caja, terminal) — el contenido recupera el
   espacio en desktop; en móvil el mobile-topbar sigue mandando. */
@media (min-width: 992px) {
    .page.no-topbar .page-wrapper { padding-top: 0; }
    .page.no-topbar .page-header.position-sticky,
    .page.no-topbar .page-header[style*='sticky'] {
        top: 0 !important;
    }
}
.app-sidebar.panel-collapsed ~ .app-topbar { left: var(--ds-rail-width); }
@media (max-width: 991.98px) {
    .app-topbar { display: none; }
}

.topbar-search {
    position: relative;
    flex: 1 1 auto;
    max-width: 540px;
}
.topbar-search > .ti-search {
    position: absolute;
    left: 0.75rem;
    top: 50%;
    transform: translateY(-50%);
    color: var(--ds-ink-5);
    font-size: 0.95rem !important;
    pointer-events: none;
    z-index: 1;
}
.topbar-search .form-control {
    padding-left: 2.2rem !important;
    padding-right: 3.2rem !important;
    background: var(--ds-surface-muted) !important;
    border-color: transparent !important;
}
.topbar-search .form-control:focus {
    background: var(--ds-surface) !important;
    border-color: var(--ds-ink) !important;
}
.topbar-kbd {
    position: absolute;
    right: 0.6rem;
    top: 50%;
    transform: translateY(-50%);
    pointer-events: none;
}
.topbar-search-menu {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    right: 0;
    background: var(--ds-surface);
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-md);
    box-shadow: var(--ds-shadow-md);
    padding: 0.35rem;
    max-height: 320px;
    overflow-y: auto;
    z-index: 1040;
    display: none;
}
.topbar-search-menu.show { display: block; }
.topbar-search-item {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.45rem 0.6rem;
    border-radius: var(--ds-radius-sm);
    color: var(--ds-ink-2);
    font-size: 1rem;
    cursor: pointer;
}
.topbar-search-item .ti {
    color: var(--ds-ink-4);
    font-size: 1rem !important;
    flex-shrink: 0;
}
.topbar-search-item small {
    margin-left: auto;
    color: var(--ds-ink-5);
    font-size: 0.8rem;
}
.topbar-search-item:hover,
.topbar-search-item.active {
    background: var(--ds-surface-muted);
    color: var(--ds-ink);
}
.topbar-search-empty {
    padding: 0.6rem;
    color: var(--ds-ink-5);
    font-size: 0.85rem;
    text-align: center;
}

.topbar-actions {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    justify-self: end;                     /* tercera zona del grid: a la derecha */
    flex-shrink: 0;
}
/* CTA héroe — el único lugar del chrome donde vive el lime Apollo */
.btn-cta {
    background: var(--ds-lime) !important;
    border-color: var(--ds-lime) !important;
    color: var(--ds-lime-ink) !important;
    font-weight: 550;
}
.btn-cta:hover {
    background: var(--ds-lime-hover) !important;
    border-color: var(--ds-lime-hover) !important;
    color: var(--ds-lime-ink) !important;
}
/* Deshabilitado: deja de gritar lime — no debe parecer accionable. */
.btn-cta:disabled,
.btn-cta.disabled,
.btn-cta[disabled] {
    background: var(--ds-surface-active) !important;
    border-color: var(--ds-border-soft) !important;
    color: var(--ds-ink-4) !important;
    cursor: not-allowed;
    opacity: 1;
}
.topbar-avatar {
    width: 30px;
    height: 30px;
    border-radius: 50%;
    border: 0;
    background: var(--ds-accent-blue-bg);
    color: var(--ds-accent-blue);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.72rem;
    font-weight: 600;
    cursor: pointer;
    text-transform: uppercase;
}

/* ─── Acción de la topbar (icono redondo, p. ej. ajuste de precio) ──── */
.topbar-action {
    width: 32px;
    height: 32px;
    border: 0;
    border-radius: var(--ds-radius-md);
    background: transparent;
    color: var(--ds-ink-3);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background-color 0.12s ease, color 0.12s ease;
}
.topbar-action:hover { background: var(--ds-surface-soft); color: var(--ds-ink); }
.topbar-action .ti { font-size: 1.1rem !important; }

/* ─── Notificaciones (campana) — entre el CTA y el usuario ─────────── */
.topbar-bell {
    position: relative;
    width: 32px;
    height: 32px;
    border: 0;
    border-radius: var(--ds-radius-md);
    background: transparent;
    color: var(--ds-ink-3);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background-color 0.12s ease, color 0.12s ease;
}
.topbar-bell:hover { background: var(--ds-surface-soft); color: var(--ds-ink); }
.topbar-bell .ti { font-size: 1.1rem !important; }
/* Punto de "no leídas" — listo para cuando exista backend de notificaciones. */
.topbar-bell[data-unread='true']::after {
    content: '';
    position: absolute;
    top: 6px;
    right: 7px;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--ds-danger);
    border: 2px solid var(--ds-surface);
}
.topbar-notif-menu { width: 408px; max-width: calc(100vw - 1.5rem); padding: 0; overflow: hidden; }
.topbar-notif-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    padding: 0.7rem 0.9rem;
    border-bottom: 1px solid var(--ds-border-soft);
}
.topbar-notif-title {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    font-weight: 600;
    font-size: 0.9rem;
    color: var(--ds-ink);
}
.topbar-notif-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.25rem;
    height: 1.25rem;
    padding: 0 0.35rem;
    border-radius: 999px;
    background: var(--ds-lime);
    color: var(--ds-lime-ink);
    font-size: 0.72rem;
    font-weight: 600;
    line-height: 1;
}
.topbar-notif-readall {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    border: 0;
    background: transparent;
    color: var(--ds-ink-3);
    font-size: 0.78rem;
    font-weight: 500;
    padding: 0.25rem 0.4rem;
    border-radius: var(--ds-radius-sm);
    cursor: pointer;
    transition: background-color 0.12s ease, color 0.12s ease;
}
.topbar-notif-readall:hover { background: var(--ds-surface-soft); color: var(--ds-ink); }

/* Lista desplazable de notificaciones */
.topbar-notif-list {
    max-height: 380px;
    overflow-y: auto;
    padding: 0.25rem 0;
}
.topbar-notif-item {
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: 0.65rem;
    padding: 0.6rem 0.9rem;
    text-decoration: none;
    color: inherit;
    transition: background-color 0.12s ease;
}
.topbar-notif-item:hover { background: var(--ds-surface-muted); }
.topbar-notif-icon {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: var(--ds-radius-md);
}
.topbar-notif-icon .ti { font-size: 1.05rem !important; }
.topbar-notif-icon.tone-danger { background: var(--ds-danger-bg); color: var(--ds-danger); }
.topbar-notif-icon.tone-violet { background: var(--ds-accent-violet-bg); color: var(--ds-accent-violet); }
.topbar-notif-icon.tone-blue   { background: var(--ds-accent-blue-bg);   color: var(--ds-accent-blue); }
.topbar-notif-icon.tone-amber  { background: var(--ds-accent-amber-bg);  color: var(--ds-accent-amber); }
.topbar-notif-icon.tone-green  { background: var(--ds-accent-green-bg);  color: var(--ds-accent-green); }
.topbar-notif-icon.tone-cyan   { background: var(--ds-accent-cyan-bg);   color: var(--ds-accent-cyan); }
.topbar-notif-body {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
}
.topbar-notif-item-title {
    font-size: 0.83rem;
    font-weight: 600;
    color: var(--ds-ink);
    line-height: 1.25;
}
.topbar-notif-item-detail {
    font-size: 0.8rem;
    color: var(--ds-ink-3);
    line-height: 1.3;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}
.topbar-notif-item-time {
    margin-top: 0.15rem;
    font-size: 0.72rem;
    color: var(--ds-ink-5);
}
.topbar-notif-dot {
    flex: 0 0 auto;
    align-self: center;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--ds-lime);
}
.topbar-notif-foot {
    border-top: 1px solid var(--ds-border-soft);
    text-align: center;
}
.topbar-notif-foot a {
    display: block;
    padding: 0.6rem 0.9rem;
    font-size: 0.8rem;
    font-weight: 500;
    color: var(--ds-ink-2);
    text-decoration: none;
    transition: background-color 0.12s ease, color 0.12s ease;
}
.topbar-notif-foot a:hover { background: var(--ds-surface-soft); color: var(--ds-ink); }
.topbar-notif-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.4rem;
    padding: 1.6rem 1rem;
    color: var(--ds-ink-5);
    font-size: 0.85rem;
    text-align: center;
}
.topbar-notif-empty .ti { font-size: 1.5rem !important; color: var(--ds-ink-5); }

/* ─── MOBILE TOPBAR ─────────────────────────────────────────────── */
.mobile-topbar {
    display: none;
}

/* ─── SIDEBAR BACKDROP ──────────────────────────────────────────── */
.sidebar-backdrop {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.4);
    z-index: 1045;
    cursor: pointer;
}

/* Mobile: sidebar collapses to overlay */
@media (max-width: 991.98px) {
    /* Top bar */
    .mobile-topbar {
        display: flex;
        align-items: center;
        height: var(--ds-header-h);
        padding: 0 0.75rem;
        background: var(--ds-surface);
        border-bottom: 1px solid var(--ds-border);
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        z-index: 1040;
        gap: 0.65rem;
    }
    .mobile-menu-btn {
        width: 36px;
        height: 36px;
        flex-shrink: 0;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        background: transparent;
        border: 0;
        border-radius: var(--ds-radius-sm);
        color: var(--ds-ink-3);
        cursor: pointer;
        transition: background-color 0.12s ease, color 0.12s ease;
    }
    .mobile-menu-btn:hover,
    .mobile-menu-btn:focus-visible {
        background: var(--ds-surface-active);
        color: var(--ds-ink);
        outline: none;
    }
    .mobile-topbar-brand {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        text-decoration: none;
    }
    .mobile-topbar-brand img {
        width: 26px;
        height: 26px;
        object-fit: contain;
    }
    .mobile-topbar-title {
        font-size: 0.88rem;
        font-weight: 600;
        color: var(--ds-ink);
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    /* Sidebar: slide-in overlay */
    .app-sidebar {
        transform: translateX(-100%);
        transition: transform 0.22s ease;
        z-index: 1050;
        box-shadow: none;
    }
    .app-sidebar.show {
        transform: translateX(0);
        box-shadow: 4px 0 24px rgba(0, 0, 0, 0.12);
    }

    /* Backdrop */
    .sidebar-backdrop.show {
        display: block;
    }

    /* Push content below the top bar */
    .page-wrapper {
        margin-left: 0;
        padding-top: var(--ds-header-h);
    }
}

.bg-surface-soft { background-color: var(--ds-surface-soft) !important; }

/* =========================================================================
   DASHBOARD WIDGETS — clinical operational widgets
   ========================================================================= */
.dashboard-list {
    display: flex;
    flex-direction: column;
}
.dashboard-list-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.85rem var(--ds-content-padding-x);
    border-bottom: 1px solid var(--ds-border-soft);
    transition: background-color 0.12s ease;
    text-decoration: none;
    color: inherit;
}
.dashboard-list-row:hover {
    background-color: var(--ds-surface-muted);
    color: inherit;
    text-decoration: none;
}
.dashboard-list-row:last-child { border-bottom: 0; }
/* ════════════════════════════════════════════════════════════════════════
   EMPTY STATE — RECETA ÚNICA homologada en TODO el sistema (listas, tablas,
   charts, paneles). Icono de línea centrado + frase sobria (sin cursiva).
     • Clase canónica nueva: `.empty-state`
     • Legacy soportada:     `.dashboard-list-empty`
     • Tablas:               `td.dataTables_empty` (mismo look)
     • Variante alto-completo (charts en cards): añadir `.is-fill`
   El icono es un token (`--ds-empty-icon`) con mask → adapta a claro/oscuro.
   ════════════════════════════════════════════════════════════════════════ */
.empty-state,
.dashboard-list-empty,
.study-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.7rem;
    text-align: center;
    padding: 2.75rem 1rem;
    min-height: 9rem;
    color: var(--ds-ink-4);
    font-size: 0.9rem;
    font-style: normal;
    font-weight: 450;
}
.empty-state.is-fill,
.dashboard-list-empty.is-fill { min-height: 100%; height: 100%; }
.study-empty { grid-column: 1 / -1; }

/* Icono contextual explícito (cualquier `<i class="ti …">` directo) gana sobre
   el token y se normaliza al mismo tamaño/peso → nunca dos iconos a la vez. */
.empty-state > .ti,
.dashboard-list-empty > .ti,
.study-empty > .ti,
td.dataTables_empty > .ti {
    font-size: 2rem;
    line-height: 1;
    color: var(--ds-ink-5);
    opacity: 0.85;
    margin: 0;
}
.empty-state:has(> .ti)::before,
.dashboard-list-empty:has(> .ti)::before,
.study-empty:has(> .ti)::before,
td.dataTables_empty:has(> .ti)::before { content: none; }

.table tbody td.dataTables_empty,
table.dataTable tbody td.dataTables_empty,
td.dataTables_empty {
    text-align: center !important;
    padding: 2.75rem 1rem !important;
    color: var(--ds-ink-4) !important;
    font-size: 0.9rem !important;
    font-style: normal;
    font-weight: 450;
    vertical-align: middle;
}

/* Icono de línea compartido por todas las variantes */
.empty-state::before,
.dashboard-list-empty::before,
.study-empty::before,
td.dataTables_empty::before {
    content: "";
    display: block;
    width: 34px;
    height: 34px;
    background-color: var(--ds-ink-5);
    opacity: 0.85;
    -webkit-mask: center / contain no-repeat var(--ds-empty-icon);
    mask: center / contain no-repeat var(--ds-empty-icon);
}
td.dataTables_empty::before { margin: 0 auto 0.85rem; }  /* td no es flex */

/* Loading = skeleton shimmer, no texto. Tres barras fantasma del ancho
   decreciente + barrido de luz. Funciona en cualquier lista del dashboard
   sin tocar JS (el "Cargando…" inicial queda invisible debajo). */
.dashboard-list-loading {
    position: relative;
    min-height: 8.5rem;
    overflow: hidden;
    color: transparent;
    font-size: 0.85rem;
    user-select: none;
}
.dashboard-list-loading::before {
    content: '';
    position: absolute;
    left: var(--ds-content-padding-x);
    right: var(--ds-content-padding-x);
    top: 1.1rem;
    bottom: 1.1rem;
    background-image:
        linear-gradient(var(--ds-surface-soft) 0 0),
        linear-gradient(var(--ds-surface-soft) 0 0),
        linear-gradient(var(--ds-surface-soft) 0 0);
    background-size: 92% 1rem, 70% 1rem, 82% 1rem;
    background-position: 0 0, 0 2.1rem, 0 4.2rem;
    background-repeat: no-repeat;
    border-radius: var(--ds-radius-sm);
}
.dashboard-list-loading::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.75), transparent);
    transform: translateX(-100%);
    animation: ds-shimmer 1.3s ease-in-out infinite;
}
@keyframes ds-shimmer {
    to { transform: translateX(100%); }
}

/* Past schedule rows: subtle de-emphasis so the eye scans to active/upcoming */
.schedule-row.is-past .schedule-time { color: var(--ds-ink-3); }
.schedule-row.is-past:hover { background-color: var(--ds-surface-muted); }

/* Next-upcoming row gets a subtle left accent so it pops on scan.
   El acento es inset box-shadow, NUNCA border-left: un borde añade 3px
   al layout y desalinea la columna de hora/avatar contra el resto. */
.schedule-row.is-next {
    background-color: var(--ds-success-bg);
    box-shadow: inset 3px 0 0 var(--ds-success);
}
.schedule-row.is-next:hover {
    background-color: var(--ds-success-bg);
}
.schedule-row.is-next .schedule-time-relative { color: var(--ds-success); font-weight: 600; }

/* In-progress row (current time within scheduled slot) */
.schedule-row.is-current {
    background-color: var(--ds-warning-bg);
    box-shadow: inset 3px 0 0 var(--ds-warning);
}
.schedule-row.is-current:hover { background-color: var(--ds-warning-bg); }
.schedule-row.is-current .schedule-time-relative { color: var(--ds-warning); font-weight: 600; }

/* Status pills column (WhatsApp delivery + confirmation).
   Cada pill con ancho mínimo uniforme y contenido centrado: cuando
   varias filas comparten los mismos estados, los pills forman columnas
   verticales limpias en vez de un borde irregular. */
.schedule-row .schedule-status {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: flex-end;
    align-items: center;
    gap: 0.3rem;
    flex-shrink: 0;
    max-width: 60%;
}
.schedule-row .schedule-status .msg-pill {
    min-width: 6.9rem;
    justify-content: center;
}
/* On narrow widths (cards in col-md-7 etc.) collapse to vertical so
   pills don't crash with the patient name column. */
@media (max-width: 991px) {
    .schedule-row .schedule-status {
        flex-direction: column;
        align-items: flex-end;
        gap: 0.15rem;
        max-width: none;
    }
}

/* Schedule row inside upcoming-schedules-list */
/* Columna de hora con ancho FIJO: "en 18 min" no debe empujar el avatar.
   Todos los avatares caen en la misma X en todas las filas. */
.schedule-row .schedule-when {
    flex: 0 0 4.6rem;
    min-width: 0;
}
.schedule-row .schedule-time {
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--ds-ink);
    line-height: 1.2;
}
.schedule-row .schedule-time-relative {
    font-size: 0.85rem;
    color: var(--ds-ink-4);
    font-family: var(--ds-font-mono);
    font-weight: 400;
    margin-top: 0.1rem;
}
/* Avatar de iniciales en la fila de cita — tinte estable por paciente,
   asignado por inicio.js con clases .tint-*. */
.schedule-row .schedule-avatar {
    width: 2.25rem;
    height: 2.25rem;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.8rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    position: relative;
    overflow: visible;
}

/* Dot de estado superpuesto al avatar (como el presence-dot de Slack /
   Linear). Sin icono: a 36px de avatar un glifo no centra limpio; el
   color ES el mensaje. Verde = confirmada; ámbar = sin confirmar;
   rojo = recordatorio fallido / sin teléfono. El anillo toma el color
   del fondo de la fila para que el dot se lea recortado, no flotando. */
.avatar-status {
    position: absolute;
    right: -1px;
    bottom: -1px;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    box-shadow: 0 0 0 2px var(--ds-surface);
    transition: box-shadow 0.12s ease;
}
.avatar-status.is-ok    { background: var(--ds-success); }
.avatar-status.is-wait  { background: var(--ds-warning); }
.avatar-status.is-alert { background: var(--ds-danger); }
.schedule-row:hover .avatar-status      { box-shadow: 0 0 0 2px var(--ds-surface-muted); }
.schedule-row.is-next .avatar-status    { box-shadow: 0 0 0 2px var(--ds-success-bg); }
.schedule-row.is-current .avatar-status { box-shadow: 0 0 0 2px var(--ds-warning-bg); }

/* ─── Línea de "Ahora" — divisor vivo entre lo que ya pasó y lo que
   viene (patrón calendario). inicio.js la inserta entre la última cita
   pasada y la siguiente. ─────────────────────────────────────────────── */
.now-divider {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.3rem var(--ds-content-padding-x);
}
.now-chip {
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    color: #fff;
    background: var(--ds-danger);
    padding: 0.12rem 0.55rem;
    border-radius: 99px;
    flex-shrink: 0;
    line-height: 1.4;
}
.now-divider::after {
    content: '';
    flex: 1 1 auto;
    height: 2px;
    background: var(--ds-danger);
    border-radius: 2px;
    opacity: 0.55;
}
.schedule-row .schedule-main { flex: 1 1 auto; min-width: 0; }
/* Los nombres llegan en MAYÚSCULAS desde la BD; el JS los baja a
   minúsculas y aquí se capitaliza cada palabra. Premium, no gritado. */
.schedule-row .schedule-patient {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--ds-ink);
    line-height: 1.3;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    text-transform: capitalize;
}
.schedule-row .schedule-meta {
    font-size: 0.85rem;
    color: var(--ds-ink-4);
    margin-top: 0.1rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    text-transform: capitalize;
}
.schedule-row .schedule-meta .schedule-meta-sep { color: var(--ds-ink-5); margin: 0 0.35rem; }

/* Inventory alert row */
.alert-row .alert-name {
    flex: 1 1 auto;
    font-size: 0.95rem;
    font-weight: 500;
    color: var(--ds-ink);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    text-transform: capitalize;
}
/* La línea de metadata (lote · unidades · vence) va sin capitalizar */
.alert-row .alert-name > div { text-transform: none; }
.alert-row .alert-stock {
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-size: 0.85rem;
    color: var(--ds-ink-3);
    flex-shrink: 0;
}
.alert-row .alert-stock.is-critical { color: var(--ds-danger); font-weight: 600; }
.alert-row .alert-stock.is-low      { color: var(--ds-warning); font-weight: 600; }

/* WhatsApp message row */
.message-row .msg-main { flex: 1 1 auto; min-width: 0; }
.message-row .msg-patient {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--ds-ink);
    line-height: 1.3;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.message-row .msg-meta {
    font-size: 0.85rem;
    color: var(--ds-ink-4);
    margin-top: 0.1rem;
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.message-row .msg-status {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.2rem;
    flex-shrink: 0;
}
.msg-pill {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    font-size: 0.85rem;
    font-weight: 500;
    padding: 0.15rem 0.4rem;
    border-radius: var(--ds-radius-sm);
    line-height: 1.3;
    white-space: nowrap;
}
.msg-pill .ti { font-size: 0.85rem !important; }
.msg-pill.is-sent       { background: var(--ds-info-bg);    color: var(--ds-info); }
.msg-pill.is-delivered  { background: var(--ds-success-bg); color: var(--ds-success); }
.msg-pill.is-failed     { background: var(--ds-danger-bg);  color: var(--ds-danger); }
.msg-pill.is-no-phone   { background: var(--ds-surface-soft); color: var(--ds-ink-3); }
.msg-pill.is-warning    { background: var(--ds-warning-bg); color: var(--ds-warning); }
.msg-pill.is-confirmed  { background: var(--ds-success-bg); color: var(--ds-success); }
.msg-pill.is-pending    { background: var(--ds-surface-soft); color: var(--ds-ink-3); }
.msg-pill.is-info       { background: var(--ds-info-bg);    color: var(--ds-info); }
.msg-pill.is-package    { background: var(--ds-warning-bg); color: var(--ds-warning); }

/* Citas por operador — compact bar list */
.operator-list { display: flex; flex-direction: column; gap: 0.55rem; }
.operator-row {
    display: grid;
    grid-template-columns: 11rem 1fr 2.5rem;
    gap: 0.85rem;
    align-items: center;
}
.operator-name {
    font-size: 1rem;
    color: var(--ds-ink-2);
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.operator-bar-track {
    height: 6px;
    background: var(--ds-surface-soft);
    border-radius: 3px;
    overflow: hidden;
}
.operator-bar-fill {
    height: 100%;
    background: var(--ds-ink);
    border-radius: 3px;
    transition: width 0.3s ease;
}
/* Rotación de acentos por fila — las barras de operadores dejan de ser
   un bloque gris y cada operador recibe un tono estable de la paleta. */
.operator-row:nth-child(8n + 1) .operator-bar-fill { background: var(--ds-accent-blue); }
.operator-row:nth-child(8n + 2) .operator-bar-fill { background: var(--ds-accent-teal); }
.operator-row:nth-child(8n + 3) .operator-bar-fill { background: var(--ds-accent-violet); }
.operator-row:nth-child(8n + 4) .operator-bar-fill { background: var(--ds-accent-amber); }
.operator-row:nth-child(8n + 5) .operator-bar-fill { background: var(--ds-accent-rose); }
.operator-row:nth-child(8n + 6) .operator-bar-fill { background: var(--ds-accent-cyan); }
.operator-row:nth-child(8n + 7) .operator-bar-fill { background: var(--ds-accent-green); }
.operator-row:nth-child(8n + 8) .operator-bar-fill { background: var(--ds-accent-orange); }
.operator-count {
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--ds-ink);
    text-align: right;
}

/* =========================================================================
   19. MEDICAL EXPEDIENTE — clinical data patterns
   --------------------------------------------------------------------------
   Patterns specific to the patient record:
     .patient-banner       Patient identity bar at the top of an expediente
     .patient-banner-stat  Each piece of patient info inside the banner
     .vital-grid           Responsive grid of vital sign cards
     .vital-card           Individual vital metric (number + unit + label)
     .section-title        Section header inside long clinical forms
     .heredity-row         Compact row for hereditary antecedents pattern
     .soap-section         SOAP note structure (Subjetivo/Objetivo/Análisis/Plan)
     .clinical-form        Scope for the full clinical history form
   ========================================================================= */

/* ─── Patient record header (receta record v3 para expedientes) ──────
   Avatar grande tintado en el record-title-row + chip de alergias en el
   record-meta (rojo si hay, neutro si "Ninguna" — la clase la pone el JS). */
.patient-avatar {
    width: 2.6rem;
    height: 2.6rem;
    border-radius: 50%;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.95rem;
    font-weight: 600;
    letter-spacing: -0.01em;
}
.patient-allergies {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
}
.patient-allergies.has-allergies {
    color: var(--ds-danger);
    font-weight: 600;
}
.patient-allergies:not(.has-allergies) .ti { display: none; }

/* ─── Estudios: dropzone + grid de archivos + visor DICOM ────────────── */
/* Explorador de archivos (estilo carpetas) */
.file-explorer {
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-lg);
    background: var(--ds-surface);
    box-shadow: var(--ds-shadow-xs);
    overflow: hidden;
    transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
.file-explorer.is-dragover {
    border-color: var(--ds-ink);
    box-shadow: var(--ds-shadow-sm);
}
.file-explorer-bar {
    display: flex;
    align-items: center;
    gap: var(--ds-space-3);
    min-height: 2.75rem;
    padding: var(--ds-space-2) var(--ds-space-4);
    border-bottom: 1px solid var(--ds-border);
    background: var(--ds-surface-muted);
}
.file-breadcrumb {
    display: flex;
    align-items: center;
    gap: var(--ds-space-2);
    font-size: 0.85rem;
}
.file-breadcrumb .ti { font-size: 1rem !important; }
.file-bc-current {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-weight: 600;
    color: var(--ds-ink);
}
.file-bc-link {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    border: 0;
    background: transparent;
    color: var(--ds-ink-4);
    cursor: pointer;
    padding: 0;
    font: inherit;
    transition: color 0.12s ease;
}
.file-bc-link:hover { color: var(--ds-ink); }
.file-bc-sep { color: var(--ds-ink-5); font-size: 0.9rem !important; }
.file-explorer-status {
    margin-left: auto;
    font-size: 0.8rem;
    color: var(--ds-ink-4);
    font-variant-numeric: tabular-nums;
}
.file-explorer-body { padding: var(--ds-space-4); }
.file-folder-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: var(--ds-space-3);
}
.file-folder {
    display: flex;
    align-items: center;
    gap: var(--ds-space-3);
    width: 100%;
    text-align: left;
    padding: var(--ds-space-3);
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-md);
    background: var(--ds-surface);
    box-shadow: var(--ds-shadow-xs);
    cursor: pointer;
    transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
.file-folder:hover {
    border-color: var(--ds-border-strong);
    box-shadow: var(--ds-shadow-sm);
}
.file-folder-icon {
    width: 2.5rem;
    height: 2.5rem;
    flex: 0 0 auto;
    border-radius: var(--ds-radius-sm);
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.file-folder-icon .ti { font-size: 1.3rem !important; }
.file-folder-info { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }
.file-folder-name { font-size: 0.9rem; font-weight: 600; color: var(--ds-ink); }
.file-folder-count { font-size: 0.8rem; color: var(--ds-ink-4); }
.file-folder-chev { margin-left: auto; color: var(--ds-ink-5); font-size: 1.1rem !important; }

.study-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
    gap: 1rem;
}
/* `.study-empty` se homologa con `.empty-state` (ver bloque EMPTY STATE);
   aquí sólo conserva el span completo dentro del grid de archivos. */
.study-card {
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-lg);
    overflow: hidden;
    background: var(--ds-surface);
    box-shadow: var(--ds-shadow-xs);
    transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
.study-card:hover { border-color: var(--ds-border-strong); box-shadow: var(--ds-shadow-sm); }
.study-thumb {
    aspect-ratio: 4 / 3;
    background-size: cover;
    background-position: center;
    background-color: var(--ds-surface-soft);
}
.study-thumb-icon {
    display: flex;
    align-items: center;
    justify-content: center;
}
.study-thumb-icon .ti { font-size: 2.4rem !important; }
.study-card-body { padding: 0.75rem 0.85rem; display: flex; flex-direction: column; gap: 0.5rem; }
.study-card-name {
    font-size: 0.9rem;
    font-weight: 500;
    color: var(--ds-ink);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.study-card-meta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.4rem;
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-size: 0.78rem;
    color: var(--ds-ink-4);
}

/* ─── Explorador estilo Drive: carpetas administrables, menús, DnD, diálogos ─ */
.file-folder { position: relative; }
.file-folder[draggable="true"] { cursor: pointer; }
.file-folder .file-folder-info { flex: 1 1 auto; }

/* Kebab (⋮) de acciones por elemento */
.fx-kebab {
    flex: 0 0 auto;
    width: 1.75rem;
    height: 1.75rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 0;
    border-radius: var(--ds-radius-sm);
    background: transparent;
    color: var(--ds-ink-4);
    cursor: pointer;
    transition: background-color 0.12s ease, color 0.12s ease, opacity 0.12s ease;
}
.fx-kebab .ti { font-size: 1.05rem !important; }
.fx-kebab:hover { background: var(--ds-surface-active); color: var(--ds-ink); }
.fx-kebab-float {
    position: absolute;
    top: 0.4rem;
    right: 0.4rem;
    z-index: 2;
    background: var(--ds-surface);
    box-shadow: var(--ds-shadow-xs);
    opacity: 0;
}
.study-card:hover .fx-kebab-float,
.study-card:focus-within .fx-kebab-float { opacity: 1; }
@media (hover: none) { .fx-kebab-float { opacity: 1; } }

/* Modo lista: tabla de columnas (Nombre · Tipo · Contenido · Fecha · ⋮) */
.fx-list { display: flex; flex-direction: column; }
.fx-list-head,
.fx-row {
    display: grid;
    grid-template-columns: 1.5rem minmax(0, 2.4fr) 1fr 1fr 1fr 2.25rem;
    align-items: center;
    gap: var(--ds-space-3);
    padding: 0.5rem var(--ds-space-3);
}
.fx-list-head {
    font-family: var(--ds-font-mono);
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--ds-ink-4);
    border-bottom: 1px solid var(--ds-border);
}
.fx-row {
    position: relative;
    border-bottom: 1px solid var(--ds-border-soft);
    border-radius: var(--ds-radius-sm);
    cursor: pointer;
    transition: background-color 0.12s ease, box-shadow 0.12s ease;
}
.fx-row:hover { background: var(--ds-surface-muted); }
.fx-row:last-child { border-bottom: 0; }
.fx-cell-check { display: flex; align-items: center; justify-content: center; }
.fx-cell-name { display: flex; align-items: center; gap: var(--ds-space-3); min-width: 0; }
.fx-row-icon {
    width: 2rem;
    height: 2rem;
    flex: 0 0 auto;
    border-radius: var(--ds-radius-sm);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background-size: cover;
    background-position: center;
}
.fx-row-icon .ti { font-size: 1.1rem !important; }
.fx-row-thumb { background-color: var(--ds-surface-soft); }
.fx-name {
    font-size: 0.9rem;
    font-weight: 500;
    color: var(--ds-ink);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Móvil: el nombre del estudio/archivo se corta con ellipsis y su valor completo
   sólo vivía en el title= (inalcanzable en touch). Se deja envolver a 2 líneas. */
@media (max-width: 767.98px) {
    .fx-name {
        white-space: normal;
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
    }
}
.fx-cell-type {
    font-size: 0.85rem;
    color: var(--ds-ink-3);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.fx-cell-meta,
.fx-cell-date {
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-size: 0.8rem;
    color: var(--ds-ink-4);
    white-space: nowrap;
}
.fx-cell-act { display: flex; justify-content: flex-end; }

/* ── Agrupación por estudio (StudyInstanceUID) ─────────────────────────── */
/* Agrupación tipográfica (DS: jerarquía por tipografía y hairlines, no cajas ni
   barras de color). El encabezado es una etiqueta con hairline superior y un
   punto pequeño; las series del estudio van sangradas. Sin acentos laterales. */
.fx-study-head {
    display: flex;
    align-items: baseline;
    gap: 0.45rem;
    padding: 0.55rem var(--ds-space-3) 0.3rem;
    margin-top: 0.3rem;
    border-top: 1px solid var(--ds-border-soft);
    cursor: pointer;
    user-select: none;
}
.fx-study-head:first-child { border-top: 0; margin-top: 0; }
.fx-study-head:hover { background: var(--ds-surface-muted); }
.fx-study-dot { width: 0.5rem; height: 0.5rem; border-radius: 50%; flex: 0 0 auto; align-self: center; }
.fx-study-head.is-sel .fx-study-title { color: var(--ds-accent-violet); }
.fx-study-title { font-size: 0.8rem; font-weight: 600; color: var(--ds-ink-2); white-space: nowrap; }
.fx-study-meta {
    font-family: var(--ds-font-mono);
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--ds-ink-4);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Series del estudio: sangría sutil para leerlas como anidadas (sin barras) */
.fx-row.fx-in-study .fx-cell-name { padding-left: 1.15rem; }

/* ── Multiselección de estudios ────────────────────────────────────────── */
.fx-check {
    flex: 0 0 auto;
    width: 1.15rem;
    height: 1.15rem;
    border: 1.5px solid var(--ds-border-strong);
    border-radius: 5px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    color: #fff;
    background: var(--ds-bg);
    transition: background 0.12s, border-color 0.12s, opacity 0.12s;
    opacity: 0;
}
.fx-row:hover .fx-check,
.fx-check.is-on { opacity: 1; }
.fx-check input { position: absolute; opacity: 0; width: 0; height: 0; }
.fx-check .ti { font-size: 0.85rem !important; opacity: 0; }
.fx-check.is-on {
    background: var(--ds-accent-violet);
    border-color: var(--ds-accent-violet);
}
.fx-check.is-on .ti { opacity: 1; }
.fx-row.is-selected { background: var(--ds-accent-violet-bg); }
.fx-row.is-selected:hover { background: var(--ds-accent-violet-bg); }

/* Barra de acciones de selección */
.fx-selbar {
    display: flex;
    align-items: center;
    gap: var(--ds-space-3);
    flex-wrap: wrap;
    padding: 0.55rem var(--ds-space-3);
    margin-bottom: var(--ds-space-2);
    background: var(--ds-accent-violet-bg);
    border: 1px solid var(--ds-accent-violet);
    border-radius: var(--ds-radius-sm);
}
.fx-sel-count {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--ds-accent-violet);
    margin-right: auto;
}
.fx-sel-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.35rem 0.7rem;
    font-size: 0.83rem;
    font-weight: 500;
    border: 1px solid var(--ds-accent-violet);
    border-radius: var(--ds-radius-sm);
    background: var(--ds-bg);
    color: var(--ds-accent-violet);
    cursor: pointer;
}
.fx-sel-btn:hover { background: var(--ds-surface-muted); }
.fx-sel-btn .ti { font-size: 1rem !important; }
.fx-sel-primary { background: var(--ds-accent-violet); color: #fff; }
.fx-sel-primary:hover { filter: brightness(1.08); background: var(--ds-accent-violet); }
.fx-sel-ghost { border-color: transparent; color: var(--ds-ink-4); }
.fx-sel-ghost:hover { background: rgba(0, 0, 0, 0.04); }

/* Estados de arrastre / destino de soltado */
.fx-dragging { opacity: 0.4; }
.fx-row.fx-folder.is-drop-target {
    background: var(--ds-surface-active);
    box-shadow: inset 0 0 0 2px var(--ds-ink);
}
@media (max-width: 640px) {
    .fx-list-head,
    .fx-row { grid-template-columns: 1.5rem minmax(0, 1fr) auto 2.25rem; }
    .fx-cell-type,
    .fx-cell-date { display: none; }
}
.file-bc-link.is-drop-target,
.file-bc-current.is-drop-target {
    border-radius: var(--ds-radius-sm);
    box-shadow: 0 0 0 2px var(--ds-ink) inset;
    color: var(--ds-ink);
}

/* Menú flotante de acciones */
.fx-menu {
    position: fixed;
    z-index: 2100;
    min-width: 190px;
    padding: 0.35rem;
    background: var(--ds-surface);
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-md);
    box-shadow: var(--ds-shadow-md);
}
.fx-menu-item {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    width: 100%;
    text-align: left;
    border: 0;
    background: transparent;
    color: var(--ds-ink-2);
    padding: 0.45rem 0.6rem;
    border-radius: var(--ds-radius-sm);
    font-size: 0.9rem;
    cursor: pointer;
    transition: background-color 0.1s ease, color 0.1s ease;
}
.fx-menu-item .ti { font-size: 1.05rem !important; color: var(--ds-ink-4); }
.fx-menu-item:hover { background: var(--ds-surface-muted); color: var(--ds-ink); }
.fx-menu-item.is-danger { color: var(--ds-danger); }
.fx-menu-item.is-danger .ti { color: var(--ds-danger); }
.fx-menu-item.is-danger:hover { background: var(--ds-danger-bg); }
.fx-menu-sep { height: 1px; margin: 0.3rem 0; background: var(--ds-border-soft); }

/* Diálogos (nombrar / confirmar / elegir carpeta) */
.fx-overlay {
    position: fixed;
    inset: 0;
    z-index: 2200;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    background: rgba(10, 10, 10, 0.35);
}
.fx-dialog {
    width: 100%;
    max-width: 26rem;
    background: var(--ds-surface);
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-lg);
    box-shadow: var(--ds-shadow-lg);
    padding: var(--ds-space-5);
}
.fx-dialog-title { font-size: 1.05rem; font-weight: 600; color: var(--ds-ink); margin: 0 0 var(--ds-space-3); }
.fx-dialog-msg { font-size: 0.9rem; color: var(--ds-ink-3); margin: 0 0 var(--ds-space-4); }
.fx-dialog-input { margin-bottom: var(--ds-space-4); }
.fx-dialog-actions { display: flex; justify-content: flex-end; gap: var(--ds-space-2); }

/* Selector de carpeta (árbol) */
.fx-pick-list {
    max-height: 18rem;
    overflow-y: auto;
    margin-bottom: var(--ds-space-4);
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-md);
    padding: 0.3rem;
}
.fx-pick-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    text-align: left;
    border: 0;
    background: transparent;
    color: var(--ds-ink-2);
    padding: 0.45rem 0.6rem;
    border-radius: var(--ds-radius-sm);
    font-size: 0.9rem;
    cursor: pointer;
    transition: background-color 0.1s ease;
}
.fx-pick-row .ti { font-size: 1.05rem !important; color: var(--ds-accent-amber); flex: 0 0 auto; }
.fx-pick-row > span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fx-pick-row:hover { background: var(--ds-surface-muted); color: var(--ds-ink); }
.fx-pick-row.is-current { cursor: default; color: var(--ds-ink-4); }
.fx-pick-row.is-current:hover { background: transparent; }
.fx-pick-here {
    margin-left: auto;
    font-family: var(--ds-font-mono);
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--ds-ink-5);
}

/* ─── Visor DICOM PROFESIONAL — overlay full-screen estilo PACS ───────── */
.dicom-spin { animation: ds-dicom-spin 0.9s linear infinite; display: inline-block; }
@keyframes ds-dicom-spin { to { transform: rotate(360deg); } }

/* ── Tokens del visor (siempre oscuro estilo PACS) ──────────────────────────
   El visor es un overlay full-screen que NO sigue el tema claro de la app, por
   eso no puede leer --ds-* directamente (serían blancos en modo claro). Define
   su propia paleta oscura en un namespace --dv-* DERIVADA de la escala dark del
   design system (grises NEUTROS R=G=B + acentos Apollo). Una sola fuente para
   retunear todo el chrome del visor 2D y 3D. */
.dicom-pro,
.cs3d-overlay {
    --dv-void:         #000;       /* área de imagen — negro puro PACS */
    --dv-chrome:       #161616;    /* barras header/footer = surface dark */
    --dv-panel:        #0d0d0d;    /* paneles laterales (un pelo bajo el bg) */
    --dv-raise:        #1f1f1f;    /* inputs/elevados = surface-muted dark */
    --dv-hover:        #262626;    /* hovers = surface-soft dark */
    --dv-active:       #2f2f2f;    /* pressed = surface-active dark */
    --dv-border:       #2a2a2a;    /* = border dark */
    --dv-border-strong:#3a3a3a;    /* = border-strong dark (hover de inputs) */
    --dv-border-soft:  #1e1e1e;    /* = border-soft dark */
    --dv-ink:          #f5f5f5;    /* = ink dark */
    --dv-ink-2:        #d6d6d6;
    --dv-ink-3:        #a8a8a8;    /* secundario */
    --dv-ink-4:        #808080;    /* muted / metadata */
    --dv-ink-5:        #5c5c5c;    /* faint / vacíos */
    --dv-accent:       #b3a5f2;    /* lavanda = accent-violet dark (identidad/activo) */
    --dv-accent-fill:  #6552d0;    /* lavanda saturado = relleno violeta (texto claro encima) */
    --dv-data:         #8ea2ff;    /* periwinkle = accent-blue dark (labels mono/overlays) */
    --dv-lime:         var(--ds-lime);
    --dv-lime-ink:     var(--ds-lime-ink);
    --dv-ok:           #6fce8a;    /* = success dark */
    --dv-danger:       #ec7a70;    /* = danger dark */
    --dv-radius:       var(--ds-radius-sm);
}

.dicom-pro {
    position: fixed;
    inset: 0;
    z-index: 2000;
    background: var(--dv-void);
    display: flex;
    flex-direction: column;
    color: var(--dv-ink);
}
.dicom-pro[hidden] { display: none; }

/* Barra superior: título + herramientas + cerrar */
.dicom-pro-bar {
    display: flex;
    align-items: center;
    gap: 1rem;
    height: 3.4rem;
    flex-shrink: 0;
    padding: 0 0.85rem;
    background: var(--dv-chrome);
    border-bottom: 1px solid var(--dv-border);
}
.dicom-pro-title {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 1.05rem;
    font-weight: 550;
    color: var(--dv-ink);
    text-transform: capitalize;
    white-space: nowrap;
    min-width: 0;
    flex: 0 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
}
.dicom-pro-title .ti { color: var(--dv-accent); font-size: 1.3rem !important; flex: 0 0 auto; }
/* Marca Circadis (trazo BLANCO, el visor es siempre oscuro) en lugar del icono genérico */
.dicom-pro-logo { height: 1.3rem; width: auto; flex: 0 0 auto; display: block; }
.dicom-pro-sub {
    font-family: var(--ds-font-mono);
    font-size: 0.95rem;
    color: var(--dv-ink-4);
    text-transform: none;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.dicom-pro-tools {
    display: flex;
    align-items: center;
    gap: 0.15rem;
    /* Empujado a la derecha: el toggle del panel queda junto al botón Cerrar. */
    margin-left: auto;
    /* Una sola fila: si no cabe, se desplaza en horizontal (antes envolvía a
       una 2ª fila que se desbordaba sobre la imagen tirando los sliders). */
    flex-wrap: nowrap;
    justify-content: center;
    min-width: 0;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
}
.dicom-pro-tools::-webkit-scrollbar { display: none; }
.dicom-pro-tools > * { flex: 0 0 auto; }
.dicom-pro-div { width: 1px; height: 1.6rem; background: var(--dv-border); margin: 0 0.3rem; flex: 0 0 auto; }
.dicom-tool,
.dicom-act {
    width: 2.15rem;
    height: 2.15rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 0;
    border-radius: var(--ds-radius-sm);
    background: transparent;
    color: var(--dv-ink-3);
    cursor: pointer;
    transition: background-color 0.12s ease, color 0.12s ease;
}
.dicom-tool .ti,
.dicom-act .ti { font-size: 1.3rem !important; }
.dicom-tool:hover,
.dicom-act:hover { background: var(--dv-border); color: var(--dv-ink); }
.dicom-tool.is-active {
    background: var(--dv-lime);
    color: var(--dv-lime-ink);
}
.dicom-pro-close {
    width: 2.3rem;
    height: 2.3rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 0;
    border-radius: var(--ds-radius-sm);
    background: transparent;
    color: var(--dv-ink-3);
    cursor: pointer;
    flex-shrink: 0;
}
.dicom-pro-close:hover { background: var(--dv-danger); color: var(--dv-ink); }
.dicom-pro-close .ti { font-size: 1.4rem !important; }

/* Stage central: barra de secuencias + rejilla de viewports */
.dicom-pro-stage {
    position: relative;
    flex: 1 1 auto;
    min-height: 0;
    background: var(--dv-void);
    overflow: hidden;
    display: flex;
}

/* ── Barra lateral de Secuencias ───────────────────────────────────────── */
.dicom-seq {
    flex: 0 0 244px;
    width: 244px;
    background: var(--dv-panel);
    border-right: 1px solid var(--dv-border);
    display: flex;
    flex-direction: column;
    min-height: 0;
}
.dicom-seq[hidden] { display: none; }
.dicom-seq-head {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.6rem 0.75rem;
    font-size: 0.88rem;
    font-weight: 600;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--dv-data);
    border-bottom: 1px solid var(--dv-border);
}
.dicom-seq-head .ti { font-size: 1.05rem !important; }
/* Colapsar (en la cabecera de Secuencias, a la derecha) */
.dicom-seq-collapse {
    margin-left: auto;
    background: none;
    border: 0;
    color: var(--dv-data);
    cursor: pointer;
    padding: 2px;
    border-radius: 4px;
    display: inline-flex;
}
.dicom-seq-collapse:hover { color: var(--dv-ink); background: rgba(255, 255, 255, 0.06); }
.dicom-seq-collapse .ti { font-size: 1.05rem !important; }
/* Botón flotante (borde izquierdo) para REABRIR Secuencias cuando está oculto */
.dicom-seq-open {
    position: absolute;
    top: 0.7rem;
    left: 0;
    z-index: 7;
    width: 1.6rem;
    height: 2.2rem;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(13, 15, 18, 0.92);
    color: var(--dv-data);
    border: 1px solid var(--dv-border);
    border-left: 0;
    border-radius: 0 8px 8px 0;
    cursor: pointer;
}
.dicom-seq-open:hover { color: var(--dv-ink); background: rgba(20, 24, 32, 0.96); }
.dicom-seq-open[hidden] { display: none; }
.dicom-seq-open .ti { font-size: 1.2rem !important; }
.dicom-seq-list { flex: 1 1 auto; overflow-y: auto; padding: 0.45rem; }
.dicom-seq-list::-webkit-scrollbar { width: 7px; }
.dicom-seq-list::-webkit-scrollbar-thumb { background: var(--dv-raise); border-radius: 4px; }
.dicom-seq-item {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    width: 100%;
    padding: 0.4rem;
    margin-bottom: 0.3rem;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 8px;
    cursor: pointer;
    text-align: left;
    transition: background 0.12s, border-color 0.12s;
}
.dicom-seq-item:hover { background: var(--dv-hover); }
.dicom-seq-item.is-shown { border-color: var(--dv-border); }
.dicom-seq-item.is-active {
    background: var(--dv-hover);
    border-color: var(--dv-accent);
}
.dicom-seq-thumb {
    flex: 0 0 54px;
    width: 54px;
    height: 54px;
    border-radius: 6px;
    background: var(--dv-void);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    color: var(--dv-ink-5);
}
.dicom-seq-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.dicom-seq-thumb .ti { font-size: 1.3rem !important; }
.dicom-seq-info { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 0.1rem; }
.dicom-seq-add {
    flex: 0 0 auto;
    width: 1.55rem;
    height: 1.55rem;
    border: 1px solid var(--dv-border);
    border-radius: 6px;
    background: var(--dv-raise);
    color: var(--dv-ink-3);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.12s, background 0.12s, color 0.12s;
}
.dicom-seq-item:hover .dicom-seq-add { opacity: 1; }
.dicom-seq-add:hover { background: var(--dv-accent-fill); border-color: var(--dv-accent-fill); color: var(--dv-ink); }
.dicom-seq-add .ti { font-size: 1rem !important; }
.dicom-seq-name {
    font-size: 0.92rem;
    font-weight: 600;
    color: var(--dv-ink);
    line-height: 1.2;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}
.dicom-seq-meta {
    font-family: var(--ds-font-mono);
    font-size: 0.84rem;
    color: var(--dv-ink-4);
}
.dicom-seq-empty { padding: 1rem 0.75rem; font-size: 0.86rem; color: var(--dv-ink-4); text-align: center; }

/* ── Rejilla de viewports (Disposición) ────────────────────────────────── */
.dicom-pro-viewports {
    position: relative;
    flex: 1 1 auto;
    min-width: 0;
    min-height: 0;
    display: grid;
    grid-template-columns: repeat(var(--cols, 1), 1fr);
    grid-template-rows: repeat(var(--rows, 1), 1fr);
    gap: 2px;
    background: var(--dv-void);
}
.dicom-cell {
    position: relative;
    min-width: 0;
    min-height: 0;
    overflow: hidden;
    background: var(--dv-void);
    box-shadow: inset 0 0 0 1px var(--dv-hover);
}
.dicom-pro-viewports[data-layout='1x1'] .dicom-cell { box-shadow: none; }
/* Borde de celda activa: va en ::after por ENCIMA del canvas de cornerstone
   (un box-shadow inset quedaría tapado por el lienzo y no se vería). */
.dicom-cell.is-active::after {
    content: '';
    position: absolute;
    inset: 0;
    border: 2px solid var(--dv-accent);
    pointer-events: none;
    z-index: 4;
}
.dicom-pro-viewports[data-layout='1x1'] .dicom-cell.is-active::after { display: none; }
.dicom-cell-el { width: 100%; height: 100%; }
.dicom-cell-el canvas { outline: none; }
/* Botón “quitar vista” (sólo en multipanel, al pasar el cursor) */
.dicom-cell-close {
    position: absolute;
    top: 0.45rem;
    right: 0.45rem;
    z-index: 5;
    width: 1.7rem;
    height: 1.7rem;
    display: none;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: 6px;
    background: rgba(8, 10, 14, 0.72);
    color: var(--dv-ink-3);
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.12s, background 0.12s, color 0.12s;
}
.dicom-pro-viewports:not([data-layout='1x1']) .dicom-cell-close { display: inline-flex; }
.dicom-cell:hover .dicom-cell-close { opacity: 1; }
.dicom-cell-close:hover { background: var(--dv-danger); color: var(--dv-ink); }
.dicom-cell-close .ti { font-size: 1.05rem !important; }
.dicom-cell-empty {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    color: var(--dv-ink-5);
    font-size: 0.82rem;
    pointer-events: none;
}
.dicom-cell-empty .ti { font-size: 2rem !important; }
.dicom-cell.has-image .dicom-cell-empty { display: none; }
/* Spinner "cargando corte": aparece al navegar a un corte aún no cacheado (scroll
   rápido / carga perezosa) → transmite que está cargando en vez de parecer trabado. */
.dicom-cell.is-loading-slice::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 34px;
    height: 34px;
    transform: translate(-50%, -50%);
    border-radius: 50%;
    border: 3px solid rgba(255, 255, 255, 0.18);
    border-top-color: var(--dv-data);
    animation: ds-dicom-spin 0.8s linear infinite;
    pointer-events: none;
    z-index: 5;
}
@media (prefers-reduced-motion: reduce) {
    .dicom-cell.is-loading-slice::after { animation: none; }
}
/* En rejillas, overlays más compactos para no saturar las celdas */
.dicom-pro-viewports[data-layout='2x2'] .dicom-ov,
.dicom-pro-viewports[data-layout='1x3'] .dicom-ov { font-size: 0.74rem; line-height: 1.35; }

/* ── Panel de atajos de teclado ────────────────────────────────────────── */
.dicom-help {
    position: absolute;
    inset: 0;
    z-index: 20;
    display: none;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(2px);
}
.dicom-help.is-open { display: flex; }
.dicom-help-card {
    width: min(30rem, 92%);
    background: var(--dv-raise);
    border: 1px solid var(--dv-border);
    border-radius: 12px;
    box-shadow: 0 18px 50px rgba(0, 0, 0, 0.5);
    overflow: hidden;
}
.dicom-help-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.75rem 1rem;
    border-bottom: 1px solid var(--dv-border);
    color: var(--dv-ink);
    font-weight: 600;
}
.dicom-help-head > span { display: inline-flex; align-items: center; gap: 0.45rem; }
.dicom-help-head .ti { color: var(--dv-accent); font-size: 1.2rem !important; }
.dicom-help-close {
    border: none;
    background: transparent;
    color: var(--dv-ink-3);
    cursor: pointer;
    font-size: 1.2rem;
    line-height: 1;
}
.dicom-help-close:hover { color: var(--dv-ink); }
.dicom-help-grid {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 0.5rem 0.9rem;
    align-items: center;
    padding: 1rem;
    max-height: 60vh;
    overflow-y: auto;
}
.dicom-help-grid kbd {
    justify-self: start;
    font-family: var(--ds-font-mono);
    font-size: 0.8rem;
    color: var(--dv-ink-3);
    background: var(--dv-raise);
    border: 1px solid var(--dv-border);
    border-bottom-width: 2px;
    border-radius: 6px;
    padding: 0.15rem 0.5rem;
    white-space: nowrap;
}
.dicom-help-grid span { color: var(--dv-ink-3); font-size: 0.86rem; }

/* ── Overlay del visor 3D (cornerstone3D, iframe) ──────────────────────── */
.cs3d-overlay {
    position: fixed;
    inset: 0;
    z-index: 2000;
    background: var(--dv-void);
}
.cs3d-frame { width: 100%; height: 100%; border: 0; display: block; }

/* ══ Visor MPR por-imagen (A2.3) — full-screen, planos servidos por el server ══ */
.mprv {
    position: fixed;
    inset: 0;
    z-index: 2000;
    background: #000;
    display: flex;
    flex-direction: column;
    color: #f2f2f2;
    font-family: var(--ds-font, system-ui, sans-serif);
}
.mprv[hidden] { display: none; }
.mprv-bar {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    height: calc(2.9rem + env(safe-area-inset-top));
    padding: env(safe-area-inset-top) 0.75rem 0;
    background: #161616;
    border-bottom: 1px solid #2a2a2a;
    flex: 0 0 auto;
}
.mprv-title { font-size: 0.92rem; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mprv-hu { margin-left: auto; font-family: var(--ds-font-mono, monospace); font-size: 0.78rem; color: #b3a5f2; }
.mprv-close {
    width: 2.4rem; height: 2.4rem; flex: 0 0 auto; border: 0; background: transparent;
    color: #cfcfcf; cursor: pointer; border-radius: 8px; display: inline-flex; align-items: center; justify-content: center;
}
.mprv-close:hover { background: #d33; color: #fff; }
.mprv-close .ti { font-size: 1.35rem !important; }
.mprv-stage { flex: 1 1 auto; min-height: 0; position: relative; background: #000; overflow: hidden; touch-action: none; }
.mprv-img {
    position: absolute; inset: 0; margin: auto; max-width: 100%; max-height: 100%;
    image-rendering: auto; -webkit-user-select: none; user-select: none;
}
.mprv-veil {
    position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
    background: rgba(0, 0, 0, 0.55); color: #cfcfcf; font-size: 0.9rem; font-family: var(--ds-font-mono, monospace);
}
.mprv-veil[hidden] { display: none; }
.mprv-foot {
    display: flex; align-items: center; gap: 0.6rem; height: 3rem; padding: 0 0.9rem;
    background: #161616; border-top: 1px solid #2a2a2a; flex: 0 0 auto;
}
.mprv-slider { flex: 1 1 auto; accent-color: #dfff54; height: 2.2rem; }
.mprv-count { font-family: var(--ds-font-mono, monospace); font-size: 0.82rem; color: #cfcfcf; min-width: 4rem; text-align: right; }
.mprv-nav {
    display: flex; align-items: stretch; gap: 2px; flex: 0 0 auto;
    padding: 3px 3px calc(3px + env(safe-area-inset-bottom));
    background: #161616; border-top: 1px solid #2a2a2a;
}
.mprv-btn {
    flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 2px; min-height: 3rem; border: 0; border-radius: 8px; background: transparent; color: #9a9a9a;
    font-size: 0.62rem; font-weight: 600; cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.mprv-btn > .ti { font-size: 1.3rem !important; }
.mprv-btn span { line-height: 1; white-space: nowrap; }
.mprv-btn:active { background: #222; }
.mprv-btn.is-axis.on { color: #dfff54; }

/* Loader sobre el iframe 3D mientras se descargan/preparan los archivos. */
.cs3d-loading {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.6);
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
}

/* Flechas laterales: cambiar de estudio/serie cargado */
.dicom-study-nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 2.6rem;
    height: 3.6rem;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.4);
    border: 1px solid var(--dv-border);
    border-radius: var(--ds-radius-sm);
    color: var(--dv-ink);
    cursor: pointer;
    z-index: 6;
    transition: background-color 0.12s ease, color 0.12s ease;
}
.dicom-study-nav:hover { background: rgba(0, 0, 0, 0.78); color: var(--dv-ink); }
.dicom-study-nav.prev { left: 0.7rem; }
.dicom-study-nav.next { right: 0.7rem; }
.dicom-study-nav .ti { font-size: 1.6rem !important; }
.dicom-study-nav[hidden] { display: none; }
.dicom-zoom-ctl {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}
.dicom-zoom-icon {
    font-size: 1.3rem !important; /* igual que los íconos de .dicom-tool / .dicom-act */
    color: rgba(255, 255, 255, 0.65);
}
.dicom-zoom-slider {
    -webkit-appearance: none;
    appearance: none;
    width: 84px;
    height: 3px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.25);
    cursor: pointer;
}
.dicom-zoom-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 13px;
    height: 13px;
    border-radius: 50%;
    background: var(--dv-lime);
    border: none;
    cursor: pointer;
}
.dicom-zoom-slider::-moz-range-thumb {
    width: 13px;
    height: 13px;
    border: none;
    border-radius: 50%;
    background: var(--dv-lime);
    cursor: pointer;
}
.dicom-zoom-pct {
    min-width: 3.4em;
    font-size: 0.95rem;
    color: rgba(255, 255, 255, 0.75);
    font-variant-numeric: tabular-nums;
    text-align: right;
}
/* ── Panel de ajustes (derecha, colapsable): W/L, zoom, presets ─────────── */
.dicom-ctrl {
    flex: 0 0 224px;
    width: 224px;
    background: var(--dv-panel);
    border-left: 1px solid var(--dv-border);
    display: flex;
    flex-direction: column;
    min-height: 0;
}
.dicom-ctrl[hidden] { display: none; }
.dicom-ctrl-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.4rem;
    padding: 0.6rem 0.75rem;
    font-size: 0.82rem;
    color: var(--dv-ink-3);
    letter-spacing: 0.02em;
    border-bottom: 1px solid var(--dv-border);
    flex: 0 0 auto;
}
.dicom-ctrl-head > span { display: inline-flex; align-items: center; gap: 0.4rem; }
.dicom-ctrl-head .ti { font-size: 1.05rem !important; }
.dicom-ctrl-close {
    background: none;
    border: 0;
    color: var(--dv-ink-4);
    cursor: pointer;
    padding: 2px;
    border-radius: 4px;
    display: inline-flex;
}
.dicom-ctrl-close:hover { color: var(--dv-ink); background: rgba(255, 255, 255, 0.06); }
.dicom-ctrl-close .ti { font-size: 1rem !important; }
.dicom-ctrl-body {
    overflow-y: auto;
    padding: 0.75rem 0.75rem 1rem;
    display: flex;
    flex-direction: column;
    gap: 1.1rem;
    min-height: 0;
}
.dicom-ctrl-sec { display: flex; flex-direction: column; gap: 0.5rem; }
.dicom-ctrl-title {
    margin: 0;
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--dv-ink-4);
    font-weight: 600;
}
.dicom-ctrl-row { display: flex; align-items: center; gap: 0.55rem; }
.dicom-ctrl .dicom-zoom-slider { flex: 1 1 auto; width: auto; }
.dicom-ctrl .dicom-preset-select { width: 100%; }
/* Disposición: 4 botones de layout en fila, a lo ancho del panel. */
.dicom-ctrl .dicom-layouts { display: flex; gap: 2px; width: 100%; }
.dicom-ctrl .dicom-layout { flex: 1 1 0; }
/* Herramientas/acciones como FILAS con icono + título (explicación). */
.dicom-ctrl .dicom-ctrl-btn {
    width: 100%;
    height: auto;
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 0.6rem;
    padding: 0.42rem 0.5rem;
    border: 1px solid transparent;
    border-radius: 6px;
    background: transparent;
    color: var(--dv-ink-3);
    font-size: 0.85rem;
    text-align: left;
    cursor: pointer;
    line-height: 1.2;
}
.dicom-ctrl .dicom-ctrl-btn:hover { background: rgba(255, 255, 255, 0.06); color: var(--dv-ink); }
.dicom-ctrl .dicom-ctrl-btn.is-active {
    background: rgba(101, 82, 208, 0.22);   /* violeta de marca (--dv-accent-fill) translúcido */
    border-color: rgba(179, 165, 242, 0.5); /* lavanda (--dv-accent) */
    color: var(--dv-ink);
}
.dicom-ctrl .dicom-ctrl-btn .ti { font-size: 1.15rem !important; flex: 0 0 auto; color: inherit; }
.dicom-ctrl .dicom-ctrl-btn span { flex: 1 1 auto; }

/* Panel de metadatos DICOM */
.dicom-meta {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: min(460px, 85vw);
    background: rgba(10, 10, 10, 0.94);
    border-left: 1px solid var(--dv-border);
    display: flex;
    flex-direction: column;
    z-index: 6;
    backdrop-filter: blur(2px);
}
.dicom-meta[hidden] {
    display: none;
}
.dicom-meta-head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.6rem 0.75rem;
    border-bottom: 1px solid var(--dv-border);
    color: var(--dv-ink);
    font-size: 0.95rem;
    font-weight: 600;
}
.dicom-meta-head > span {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    white-space: nowrap;
}
/* Íconos del panel: tamaño explícito (si no, heredan el global .ti = 2em). */
.dicom-meta .ti {
    font-size: 1.2rem !important;
    line-height: 1;
    vertical-align: middle;
}
.dicom-meta-search {
    flex: 1 1 auto;
    min-width: 0;
    background: var(--dv-raise);
    border: 1px solid var(--dv-border);
    border-radius: 6px;
    color: var(--dv-ink-2);
    font-size: 0.9rem;
    font-weight: 400;
    padding: 0.3rem 0.55rem;
}
.dicom-meta-search:focus {
    outline: none;
    border-color: var(--dv-lime);
}
.dicom-meta-close {
    flex: 0 0 auto;
    background: transparent;
    border: none;
    color: var(--dv-ink-4);
    cursor: pointer;
    font-size: 1.2rem;
    line-height: 1;
    padding: 0.15rem;
}
.dicom-meta-close:hover {
    color: var(--dv-ink);
}
.dicom-meta-body {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 0.4rem 0;
    font-size: 0.9rem;
    font-variant-numeric: tabular-nums;
}
.dicom-meta-row {
    display: grid;
    grid-template-columns: 1fr 1.2fr;
    gap: 0.6rem;
    align-items: baseline;
    padding: 0.32rem 0.85rem;
    border-bottom: 1px solid rgba(255, 255, 255, 0.04);
}
.dicom-meta-row:hover {
    background: rgba(255, 255, 255, 0.04);
}
.dicom-meta-k {
    color: var(--dv-ink-4);
    min-width: 0;
    word-break: break-word;
}
.dicom-meta-k .dicom-meta-tag {
    display: block;
    color: var(--dv-ink-5);
    font-size: 0.8rem;
    font-family: var(--ds-font-mono, ui-monospace, monospace);
}
.dicom-meta-v {
    color: var(--dv-ink-2);
    word-break: break-word;
}
.dicom-meta-empty {
    padding: 1rem 0.75rem;
    color: var(--dv-ink-4);
}
.dicom-pro-loading,
.dicom-pro-error {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    padding: 2rem;
    text-align: center;
}

/* ── Loader premium por etapa (descarga → análisis → render) ─────────────── */
.dicom-loader-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.65rem;
    padding: 1.25rem 1.6rem;
    background: rgba(13, 15, 19, 0.72);
    border: 1px solid var(--dv-border);
    border-radius: var(--ds-radius-lg);
    box-shadow: 0 12px 34px rgba(0, 0, 0, 0.45);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    animation: dicom-loader-in 0.25s ease both;
}
@keyframes dicom-loader-in {
    from { opacity: 0; transform: translateY(6px) scale(0.98); }
    to   { opacity: 1; transform: none; }
}
.dicom-loader-ring {
    position: relative;
    width: 56px;
    height: 56px;
    display: grid;
    place-items: center;
}
/* Anillo de gradiente girando (máscara radial = solo el borde) */
.dicom-loader-ring::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: conic-gradient(from 0deg, rgba(124, 138, 240, 0) 0deg, var(--dv-data) 250deg, var(--dv-accent) 320deg, rgba(124, 138, 240, 0) 360deg);
    -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 3px), var(--dv-void) calc(100% - 2px));
            mask: radial-gradient(farthest-side, transparent calc(100% - 3px), var(--dv-void) calc(100% - 2px));
    animation: ds-dicom-spin 0.9s linear infinite;
}
/* Halo suave detrás del glifo */
.dicom-loader-ring::after {
    content: '';
    position: absolute;
    inset: 8px;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(67, 83, 197, 0.22), transparent 70%);
}
.dicom-loader-ring .ti {
    position: relative;
    color: var(--dv-ink);
    animation: dicom-loader-pulse 1.6s ease-in-out infinite;
}
@keyframes dicom-loader-pulse {
    0%, 100% { opacity: 0.65; transform: scale(0.96); }
    50%      { opacity: 1;    transform: scale(1.04); }
}
.dicom-loader-text {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.2rem;
}
.dicom-loader-title {
    color: var(--dv-ink);
    font-size: 0.92rem;
    font-weight: 500;
    letter-spacing: 0.01em;
}
.dicom-loader-sub {
    color: var(--dv-ink-4);
    font-size: 0.78rem;
    font-family: var(--ds-font-mono);
    min-height: 1em;
    max-width: 260px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.dicom-loader-bar {
    position: relative;
    width: 180px;
    height: 3px;
    border-radius: 99px;
    background: var(--dv-raise);
    overflow: hidden;
}
.dicom-loader-bar > span {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 40%;
    border-radius: 99px;
    background: linear-gradient(90deg, transparent, var(--dv-data), var(--dv-accent), transparent);
    animation: dicom-loader-slide 1.15s ease-in-out infinite;
}
@keyframes dicom-loader-slide {
    0%   { left: -45%; }
    100% { left: 100%; }
}
@media (prefers-reduced-motion: reduce) {
    .dicom-loader-ring::before,
    .dicom-loader-ring .ti,
    .dicom-loader-bar > span,
    .dicom-loader-card { animation: none; }
}

/* ── Spinner de marca Circadis (el logo girando entero) ─────────────────────
   Los trazos del logo NO son circunferencias perfectas: rotarlos por separado se
   ve raro. Rotamos el GRUPO completo como pieza rígida, alrededor del centro real
   del logo (transform-box: view-box + transform-origin en el centro del viewBox)
   → gira coherente y en reposo ES el logo. Hereda color por `currentColor`.
   Loader premium del visor DICOM y otras cargas de marca. */
.circadis-spinner { display: inline-block; width: 56px; height: 56px; color: var(--ds-accent-blue); }
.circadis-spinner svg { width: 100%; height: 100%; display: block; overflow: visible; }
.circadis-spinner .cs-arc { fill: currentColor; }
.circadis-spinner .cs-rot {
    transform-box: view-box;
    transform-origin: 126.5px 120px;
    animation: cs-spin 1.4s linear infinite;
}
@keyframes cs-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
    .circadis-spinner .cs-rot { animation: none; }
}
/* En el loader del visor DICOM (fondo oscuro): color de dato periwinkle, tamaño
   compacto (minimalista). */
.dicom-loader-card .circadis-spinner,
.cs3d-loading .circadis-spinner { color: var(--dv-data); width: 40px; height: 40px; }

/* ── Tarjeta de error del visor ─────────────────────────────────────────── */
.dicom-error-card {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    max-width: 420px;
    padding: 0.9rem 1.15rem;
    color: var(--dv-danger);
    font-size: 0.88rem;
    line-height: 1.4;
    text-align: left;
    background: linear-gradient(180deg, rgba(40, 22, 22, 0.92), rgba(24, 14, 14, 0.92));
    border: 1px solid var(--dv-border);
    border-radius: var(--ds-radius-lg);
    box-shadow: 0 14px 40px rgba(0, 0, 0, 0.5);
}
.dicom-error-card .ti { color: var(--dv-danger); flex: 0 0 auto; }

/* Overlays PACS en las esquinas */
.dicom-ov {
    position: absolute;
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-size: 1rem;
    line-height: 1.45;
    color: var(--dv-ink-3);
    text-shadow: 0 1px 2px var(--dv-void);
    pointer-events: none;
}
.dicom-ov-tl { top: 0.6rem; left: 0.7rem; color: var(--dv-ink); max-width: 45%; }
.dicom-ov-tr { top: 0.6rem; right: 0.7rem; text-align: right; max-width: 45%; }
.dicom-ov-bl { bottom: 0.6rem; left: 0.7rem; }
.dicom-ov-br { bottom: 0.6rem; right: 0.7rem; text-align: right; }
.dicom-ov b { color: var(--dv-ink); font-weight: 600; }
.dicom-ov .dicom-ov-dim { color: var(--dv-ink-4); }
/* Toggle de anotaciones en imagen */
.dicom-pro-viewports.hide-ov .dicom-ov { display: none; }

/* ── Selector de Disposición (1×1 · 1×2 · 1×3 · 2×2) ───────────────────── */
.dicom-layouts { display: inline-flex; gap: 2px; background: var(--dv-raise); border-radius: 8px; padding: 2px; }
.dicom-layout {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border: none;
    border-radius: 6px;
    background: transparent;
    color: var(--dv-ink-3);
    cursor: pointer;
}
.dicom-layout .ti { font-size: 1.2rem !important; }
.dicom-layout:hover { background: var(--dv-border); color: var(--dv-ink); }
.dicom-layout.is-active { background: var(--dv-accent-fill); color: var(--dv-ink); }

/* ── Dropdown de Nivel predefinido (presets W/L) ───────────────────────── */
.dicom-preset-select {
    height: 2rem;
    max-width: 9.5rem;
    background: var(--dv-raise);
    color: var(--dv-ink);
    border: 1px solid var(--dv-border);
    border-radius: 8px;
    padding: 0 0.5rem;
    font-size: 0.85rem;
    cursor: pointer;
}
.dicom-preset-select:hover { border-color: var(--dv-border-strong); }
.dicom-preset-select:focus { outline: none; border-color: var(--dv-accent); }
.dicom-preset-select option { background: var(--dv-raise); color: var(--dv-ink); }

/* Footer: scrubber de serie + cine */
.dicom-pro-foot {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    height: 3.4rem;
    flex-shrink: 0;
    padding: 0 1rem;
    background: var(--dv-chrome);
    border-top: 1px solid var(--dv-border);
}
.dicom-pro-foot .btn-icon {
    background: transparent !important;
    border-color: var(--dv-border) !important;
    color: var(--dv-ink-3) !important;
}
.dicom-pro-foot .btn-icon:hover { background: var(--dv-border) !important; color: var(--dv-ink) !important; }
.dicom-pro-foot .btn-icon .ti { font-size: 1.3rem; }
.dicom-pro-slider { flex: 1 1 auto; margin: 0; }
.dicom-pro-count {
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-size: 1rem;
    font-weight: 600;
    color: var(--dv-ink-2);
    white-space: nowrap;
    min-width: 4.5rem;
    text-align: right;
}

/* ════════════════════════════════════════════════════════════════════════
   VISOR DICOM — CAPA MÓVIL / TÁCTIL (≤768px)
   Barra de modo de 1 dedo (Ventana/Cortes/Zoom/Mover) + paneles laterales
   convertidos en hojas inferiores (bottom sheets) que NO aplastan la imagen.
   El motor cornerstone no se toca; esto es solo layout + objetivos táctiles.
   ════════════════════════════════════════════════════════════════════════ */
.dicom-mbar { display: none; } /* solo móvil */

@media (max-width: 768px) {
    /* ── Barra superior compacta (con safe-area del notch) ── */
    .dicom-pro-bar {
        height: calc(3rem + var(--ds-safe-top));
        padding: var(--ds-safe-top) 0.5rem 0;
        gap: 0.5rem;
    }
    .dicom-pro-logo,
    .dicom-pro-sub { display: none; }
    .dicom-pro-title { min-width: 0; font-size: 0.92rem; }
    #dicom-pro-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .dicom-pro-tools { display: none; } /* el toggle de Ajustes vive en la barra de modo */
    .dicom-pro-close { width: 2.5rem; height: 2.5rem; flex: 0 0 auto; }

    /* ── Paneles laterales → hojas inferiores que se deslizan sobre la imagen ── */
    .dicom-seq,
    .dicom-ctrl {
        position: absolute;
        left: 0;
        right: 0;
        bottom: 0;
        top: auto;
        width: 100% !important;
        flex-basis: auto !important;
        max-height: 74%;
        border: 0;
        border-top: 1px solid var(--dv-border);
        border-radius: var(--ds-radius-xl) var(--ds-radius-xl) 0 0;
        z-index: 40;
        box-shadow: 0 -14px 44px rgba(0, 0, 0, 0.55);
        animation: dicomSheetUp 0.24s cubic-bezier(0.22, 1, 0.36, 1);
        padding-bottom: var(--ds-safe-bottom);
    }
    /* Asa de arrastre visual en la cabecera de cada hoja */
    .dicom-seq-head,
    .dicom-ctrl-head { position: relative; padding-top: 1.1rem; }
    .dicom-seq-head::before,
    .dicom-ctrl-head::before {
        content: '';
        position: absolute;
        top: 0.4rem;
        left: 50%;
        transform: translateX(-50%);
        width: 2.4rem;
        height: 0.28rem;
        border-radius: 999px;
        background: var(--dv-raise);
    }
    @keyframes dicomSheetUp {
        from { transform: translateY(100%); }
        to { transform: translateY(0); }
    }
    .dicom-seq-open { display: none !important; } /* se abre desde la barra de modo */

    /* Secuencias como grid de miniaturas táctiles */
    .dicom-seq-list {
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr));
        gap: 0.5rem;
        max-height: none;
    }
    .dicom-seq-item { flex-direction: column; align-items: stretch; text-align: left; }
    .dicom-seq-thumb { width: 100%; height: 5.5rem; }
    .dicom-seq-add { opacity: 1 !important; }

    /* Metadatos DICOM a pantalla completa */
    .dicom-meta {
        position: absolute;
        inset: 0;
        width: 100%;
        z-index: 45;
        padding-bottom: var(--ds-safe-bottom);
    }

    /* ── Pie (scrubber de cortes) más grande y agarrable ── */
    .dicom-pro-foot {
        height: 3.3rem;
        gap: 0.4rem;
        padding: 0 0.6rem;
    }
    .dicom-pro-foot .btn-icon { width: 2.6rem; height: 2.6rem; }
    .dicom-pro-slider { height: 2.4rem; }
    .dicom-pro-count { font-size: 0.86rem; min-width: 3.6rem; }

    /* ── Barra de MODO de 1 dedo (qué hace el dedo al arrastrar) ──
       Espeja la barra inferior canónica del DS (.mobile-bottomnav): mismos
       flex/tipografía/altura/safe-area; solo cambia la paleta a la superficie
       oscura del visor (--dv-*). El estado activo usa el mismo lima que toda
       herramienta activa del visor (.dicom-tool.is-active), por color —no relleno. */
    .dicom-mbar {
        display: flex;
        align-items: stretch;
        justify-content: space-around;
        flex: 0 0 auto;
        height: calc(var(--ds-bottomnav-h) + var(--ds-safe-bottom));
        padding-bottom: var(--ds-safe-bottom);
        background: var(--dv-chrome);
        border-top: 1px solid var(--dv-border);
    }
    .dicom-mbar-btn {
        flex: 1 1 0;
        min-width: 0;
        width: auto;
        height: auto;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 2px;
        padding: 0.3rem 0.2rem;
        border: 0;
        border-radius: 0;
        background: transparent;
        color: var(--dv-ink-4);
        font-size: 0.72rem;
        font-weight: 550;
        line-height: 1;
        cursor: pointer;
        -webkit-tap-highlight-color: transparent;
        transition: color 0.12s ease;
    }
    .dicom-mbar-btn .ti { font-size: 1.2rem !important; }
    .dicom-mbar-btn span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
    .dicom-mbar-btn:hover,
    .dicom-mbar-btn:active { background: transparent; color: var(--dv-ink); }
    .dicom-mbar .dicom-mbar-btn.is-active { background: transparent; color: var(--dv-lime); }
}

/* Contador de cortes sobre el thumb de una serie en el grid */
.study-thumb-icon { position: relative; }
.study-thumb-count {
    position: absolute;
    top: 0.5rem;
    right: 0.5rem;
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--ds-bg);
    background: var(--ds-ink);
    padding: 0.1rem 0.4rem;
    border-radius: var(--ds-radius-sm);
}

/* ─── Patient banner (legacy — superseded por patient record header) ─── */
.patient-banner {
    display: flex;
    align-items: center;
    gap: 1.25rem;
    padding: 1rem 1.25rem;
    background: var(--ds-surface);
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-lg);
}
.patient-banner-avatar {
    width: 3rem;
    height: 3rem;
    border-radius: 50%;
    background: var(--ds-accent-violet-bg);
    color: var(--ds-accent-violet);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-family: var(--ds-font-sans);
    font-weight: 600;
    font-size: 1rem;
    letter-spacing: -0.02em;
    flex-shrink: 0;
    text-transform: uppercase;
}
.patient-banner-main {
    flex: 1 1 auto;
    min-width: 0;
}
.patient-banner-name {
    font-size: 1rem;
    font-weight: 600;
    color: var(--ds-ink);
    letter-spacing: -0.02em;
    line-height: 1.2;
    margin: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.patient-banner-meta {
    color: var(--ds-ink-4);
    font-size: 0.85rem;
    margin-top: 0.15rem;
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    letter-spacing: -0.005em;
}
.patient-banner-stats {
    display: flex;
    gap: 1.5rem;
    flex-wrap: wrap;
}
.patient-banner-stat {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    min-width: 0;
}
.patient-banner-stat .stat-label {
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--ds-ink-4);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.patient-banner-stat .stat-value {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--ds-ink);
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    letter-spacing: -0.01em;
}
.patient-banner-stat .stat-value.text-only {
    font-family: var(--ds-font-sans);
}
.patient-banner-actions {
    display: flex;
    gap: 0.4rem;
    flex-shrink: 0;
}

/* ─── Vital signs grid ───────────────────────────────────────────────── */
.vital-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: 0.65rem;
}
.vital-card {
    background: var(--ds-surface);
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-md);
    padding: 0.7rem 0.85rem;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    transition: border-color 0.12s ease;
}
.vital-card:focus-within {
    border-color: var(--ds-ink);
    box-shadow: 0 0 0 3px rgba(10, 10, 10, 0.05);
}
.vital-card-label {
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--ds-ink-4);
    letter-spacing: -0.005em;
    text-transform: none;
    margin: 0;
}
.vital-card-input-row {
    display: flex;
    align-items: baseline;
    gap: 0.35rem;
}
.vital-card-input {
    flex: 1 1 auto;
    border: 0 !important;
    background: transparent !important;
    padding: 0 !important;
    font-family: var(--ds-font-mono) !important;
    font-feature-settings: 'tnum';
    font-size: 1.15rem !important;
    font-weight: 500 !important;
    color: var(--ds-ink) !important;
    letter-spacing: -0.025em;
    width: 100%;
    min-height: 0 !important;
    outline: none !important;
    box-shadow: none !important;
}
.vital-card-input::placeholder {
    color: var(--ds-ink-5);
    font-weight: 400;
}
.vital-card-input:focus {
    border: 0 !important;
    box-shadow: none !important;
    background: transparent !important;
}
.vital-card-input[disabled],
.vital-card-input[readonly] {
    color: var(--ds-ink-3) !important;
    background: transparent !important;
}
.vital-card-unit {
    font-family: var(--ds-font-sans);
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--ds-ink-4);
    flex-shrink: 0;
    letter-spacing: -0.005em;
}

/* ─── Historia clínica: barra de acción sticky + nav de secciones ──────
   El form es largo; la barra mantiene título, autoría y Guardar siempre a la
   vista, y la nav (chips con scrollspy) permite saltar entre secciones. */
/* UN solo contenedor sticky para barra + nav (evita el desfase/corte de tener
   dos sticky con offsets distintos). El fondo enmascara el contenido detrás. */
.hc-sticky {
    position: sticky;
    top: var(--ds-header-h);
    z-index: 20;
    background: var(--ds-bg);
    margin-bottom: 1rem;
}
.hc-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.85rem 0 0.7rem;
    border-bottom: 1px solid var(--ds-border-soft);
}
.hc-bar-title { font-size: 1.4rem; font-weight: 650; letter-spacing: -0.02em; margin: 0; line-height: 1.15; }
.hc-bar-meta {
    margin: 0.15rem 0 0;
    font-family: var(--ds-font-mono);
    font-size: 0.72rem;
    color: var(--ds-ink-4);
    letter-spacing: 0.01em;
    display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap;
}
.hc-bar-meta .hc-meta-dot { width: 5px; height: 5px; border-radius: 50%; background: var(--ds-ink-5); flex: 0 0 auto; }
.hc-bar-meta b { color: var(--ds-ink-2); font-weight: 550; text-transform: capitalize; }

/* Fila de navegación: flechas a los lados + chips scrolleables en medio */
.hc-nav-wrap {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    border-bottom: 1px solid var(--ds-border-soft);
}
.hc-nav {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    gap: 0.4rem;
    overflow-x: auto;
    padding: 0.6rem 0;
    scrollbar-width: none;
    scroll-behavior: smooth;
}
.hc-nav::-webkit-scrollbar { display: none; }
.hc-nav a {
    flex: 0 0 auto;
    display: inline-flex; align-items: center; gap: 0.4rem;
    padding: 0.4rem 0.85rem;
    border-radius: 999px;
    font-size: 0.86rem;
    font-weight: 500;
    color: var(--ds-ink-4);
    text-decoration: none !important;
    white-space: nowrap;
    transition: background-color 0.14s ease, color 0.14s ease;
}
.hc-nav a .ti { font-size: 1rem; }
.hc-nav a:hover { background: var(--ds-surface-muted); color: var(--ds-ink-2); }
.hc-nav a.is-active { background: var(--ds-surface-active); color: var(--ds-ink); }

/* Flechas para recorrer las secciones */
.hc-nav-arrow {
    flex: 0 0 auto;
    width: 1.9rem; height: 1.9rem;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--ds-border);
    background: var(--ds-surface);
    color: var(--ds-ink-3);
    border-radius: 999px;
    cursor: pointer;
    transition: background-color 0.14s ease, color 0.14s ease, border-color 0.14s ease, opacity 0.14s ease;
}
.hc-nav-arrow .ti { font-size: 1rem; }
.hc-nav-arrow:hover { background: var(--ds-surface-active); color: var(--ds-ink); border-color: var(--ds-border-strong); }
.hc-nav-arrow[hidden] { display: none; }
/* offset de anclaje para que la sección no quede bajo las barras sticky */
.clinical-form .section-title { scroll-margin-top: calc(var(--ds-header-h) + 7rem); }

/* Modo VISTA (read-only) de la nota: mismo lienzo que editar pero nada editable —
   se bloquea la interacción del CONTENIDO (no la barra/nav sticky). */
.ev-form.is-readonly .ev-section { pointer-events: none; }
.ev-form.is-readonly .ev-section img,
.ev-form.is-readonly .ev-section .ne-image { pointer-events: auto; cursor: zoom-in; }
.ev-form.is-readonly :disabled { opacity: 1; }
/* En vista no se sube ni se borra: se ocultan zonas de subida y los botones de borrar. */
.ev-form.is-readonly .ev-evidence-grid,
.ev-form.is-readonly .remove-image,
.ev-form.is-readonly .delete-diagnostico { display: none !important; }
/* Estado vacío de evidencia en modo vista (cuando la nota no tiene fotos). */
.ev-empty-evidence {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 1.1rem 1.25rem;
    border: 1px dashed var(--ds-border-strong);
    border-radius: var(--ds-radius-lg);
    color: var(--ds-ink-4);
    font-size: 0.9rem;
}
.ev-empty-evidence .ti { font-size: 1.15rem; color: var(--ds-ink-5); }

/* ── Modal "Programar estudio": typeahead de paciente + nota de catálogo ──── */
.sch-typeahead-ico {
    position: absolute;
    right: 0;
    top: 0;
    bottom: 0;
    width: 2.2rem;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--ds-ink-4);
    pointer-events: none;
}
.sch-typeahead .form-control { padding-right: 2.2rem; }
.sch-typeahead-menu {
    position: absolute;
    z-index: 1080;
    left: 0;
    right: 0;
    top: calc(100% + 4px);
    background: var(--ds-surface);
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-lg);
    box-shadow: var(--ds-shadow-md);
    max-height: 16rem;
    overflow-y: auto;
    padding: 4px;
}
.sch-ta-item {
    display: flex;
    flex-direction: column;
    gap: 1px;
    width: 100%;
    text-align: left;
    border: 0;
    background: transparent;
    padding: 0.45rem 0.6rem;
    border-radius: var(--ds-radius-md);
    cursor: pointer;
}
.sch-ta-item:hover { background: var(--ds-surface-muted); }
.sch-ta-name { font-weight: 500; text-transform: capitalize; }
.sch-ta-meta { font-family: var(--ds-font-mono); font-size: 0.72rem; color: var(--ds-ink-4); }
.sch-ta-empty { padding: 0.6rem; color: var(--ds-ink-4); font-size: 0.85rem; text-align: center; }
#sch-patient-picked { display: inline-flex; align-items: center; gap: 0.3rem; color: var(--ds-success); margin-top: 0.3rem; }

.sch-study-note { margin-top: 0.5rem; display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center; }
.sch-chip {
    display: inline-flex; align-items: center; gap: 0.25rem;
    font-size: 0.78rem; padding: 0.2rem 0.55rem; border-radius: 999px;
    background: var(--ds-surface-soft); color: var(--ds-ink-3);
}
.sch-chip-warn { background: var(--ds-warning-bg); color: var(--ds-warning); }
.sch-prep { display: inline-flex; align-items: center; gap: 0.3rem; font-size: 0.82rem; color: var(--ds-ink-3); }

/* ─── Section title (inside long clinical forms) ────────────────────── */
.section-title {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    margin-top: 1.5rem;
    margin-bottom: 0.85rem;
    padding-bottom: 0.5rem;
    border-bottom: 1px solid var(--ds-border-soft);
}
.section-title:first-child { margin-top: 0; }
.section-title h3,
.section-title h4 {
    font-size: 0.875rem !important;
    font-weight: 600 !important;
    color: var(--ds-ink) !important;
    margin: 0 !important;
    letter-spacing: -0.018em;
}
.section-title .section-icon {
    width: 1.6rem;
    height: 1.6rem;
    background: var(--ds-surface-soft);
    color: var(--ds-ink-3);
    border-radius: var(--ds-radius-sm);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.section-title .section-icon .ti {
    font-size: 0.95rem !important;
}
.section-title .section-hint {
    color: var(--ds-ink-4);
    font-size: 0.85rem;
    font-weight: 400;
    margin-left: auto;
}

/* ─── Heredity row (compact disease + parentesco) ───────────────────── */
.heredity-row {
    display: grid;
    grid-template-columns: minmax(140px, auto) 1fr;
    align-items: center;
    gap: 0.85rem;
    padding: 0.45rem 0;
    border-bottom: 1px dashed var(--ds-border-soft);
}
.heredity-row:last-child { border-bottom: 0; }
.heredity-row .form-check { margin: 0; padding-left: 1.6rem; }
.heredity-row .form-check-label {
    font-size: 1rem;
    color: var(--ds-ink-2);
    font-weight: 500;
}
.heredity-row .ts-control { background: var(--ds-surface-muted) !important; }

/* ─── SOAP sections (Evolution notes structure) ─────────────────────── */
.soap-section {
    box-shadow: inset 2px 0 0 var(--ds-border); /* DS regla dura #3: acento lateral por inset box-shadow, nunca border-left */
    padding-left: 0.85rem;
    margin-bottom: 1.25rem;
}
.soap-section.active { box-shadow: inset 2px 0 0 var(--ds-ink); }
.soap-section-label {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--ds-ink-3);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin-bottom: 0.3rem;
}
.soap-section-label .ti {
    color: var(--ds-ink-4);
    font-size: 0.85rem !important;
    margin-right: 0.3rem;
}

/* ─── Clinical form scope tweaks ────────────────────────────────────── */
.clinical-form .form-label {
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--ds-ink-3);
}
.clinical-form .form-control,
.clinical-form .form-select {
    background: var(--ds-surface);
}
.clinical-form .form-check-input {
    margin-top: 0.2rem;
}

/* ─── Evolution notes table — clinical record entries ───────────────── */
#evolution-notes-table tbody tr { cursor: pointer; }
#evolution-notes-table thead th { vertical-align: middle; }

/* Date column: stacked date over time */
.evo-date {
    line-height: 1.3;
}
.evo-date-primary {
    font-size: 1rem;
    font-weight: 600;
    color: var(--ds-ink);
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    letter-spacing: -0.01em;
    text-transform: capitalize;
}
.evo-date-secondary {
    font-size: 0.85rem;
    color: var(--ds-ink-4);
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    margin-top: 0.1rem;
}
/* Autoría de la nota (quién la elaboró) — NOM-004/024 */
.evo-date-author {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    margin-top: 0.3rem;
    font-size: 0.78rem;
    color: var(--ds-ink-4);
    text-transform: capitalize;
    max-width: 9rem;
}
.evo-date-author .ti { font-size: 0.85rem; color: var(--ds-ink-5); flex: 0 0 auto; }
.evo-date-author span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Consultation column: diagnostic tags + treatment preview */
.evo-consult-cell {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    max-width: 540px;
}
.evo-diagnostics {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    align-items: center;
}
.evo-diag-tag {
    display: inline-flex;
    align-items: center;
    background: var(--ds-surface-soft);
    border: 1px solid var(--ds-border);
    color: var(--ds-ink-2);
    font-size: 0.85rem;
    font-weight: 500;
    padding: 0.18rem 0.5rem;
    border-radius: var(--ds-radius-sm);
    line-height: 1.3;
    letter-spacing: -0.005em;
    max-width: 220px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.evo-diag-more {
    display: inline-flex;
    align-items: center;
    background: transparent;
    color: var(--ds-ink-4);
    font-size: 0.85rem;
    font-weight: 500;
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    padding: 0.18rem 0.4rem;
}
.evo-diag-empty {
    color: var(--ds-ink-4);
    font-size: 0.85rem;
    font-style: italic;
}
.evo-treatment {
    color: var(--ds-ink-3);
    font-size: 0.85rem;
    line-height: 1.45;
    white-space: normal;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}

/* Status column: stacked status pills */
.evo-status-stack {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    align-items: flex-start;
}
.evo-status {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    font-size: 0.85rem;
    font-weight: 500;
    padding: 0.18rem 0.5rem;
    border-radius: var(--ds-radius-sm);
    line-height: 1.3;
    letter-spacing: -0.005em;
    white-space: nowrap;
}
.evo-status .ti { font-size: 0.85rem !important; line-height: 1; }
.evo-status-finished {
    background: var(--ds-success-bg);
    color: var(--ds-success);
}
.evo-status-pending {
    background: var(--ds-surface-soft);
    color: var(--ds-ink-3);
    border: 1px solid var(--ds-border);
}
.evo-status-controlled {
    background: var(--ds-warning-bg);
    color: var(--ds-warning);
}

/* Media count: photo icon + tabular-nums count */
.evo-media-count {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    color: var(--ds-ink-3);
    font-size: 0.85rem;
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-weight: 500;
}
.evo-media-count .ti {
    color: var(--ds-ink-4);
    font-size: 0.95rem !important;
}

/* Receta column: medication count + revenue generated (dispensed) */
.evo-receta-cell {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    align-items: flex-start;
}
.evo-receta-count {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    color: var(--ds-ink-2);
    font-size: 0.85rem;
    font-weight: 500;
    white-space: nowrap;
}
.evo-receta-count .ti { color: var(--ds-ink-4); font-size: 0.95rem !important; }
.evo-receta-money {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    color: var(--ds-success);
    font-size: 0.82rem;
    font-weight: 600;
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    white-space: nowrap;
}
.evo-receta-money .ti { font-size: 0.9rem !important; line-height: 1; }
.evo-receta-money--none {
    color: var(--ds-ink-4);
    font-weight: 500;
    font-family: inherit;
}

/* Top-aligned cells in the evolution table for better timeline scanning */
#evolution-notes-table tbody td.align-top {
    vertical-align: top !important;
    padding-top: 0.85rem !important;
}

/* ─── Evolution note display modal — clinical record reader ─────────── */
.evo-modal-header {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    padding: 0.85rem var(--ds-content-padding-x);
    border-bottom: 1px solid var(--ds-border);
    background: var(--ds-surface);
}
.evo-modal-header .evo-modal-icon {
    width: 2.25rem;
    height: 2.25rem;
    border-radius: var(--ds-radius-md);
    background: var(--ds-surface-active);
    color: var(--ds-ink-2);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.evo-modal-header .evo-modal-icon .ti { font-size: 1.05rem !important; }
.evo-modal-header .evo-modal-titles { flex: 1 1 auto; min-width: 0; }
.evo-modal-header .evo-modal-title {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--ds-ink);
    line-height: 1.2;
    letter-spacing: -0.018em;
    margin: 0;
}
.evo-modal-header .evo-modal-subtitle {
    color: var(--ds-ink-4);
    font-size: 0.85rem;
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    margin-top: 0.15rem;
}

.evo-modal-body { padding: var(--ds-content-padding-x); background: var(--ds-bg); }

.evo-block { margin-bottom: 1.5rem; }
.evo-block:last-child { margin-bottom: 0; }
.evo-block-title {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--ds-ink-3);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin-bottom: 0.65rem;
}
.evo-block-title .ti {
    color: var(--ds-ink-4);
    font-size: 0.95rem !important;
}
.evo-block-content {
    background: var(--ds-surface);
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-md);
    padding: 0.85rem 1rem;
    color: var(--ds-ink-2);
    font-size: 1rem;
    line-height: 1.55;
    white-space: pre-wrap;
    word-break: break-word;
}
.evo-block-content.is-empty {
    color: var(--ds-ink-5);
    font-style: italic;
}
.evo-block-actions { display: flex; gap: 0.4rem; align-items: center; }
.evo-block-pill {
    margin-left: auto;
    background: var(--ds-surface-soft);
    color: var(--ds-ink-3);
    font-size: 0.85rem;
    font-weight: 500;
    padding: 0.18rem 0.45rem;
    border-radius: var(--ds-radius-sm);
    letter-spacing: -0.005em;
    text-transform: none;
}

/* Vital grid inside the modal — fixed 4 columns × 2 rows (8 vitals total)
   for visual symmetry. Collapses gracefully on narrower viewports. */
.evo-vital-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 0.5rem;
}
@media (max-width: 768px) {
    .evo-vital-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 420px) {
    .evo-vital-grid { grid-template-columns: 1fr; }
}
.evo-vital-cell {
    background: var(--ds-surface);
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-md);
    padding: 0.65rem 0.85rem;
}
.evo-vital-label {
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--ds-ink-4);
    margin-bottom: 0.15rem;
}
.evo-vital-value {
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-size: 1.05rem;
    font-weight: 500;
    color: var(--ds-ink);
    letter-spacing: -0.02em;
    line-height: 1.2;
}
.evo-vital-value .evo-vital-unit {
    font-family: var(--ds-font-sans);
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--ds-ink-4);
    margin-left: 0.2rem;
}
.evo-vital-value.is-empty {
    color: var(--ds-ink-5);
    font-weight: 400;
}

/* Diagnostics table inside the modal */
.evo-dx-table {
    width: 100%;
    border-collapse: collapse;
    background: var(--ds-surface);
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-md);
    overflow: hidden;
}
.evo-dx-table th,
.evo-dx-table td {
    padding: 0.55rem 0.85rem;
    text-align: left;
    border-bottom: 1px solid var(--ds-border-soft);
    font-size: 0.85rem;
    vertical-align: top;
}
.evo-dx-table tr:last-child td { border-bottom: 0; }
.evo-dx-table th {
    background: var(--ds-surface-muted);
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--ds-ink-4);
    letter-spacing: -0.005em;
}
.evo-dx-table td.evo-dx-key {
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    color: var(--ds-ink-3);
    font-size: 0.85rem;
    width: 6rem;
    white-space: nowrap;
}
.evo-dx-table td.evo-dx-name { color: var(--ds-ink); font-weight: 500; }
.evo-dx-table td.evo-dx-obs { color: var(--ds-ink-3); }

/* Treatment block — emphasizes controlled flag */
.evo-tx-flag {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.85rem;
    font-weight: 500;
    padding: 0.2rem 0.5rem;
    border-radius: var(--ds-radius-sm);
    line-height: 1.3;
}
.evo-tx-flag.is-controlled {
    background: var(--ds-warning-bg);
    color: var(--ds-warning);
}
.evo-tx-flag.is-uncontrolled {
    background: var(--ds-success-bg);
    color: var(--ds-success);
}
.evo-tx-flag .ti { font-size: 0.85rem !important; }

/* Treatment sub-card — clean label + body, no auto-margin nonsense */
.evo-tx-card {
    background: var(--ds-surface);
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-md);
    padding: 0.7rem 0.85rem;
    margin-bottom: 0.5rem;
}
.evo-tx-card:last-child { margin-bottom: 0; }
.evo-tx-card-label {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.85rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    padding: 0.18rem 0.5rem;
    border-radius: var(--ds-radius-sm);
    margin-bottom: 0.5rem;
    line-height: 1.3;
}
.evo-tx-card-label.is-controlled {
    background: var(--ds-warning-bg);
    color: var(--ds-warning);
}
.evo-tx-card-label.is-uncontrolled {
    background: var(--ds-surface-soft);
    color: var(--ds-ink-3);
}
.evo-tx-card-text {
    color: var(--ds-ink-2);
    font-size: 1rem;
    line-height: 1.55;
    white-space: pre-wrap;
    word-break: break-word;
}

/* Photo gallery inside modal */
.evo-gallery {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
    gap: 0.35rem;
}
.evo-gallery a {
    display: block;
    aspect-ratio: 1 / 1;
    border-radius: var(--ds-radius-md);
    overflow: hidden;
    background: var(--ds-surface-soft, #f4f5f7);
    cursor: zoom-in;
    transition: transform 0.18s ease;
}
.evo-gallery a:hover { transform: translateY(-1px); }
.evo-gallery img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform 0.18s ease;
}
.evo-gallery a:hover img { transform: scale(1.04); }
.evo-gallery-empty {
    color: var(--ds-ink-5);
    font-size: 0.85rem;
    font-style: italic;
    text-align: center;
    padding: 1rem;
    border: 1px dashed var(--ds-border);
    border-radius: var(--ds-radius-md);
    background: var(--ds-surface-muted);
}
.evo-gallery-loading {
    display: flex;
    justify-content: center;
    padding: 1.5rem;
}

.evo-modal-footer {
    padding: 0.85rem var(--ds-content-padding-x);
    border-top: 1px solid var(--ds-border);
    background: var(--ds-surface);
    display: flex;
    gap: 0.4rem;
    justify-content: flex-end;
}

/* -------------------------------------------------------------------------
   14. Mono in product/POS specific contexts — Caja totals, prices, MXN,
       SKU columns, ticket numbers, stock counts.
   ------------------------------------------------------------------------- */
/* Anything that ends in "MXN" / "USD" or starts with "$" anywhere in the app */
.cart-total,
.cart-subtotal,
.cart-tax,
.cart-discount,
[id*='subtotal'],
[id*='total'],
[id*='-amount'],
[id*='-price'],
[id*='-mxn'],
[class*='-amount'],
[class*='-price'],
[class*='-total'],
[data-amount],
[data-price],
[data-total],
[data-currency] {
    font-family: var(--ds-font-mono) !important;
    font-feature-settings: 'tnum', 'zero';
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
}

/* Los matchers de montos de arriba usan substrings (`[id*="-price"]`,
   `[id*="total"]`…) que por accidente capturan CONTENEDORES cuyo id/clase
   contiene esas palabras (ej. #change-price-modal) y volvían mono TODO el
   diálogo por herencia. Re-anclamos los modales que matchean a sans; los
   valores reales siguen mono porque cada hoja matchea su propia regla
   (montos `-total`, horas `.order-time`, chips `.badge-mono`, overlines). */
.modal[id*='subtotal'],
.modal[id*='total'],
.modal[id*='-amount'],
.modal[id*='-price'],
.modal[id*='-mxn'],
.modal[class*='-amount'],
.modal[class*='-price'],
.modal[class*='-total'] {
    font-family: var(--ds-font-sans) !important;
}

/* Inputs masked as currency (imask, etc.) */
input[data-mask*='9'],
input[data-mask*='money'],
input[data-imask],
input.money,
input.currency,
input.tel,
input.phone {
    font-family: var(--ds-font-mono) !important;
    font-variant-numeric: tabular-nums;
}

/* Pagination + datatables info already mono via the rule above; ensure size */
.dataTables_info,
.dataTables_length,
.dataTables_length label,
.dataTables_filter label {
    font-size: 0.85rem;
    color: var(--ds-ink-4);
}
.dataTables_length label,
.dataTables_filter label { font-family: var(--ds-font-sans); }

/* Tom-select option: numeric-looking values (SKU, codes) detected via class */
.ts-dropdown .option .sku,
.ts-dropdown .option .code,
.ts-dropdown .option .id {
    font-family: var(--ds-font-mono);
    font-size: 0.85rem;
    color: var(--ds-ink-4);
    margin-left: 0.4rem;
    font-feature-settings: 'tnum';
}

/* =========================================================================
   15. SEARCH + FILTERS — homologation across all listing views
   --------------------------------------------------------------------------
   The codebase mixes 4 patterns for filter toolbars. This section forces
   them all into one coherent look without editing 30+ EJS files.
   ========================================================================= */

/* ---- Tabler's .input-icon (search input with icon on the right) ---- */
.input-icon {
    position: relative;
    display: flex;
    align-items: stretch;
}
.input-icon .form-control {
    padding-right: 2.25rem !important;
}
.input-icon .input-icon-addon {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    pointer-events: none;
    color: var(--ds-ink-5);
    font-size: 0.95rem;
}
.input-icon .input-icon-addon .ti {
    font-size: 1rem;
}

/* ---- "Github" colour aliases used everywhere → grafito grade ---- */
.btn-github {
    background-color: var(--ds-ink) !important;
    border-color: var(--ds-ink) !important;
    color: var(--ds-bg) !important;
}
.btn-github:hover {
    background-color: var(--ds-ink-2) !important;
    border-color: var(--ds-ink-2) !important;
}
.bg-github {
    background-color: var(--ds-ink) !important;
    color: var(--ds-bg) !important;
}
.bg-github-lt {
    background-color: var(--ds-surface-muted) !important;
    color: var(--ds-ink-2) !important;
}

/* ---- Filter toggle button: outline neutral, never primary ---- */
.btn[data-bs-target*='filter'],
.btn[data-bs-target*='Filter'],
.btn.btn-filter,
.btn-github.btn-icon[data-bs-target*='filter'],
.btn-github.btn-icon[data-bs-target*='Filter'] {
    background-color: var(--ds-surface) !important;
    border: 1px solid var(--ds-border-strong) !important;
    color: var(--ds-ink-2) !important;
}
.btn[data-bs-target*='filter']:hover,
.btn[data-bs-target*='Filter']:hover,
.btn.btn-filter:hover,
.btn-github.btn-icon[data-bs-target*='filter']:hover {
    background-color: var(--ds-surface-muted) !important;
    color: var(--ds-ink) !important;
    border-color: var(--ds-border-strong) !important;
}
.btn[data-bs-target*='filter'][aria-expanded='true'],
.btn[data-bs-target*='Filter'][aria-expanded='true'] {
    background-color: var(--ds-surface-active) !important;
    color: var(--ds-ink) !important;
}

/* ---- <small> used as filter-field label (legacy markup `<small for>`) ---- */
small[for],
.collapse small[for],
.collapse .card-body small,
.collapse .row small {
    display: block;
    font-size: 0.85rem !important;
    font-weight: 500;
    color: var(--ds-ink-2);
    margin-bottom: 0.3rem;
    letter-spacing: -0.005em;
    line-height: 1.3;
}

/* ---- Filter collapse panel: clean recessed surface ---- */
.collapse[id*='filter'] > .card,
.collapse[id*='Filter'] > .card,
.collapse[id*='filter'] .card,
.collapse[id*='Filter'] .card {
    background-color: var(--ds-surface-muted) !important;
    border: 1px solid var(--ds-border) !important;
    box-shadow: none !important;
}
.collapse[id*='filter'] .card-body,
.collapse[id*='Filter'] .card-body {
    padding: 0.85rem !important;
}
.collapse[id*='filter'] .row,
.collapse[id*='Filter'] .row {
    --bs-gutter-x: 0.65rem;
    --bs-gutter-y: 0.65rem;
}

/* ---- Search-row: input + filter button. Common across views ---- */
.search-bar,
.d-flex.gap-2:has(> .form-control + .btn-icon),
.d-flex.gap-2:has(> .input-icon + .btn-icon) {
    align-items: stretch !important;
}
.search-bar .form-control,
.search-bar .input-icon {
    flex: 1 1 auto;
    min-width: 0;
}
.search-bar .btn-icon,
.search-bar .btn {
    flex-shrink: 0;
}

/* ---- Results-info row (under filters): coherent muted typography ---- */
.results-info,
.results-count,
.dataTables_info {
    color: var(--ds-ink-4);
    font-size: 0.85rem;
    font-family: var(--ds-font-sans);
}
.results-info .count,
.results-count .count,
.dataTables_info .count {
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    color: var(--ds-ink-2);
}

/* =========================================================================
   16. INLINE ROW ACTIONS — ghost icons with hover-revealed semantic color
   --------------------------------------------------------------------------
   Across the codebase 7+ button styles compete in the last cell of tables
   (solid red, solid blue, outline danger, github black, plain icon, dropdown).
   Forcing them all into one consistent ghost-icon shape, with the semantic
   color appearing only on hover. Action lives on the right of the row.
   ========================================================================= */

/* Last column = actions: right-aligned, never wraps */
.table tbody td:last-child:has(.btn),
.table tbody td.actions,
.table tbody td.row-actions {
    text-align: right;
    white-space: nowrap;
    width: 1%;
}

/* Reset every flavour of action button down to a neutral icon ghost */
.table tbody td .btn,
.table tbody td .btn-icon,
.table tbody td .btn-sm,
.table tbody td a.btn,
.table tbody td button.btn {
    background-color: transparent !important;
    background-image: none !important;
    border: 1px solid transparent !important;
    color: var(--ds-ink-4) !important;
    box-shadow: none !important;
    padding: 0.3rem !important;
    min-width: 1.85rem;
    height: 1.85rem;
    border-radius: var(--ds-radius-sm) !important;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background-color 0.12s ease, color 0.12s ease;
}
.table tbody td .btn .ti,
.table tbody td .btn-icon .ti {
    font-size: 0.95rem !important;
    margin: 0 !important;
}
.table tbody td .btn + .btn,
.table tbody td .btn + a.btn,
.table tbody td a.btn + .btn,
.table tbody td a.btn + a.btn {
    margin-left: 0.15rem !important;
}

/* Default hover: subtle gray surface */
.table tbody td .btn:hover,
.table tbody td .btn-icon:hover,
.table tbody td .btn-sm:hover {
    background-color: var(--ds-surface-muted) !important;
    color: var(--ds-ink) !important;
}

/* Semantic hover — red surfaces on destructive / delete-flagged buttons */
.table tbody td .btn-danger:hover,
.table tbody td .btn-outline-danger:hover,
.table tbody td .btn[class*='delete']:hover,
.table tbody td .btn[class*='remove']:hover,
.table tbody td .btn[class*='trash']:hover,
.table tbody td button[id*='delete']:hover,
.table tbody td button[id*='remove']:hover,
.table tbody td a[class*='delete']:hover {
    background-color: var(--ds-danger-bg) !important;
    color: var(--ds-danger) !important;
    border-color: transparent !important;
}

/* Semantic hover — neutral edit (matches the rest of the design, no blue noise) */
.table tbody td .btn-primary:hover,
.table tbody td .btn-outline-primary:hover,
.table tbody td .btn[class*='edit']:hover,
.table tbody td a[class*='edit']:hover,
.table tbody td a[href*='editar']:hover,
.table tbody td a[href*='/edit']:hover {
    background-color: var(--ds-surface-active) !important;
    color: var(--ds-ink) !important;
    border-color: transparent !important;
}

/* Semantic hover — view / detail */
.table tbody td .btn[class*='view']:hover,
.table tbody td .btn[class*='detail']:hover,
.table tbody td a[class*='view']:hover,
.table tbody td .btn[class*='show']:hover {
    background-color: var(--ds-info-bg) !important;
    color: var(--ds-info) !important;
}

/* Semantic hover — download / export */
.table tbody td .btn[class*='download']:hover,
.table tbody td .btn[class*='export']:hover,
.table tbody td a[class*='download']:hover {
    background-color: var(--ds-success-bg) !important;
    color: var(--ds-success) !important;
}

/* Kebab dropdown trigger inside a row */
.table tbody td .btn[data-bs-toggle='dropdown'] .ti-dots,
.table tbody td .btn[data-bs-toggle='dropdown'] .ti-dots-vertical {
    font-size: 1rem !important;
}
.table tbody td .btn[data-bs-toggle='dropdown']:hover {
    background-color: var(--ds-surface-muted) !important;
    color: var(--ds-ink) !important;
}

/* Hide row actions until row is hovered — Notion / Linear style.
   Only on rows that have actions (not all tbody td). */
.table tbody tr td:last-child .btn {
    opacity: 0.55;
    transition: opacity 0.1s ease, background-color 0.12s ease, color 0.12s ease;
}
.table tbody tr:hover td:last-child .btn,
.table tbody tr:focus-within td:last-child .btn {
    opacity: 1;
}

/* =========================================================================
   17. TABLES INSIDE CARDS — coherent edge alignment + tight padding
   ========================================================================= */

/* When a card-body contains nothing but a table/.table-responsive, kill
   the body padding so the table aligns to the card edges. */
.card > .card-body:has(> .table-responsive:only-child),
.card > .card-body:has(> .table:only-child),
.card-body.p-0 {
    padding: 0 !important;
}
/* `px-0` is horizontal-only by Bootstrap convention: zero the side padding so
   the table bleeds to the card edges, but KEEP vertical padding so headers and
   buttons above the table don't end up glued to the card's top edge. */
.card-body.px-0 {
    padding-left: 0 !important;
    padding-right: 0 !important;
}

/* Tabler `card-table`: remove its own border, let card border own it */
.table.card-table {
    border: 0 !important;
    margin-bottom: 0 !important;
}

/* Edge alignment for table cells inside cards is now handled by the global
   .table rule above, which uses --ds-content-padding-x. Keeping this block
   only as a safety net for Tabler `.card-table` first-cell override. */
.card-table tr td:first-child,
.card-table tr th:first-child {
    padding-left: var(--ds-content-padding-x) !important;
}
.card-table tr td:last-child,
.card-table tr th:last-child {
    padding-right: var(--ds-content-padding-x) !important;
}

/* ─── Tabla → tarjetas apiladas en móvil (opt-in: .table-stack-mobile) ───
   Patrón para tablas server-render que NO deben scrollear horizontalmente en
   el teléfono (doble scroll dentro de una página que ya scrollea). En <768px
   cada fila se vuelve una tarjeta: la celda .stack-primary encabeza, el resto
   se lista como "etiqueta (data-label) · valor", y .stack-action baja como
   botón de ancho completo. Opt-in por clase para no tocar las demás tablas. */
@media (max-width: 767.98px) {
    .table-stack-mobile thead { display: none; }
    .table-stack-mobile,
    .table-stack-mobile tbody { display: block; width: 100%; }
    .table-stack-mobile tr {
        display: flex;
        flex-direction: column;
        gap: 0.4rem;
        padding: 0.9rem var(--ds-content-padding-x);
        border-bottom: 1px solid var(--ds-border);
    }
    .table-stack-mobile tr:last-child { border-bottom: 0; }
    .table-stack-mobile td {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 1rem;
        width: 100%;
        border: 0 !important;
        text-align: left !important;
        min-height: 0;
    }
    /* Anula el padding lateral de .card-table (mayor especificidad): las celdas
       apiladas heredan el padding horizontal de la fila-tarjeta. */
    .table-stack-mobile.card-table tr td,
    .table-stack-mobile.card-table tr td:first-child,
    .table-stack-mobile.card-table tr td:last-child {
        padding-left: 0 !important;
        padding-right: 0 !important;
        padding-top: 0 !important;
        padding-bottom: 0 !important;
    }
    /* Etiqueta mono desde data-label a la izquierda del valor */
    .table-stack-mobile td[data-label]::before {
        content: attr(data-label);
        font-family: var(--ds-font-mono);
        font-size: 0.68rem;
        letter-spacing: 0.06em;
        text-transform: uppercase;
        color: var(--ds-ink-4);
        flex: 0 0 auto;
    }
    /* Celda primaria: nombre del estudio, arriba y a ancho completo, sin label */
    .table-stack-mobile td.stack-primary {
        order: -1;
        justify-content: flex-start;
        flex-wrap: wrap;
        font-size: 1rem;
    }
    /* Acción: botón de ancho completo al pie de la tarjeta */
    .table-stack-mobile td.stack-action { margin-top: 0.25rem; }
    .table-stack-mobile td.stack-action .btn { width: 100%; justify-content: center; }
    .table-stack-mobile td.stack-action .wl-hint { width: 100%; text-align: center; }
}

/* Table directly under a card-header: no top border (header has its own) */
.card-header + .table-responsive .table thead th,
.card-header + .table thead th {
    border-top: 0 !important;
}

/* Pagination + length/info under a card table — coherent footer padding */
.card .dataTables_wrapper .row:last-child,
.card .bottom-table {
    padding: 0.65rem var(--ds-content-padding-x) !important;
    border-top: 1px solid var(--ds-border-soft);
    margin-top: 0 !important;
}

/* `.table-bordered` is intentional spreadsheet-style (Historial, etc.).
   Keep the grid but refine the border color to the design system palette
   so it reads sober rather than harsh. */
.table.table-bordered,
.table.table-bordered > :not(caption) > * > *,
.table.table-bordered thead th,
.table.table-bordered tbody td,
.table.table-bordered tfoot td {
    border-color: var(--ds-border-soft) !important;
}
.table.table-bordered thead th {
    border-bottom-color: var(--ds-border) !important;
}

/* DataTables Scroller (Historial uses it) wraps the thead in its own div
   with extra borders. Strip the wrapper chrome but keep the inner table's
   own border-collapse so .table-bordered shows a single grid line per edge. */
.dataTables_scroll,
.dataTables_scrollHead,
.dataTables_scrollHeadInner,
.dataTables_scrollBody,
.dts .dataTables_scrollHead,
.dts .dataTables_scrollBody,
div.dts div.dataTables_scrollHead,
div.dts div.dataTables_scrollBody,
div.dts > div {
    border: 0 !important;
    background: transparent !important;
}
.dataTables_scrollHead table,
.dataTables_scrollBody table {
    border-collapse: collapse !important;
    margin: 0 !important;
}

/* DataTables clones the <thead> inside .dataTables_scrollBody with
   aria-hidden="true" to keep column widths in sync. With .table-bordered
   the clone's cell borders render → an empty ghost row at the top.
   Collapse it to zero height while keeping its column widths intact. */
.dataTables_scrollBody > table > thead,
.dataTables_scrollBody > table > thead tr,
.dataTables_scrollBody > table > thead th,
.dataTables_scrollBody [aria-hidden='true'],
.dataTables_scrollBody [aria-hidden='true'] th,
.dataTables_scrollBody [aria-hidden='true'] td {
    height: 0 !important;
    padding: 0 !important;
    line-height: 0 !important;
    border: 0 !important;
    font-size: 0 !important;
    overflow: hidden !important;
}
.dataTables_scrollBody > table > thead th > * {
    height: 0 !important;
    margin: 0 !important;
    padding: 0 !important;
    line-height: 0 !important;
    visibility: hidden;
}

/* ────────────────────────────────────────────────────────────────────
   Project-specific overrides previously inlined into tabler.css.
   Moved here so we can serve the unmodified tabler.min.css safely.
   ──────────────────────────────────────────────────────────────────── */

/* Tabler icon base scale (1049+ usages of `.ti`/`.ti-sm` across views).
   Component contexts override these with their own font-size below. */
.ti      { font-size: 2em; }
.ti-sm   { font-size: 1.3em; }
.ti-xs   { font-size: 1.15em; }

/* DataTables custom dom slot — pagination + length/info row at the bottom
   of every table view (81 usages). The padding rule sits inside the
   `card .bottom-table` block above; this is the standalone layout. */
.bottom-table {
    display: flex;
    align-items: center;
    justify-content: space-between;
}
.bottom-table .form-select {
    padding: 0.3rem 1.5rem !important;
    border-radius: var(--ds-radius-md) !important;
}
.dataTables_paginate { padding-top: 0 !important; }
.dataTables_paginate .pagination {
    margin-bottom: 0;
    justify-content: end;
}
.dataTables_length { display: flex; align-items: center; }
.dataTables_scrollHead tr { border-bottom: 0 !important; }

/* Flatpickr structural tweaks — los colores viven en la sección 12;
   aquí solo queda layout que la sección 12 no cubre. */
.flatpickr-calendar { z-index: 9999 !important; }
.flatpickr-calendar.hasTime.noCalendar { width: 150px; }
.flatpickr-disabled:hover {
    background-color: transparent !important;
    cursor: default !important;
}

/* =========================================================================
   20. ACCENT TINTS — el color del sistema
   --------------------------------------------------------------------------
   Utilidades para vestir avatares, icon-tiles, chips y stats con la paleta
   de 8 acentos. El chrome (botones, bordes, nav) permanece neutro; el
   color marca IDENTIDAD (personas, módulos, categorías) y DATOS.

   Uso:
     <span class="avatar tint-violet">SF</span>
     <span class="icon-tile tint-teal"><i class="ti ti-calendar"></i></span>
     <span class="badge tint-rose">Dermatología</span>
   ========================================================================= */
.tint-blue   { background-color: var(--ds-accent-blue-bg)   !important; color: var(--ds-accent-blue)   !important; border-color: transparent !important; }
.tint-cyan   { background-color: var(--ds-accent-cyan-bg)   !important; color: var(--ds-accent-cyan)   !important; border-color: transparent !important; }
.tint-teal   { background-color: var(--ds-accent-teal-bg)   !important; color: var(--ds-accent-teal)   !important; border-color: transparent !important; }
.tint-green  { background-color: var(--ds-accent-green-bg)  !important; color: var(--ds-accent-green)  !important; border-color: transparent !important; }
.tint-amber  { background-color: var(--ds-accent-amber-bg)  !important; color: var(--ds-accent-amber)  !important; border-color: transparent !important; }
.tint-orange { background-color: var(--ds-accent-orange-bg) !important; color: var(--ds-accent-orange) !important; border-color: transparent !important; }
.tint-rose   { background-color: var(--ds-accent-rose-bg)   !important; color: var(--ds-accent-rose)   !important; border-color: transparent !important; }
.tint-violet { background-color: var(--ds-accent-violet-bg) !important; color: var(--ds-accent-violet) !important; border-color: transparent !important; }

/* Versión sólida (texto blanco) para los pocos casos que piden peso:
   dots de calendario, indicadores, leyendas de gráficas. */
.tint-solid-blue   { background-color: var(--ds-accent-blue)   !important; color: #fff !important; }
.tint-solid-cyan   { background-color: var(--ds-accent-cyan)   !important; color: #fff !important; }
.tint-solid-teal   { background-color: var(--ds-accent-teal)   !important; color: #fff !important; }
.tint-solid-green  { background-color: var(--ds-accent-green)  !important; color: #fff !important; }
.tint-solid-amber  { background-color: var(--ds-accent-amber)  !important; color: #fff !important; }
.tint-solid-orange { background-color: var(--ds-accent-orange) !important; color: #fff !important; }
.tint-solid-rose   { background-color: var(--ds-accent-rose)   !important; color: #fff !important; }
.tint-solid-violet { background-color: var(--ds-accent-violet) !important; color: #fff !important; }

/* =========================================================================
   20b. LENGUAJE EDITORIAL "HANDLE" — el estilo propio del sistema
   --------------------------------------------------------------------------
   Tipografía display gigante, labels overline en mono uppercase, mesh
   gradients con glows amplios y ruido fino, estados LIVE en mono.
   Se usa en superficies hero (Agentes, futuros módulos IA).
   ========================================================================= */
/* ESCALA EDITORIAL ESTRICTA — UN solo tamaño display en toda la app
   (auditado contra Handle: su home y sus records titulan igual de grande).
   Hub y record se diferencian por ESTRUCTURA (overline, meta, status chip),
   nunca por tamaño. Prohibido font-size inline en títulos.
   Estructura obligatoria del encabezado:
     hub:    .home-hero  > .overline + .display-title (+ .overline fecha)
     record: .record-header > .overline + .record-title-row(.display-title
             + .status-chip) + .record-meta
   Los márgenes los pone el sistema (reglas de abajo) — cero estilos inline. */
:root {
    --ds-display: 3rem;
}
.display-title {
    font-size: var(--ds-display);
    font-weight: 600;
    letter-spacing: -0.05em;
    line-height: 1.02;
    color: var(--ds-ink);
    margin: 0;
}

/* Márgenes estructurales del encabezado editorial */
.home-hero > .overline:first-child,
.record-header > .overline:first-child {
    margin: 0 0 0.6rem;
}
/* Ritmo vertical estructural: el strip editorial SIEMPRE respira igual
   después de cualquier encabezado — las vistas no traen márgenes inline.
   (Doble clase: gana al shorthand margin de .stat-strip definido después.) */
.stat-strip.stat-strip-editorial { margin-bottom: 1.4rem; }
.home-hero .display-title + .overline,
.home-hero .display-title + .text-capitalize + .overline {
    margin: 0.9rem 0 0;
    color: var(--ds-ink-5);
}

.overline {
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-size: 0.72rem;
    font-weight: 500;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--ds-ink-4);
}

/* Estado de agente — cuadrito + label mono (patrón Handle "■ LIVE") */
.status-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    font-family: var(--ds-font-mono);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
.status-chip::before {
    content: '';
    width: 8px;
    height: 8px;
    background: currentColor;
    flex-shrink: 0;
}
.status-chip.is-live   { color: var(--ds-success); }
.status-chip.is-paused { color: var(--ds-ink-4); }
.status-chip.is-soon   { color: var(--ds-accent-violet); }

/* ─── Mesh gradient + ruido fino ─────────────────────────────────────
   Arte generativo de los agentes: glows amplios sobre base pastel y grano
   orgánico muy leve. Sin retícula de puntos para que se lea más premium. */
.mesh {
    position: relative;
    overflow: hidden;
    isolation: isolate;
}
.mesh::before {
    content: '';
    position: absolute;
    inset: -15%;
    z-index: -1;
    background:
        radial-gradient(52% 66% at 22% 28%, color-mix(in srgb, var(--mesh-a) 88%, transparent), transparent 76%),
        radial-gradient(54% 70% at 78% 20%, color-mix(in srgb, var(--mesh-b) 82%, transparent), transparent 78%),
        radial-gradient(58% 72% at 58% 84%, color-mix(in srgb, var(--mesh-c) 78%, transparent), transparent 80%),
        radial-gradient(44% 54% at 12% 88%, color-mix(in srgb, var(--mesh-b) 42%, transparent), transparent 82%),
        linear-gradient(140deg, var(--mesh-base) 0%, var(--mesh-end, #ffffff) 118%);
    filter: saturate(1.04) contrast(1.01);
}
.mesh::after {
    content: '';
    position: absolute;
    inset: 0;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240' viewBox='0 0 240 240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.58' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 0.48 0 0 0 0 0.48 0 0 0 0 0.48 0 0 0 0.20 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
    opacity: var(--mesh-noise-opacity, 0.18);
    mix-blend-mode: var(--mesh-blend, soft-light);
    pointer-events: none;
}
.mesh-lime   { --mesh-base: #f4fbd7; --mesh-a: #dfff54; --mesh-b: #bce9a6; --mesh-c: #93d6b9; }
.mesh-violet { --mesh-base: #ebe7fd; --mesh-a: #c5b9fb; --mesh-b: #dfe4fd; --mesh-c: #a9b6f5; }
.mesh-rose   { --mesh-base: #f9e5f5; --mesh-a: #f2bfe5; --mesh-b: #f6e3d3; --mesh-c: #dfb3ee; }
.mesh-blue   { --mesh-base: #e7eafc; --mesh-a: #b9c4f9; --mesh-b: #d8f3e3; --mesh-c: #9fb0f2; }
.mesh-imaging { --mesh-base: #e9eff7; --mesh-a: #dfe4fd; --mesh-b: #d8f3e3; --mesh-c: #b9c4f9; }

/* Mesh en DARK — base oscura del tono + glows joya (más saturados, lightness
   media para que brillen sobre negro), ruido fino en `screen`.
   El arte se mantiene; solo cambia la paleta para no lavar a blanco. */
:root[data-theme="dark"] .mesh {
    --mesh-end: #0a0a0a;
    --mesh-blend: screen;
    --mesh-noise-opacity: 0.08;
}
:root[data-theme="dark"] .mesh-lime   { --mesh-base: #0e120a; --mesh-a: #4a5510; --mesh-b: #23401e; --mesh-c: #16332c; }
:root[data-theme="dark"] .mesh-violet { --mesh-base: #14122a; --mesh-a: #3b3382; --mesh-b: #221f48; --mesh-c: #2d2678; }
:root[data-theme="dark"] .mesh-rose   { --mesh-base: #221026; --mesh-a: #71295c; --mesh-b: #3a231e; --mesh-c: #5c2a69; }
:root[data-theme="dark"] .mesh-blue   { --mesh-base: #101430; --mesh-a: #2b3c8e; --mesh-b: #163026; --mesh-c: #20397e; }
:root[data-theme="dark"] .mesh-imaging { --mesh-base: #101521; --mesh-a: #263159; --mesh-b: #143026; --mesh-c: #20397e; }

/* ─── Agent feature card — fila editorial: arte mesh + ficha ───────── */
.agent-card {
    display: grid;
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    gap: 2.4rem;
    align-items: center;
    padding: 2.4rem 0;
    border-top: 1px solid var(--ds-border-soft);
}
.agent-card:first-of-type { border-top: 0; }
.agent-card-art {
    aspect-ratio: 16 / 10;
    border-radius: var(--ds-radius-xl);
    border: 1px solid var(--ds-border-soft);
}
.agent-index {
    font-size: 4.2rem;
    font-weight: 650;
    letter-spacing: -0.04em;
    line-height: 0.9;
    color: var(--ds-surface-active);
    user-select: none;
}
.agent-name {
    font-size: 1.85rem;
    font-weight: 600;
    letter-spacing: -0.04em;
    line-height: 1.1;
    color: var(--ds-ink);
    margin: 0.5rem 0 0.65rem;
}
.agent-stats {
    list-style: none;
    margin: 1.1rem 0 1.4rem;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.45rem;
}
.agent-stats li {
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum', 'zero';
    font-size: 0.82rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--ds-ink-3);
}
.agent-stats li b {
    font-weight: 600;
    color: var(--ds-ink);
}
.agent-channels {
    display: flex;
    gap: 0.4rem;
    margin-top: 0.85rem;
    flex-wrap: wrap;
}
/* El badge de canal centra verticalmente icono + texto (como flex-item su
   inline-block se blockifica → hay que hacerlo flex interno para centrar). */
.agent-channels .badge {
    display: inline-flex;
    align-items: center;
}
.agent-actions {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
}
@media (max-width: 767.98px) {
    .agent-card { grid-template-columns: 1fr; gap: 1.25rem; padding: 1.75rem 0; }
    .agent-index { font-size: 3rem; }
}

/* ─── Vistas internas (record/detalle) — patrones Handle ─────────────
   record-header: título display + chip de estado + meta en mono.
   money-cells: resumen de dinero en celdas con divisores (primera activa).
   activity-feed: timeline de eventos (actor + chip + descripción + hace X).
   badge-mono: chip de estado COTIZADO/ERROR-style.
   nav-tabs-editorial: tabs en mono uppercase. */
.record-header { padding: 1.7rem 0 1.2rem; }
.record-title-row {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    flex-wrap: wrap;
}
.record-meta {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin-top: 0.65rem;
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-size: 0.75rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ds-ink-4);
}
.record-meta .record-meta-sep { color: var(--ds-ink-5); }

/* ─── Capa móvil del record-header (<992px) ──────────────────────────────
   El encabezado editorial (título display + acciones + meta) está calibrado
   para desktop. En móvil el título a 3rem se come el alto y la meta en una
   sola línea con "·" se sale de pantalla. Compactamos de forma GLOBAL: toda
   vista con .record-header (expedientes, recetas, clientes…) se beneficia. */
@media (max-width: 991.98px) {
    .record-header { padding: 1rem 0 0.85rem; }
    .display-title { font-size: 2rem; letter-spacing: -0.03em; line-height: 1.05; }
    /* La meta pasa a envolver: age/sex/sangre/alergias fluyen en varias
       líneas en vez de recortarse contra el borde derecho. */
    .record-meta { flex-wrap: wrap; row-gap: 0.35rem; }
    /* Las acciones bajan a una barra propia de ancho completo (el margin-left
       auto inline las empujaba a la derecha y se apilaban ragged). */
    .record-title-row > .d-flex {
        margin-left: 0 !important;
        width: 100%;
        flex-wrap: wrap;
    }
    .record-title-row > .d-flex > .btn { flex: 1 1 auto; justify-content: center; }
}
/* Meta como chips en móvil: al envolver, la línea con "·" se ve suelta y los
   datos "flotan". Debajo de 768px cada dato pasa a chip con borde (los que YA
   son chips —visibilidad, alergias— se excluyen para no doble-estilarlos) y se
   ocultan los separadores. En desktop la línea mono con "·" queda intacta. */
@media (max-width: 767.98px) {
    .record-meta { column-gap: 0.4rem; row-gap: 0.4rem; }
    .record-meta .record-meta-sep { display: none; }
    .record-meta > span:not(.record-meta-sep):not(.badge):not(.patient-allergies) {
        padding: 0.2rem 0.5rem;
        border: 1px solid var(--ds-border);
        border-radius: var(--ds-radius-sm);
        background: var(--ds-surface-soft);
        color: var(--ds-ink-3);
        line-height: 1.3;
    }
}
@media (max-width: 575.98px) {
    .display-title { font-size: 1.65rem; }
}

.badge-mono {
    display: inline-flex;
    align-items: center;
    font-family: var(--ds-font-mono) !important;
    font-size: 0.78rem !important;
    font-weight: 600 !important;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    padding: 0.28rem 0.58rem;
    border-radius: var(--ds-radius-sm);
    line-height: 1.2;
}
/* Safety net: an icon inside a chip rides the chip's font size, never the
   2em `.ti` base. Mirrors `.btn .ti` so badges don't blow up if `ti-sm` is
   forgotten in markup. */
.badge-mono .ti { font-size: 1.05em !important; line-height: 1; }

.nav-tabs.nav-tabs-editorial .nav-link {
    font-family: var(--ds-font-mono) !important;
    font-size: 0.8rem !important;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.money-cells {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-lg);
    overflow: hidden;
    background: var(--ds-surface);
    box-shadow: var(--ds-shadow-xs);
}
.money-cell {
    padding: 1.15rem 1.4rem;
    border-left: 1px solid var(--ds-border-soft);
    min-width: 0;
}
.money-cell:first-child { border-left: 0; }
.money-cell.is-active { background: var(--ds-surface-muted); }
.money-cell-value {
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum', 'zero';
    font-size: 1.8rem;
    font-weight: 500;
    letter-spacing: -0.04em;
    color: var(--ds-ink);
    line-height: 1.15;
    margin: 0.35rem 0 0.3rem;
    white-space: nowrap;
}
.money-cell.is-danger .money-cell-value { color: var(--ds-danger); }
.money-cell-sub {
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-size: 0.75rem;
    color: var(--ds-ink-4);
}
@media (max-width: 767.98px) {
    .money-cells { grid-template-columns: 1fr; }
    .money-cell { border-left: 0; border-top: 1px solid var(--ds-border-soft); }
    .money-cell:first-child { border-top: 0; }
}
.money-cells-spaced { margin-top: 1.1rem; }

/* ── Pulso del hospital ───────────────────────────────────────────────────
   Bloque operativo compartido por la Torre de control (/control-tower/hospital) y
   el dashboard de Inicio: flujo ADT (hov-*), censo por servicio (reusa
   .operator-row) y alertas de excepción (.alert-item). Antes vivía como <style>
   inline en Overview.ejs; promovido aquí para reuso. */
.hov-flow {
    display: flex;
    align-items: stretch;
    gap: 0.4rem;
    flex-wrap: wrap;
    margin-top: 1.1rem;
}
.hov-stage {
    flex: 1 1 110px;
    display: flex;
    align-items: center;
    gap: 0.55rem;
    text-decoration: none;
    color: inherit;
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-lg);
    padding: 0.6rem 0.75rem;
    transition: background-color 0.12s ease, border-color 0.12s ease;
}
.hov-stage:hover { background: var(--ds-surface-muted); border-color: var(--ds-border-strong); }
.hov-stage-n {
    font-family: var(--ds-font-mono);
    font-weight: 600;
    font-size: 1.2rem;
    font-variant-numeric: tabular-nums;
    color: var(--ds-ink);
    line-height: 1;
}
.hov-stage-l {
    font-size: 0.72rem;
    font-family: var(--ds-font-mono);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--ds-ink-4);
}
.hov-arrow { display: flex; align-items: center; color: var(--ds-ink-5); }
.hov-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1.6rem;
    align-items: start;
    margin-top: 1.6rem;
}
@media (max-width: 860px) { .hov-grid { grid-template-columns: 1fr; } }
.operator-count .o-ratio { font-size: 0.72rem; color: var(--ds-ink-4); white-space: nowrap; }
.hov-grid .operator-count { white-space: nowrap; }
/* Censo por servicio: el conteo es "92% 11/12" (porcentaje + ratio). La columna
   base de 2.5rem desbordaba la tarjeta; se le da ancho fijo y se separan
   porcentaje y ratio en dos sub-columnas de ancho fijo para que todas las filas
   queden alineadas en vertical. */
.hov-grid .operator-row { grid-template-columns: minmax(0, 9rem) 1fr auto; }
.hov-grid .operator-count {
    display: inline-flex;
    gap: 0.45rem;
    align-items: baseline;
    justify-content: flex-end;
}
.hov-grid .operator-count .o-pct { min-width: 2.4rem; text-align: right; }
.hov-grid .operator-count .o-ratio { min-width: 3.4rem; text-align: right; }
.census-legend { display: flex; gap: 1rem; margin-top: 0.9rem; }
.census-legend span {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.75rem;
    color: var(--ds-ink-3);
}
/* Alertas de excepción ("Requiere acción") — lista carded que reusa
   .dashboard-list-row: icon-tile suave (tinte por severidad) + texto en ink +
   chip mono semántico (.badge-mono.is-*). Sin cajas de color rellenas (se
   sentían pesadas/genéricas). Compartida por tower-board y hospital-pulse-board
   vía views/components/alert-list.ejs. */
.alert-item-text {
    flex: 1;
    min-width: 0;
    font-size: 0.9rem;
    color: var(--ds-ink);
    line-height: 1.35;
}
.alert-item-text .alert-item-meta {
    display: block;
    font-size: 0.78rem;
    color: var(--ds-ink-4);
    margin-top: 0.1rem;
}
.dashboard-list-row > .badge-mono { flex-shrink: 0; margin-left: auto; }

/* ── Trazabilidad de pacientes (/control-tower/patients) ──────────────────── */
.trace-toolbar {
    display: flex;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
    margin-top: 1.1rem;
}
.trace-daterange { max-width: 13rem; }
/* Tablero de ubicación: tiles de etapa que filtran la lista (reusan hov-stage). */
.trace-stages {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-top: 1.1rem;
}
.trace-stage {
    flex: 1 1 120px;
    display: flex;
    align-items: center;
    gap: 0.55rem;
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-lg);
    padding: 0.6rem 0.75rem;
    background: var(--ds-surface);
    cursor: pointer;
    text-align: left;
    transition: background-color 0.12s ease, border-color 0.12s ease;
}
.trace-stage:hover { background: var(--ds-surface-muted); }
.trace-stage.is-active { border-color: var(--ds-ink); background: var(--ds-surface-active); }
/* Filas de paciente: dashboard-list-row sobre <button> (reset de botón). */
.trace-row {
    width: 100%;
    background: none;
    border: 0;
    border-bottom: 1px solid var(--ds-border-soft);
    cursor: pointer;
    text-align: left;
    font: inherit;
}
.trace-row:last-child { border-bottom: 0; }
.trace-row.is-selected { background: var(--ds-surface-active); }
.trace-row-end {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-shrink: 0;
}
.trace-amount {
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--ds-ink);
    white-space: nowrap;
}
/* Detalle: sticky bajo el header; solo el panel del paciente activo se ve. */
.trace-detail { position: sticky; top: calc(var(--ds-header-h) + 1rem); }
.trace-detail-panel { display: none; }
.trace-detail-panel.is-active { display: block; }
.trace-detail-head {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    padding-bottom: 1rem;
    border-bottom: 1px solid var(--ds-border-soft);
}
.trace-detail-name {
    font-size: 1rem;
    font-weight: 600;
    color: var(--ds-ink);
    text-transform: capitalize;
}
.trace-detail-sub { font-size: 0.8rem; color: var(--ds-ink-4); }
.trace-detail-head .badge-mono { margin-left: auto; }
.trace-timeline { margin-top: 1.1rem; }
.trace-evt-amount {
    margin-left: auto;
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--ds-ink);
}
/* Cuando hay monto, la hora va después de él (sin empujar todo a la derecha). */
.trace-timeline .trace-evt-amount + .activity-time { margin-left: 0.6rem; }

/* ── Recepción · bandeja de mensajes (/control-tower/reception) ────────────── */
/* Las filas de bandeja son <button> → reset (sin chrome de botón); fila editorial
   con hairline inferior, igual que .trace-row/.wl-row. */
.inbox-row {
    width: 100%;
    background: none;
    border: 0;
    border-bottom: 1px solid var(--ds-border-soft);
    cursor: pointer;
    text-align: left;
    font: inherit;
    align-items: flex-start;
}
.inbox-row:last-child { border-bottom: 0; }
.inbox-row.is-selected { background: var(--ds-surface-active); }
.inbox-row .order-avatar { margin-top: 0.1rem; }
.inbox-row-top { display: flex; align-items: center; gap: 0.5rem; }
.inbox-name {
    font-size: 0.92rem;
    font-weight: 600;
    color: var(--ds-ink);
    text-transform: capitalize;
}
.inbox-channel {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    text-transform: none;
    letter-spacing: 0;
}
.inbox-channel .ti { font-size: 0.9em; }
.inbox-preview {
    font-size: 0.82rem;
    color: var(--ds-ink-3);
    margin-top: 0.15rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 38ch;
}
.inbox-intent { color: var(--ds-ink-4); font-weight: 500; }
.inbox-row-end {
    margin-left: auto;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.3rem;
    flex-shrink: 0;
}
.inbox-wait {
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-size: 0.72rem;
    color: var(--ds-ink-5);
    white-space: nowrap;
}
.inbox-detail-panel { display: none; }
.inbox-detail-panel.is-active { display: block; }
.inbox-help-note {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin-top: 0.9rem;
    padding: 0.55rem 0.7rem;
    border-radius: var(--ds-radius-md);
    background: var(--ds-danger-bg);
    color: var(--ds-danger);
    font-size: 0.82rem;
}
.msg-context {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.6rem 1rem;
    margin-top: 1.1rem;
    padding: 0.9rem 1rem;
    border: 1px solid var(--ds-border-soft);
    border-radius: var(--ds-radius-lg);
    background: var(--ds-surface-muted);
}
.msg-context-item { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }
.msg-context-val {
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-size: 0.85rem;
    color: var(--ds-ink);
}
.msg-thread { display: flex; flex-direction: column; gap: 0.5rem; margin-top: 1.1rem; }
.msg-bubble {
    max-width: 85%;
    padding: 0.5rem 0.7rem;
    border-radius: var(--ds-radius-lg);
    font-size: 0.85rem;
    line-height: 1.4;
    color: var(--ds-ink);
}
.msg-bubble.from-patient {
    align-self: flex-start;
    background: var(--ds-surface-soft);
    border-bottom-left-radius: var(--ds-radius-sm);
}
.msg-bubble.from-staff {
    align-self: flex-end;
    background: var(--ds-accent-blue-bg);
    border-bottom-right-radius: var(--ds-radius-sm);
}
.msg-bubble-time {
    display: block;
    margin-top: 0.2rem;
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-size: 0.72rem;
    color: var(--ds-ink-5);
}
.msg-reply {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    margin-top: 1.1rem;
    font-size: 0.82rem;
    color: var(--ds-ink-2);
    text-decoration: none;
}
.msg-reply:hover { color: var(--ds-ink); }
/* Notas de escalamiento por severidad (danger es el default del .inbox-help-note). */
.inbox-help-note.sev-warning { background: var(--ds-warning-bg); color: var(--ds-warning); }
.inbox-help-note.sev-info { background: var(--ds-info-bg); color: var(--ds-info); }

/* ── Worklist board genérico (clínica/comercio/imagen/lab) ─────────────────── */
.wl-row {
    width: 100%;
    background: none;
    border: 0;
    border-bottom: 1px solid var(--ds-border-soft);
    cursor: pointer;
    text-align: left;
    font: inherit;
}
.wl-row:last-child { border-bottom: 0; }
.wl-row.is-selected { background: var(--ds-surface-active); }
.wl-detail-panel { display: none; }
.wl-detail-panel.is-active { display: block; }

.activity-feed {
    display: flex;
    flex-direction: column;
}
.activity-item {
    padding: 0.8rem 0;
    border-top: 1px solid var(--ds-border-soft);
}
.activity-item:first-child { border-top: 0; padding-top: 0; }
.activity-head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}
.activity-actor {
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--ds-ink);
}
.activity-time {
    margin-left: auto;
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-size: 0.72rem;
    color: var(--ds-ink-5);
    white-space: nowrap;
}
.activity-desc {
    font-size: 0.85rem;
    color: var(--ds-ink-3);
    line-height: 1.5;
    margin-top: 0.25rem;
}

/* ─── Agent feature — versión compacta para el dashboard (el "Quoting
   Agent" del home de Handle): arte mesh + ficha, toda la card navega. */
.agent-feature {
    display: grid;
    grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.4fr);
    gap: 1.6rem;
    align-items: center;
    background: var(--ds-surface);
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-xl);
    box-shadow: var(--ds-shadow-xs);
    padding: 1.1rem;
    text-decoration: none !important;
    color: inherit;
    transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
.agent-feature:hover {
    border-color: var(--ds-border-strong);
    box-shadow: var(--ds-shadow-sm);
    color: inherit;
}
.agent-feature-art {
    aspect-ratio: 16 / 7;
    border-radius: var(--ds-radius-lg);
    border: 1px solid var(--ds-border-soft);
    align-self: stretch;
}
.agent-feature-info h3 {
    font-size: 1.35rem;
    font-weight: 600;
    letter-spacing: -0.03em;
    margin: 0.45rem 0 0;
}
.agent-feature-info .agent-stats { margin: 0.75rem 0 0; gap: 0.35rem; }
.agent-feature-cta {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    margin-top: 0.9rem;
}
.agent-feature:hover .agent-feature-cta .ti { transform: translateX(2px); }
.agent-feature-cta .ti { transition: transform 0.12s ease; }
@media (max-width: 767.98px) {
    .agent-feature { grid-template-columns: 1fr; gap: 1rem; }
}

/* Variante editorial del stat-strip (labels overline mono, número más
   grande) — Handle-style para páginas hero. */
.stat-strip-editorial .stat-label {
    font-family: var(--ds-font-mono);
    font-size: 0.72rem;
    font-weight: 500;
    letter-spacing: 0.09em;
    text-transform: uppercase;
}
.stat-strip-editorial .stat-value {
    font-size: 2.2rem;
    letter-spacing: -0.04em;
}
/* Marca «muestra»: KPI/sección alimentada con datos de ejemplo (sin endpoint
   real todavía). Discreto, para no confundirse con datos en vivo. */
.stat-mock {
    margin-left: 0.35rem;
    font-family: var(--ds-font-mono);
    font-size: 0.72rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ds-ink-4);
    vertical-align: 1px;
}

/* =========================================================================
   21. HOME HERO + QUICK ACCESS — dashboard estilo ElevenLabs
   --------------------------------------------------------------------------
   Saludo grande con pretitle y una fila de tiles de acceso rápido:
   tarjeta gris suave con icon-tile de color centrado y label debajo.
   ========================================================================= */
.home-hero {
    padding: 2.4rem 0 1.9rem;
}
/* (.home-hero-pretitle / .home-hero-title ELIMINADAS — el encabezado
   editorial usa .overline + .display-title con la escala estricta de
   §20b. No reintroducir clases de título paralelas.) */

.quick-grid {
    display: grid;
    /* Columnas balanceadas: el home admin fija --quick-cols inline para que las
       áreas llenen filas simétricas (p. ej. 10 áreas → 5×2). Las media queries
       fijan grid-template-columns directo, así ganan sobre el inline en móvil. */
    grid-template-columns: repeat(var(--quick-cols, 6), minmax(0, 1fr));
    gap: 1rem;
}
@media (max-width: 991.98px) {
    .quick-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 575.98px) {
    .quick-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.quick-tile {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    text-decoration: none !important;
}
.quick-tile-card {
    aspect-ratio: 16 / 10;
    background: var(--ds-surface-muted);
    border: 1px solid var(--ds-border-soft);
    border-radius: var(--ds-radius-xl);
    display: flex;
    align-items: center;
    justify-content: center;
    transition: border-color 0.12s ease, background-color 0.12s ease, transform 0.12s ease;
}
.quick-tile:hover .quick-tile-card {
    border-color: var(--ds-border-strong);
    background: var(--ds-surface-soft);
    transform: translateY(-1px);
}
.quick-tile-card .icon-tile-lg {
    width: 3rem;
    height: 3rem;
    transition: transform 0.16s ease;
}
.quick-tile-card .icon-tile-lg .ti { font-size: 1.45rem !important; }
.quick-tile:hover .quick-tile-card .icon-tile-lg { transform: scale(1.08); }
.quick-tile-label {
    text-align: center;
    font-size: 0.95rem;
    font-weight: 450;
    color: var(--ds-ink-2);
    letter-spacing: -0.008em;
}
.quick-tile:hover .quick-tile-label { color: var(--ds-ink); }

/* ─── Section header fuera de cards ("Latest from the library") ──────
   Título a la izquierda, acciones quietas a la derecha. El contenido
   vive debajo, en una card hairline o directamente sobre la página. */
/* Una sección de nivel superior que sigue a una FILA de cards necesita más
   aire: dos bloques pesados apilados a 2.1rem se sienten pegados. Solo
   aplica a secciones hermanas de un .row (no a las anidadas en columnas). */
.row + .home-section {
    margin-top: 3rem;
}
.home-section {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    flex-wrap: wrap;
    margin: 2.1rem 0 0.9rem;
}
.home-section-title {
    font-size: 1.25rem;
    font-weight: 600;
    letter-spacing: -0.028em;
    color: var(--ds-ink);
    margin: 0;
    line-height: 1.2;
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    min-width: 0;
}
.home-section-title small {
    font-size: 0.85rem;
    font-weight: 400;
    color: var(--ds-ink-4);
    letter-spacing: -0.005em;
}
.home-section-actions {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    flex-shrink: 0;
}
/* Título-link (patrón ElevenLabs "Trending voices ›"): el título de la
   sección ES la navegación a su módulo. Chevron discreto que se asoma
   al hover. */
a.home-section-title {
    text-decoration: none !important;
    color: var(--ds-ink);
}
.home-section-title .ti-chevron-right {
    font-size: 1rem !important;
    color: var(--ds-ink-5);
    align-self: center;
    position: relative;
    top: 1px;            /* centrado óptico contra la x-height del título */
    margin-left: -0.1rem;
    transition: transform 0.12s ease, color 0.12s ease;
}
a.home-section-title:hover .ti-chevron-right {
    transform: translateX(2px);
    color: var(--ds-ink-2);
}

/* ─── Stat strip — métricas sin cajas, separadas por hairlines ───────
   Número grande en mono + label pequeño con dot de acento. El patrón
   premium: la jerarquía la hace la tipografía, no los bordes. */
.stat-strip {
    display: grid;
    /* Por defecto 5 columnas; una vista con más/menos KPIs fija --stat-cols inline
       para que TODOS quepan en una fila (evita que el último salte de renglón). */
    grid-template-columns: repeat(var(--stat-cols, 5), minmax(0, 1fr));
    margin: 0.5rem 0 0;
}
.stat-item {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    padding: 0.35rem 1.5rem;
    border-left: 1px solid var(--ds-border);
    min-width: 0;
}
.stat-item:first-child { border-left: 0; padding-left: 0; }
.stat-item[data-bs-toggle],
.stat-item[role='button'] {
    cursor: pointer;
    border-radius: var(--ds-radius-md);
    transition: background-color 0.12s ease;
}
.stat-item[data-bs-toggle]:hover { background-color: var(--ds-surface-muted); }
.stat-label {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    font-size: 0.85rem;
    font-weight: 450;
    color: var(--ds-ink-4);
    letter-spacing: -0.005em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.stat-dot {
    width: 7px;
    height: 7px;
    border-radius: 99px;
    flex-shrink: 0;
}
.stat-value {
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum', 'zero';
    font-size: 1.6rem;
    font-weight: 500;
    letter-spacing: -0.035em;
    color: var(--ds-ink);
    line-height: 1.15;
    display: flex;
    align-items: baseline;
    gap: 0.35rem;
    white-space: nowrap;
}
.stat-value small {
    font-family: var(--ds-font-sans);
    font-size: 0.85rem;
    font-weight: 400;
    color: var(--ds-ink-4);
}
@media (max-width: 991.98px) {
    /* !important para ganar a los `style="grid-template-columns: repeat(4,…)"`
       inline (p. ej. EditarCliente) que si no dejan 4 tiles ilegibles en móvil. */
    .stat-strip { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; row-gap: 1.1rem; }
    .stat-item { border-left: 0; padding-left: 0; }
}

/* ─── Ops banner — franja accionable bajo el header (patrón ElevenLabs:
   el pill "New · Become an affiliate"). Solo aparece cuando hay algo
   pendiente del día: citas sin confirmar, recordatorios fallidos,
   lotes caducados. Gestión por excepción, no decoración. ─────────────── */
.ops-banner {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    background: var(--ds-surface-muted);
    border: 1px solid var(--ds-border-soft);
    border-radius: 99px;
    padding: 0.45rem 0.55rem 0.45rem 0.55rem;
    margin: 1.5rem 0 0;
    text-decoration: none !important;
    color: inherit;
    transition: border-color 0.12s ease, background-color 0.12s ease;
}
.ops-banner:hover { border-color: var(--ds-border-strong); }
.ops-banner-chip {
    background: var(--ds-ink);
    color: var(--ds-bg);
    font-size: 0.8rem;
    font-weight: 550;
    padding: 0.22rem 0.65rem;
    border-radius: 99px;
    flex-shrink: 0;
    letter-spacing: -0.005em;
}
.ops-banner-text {
    font-size: 0.9rem;
    color: var(--ds-ink-2);
    font-weight: 450;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ops-banner-text b {
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-weight: 600;
    color: var(--ds-ink);
}
.ops-banner-text .ops-sep { color: var(--ds-ink-5); margin: 0 0.45rem; }
.ops-banner-cta {
    margin-left: auto;
    width: 1.8rem;
    height: 1.8rem;
    border-radius: 50%;
    border: 1px solid var(--ds-border);
    background: var(--ds-surface);
    color: var(--ds-ink-2);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.ops-banner-cta .ti { font-size: 0.9rem !important; }
.ops-banner:hover .ops-banner-cta {
    background: var(--ds-ink);
    border-color: var(--ds-ink);
    color: var(--ds-bg);
}

/* ─── Lot tile — severidad del lote como icon-tile (rojo caducado,
   ámbar <60 días, neutro después) ────────────────────────────────────── */
.lot-tile { border-radius: var(--ds-radius-sm); }
.lot-tile.is-critical { background: var(--ds-danger-bg) !important;  color: var(--ds-danger) !important; }
.lot-tile.is-low      { background: var(--ds-warning-bg) !important; color: var(--ds-warning) !important; }

/* ─── Avatar chip en filas de operador ───────────────────────────────── */
.operator-name {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    text-transform: capitalize;
}
.operator-avatar {
    width: 22px;
    height: 22px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.72rem;
    font-weight: 600;
    flex-shrink: 0;
    letter-spacing: 0;
}

/* ─── Órdenes recientes — fila tipo lista ElevenLabs ─────────────────
   Entidad con avatar primero, chips quietos en medio, dinero en mono a
   la derecha. Renderers en inicio.js.
   table-layout: fixed mata el scroll horizontal: las columnas se reparten
   por porcentaje y los nombres largos truncan con ellipsis en vez de
   estirar la tabla más allá del contenedor (el `td { nowrap }` global +
   autoWidth de DataTables eran la causa). ──────────────────────────── */
#ordersTable {
    table-layout: fixed;
    width: 100% !important;
}
/* nth-child(1) es el chevron (ancho fijo de .row-chevron) */
#ordersTable thead th:nth-child(2) { width: auto; }   /* Cliente: flexible */
#ordersTable thead th:nth-child(3) { width: 26%; }    /* Atendió (cajero + caja) */
#ordersTable thead th:nth-child(4) { width: 11%; }    /* Fecha */
#ordersTable thead th:nth-child(5) { width: 14%; }    /* Total */

/* Celda "Atendió": cajero (capitalizado) sobre chip de caja, denso */
.order-served {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.25rem;
    line-height: 1.2;
}
.order-served-name {
    text-transform: capitalize;
    font-weight: 500;
    color: var(--ds-ink-2);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}

/* ─── Por empresa: el panel ES la leyenda del chart de Ventas ─────────
   Cada fila = un punto del mismo color que su línea en el chart + nombre,
   monto mono y barra de participación. Llena la altura de la card (la
   leyenda del chart se oculta para no duplicar). */
.company-list {
    display: flex;
    flex-direction: column;
    justify-content: center;   /* grupo de filas centrado: whitespace balanceado arriba/abajo */
    gap: 1.5rem;
    height: 100%;
    min-height: 16rem;
}
.company-row {
    display: grid;
    grid-template-columns: 1fr auto;
    grid-template-rows: auto auto;
    align-items: center;
    column-gap: 0.85rem;
    row-gap: 0.45rem;
}
.company-name {
    grid-column: 1;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.95rem;
    font-weight: 500;
    color: var(--ds-ink);
    text-transform: capitalize;
    min-width: 0;
}
.company-name .company-dot {
    width: 9px;
    height: 9px;
    border-radius: 3px;
    flex-shrink: 0;
}
.company-name .company-label {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.company-amount {
    grid-column: 2;
    grid-row: 1;
    text-align: right;
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--ds-ink);
    white-space: nowrap;
}
.company-row .operator-bar-track {
    grid-column: 1;
    grid-row: 2;
}
.company-share {
    grid-column: 2;
    grid-row: 2;
    text-align: right;
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-size: 0.78rem;
    color: var(--ds-ink-4);
}
/* Componentes de fila-entidad — GLOBALES (no scopeados a #ordersTable):
   cualquier tabla del sistema puede usar .order-customer/.order-avatar/
   .order-cashbox-chip; los usan Órdenes recientes y las vistas de agentes. */
.order-customer {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    min-width: 0;
    overflow: hidden;
}
.order-cashier {
    color: var(--ds-ink-3);
    font-weight: 450;
    text-transform: capitalize;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    display: block;
}
.order-avatar {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0;
    flex-shrink: 0;
    background: var(--ds-surface-soft);
    color: var(--ds-ink-3);
}
.order-avatar .ti { font-size: 0.85rem !important; }
.order-customer-name {
    text-transform: capitalize;
    font-weight: 500;
    color: var(--ds-ink);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Metadata secundaria bajo el nombre en una fila-entidad (email, folio…) */
.order-sub {
    display: block;
    font-size: 0.82rem;
    color: var(--ds-ink-4);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 22rem;
}
.order-cashbox-chip {
    display: inline-flex;
    align-items: center;
    background: var(--ds-surface-soft);
    border: 1px solid var(--ds-border-soft);
    color: var(--ds-ink-3);
    font-size: 0.85rem;
    font-weight: 500;
    padding: 0.14rem 0.55rem;
    /* Chips de metadata en tabla: rect suave (Handle "Hoy"), no cápsula */
    border-radius: var(--ds-radius-sm);
    text-transform: capitalize;
    line-height: 1.35;
    white-space: nowrap;
}

/* ===== Conceptos — desglose fiscal de un servicio =====
   Medidor de distribución (los splits deben sumar 100%) + celdas de tabla. */
.concepts-meter {
    margin-bottom: 0.85rem;
}
.concepts-meter-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.5rem;
    margin-bottom: 0.4rem;
}
.concepts-meter-total {
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--ds-ink);
    line-height: 1;
}
.concepts-meter-total small {
    font-size: 0.72rem;
    font-weight: 500;
    color: var(--ds-ink-3);
    margin-left: 0.2rem;
}
.concepts-meter-status {
    font-size: 0.78rem;
    font-weight: 500;
    color: var(--ds-ink-3);
    text-align: right;
}
.concepts-meter-status.is-complete { color: var(--ds-success); }
.concepts-meter-status.is-under { color: var(--ds-warning); }
.concepts-meter-status.is-over { color: var(--ds-danger); }
.concepts-meter-track {
    display: flex;
    gap: 2px;
    height: 0.5rem;
    border-radius: 999px;
    overflow: hidden;
    background: var(--ds-surface-soft);
    border: 1px solid var(--ds-border-soft);
}
.concepts-meter.is-empty .concepts-meter-track {
    gap: 0;
}
.concepts-meter-seg {
    height: 100%;
    min-width: 2px;
    transition: width 0.25s ease;
}

/* Celdas de la tabla de conceptos */
.concept-name-cell {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
}
.concept-dot {
    flex: 0 0 auto;
    width: 0.55rem;
    height: 0.55rem;
    border-radius: 50%;
}
.concept-name-text {
    font-weight: 500;
}
.concept-fee-tag {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    font-size: 0.7rem;
    font-weight: 500;
    color: var(--ds-accent-green);
    background: var(--ds-accent-green-bg);
    border-radius: var(--ds-radius-sm);
    padding: 0.05rem 0.35rem;
    white-space: nowrap;
}
.concept-pct {
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-weight: 600;
    color: var(--ds-ink);
}
.concept-sat-chip {
    display: inline-flex;
    align-items: center;
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-size: 0.8rem;
    background: var(--ds-surface-soft);
    border: 1px solid var(--ds-border-soft);
    color: var(--ds-ink-3);
    padding: 0.1rem 0.45rem;
    border-radius: var(--ds-radius-sm);
}

/* Pista de "porcentaje restante" en el modal de concepto */
.concept-split-hint {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin-top: 0.35rem;
}
.concept-split-hint .concept-split-remaining {
    font-size: 0.78rem;
    color: var(--ds-ink-3);
}
.concept-split-hint .concept-split-remaining strong {
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    color: var(--ds-ink);
}

/* Modo simple — resumen del único concepto fiscal */
.simple-concept-empty {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 1rem;
    padding: 0.9rem 1rem;
    border: 1px dashed var(--ds-border);
    border-radius: var(--ds-radius-md);
    background: var(--ds-surface-soft);
}
.simple-concept-empty-text {
    color: var(--ds-ink-3);
    font-size: 0.9rem;
}
.simple-concept-card {
    border: 1px solid var(--ds-border-soft);
    border-radius: var(--ds-radius-md);
    padding: 0.9rem 1rem;
    background: var(--ds-surface-soft);
}
.simple-concept-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
    gap: 0.75rem 1.5rem;
}
.simple-concept-item {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}
.simple-concept-label {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--ds-ink-3);
}
.simple-concept-value {
    font-weight: 500;
    color: var(--ds-ink);
}
.simple-concept-value.is-mono {
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
}
.simple-concept-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    margin-top: 0.85rem;
    padding-top: 0.75rem;
    border-top: 1px solid var(--ds-border-soft);
}

.order-when {
    display: flex;
    flex-direction: column;
    line-height: 1.25;
}
.order-time {
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--ds-ink);
}
.order-day {
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-size: 0.8rem;
    color: var(--ds-ink-4);
    text-transform: capitalize;
}
td.order-total-cell {
    font-weight: 600;
    color: var(--ds-ink);
}

/* badge-mono neutro: bg-secondary sin la clase .badge no recibe el remapa
   de Tabler — aquí el neutro correcto (gris suave, nunca gris oscuro). */
.badge-mono.bg-secondary {
    background: var(--ds-surface-soft) !important;
    color: var(--ds-ink-3) !important;
    border: 1px solid var(--ds-border-soft);
}

/* ─── Señalización semántica de estados (USAR ESTAS en tablas) ───────
   Cinco señales, cinco significados — no mezclar con tints (los tints
   son categóricos: actividad, canales; esto es ESTADO de proceso). */
.badge-mono.is-success { background: var(--ds-success-bg) !important; color: var(--ds-success) !important; }
.badge-mono.is-warning { background: var(--ds-warning-bg) !important; color: var(--ds-warning) !important; }
.badge-mono.is-danger  { background: var(--ds-danger-bg) !important;  color: var(--ds-danger) !important; }
.badge-mono.is-info    { background: var(--ds-info-bg) !important;    color: var(--ds-info) !important; }
.badge-mono.is-neutral { background: var(--ds-surface-soft) !important; color: var(--ds-ink-3) !important; border: 1px solid var(--ds-border-soft); }

/* ─── ApexCharts → tokens del sistema ────────────────────────────────
   Leyenda/tooltip capitalizados (los nombres llegan en minúsculas desde
   JS), ejes en Geist Mono, tooltip con la sombra y radios del sistema. */
.apexcharts-legend-text {
    text-transform: capitalize;
    letter-spacing: -0.005em;
}
.apexcharts-yaxis-label,
.apexcharts-xaxis-label {
    font-family: var(--ds-font-mono) !important;
    font-feature-settings: 'tnum';
}
.apexcharts-tooltip {
    border: 1px solid var(--ds-border) !important;
    border-radius: var(--ds-radius-md) !important;
    box-shadow: var(--ds-shadow-md) !important;
    text-transform: capitalize;
}
.apexcharts-tooltip-title {
    background: var(--ds-surface-muted) !important;
    border-bottom: 1px solid var(--ds-border-soft) !important;
    font-family: var(--ds-font-mono) !important;
    font-weight: 600;
}
.apexcharts-tooltip-text-y-value {
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
}

/* ─── Pills slim — tabs de filtro discretos, forma cápsula ─────────── */
.nav-pills.nav-pills-slim { gap: 0.2rem; }
.nav-pills.nav-pills-slim .nav-link {
    font-size: 0.85rem;
    font-weight: 500;
    padding: 0.28rem 0.7rem !important;
    border-radius: 99px;
    color: var(--ds-ink-4);
}
.nav-pills.nav-pills-slim .nav-link .badge {
    font-family: var(--ds-font-mono);
    font-feature-settings: 'tnum';
    font-size: 0.8rem;
    padding: 0.08rem 0.35rem;
}
.nav-pills.nav-pills-slim .nav-link.active {
    background-color: var(--ds-ink) !important;
    color: var(--ds-bg) !important;
}
.nav-pills.nav-pills-slim .nav-link.active .badge {
    background-color: rgba(255, 255, 255, 0.16) !important;
    color: #fff !important;
}
/* Dark mode: la píldora activa usa --ds-ink, que se invierte a casi-blanco, así
   que el badge blanco-sobre-blanco quedaba ilegible. Sobre la píldora clara el
   conteo va en oscuro con velo oscuro. */
:root[data-theme="dark"] .nav-pills.nav-pills-slim .nav-link.active .badge {
    background-color: rgba(0, 0, 0, 0.16) !important;
    color: var(--ds-bg) !important;
}
/* Filtro canónico: .badge-button es el hook JS (click → DataTable.search);
   dentro de la cápsula slim conserva la forma cápsula sobre el radio md
   que .badge-button impone con !important. */
.nav-pills.nav-pills-slim .nav-link.badge-button { border-radius: 99px !important; }

/* Icon-tile — cuadrado redondeado con icono, patrón ElevenLabs para dar
   identidad visual a secciones, módulos y empty-states. */
.icon-tile {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: var(--ds-radius-md);
    background: var(--ds-surface-soft);
    color: var(--ds-ink-3);
    flex-shrink: 0;
}
.icon-tile .ti { font-size: 1.1rem !important; line-height: 1; }
.icon-tile.icon-tile-lg { width: 2.75rem; height: 2.75rem; border-radius: var(--ds-radius-lg); }
.icon-tile.icon-tile-lg .ti { font-size: 1.3rem !important; }
.icon-tile.icon-tile-sm { width: 1.75rem; height: 1.75rem; border-radius: var(--ds-radius-sm); }
.icon-tile.icon-tile-sm .ti { font-size: 0.95rem !important; }

/* Avatares existentes en las vistas (Inicio, Caja) usan bg-primary-lt /
   bg-yellow-lt como fondo gris/ámbar. En avatares el "soft neutro" se
   convierte en tinte azul para que la gente tenga color sin tocar EJS. */
.avatar.bg-primary-lt,
.avatar.bg-secondary-lt,
span.avatar.bg-primary-lt {
    background-color: var(--ds-accent-blue-bg) !important;
    color: var(--ds-accent-blue) !important;
}

/* Rotación estable de acentos para avatares en listas (filas del
   dashboard, tablas, paneles). El tono depende de la posición de la fila,
   no del contenido — suficiente para que una lista respire color.
   Excluye: avatares con foto (img / background-image) y avatares con
   .tint-* explícito, que siempre gana. */
.dashboard-list-row:nth-child(8n + 1) .avatar:not(img):not([style*='background-image']):not([class*='tint-']),
.table tbody tr:nth-child(8n + 1) .avatar:not(img):not([style*='background-image']):not([class*='tint-']) { background-color: var(--ds-accent-blue-bg) !important;   color: var(--ds-accent-blue) !important; }
.dashboard-list-row:nth-child(8n + 2) .avatar:not(img):not([style*='background-image']):not([class*='tint-']),
.table tbody tr:nth-child(8n + 2) .avatar:not(img):not([style*='background-image']):not([class*='tint-']) { background-color: var(--ds-accent-teal-bg) !important;   color: var(--ds-accent-teal) !important; }
.dashboard-list-row:nth-child(8n + 3) .avatar:not(img):not([style*='background-image']):not([class*='tint-']),
.table tbody tr:nth-child(8n + 3) .avatar:not(img):not([style*='background-image']):not([class*='tint-']) { background-color: var(--ds-accent-violet-bg) !important; color: var(--ds-accent-violet) !important; }
.dashboard-list-row:nth-child(8n + 4) .avatar:not(img):not([style*='background-image']):not([class*='tint-']),
.table tbody tr:nth-child(8n + 4) .avatar:not(img):not([style*='background-image']):not([class*='tint-']) { background-color: var(--ds-accent-amber-bg) !important;  color: var(--ds-accent-amber) !important; }
.dashboard-list-row:nth-child(8n + 5) .avatar:not(img):not([style*='background-image']):not([class*='tint-']),
.table tbody tr:nth-child(8n + 5) .avatar:not(img):not([style*='background-image']):not([class*='tint-']) { background-color: var(--ds-accent-rose-bg) !important;   color: var(--ds-accent-rose) !important; }
.dashboard-list-row:nth-child(8n + 6) .avatar:not(img):not([style*='background-image']):not([class*='tint-']),
.table tbody tr:nth-child(8n + 6) .avatar:not(img):not([style*='background-image']):not([class*='tint-']) { background-color: var(--ds-accent-cyan-bg) !important;   color: var(--ds-accent-cyan) !important; }
.dashboard-list-row:nth-child(8n + 7) .avatar:not(img):not([style*='background-image']):not([class*='tint-']),
.table tbody tr:nth-child(8n + 7) .avatar:not(img):not([style*='background-image']):not([class*='tint-']) { background-color: var(--ds-accent-green-bg) !important;  color: var(--ds-accent-green) !important; }
.dashboard-list-row:nth-child(8n + 8) .avatar:not(img):not([style*='background-image']):not([class*='tint-']),
.table tbody tr:nth-child(8n + 8) .avatar:not(img):not([style*='background-image']):not([class*='tint-']) { background-color: var(--ds-accent-orange-bg) !important; color: var(--ds-accent-orange) !important; }


/* ════════════════════════════════════════════════════════════════════════
   Quick-create — paleta "Nuevo" (estilo Linear × Handle design system)
   Botón genérico en la topbar + modal centralizado de acciones de creación.
   ════════════════════════════════════════════════════════════════════════ */
.btn-cta .btn-kbd {
    margin-left: 0.45rem;
    font-size: 0.72rem;
    line-height: 1.4;
    padding: 0.02rem 0.32rem;
    border: 0;
    border-radius: 4px;
    background: rgba(255, 255, 255, 0.18);
    color: inherit;
}

.qc-overlay {
    position: fixed;
    inset: 0;
    z-index: 1090;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: 12vh 1rem 1rem;
    background: rgba(10, 10, 10, 0.32);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    animation: qc-fade 0.12s ease;
}
.qc-overlay[hidden] { display: none; }
@keyframes qc-fade { from { opacity: 0; } to { opacity: 1; } }

.qc-modal {
    width: min(560px, 94vw);
    max-height: 70vh;
    display: flex;
    flex-direction: column;
    background: var(--ds-surface);
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-md);
    box-shadow: 0 24px 60px -12px rgba(10, 10, 10, 0.30), 0 0 0 1px rgba(10, 10, 10, 0.02);
    overflow: hidden;
    animation: qc-pop 0.14s cubic-bezier(0.2, 0.7, 0.3, 1);
}
@keyframes qc-pop {
    from { transform: translateY(-6px) scale(0.985); opacity: 0; }
    to   { transform: none; opacity: 1; }
}

.qc-search {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.85rem 1rem;
    border-bottom: 1px solid var(--ds-border-soft);
    flex: 0 0 auto;
}
.qc-search > .ti { font-size: 1.1rem; color: var(--ds-ink-4); }
.qc-search input {
    flex: 1 1 auto;
    border: 0;
    outline: 0;
    background: transparent;
    font-size: 1rem;
    color: var(--ds-ink);
    padding: 0;
}
.qc-search input::placeholder { color: var(--ds-ink-5); }

.qc-kbd,
.qc-foot kbd {
    font-family: var(--ds-font-mono);
    font-size: 0.7rem;
    line-height: 1.5;
    color: var(--ds-ink-4);
    background: var(--ds-surface-muted);
    border: 1px solid var(--ds-border);
    border-radius: 4px;
    padding: 0.04rem 0.34rem;
}

.qc-list { overflow-y: auto; padding: 0.4rem; }
.qc-empty { padding: 1.5rem; text-align: center; color: var(--ds-ink-4); font-size: 0.9rem; }

.qc-group {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 600;
    color: var(--ds-ink-5);
    padding: 0.6rem 0.6rem 0.3rem;
}

.qc-item {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    width: 100%;
    padding: 0.5rem 0.6rem;
    border: 0;
    background: transparent;
    border-radius: var(--ds-radius-sm);
    cursor: pointer;
    text-align: left;
    color: var(--ds-ink-2);
    transition: background-color 0.1s ease;
}
.qc-ico {
    flex: 0 0 auto;
    width: 1.9rem;
    height: 1.9rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--ds-radius-sm);
    background: var(--ds-surface-active);
    color: var(--ds-ink-3);
    transition: background-color 0.1s ease, color 0.1s ease;
}
.qc-ico .ti { font-size: 1.05rem; }
.qc-label { flex: 1 1 auto; font-size: 0.92rem; font-weight: 500; color: var(--ds-ink); }
.qc-meta { font-size: 0.78rem; color: var(--ds-ink-5); }

.qc-item.active { background: var(--ds-surface-muted); }
.qc-item.active .qc-ico { background: var(--ds-ink); color: var(--ds-bg); }

.qc-foot {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 0.6rem 1rem;
    border-top: 1px solid var(--ds-border-soft);
    font-size: 0.78rem;
    color: var(--ds-ink-4);
    flex: 0 0 auto;
}
.qc-foot span { display: inline-flex; align-items: center; gap: 0.3rem; }
.qc-foot-brand { margin-left: auto; font-weight: 600; }
.qc-foot-brand .ti { font-size: 0.9rem; }

body.qc-open { overflow: hidden; }

/* ── Búsqueda global: subtítulo apilado + estado de carga ── */
.qc-text {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    line-height: 1.25;
}
.qc-text .qc-label {
    flex: 0 0 auto;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.gs-sub {
    font-size: 0.76rem;
    color: var(--ds-ink-5);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.gs-loading {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.7rem 0.6rem;
    color: var(--ds-ink-4);
    font-size: 0.85rem;
}
.gs-spinner {
    width: 0.9rem;
    height: 0.9rem;
    border: 2px solid var(--ds-border-strong);
    border-top-color: var(--ds-ink);
    border-radius: 50%;
    animation: gs-spin 0.6s linear infinite;
}
@keyframes gs-spin { to { transform: rotate(360deg); } }

/* ════════════════════════════════════════════════════════════════════
   Drawer (offcanvas) — RECETA ESTÁNDAR DEL SISTEMA
   Un solo lenguaje para todos los paneles laterales: encabezado editorial
   (overline + título 1.25rem), cuerpo con scroll y footer de acciones que
   queda fijo abajo. Lo consumen promociones, bloqueos de agenda, cita,
   recordatorios, smart-schedule e historial de servicios.
   Uso: <div class="offcanvas offcanvas-end" style="width: 34rem; max-width: 95vw">
          <div class="offcanvas-header drawer-header">
            <div><p class="overline">Sección / Detalle</p>
                 <h2 class="offcanvas-title drawer-title">Título</h2></div>
            <button class="btn-close" data-bs-dismiss="offcanvas"></button>
          </div>
          <div class="offcanvas-body drawer-body d-flex flex-column">
            … contenido …
            <div class="drawer-footer">…botones…</div>
          </div>
        </div>
   ════════════════════════════════════════════════════════════════════ */
.drawer-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    padding: 1.2rem var(--ds-content-padding-x) 1rem;
    border-bottom: 1px solid var(--ds-border);
}
.drawer-header .overline { margin: 0 0 0.15rem; }
.drawer-title { font-size: 1.25rem; line-height: 1.15; margin: 0; }
.drawer-body { padding: 1.2rem var(--ds-content-padding-x); overflow-y: auto; }
/* Footer de acciones: vive dentro de un .offcanvas-body.d-flex.flex-column y
   se ancla al fondo con margin-top:auto; hereda el padding lateral del cuerpo. */
.drawer-footer {
    display: flex;
    gap: 0.5rem;
    padding-top: 0.9rem;
    margin-top: auto;
    border-top: 1px solid var(--ds-border);
}
.drawer-footer .btn { flex: 1; justify-content: center; }

/* ═══════════════════════════════════════════════════════════════════════
   Navegación por ÁREAS (tercer nivel, estilo Odoo)
   El rail solo muestra los módulos del área activa (+ los fijos); el
   conmutador abre un lanzador a pantalla completa que agrupa todo por área.
   ═══════════════════════════════════════════════════════════════════════ */

/* Rail acotado: los módulos de área arrancan OCULTOS (evita el flash de todos
   los íconos al cargar); el JS revela solo el área activa con rail-area-shown. */
.rail-item[data-area]:not([data-pinned]) { display: none; }
.rail-item.rail-area-shown { display: flex !important; }
.rail-item.rail-area-hidden { display: none !important; }
/* El divisor de módulos también arranca oculto; el JS lo muestra si el área no es 'general'. */
.rail-divider-area { display: none; }

/* Conmutador de área — botón del rail; el icono lleva el tinte del área. */
.rail-area-switch {
    border: 0;
    background: transparent;
    cursor: pointer;
    color: var(--ds-ink-2);
}
.rail-area-switch:hover { background: var(--ds-surface-muted); color: var(--ds-ink); }
.rail-divider-area { /* hook: separa fijos de módulos del área (hereda rail-divider) */ }

/* ── Lanzador a pantalla completa ─────────────────────────────────────── */
body.launcher-open { overflow: hidden; }
.app-launcher { position: fixed; inset: 0; z-index: 1090; display: flex; }
.app-launcher[hidden] { display: none; }
.app-launcher-backdrop {
    position: absolute; inset: 0;
    background: rgba(10, 10, 10, 0.42);
    backdrop-filter: blur(2px);
}
.app-launcher-panel {
    position: relative;
    margin: auto;
    width: min(880px, 92vw);
    /* Altura DEFINIDA: el panel no cambia de tamaño entre el estado vacío
       (invitación a buscar) y el de resultados; el cuerpo hace scroll dentro. */
    height: min(560px, 86vh);
    display: flex;
    flex-direction: column;
    background: var(--ds-surface);
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-xl);
    box-shadow: var(--ds-shadow-lg);
    overflow: hidden;
}
.app-launcher-head {
    display: flex; align-items: center; gap: 0.6rem;
    padding: 0.85rem 1.1rem;
    border-bottom: 1px solid var(--ds-border-soft);
}
.app-launcher-head > .ti { color: var(--ds-ink-4); }
.app-launcher-head input {
    flex: 1; border: 0; outline: 0; background: transparent;
    font-size: 1rem; color: var(--ds-ink);
}
.app-launcher-close {
    border: 0; background: transparent; color: var(--ds-ink-3);
    width: 2rem; height: 2rem; border-radius: var(--ds-radius-sm);
    display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
}
.app-launcher-close:hover { background: var(--ds-surface-muted); color: var(--ds-ink); }
.app-launcher-body { padding: 1rem 1.1rem 1.3rem; overflow-y: auto; flex: 1 1 auto; display: flex; flex-direction: column; }
.launcher-band { margin-bottom: 1.3rem; }
.launcher-band:last-child { margin-bottom: 0; }
.launcher-band-head { display: flex; align-items: center; gap: 0.55rem; margin-bottom: 0.75rem; }
.launcher-band-name {
    font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.08em;
    color: var(--ds-ink-3); font-weight: 600;
}
.launcher-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(7rem, 1fr));
    gap: 0.6rem;
}
/* Áreas: ~5 por fila pero con FLEX centrado, no grid rígido. Así, cuando el número
   de áreas no es múltiplo de 5 (hoy 11 con General), la última fila se CENTRA en
   vez de dejar un tile huérfano pegado a la izquierda. Reflowa a 3/2 por fila en
   pantallas angostas. La separación (gap: 0.6rem) la hereda de .launcher-grid. */
.launcher-grid-areas {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
}
.launcher-grid-areas .launcher-tile {
    flex: 0 1 calc((100% - 4 * 0.6rem) / 5);
}
@media (max-width: 760px) {
    .launcher-grid-areas .launcher-tile { flex-basis: calc((100% - 2 * 0.6rem) / 3); }
}
@media (max-width: 480px) {
    .launcher-grid-areas .launcher-tile { flex-basis: calc((100% - 1 * 0.6rem) / 2); }
}
.launcher-tile {
    display: flex; flex-direction: column; align-items: center; gap: 0.5rem;
    padding: 0.95rem 0.5rem; text-align: center;
    border: 1px solid var(--ds-border-soft);
    border-radius: var(--ds-radius-lg);
    color: var(--ds-ink); text-decoration: none;
}
.launcher-tile:hover { background: var(--ds-surface-muted); border-color: var(--ds-border-strong); }
.launcher-tile-label { font-size: 0.8rem; line-height: 1.2; }

/* ── Banda de resultados (búsqueda avanzada de submódulos/secciones) ────── */
.launcher-results { display: flex; flex-direction: column; gap: 0.2rem; }
.launcher-result {
    display: flex; align-items: center; gap: 0.7rem;
    padding: 0.5rem 0.55rem;
    border-radius: var(--ds-radius-md);
    color: var(--ds-ink); text-decoration: none;
}
.launcher-result:hover { background: var(--ds-surface-muted); }
.launcher-result-text { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.launcher-result-label { font-size: 0.88rem; line-height: 1.25; }
.launcher-result-path {
    font-size: 0.72rem; line-height: 1.2; color: var(--ds-ink-4);
}
.launcher-result-go { color: var(--ds-ink-5); opacity: 0; transition: opacity 0.12s ease; }
.launcher-result:hover .launcher-result-go { opacity: 1; }

.launcher-empty {
    display: flex; flex-direction: column; align-items: center; gap: 0.5rem;
    padding: 2.5rem 1rem; color: var(--ds-ink-4);
}
.launcher-empty .ti { font-size: 1.5rem; }

/* Estado inicial (sin búsqueda): invita a buscar por módulos. Crece para llenar
   la altura definida del panel y centrar el mensaje bajo la banda de áreas. */
.launcher-hint {
    flex: 1 1 auto;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 0.4rem; padding: 2rem 1rem; text-align: center;
    color: var(--ds-ink-4);
}
.launcher-hint .ti { font-size: 1.75rem; color: var(--ds-ink-5); }
.launcher-hint-title { font-size: 0.92rem; font-weight: 550; color: var(--ds-ink-3); }
.launcher-hint-sub { font-size: 0.8rem; color: var(--ds-ink-5); max-width: 22rem; }
.launcher-hint[hidden] { display: none; }

/* ── Panel rico por área: módulos como grupos con cabecera ─────────────── */
.panel-module { margin-bottom: 0.2rem; }
.panel-module-head {
    display: flex; align-items: center; gap: 0.5rem;
    margin: 0.9rem 0.75rem 0.3rem;
    font-size: 0.72rem; font-weight: 600; letter-spacing: 0.06em;
    text-transform: uppercase; color: var(--ds-ink-4); user-select: none;
}
.panel-module-head .ti { font-size: 0.95rem; color: var(--ds-ink-4); }
.panel-nav > .panel-module:first-child .panel-module-head { margin-top: 0.1rem; }

/* Tintes de ÁREA (rail activo + ícono del item activo en su panel).
   Administración (rose) y Configuración (violet) se definen arriba. */
.rail-item.current[data-section='consultorio'],
.rail-item[aria-expanded='true'][data-section='consultorio'] { background: var(--ds-accent-blue-bg); color: var(--ds-accent-blue); }
.rail-item.current[data-section='hospital'],
.rail-item[aria-expanded='true'][data-section='hospital'] { background: var(--ds-accent-cyan-bg); color: var(--ds-accent-cyan); }
.rail-item.current[data-section='recepcion'],
.rail-item[aria-expanded='true'][data-section='recepcion'] { background: var(--ds-accent-green-bg); color: var(--ds-accent-green); }
.rail-item.current[data-section='comercio'],
.rail-item[aria-expanded='true'][data-section='comercio'] { background: var(--ds-accent-amber-bg); color: var(--ds-accent-amber); }
.rail-item.current[data-section='analitica'],
.rail-item[aria-expanded='true'][data-section='analitica'] { background: var(--ds-accent-teal-bg); color: var(--ds-accent-teal); }
.panel-section[data-section='consultorio'] .panel-item.current .ti { color: var(--ds-accent-blue); }
.panel-section[data-section='hospital'] .panel-item.current .ti    { color: var(--ds-accent-cyan); }
.panel-section[data-section='recepcion'] .panel-item.current .ti   { color: var(--ds-accent-green); }
.panel-section[data-section='comercio'] .panel-item.current .ti    { color: var(--ds-accent-amber); }
.panel-section[data-section='analitica'] .panel-item.current .ti   { color: var(--ds-accent-teal); }

/* ── Menú de cuenta: organización activa + switcher (estilo Stripe) ─────── */
.acct-menu {
    width: 22.5rem; padding: 0.5rem;
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-xl);
    box-shadow: var(--ds-shadow-lg);
}
.acct-menu .dropdown-divider { margin: 0.5rem 0.15rem; border-color: var(--ds-border-soft); }

/* Encabezado de la org activa: tarjeta destacada con superficie suave */
.acct-org-head {
    display: flex; align-items: center; gap: 0.75rem;
    padding: 0.7rem 0.7rem;
    background: var(--ds-surface-muted);
    border: 1px solid var(--ds-border-soft);
    border-radius: var(--ds-radius-lg);
    margin-bottom: 0.15rem;
}
.acct-org-logo {
    width: 2.5rem; height: 2.5rem; flex: 0 0 auto; border-radius: var(--ds-radius-md);
    display: inline-flex; align-items: center; justify-content: center;
    color: #fff; font-weight: 600; font-size: 0.9rem; font-family: var(--ds-font-mono);
    box-shadow: var(--ds-shadow-xs), inset 0 0 0 1px rgba(0, 0, 0, 0.08);
}
.acct-org-logo.sm { width: 2rem; height: 2rem; font-size: 0.74rem; border-radius: var(--ds-radius-sm); }
.acct-org-info { min-width: 0; }
.acct-org-name { font-weight: 650; font-size: 0.95rem; line-height: 1.25; color: var(--ds-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.acct-org-meta { font-size: 0.78rem; line-height: 1.3; color: var(--ds-ink-4); }
.acct-section-label {
    font-family: var(--ds-font-mono); font-size: 0.72rem; text-transform: uppercase;
    letter-spacing: 0.1em; color: var(--ds-ink-5); font-weight: 600;
    margin: 0.55rem 0.65rem 0.3rem;
}
.acct-item {
    border-radius: var(--ds-radius-md);
    font-size: 0.88rem; color: var(--ds-ink-2);
    padding: 0.5rem 0.65rem;
    transition: background-color 0.12s ease;
}
.acct-item .ti { color: var(--ds-ink-4); transition: color 0.12s ease; }
.acct-item:hover, .acct-item:focus { background: var(--ds-surface-muted); }
.acct-item:hover .ti, .acct-item:focus .ti { color: var(--ds-ink-2); }

.acct-org-item {
    display: flex; align-items: center; gap: 0.7rem;
    border-radius: var(--ds-radius-md);
    padding: 0.45rem 0.55rem;
    border: 1px solid transparent;
    transition: background-color 0.12s ease, border-color 0.12s ease;
}
.acct-org-item:hover, .acct-org-item:focus { background: var(--ds-surface-muted); }
.acct-org-item-body { display: flex; flex-direction: column; min-width: 0; }
.acct-org-item-name { font-size: 0.88rem; font-weight: 550; color: var(--ds-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.acct-org-item-plan { font-size: 0.74rem; color: var(--ds-ink-4); }
.acct-org-item.is-active {
    background: var(--ds-surface);
    border-color: var(--ds-border);
    box-shadow: var(--ds-shadow-xs);
}
.acct-org-item.is-active:hover { background: var(--ds-surface); }
.acct-org-check { margin-left: auto; color: var(--ds-success); }

.acct-user-head { display: flex; flex-direction: column; padding: 0.35rem 0.65rem 0.25rem; }
.acct-user-name { font-weight: 600; font-size: 0.88rem; color: var(--ds-ink); }
.acct-user-role { font-size: 0.74rem; color: var(--ds-ink-4); }

/* Selector "Ver como rol" */
.acct-role-select {
    font-size: 0.85rem; border-radius: var(--ds-radius-md);
    border-color: var(--ds-border-strong);
}

/* ===========================================================================
   EXPERIENCIA MÓVIL  ·  capa responsive global (cascada a las 148 vistas)
   ---------------------------------------------------------------------------
   El chrome conmuta a < 992 px: topbar de escritorio oculta, mobile-topbar +
   cajón deslizable + barra inferior (zona del pulgar). Todo lo demás (tablas,
   modales, offcanvas, formularios, rejillas) se refluye aquí en un solo lugar.
   =========================================================================== */
:root {
    --ds-bottomnav-h: 58px;
    --ds-safe-bottom: env(safe-area-inset-bottom, 0px);
    --ds-safe-top: env(safe-area-inset-top, 0px);
}

/* ── Acciones del mobile-topbar (búsqueda + avisos a la derecha) ─────────── */
.mobile-topbar-actions { display: none; }
@media (max-width: 991.98px) {
    .mobile-topbar { padding-top: var(--ds-safe-top); height: calc(var(--ds-header-h) + var(--ds-safe-top)); }
    .mobile-topbar-brand { flex: 1 1 auto; min-width: 0; }
    .mobile-topbar-actions { display: inline-flex; align-items: center; gap: 0.15rem; margin-left: auto; }
    .mobile-topbar-action {
        width: 40px; height: 40px; flex: 0 0 40px;
        display: inline-flex; align-items: center; justify-content: center;
        background: transparent; border: 0; border-radius: var(--ds-radius-md);
        color: var(--ds-ink-3); text-decoration: none; cursor: pointer;
        transition: background-color 0.12s ease, color 0.12s ease;
    }
    .mobile-topbar-action:hover,
    .mobile-topbar-action:active { background: var(--ds-surface-active); color: var(--ds-ink); }
}

/* ── Cajón (drawer): el sidebar completo rail+panel se desliza desde la izq. ─ */
@media (max-width: 991.98px) {
    .app-sidebar {
        top: 0; bottom: 0;
        width: min(86vw, 320px);            /* deja ver el backdrop, ancho cómodo */
        max-width: 320px;
        padding-top: var(--ds-safe-top);
    }
    /* Sección activa: rail de iconos + panel etiquetado (dos paneles). */
    .app-panel { flex: 1 1 auto; min-width: 0; }
    .app-rail { flex: 0 0 var(--ds-rail-width); }
    /* Sin sección activa (Inicio): no hay panel que mostrar → el rail se
       convierte en un menú legible revelando las etiquetas (tooltips) en
       línea, en vez de dejar un panel vacío. */
    .app-sidebar.panel-collapsed { width: min(86vw, 320px); }
    .app-sidebar.panel-collapsed .app-panel { display: none; }
    .app-sidebar.panel-collapsed .app-rail { width: 100%; flex: 1 1 auto; }
    .app-sidebar.panel-collapsed .rail-items { padding: 0.4rem 0.5rem; }
    .app-sidebar.panel-collapsed .rail-item {
        width: 100%; height: 42px; margin: 0;
        justify-content: flex-start; gap: 0.85rem; padding: 0 0.7rem;
    }
    .app-sidebar.panel-collapsed .rail-item .rail-tooltip {
        position: static; opacity: 1; visibility: visible; transform: none;
        background: transparent; color: inherit; box-shadow: none;
        padding: 0; font-size: 0.92rem; font-weight: 500;
        pointer-events: auto; z-index: auto; transition: none;
    }
    .app-sidebar.panel-collapsed .rail-divider { margin: 0.4rem 0.7rem; width: auto; }
    .app-sidebar.panel-collapsed .rail-footer { padding: 0.4rem 0.5rem; }
    .app-sidebar.panel-collapsed .rail-lock { position: static; margin-left: auto; }
    /* El contenido nunca se desplaza por el cajón en móvil. */
    .page-wrapper,
    .app-sidebar.panel-collapsed ~ .page-wrapper { margin-left: 0; }
    /* Espacio para topbar (arriba) y barra inferior (abajo). */
    .page-wrapper {
        padding-top: calc(var(--ds-header-h) + var(--ds-safe-top));
        padding-bottom: calc(var(--ds-bottomnav-h) + var(--ds-safe-bottom) + 0.5rem);
    }
    /* La topbar de escritorio queda fuera; el lanzador a pantalla completa
       respeta el notch superior. */
    .app-launcher-panel { padding-top: var(--ds-safe-top); }
}

/* ── Barra de navegación inferior (zona del pulgar) ─────────────────────── */
.mobile-bottomnav { display: none; }
@media (max-width: 991.98px) {
    .mobile-bottomnav {
        position: fixed; left: 0; right: 0; bottom: 0; z-index: 1035;
        display: flex; align-items: stretch; justify-content: space-around;
        height: calc(var(--ds-bottomnav-h) + var(--ds-safe-bottom));
        padding-bottom: var(--ds-safe-bottom);
        background: var(--ds-surface);
        border-top: 1px solid var(--ds-border);
        box-shadow: 0 -2px 16px rgba(0, 0, 0, 0.06);
    }
    .mobile-bottomnav-item {
        flex: 1 1 0; min-width: 0;
        display: flex; flex-direction: column; align-items: center; justify-content: center;
        gap: 2px; padding: 0.3rem 0.2rem;
        background: transparent; border: 0; cursor: pointer; text-decoration: none;
        color: var(--ds-ink-4); font-size: 0.72rem; font-weight: 550; line-height: 1;
        transition: color 0.12s ease;
    }
    .mobile-bottomnav-item .ti { font-size: 1.2rem !important; }
    .mobile-bottomnav-item span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
    .mobile-bottomnav-item:hover,
    .mobile-bottomnav-item:active,
    .mobile-bottomnav-item.is-active { color: var(--ds-ink); }
    .mobile-bottomnav-item.is-active { color: var(--ds-accent, var(--ds-ink)); }
    /* FAB central "Nuevo" — sobresale por encima de la barra. */
    .mobile-bottomnav-fab {
        flex: 0 0 auto; align-self: center;
        width: 50px; height: 50px; margin-top: -16px;
        display: inline-flex; align-items: center; justify-content: center;
        border: 0; border-radius: 50%; cursor: pointer;
        background: var(--ds-ink); color: var(--ds-surface);
        box-shadow: 0 6px 18px rgba(0, 0, 0, 0.22);
        transition: transform 0.12s ease, box-shadow 0.12s ease;
    }
    .mobile-bottomnav-fab .ti { font-size: 1.5rem !important; }
    .mobile-bottomnav-fab:active { transform: scale(0.94); }
    /* En páginas sin topbar (POS), la barra inferior no se renderiza: el POS
       ocupa toda la pantalla con su propio chrome. */
}

/* ── Tablas: scroll horizontal seguro + densidad táctil ─────────────────── */
@media (max-width: 767.98px) {
    .table-responsive { -webkit-overflow-scrolling: touch; }
    .table { font-size: 0.8rem; }
    .table > :not(caption) > * > * { padding: 0.45rem 0.55rem; }
    /* DataTables: apila los controles superiores (buscar / longitud / botones). */
    .dataTables_wrapper .dataTables_length,
    .dataTables_wrapper .dataTables_filter,
    .dataTables_wrapper .dt-buttons {
        float: none; text-align: left; width: 100%; margin-bottom: 0.4rem;
    }
    .dataTables_wrapper .dataTables_filter input { width: 100%; margin-left: 0; }
    .dataTables_wrapper .dataTables_paginate { float: none; text-align: center; }
    .dataTables_wrapper .dataTables_info { text-align: center; }
}

/* ── Modales → hoja inferior (bottom sheet) en móvil ────────────────────── */
@media (max-width: 575.98px) {
    .modal-dialog:not(.modal-fullscreen) {
        margin: 0; min-height: 100%;
        display: flex; align-items: flex-end;
    }
    .modal-dialog:not(.modal-fullscreen) .modal-content {
        width: 100%;
        border-bottom-left-radius: 0; border-bottom-right-radius: 0;
        border-top-left-radius: var(--ds-radius-lg, 16px);
        border-top-right-radius: var(--ds-radius-lg, 16px);
        max-height: 92vh;
    }
    .modal-dialog:not(.modal-fullscreen) .modal-body { overflow-y: auto; }
    /* Offcanvas: ancho completo (lateral) o casi (inferior). */
    .offcanvas-start, .offcanvas-end { width: 92vw !important; max-width: 360px; }
    .offcanvas-bottom { height: 88vh !important; }
}

/* ── Formularios y toques: evita el zoom de iOS y agranda objetivos ──────── */
@media (max-width: 767.98px) {
    /* iOS hace zoom al enfocar un input < 16px. El reboot de Tabler pone
       `font-size: inherit` y el :root está en 13px, así que TODO input no
       whitelisted caía a 13px y hacía zoom. Regla blanket (gana por !important
       + orden de fuente) sobre cualquier input/select/textarea editable — cubre
       los custom (.cr-*, .vital-card-input, buscadores de overlay, .phone-input,
       selects nativos de filtros, etc.). Excluye los no-tipográficos. */
    input:not([type=hidden]):not([type=checkbox]):not([type=radio]):not([type=range]):not([type=color]):not([type=file]),
    select, textarea, .ts-control input { font-size: 16px !important; }
    /* Objetivos táctiles estilo app nativa: 44px (Apple HIG). Antes .btn quedaba
       en ~38px (--ds-control-h) y .btn-icon en 38px. */
    .btn { min-height: 44px; }
    .btn-icon { min-width: 44px; min-height: 44px; }
    /* Botoneras de cabecera y barras de acción se envuelven, no desbordan. */
    .page-header .btn-list,
    .page-header .d-flex.gap-2,
    .card-header .btn-list { flex-wrap: wrap; }
    /* El "Nuevo"/acciones a ancho completo cuando la cabecera ya envolvió. */
    .page-header .btn-list > .btn { flex: 1 1 auto; }
    /* Badges: en celdas/cabeceras apretadas de móvil no deben desbordar; los
       cortos (conteos) no se ven afectados. */
    .badge { max-width: 100%; white-space: normal; overflow-wrap: anywhere; }
}

/* ── Pills de filtro deslizables (misma cura que las nav-tabs) ────────────
   `.nav-pills-slim` no tenía overflow: unas vistas la fuerzan a `nowrap` y se
   cortaban (agenda/cirugía), otras envolvían a 2-3 filas. En <992px pasa a un
   scroller horizontal con scrollbar oculto. */
@media (max-width: 991.98px) {
    .nav-pills-slim {
        flex-wrap: nowrap !important;
        overflow-x: auto;
        overflow-y: hidden;
        scrollbar-width: none;
        -webkit-overflow-scrolling: touch;
    }
    .nav-pills-slim::-webkit-scrollbar { display: none; }
    .nav-pills-slim > .nav-item,
    .nav-pills-slim > li,
    .nav-pills-slim > .nav-link { flex: 0 0 auto; }
}

/* ── Guardas globales: sin scroll horizontal accidental, media fluida ────── */
@media (max-width: 991.98px) {
    html, body { overflow-x: hidden; }
    img, video, canvas, svg:not(.ti) { max-width: 100%; height: auto; }
    /* Contenedores de página al ancho real (sin gutters fijos que desborden). */
    .container, .container-xl, .container-fluid, .container-lg { padding-left: 0.75rem; padding-right: 0.75rem; }
    /* Barras de acción pegadas al fondo (p. ej. "Guardar") suben sobre la nav. */
    .sticky-bottom, .ds-actionbar, .page-actionbar, [data-sticky-bottom] {
        bottom: calc(var(--ds-bottomnav-h) + var(--ds-safe-bottom)) !important;
    }
}

/* ── Overlays y flotantes: que no se corten ni queden bajo el chrome móvil ── */
@media (max-width: 767.98px) {
    /* Menús desplegables sin ancho tope se salían del viewport (menús anchos o
       -end pegados al borde derecho). Se acotan al ancho de pantalla. */
    .dropdown-menu { max-width: calc(100vw - 1rem); }
    /* Toasts inferiores: subir sobre la barra de navegación + notch (antes bottom:0
       los dejaba encima/detrás de la nav). */
    #ds-toast-container.toast-bottom-right,
    #ds-toast-container.toast-bottom-left,
    #ds-toast-container.toast-bottom-center {
        bottom: calc(var(--ds-bottomnav-h) + var(--ds-safe-bottom) + 0.5rem);
    }
    /* Info clave que sólo vivía en dos columnas apretadas → una sola. */
    .msg-context { grid-template-columns: 1fr !important; }
}
/* ── Aviso "mejor en escritorio" (velo reutilizable) ─────────────────────
   Para pantallas densas de operación (POS mostrador, tableros) que no valen
   la pena reflowear a teléfono. Se muestra SOLO <768px; el usuario puede
   "ver de todos modos" (checkbox + :has, sin JS). Poner el markup de
   components/desktop-only-notice.ejs como primer hijo del contenedor. */
.desktop-only-veil { display: none; }
@media (max-width: 767.98px) {
    .desktop-only-veil {
        position: fixed; inset: 0; z-index: 3000;
        display: flex; align-items: center; justify-content: center;
        padding: 1.5rem calc(1.5rem + var(--ds-safe-bottom));
        background: var(--ds-surface);
    }
    .desktop-only-veil:has(.dov-dismiss:checked) { display: none; }
    .dov-card { max-width: 22rem; text-align: center; }
    .dov-icon {
        width: 3.2rem; height: 3.2rem; margin: 0 auto 1rem;
        display: inline-flex; align-items: center; justify-content: center;
        border-radius: var(--ds-radius-lg); background: var(--ds-surface-soft);
        color: var(--ds-ink-3);
    }
    .dov-icon .ti { font-size: 1.6rem !important; }
    .dov-card h2 { font-size: 1.15rem; font-weight: 600; color: var(--ds-ink); margin: 0 0 0.5rem; }
    .dov-card p { font-size: 0.9rem; color: var(--ds-ink-3); line-height: 1.55; margin: 0 0 1.25rem; }
    .dov-dismiss-btn { cursor: pointer; }
}

/* El panel de opciones de Tom-Select se dibujaba en z-60, DEBAJO del bottom nav
   (z-1035): un select bajo en la página abría su lista oculta tras la barra.
   Se eleva por encima del chrome. */
.ts-dropdown { z-index: 1040 !important; }
/* Acciones/checks revelados sólo en hover son inalcanzables en touch. El check de
   multiselección del explorador de estudios estaba opacity:0 (sólo hover) — se
   revela en dispositivos sin hover (mismo patrón que .fx-kebab-float). */
@media (hover: none) {
    .fx-check { opacity: 1 !important; }
}

/* ═════════════════════════════════════════════════════════════════════════
   Matriz de permisos (compartida por /users/roles y Crear/Editar usuario).
   Agrupada por ÁREA de navegación: banda de encabezado por área + filas de
   módulo. El agrupado empata 1:1 con el rail que el admin recorre. Jerarquía
   por tipografía/fondo (no por chrome), coherente con el DS.
   ═════════════════════════════════════════════════════════════════════════ */
.pm-matrix { width: 100%; }
.pm-matrix .pm-module-head { width: 42%; }
/* Banda de encabezado de área — franja mono uppercase, sin font-size inline. */
.pm-matrix tr.pm-area > td {
    background: var(--ds-surface-soft);
    border-top: 1px solid var(--ds-border-soft);
    padding: .5rem .75rem;
}
.pm-matrix tr.pm-area:first-child > td { border-top: 0; }
.pm-area-label {
    display: inline-flex; align-items: center; gap: .4rem;
    text-transform: uppercase; letter-spacing: .05em; font-weight: 650;
    font-size: .72rem; color: var(--ds-ink-3);
}
.pm-area-label .ti { color: var(--ds-ink-4); }
/* Chip "No activo" cuando el módulo de producto del área no está licenciado. */
.pm-area-off {
    display: inline-flex; align-items: center; gap: .25rem; margin-left: .55rem;
    padding: .05rem .4rem; border-radius: 999px;
    border: 1px solid var(--ds-border-soft); background: var(--ds-surface);
    font-size: .66rem; text-transform: uppercase; letter-spacing: .04em;
    color: var(--ds-ink-4); vertical-align: middle;
}
.pm-matrix tr.pm-row > td { padding: .5rem .75rem; }
.pm-matrix td.pm-module { color: var(--ds-ink-2); font-weight: 550; }
.pm-matrix tr.pm-row:hover > td { background: var(--ds-surface-muted); }
/* Área inactiva: filas y encabezado atenuados, pero SIGUEN editables (el admin
   puede pre-configurar permisos aunque el módulo aún no esté licenciado). */
.pm-matrix tr.is-off.pm-area > td .pm-area-label,
.pm-matrix tr.is-off.pm-row > td.pm-module { opacity: .55; }
.pm-matrix tr.is-off.pm-row .form-check-input:not(:checked) { opacity: .5; }

/* ── Triage de idoneidad para reconstrucción MPR/3D (pestaña Estudios) ──────
   Panel que clasifica las series del paciente en recomendada / usables /
   descartadas. Usa tokens --ds-* → hereda dark mode automáticamente. */
.dicom-triage {
    margin: var(--ds-space-3) 0 var(--ds-space-5);
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-lg);
    background: var(--ds-surface);
    padding: var(--ds-space-4);
}
.dicom-triage-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--ds-space-3);
    margin-bottom: var(--ds-space-3);
}
.dicom-triage-head h3 {
    margin: 0;
    font-size: 0.95rem;
    font-weight: 650;
    color: var(--ds-ink);
    display: flex;
    align-items: center;
}
.dicom-triage-policy {
    font-size: 0.72rem;
    color: var(--ds-surface-muted);
    border: 1px solid var(--ds-border-soft);
    border-radius: var(--ds-radius-sm);
    padding: 2px 8px;
    white-space: nowrap;
}
.dicom-triage-empty {
    color: var(--ds-surface-muted);
    font-size: 0.85rem;
    padding: var(--ds-space-2) 0;
}
.dicom-triage-group { margin-top: var(--ds-space-3); }
.dtg-label {
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--ds-surface-muted);
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: var(--ds-space-2);
    cursor: default;
}
details.dtg-discarded > summary { cursor: pointer; list-style: none; }
details.dtg-discarded > summary::-webkit-details-marker { display: none; }
.dtg-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
    gap: var(--ds-space-2);
}
/* Tarjeta de serie (botón). Acciona el visor 3D si es usable. */
.dicom-triage-card {
    text-align: left;
    width: 100%;
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-md);
    background: var(--ds-surface-soft);
    padding: var(--ds-space-3);
    display: flex;
    flex-direction: column;
    gap: 4px;
    transition: border-color 0.15s, box-shadow 0.15s, transform 0.1s;
}
.dicom-triage-card[data-open3d] { cursor: pointer; }
.dicom-triage-card[data-open3d]:hover {
    border-color: var(--ds-accent-violet);
    box-shadow: var(--ds-shadow-sm);
}
.dicom-triage-card[data-open3d]:active { transform: translateY(1px); }
.dicom-triage-card.is-primary {
    border-color: var(--ds-accent-violet);
    background: var(--ds-accent-violet-bg);
    max-width: 420px;
}
.dicom-triage-card.is-discarded { opacity: 0.72; cursor: not-allowed; }
.dtc-head { display: flex; align-items: baseline; gap: 8px; }
.dtc-mod {
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    color: var(--ds-accent-violet);
    background: var(--ds-accent-violet-bg);
    border-radius: var(--ds-radius-sm);
    padding: 1px 6px;
    flex: none;
}
.dtc-title {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--ds-ink);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.dtc-score {
    margin-left: auto;
    font-family: var(--ds-font-mono);
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--ds-success);
    flex: none;
}
.dtc-geo {
    font-size: 0.72rem;
    color: var(--ds-surface-muted);
    font-family: var(--ds-font-mono);
}
.dtc-reason {
    font-size: 0.72rem;
    color: var(--ds-surface-muted);
}
.dicom-triage-card.is-discarded .dtc-reason { color: var(--ds-danger); }
