/*! Flora · CSS · compilado 2026-04-26 07:27:25 */

/* ===== resources/css/01-reset.css ===== */
/* ==========================================================================
   Flora · Reset
   Normalización mínima y moderna. No imponemos estilo, sólo neutralizamos
   inconsistencias entre navegadores.
   ========================================================================== */

*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    -webkit-text-size-adjust: 100%;
    -moz-tab-size: 4;
    tab-size: 4;
    line-height: 1.5;
}

body {
    margin: 0;
    min-height: 100vh;
    font-family: inherit;
    line-height: inherit;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
}

h1, h2, h3, h4, h5, h6 {
    margin: 0;
    font-size: inherit;
    font-weight: inherit;
}

p,
figure,
blockquote,
dl,
dd {
    margin: 0;
}

ul[role="list"],
ol[role="list"] {
    list-style: none;
    padding: 0;
    margin: 0;
}

a {
    color: inherit;
    text-decoration: inherit;
}

img,
picture,
video,
canvas,
svg {
    display: block;
    max-width: 100%;
    height: auto;
}

input,
button,
textarea,
select {
    font: inherit;
    color: inherit;
    background: transparent;
    border: 0;
    margin: 0;
    padding: 0;
}

button {
    cursor: pointer;
    text-align: inherit;
}

button:disabled,
[disabled] {
    cursor: not-allowed;
}

textarea {
    resize: vertical;
}

table {
    border-collapse: collapse;
    border-spacing: 0;
}

hr {
    height: 1px;
    margin: 0;
    border: 0;
    background: currentColor;
    opacity: 0.1;
}

:focus:not(:focus-visible) {
    outline: none;
}

::selection {
    background: var(--fl-acento);
    color: var(--fl-acento-texto-sobre);
}


/* ===== resources/css/02-tokens-base.css ===== */
/* ==========================================================================
   Flora · Tokens base
   Valores que NO cambian entre modo claro y oscuro ni entre paletas.
   Espaciado, radios, sombras, transiciones, capas z-index.
   ========================================================================== */

:root {
    /* Espaciado — base 4px */
    --fl-sp-0: 0;
    --fl-sp-0-5: 0.125rem;   /* 2px  */
    --fl-sp-1: 0.25rem;      /* 4px  */
    --fl-sp-1-5: 0.375rem;   /* 6px  */
    --fl-sp-2: 0.5rem;       /* 8px  */
    --fl-sp-2-5: 0.625rem;   /* 10px */
    --fl-sp-3: 0.75rem;      /* 12px */
    --fl-sp-4: 1rem;         /* 16px */
    --fl-sp-5: 1.25rem;      /* 20px */
    --fl-sp-6: 1.5rem;       /* 24px */
    --fl-sp-7: 1.75rem;      /* 28px */
    --fl-sp-8: 2rem;         /* 32px */
    --fl-sp-10: 2.5rem;      /* 40px */
    --fl-sp-12: 3rem;        /* 48px */
    --fl-sp-16: 4rem;        /* 64px */
    --fl-sp-20: 5rem;        /* 80px */
    --fl-sp-24: 6rem;        /* 96px */

    /* Radios de borde — escala tensa, afilada. No los valores safe de Tailwind.
       Prefiere 5/10 sobre 6/8 — sutil diferencia que acumula identidad. */
    --fl-r-0: 0;
    --fl-r-xs: 1px;
    --fl-r-sm: 3px;
    --fl-r-md: 5px;          /* inputs, chips, buttons */
    --fl-r-lg: 10px;         /* cards, modales */
    --fl-r-xl: 14px;
    --fl-r-2xl: 20px;
    --fl-r-full: 9999px;

    /* Anchos de borde */
    --fl-b-0: 0;
    --fl-b-1: 1px;
    --fl-b-2: 2px;
    --fl-b-4: 4px;

    /* Sombras — sutiles, atemporales */
    --fl-sombra-0: 0 0 #0000;
    --fl-sombra-xs: 0 1px 2px 0 rgb(0 0 0 / 0.05);
    --fl-sombra-sm: 0 1px 3px 0 rgb(0 0 0 / 0.08), 0 1px 2px -1px rgb(0 0 0 / 0.04);
    --fl-sombra-md: 0 4px 6px -1px rgb(0 0 0 / 0.08), 0 2px 4px -2px rgb(0 0 0 / 0.04);
    --fl-sombra-lg: 0 10px 15px -3px rgb(0 0 0 / 0.08), 0 4px 6px -4px rgb(0 0 0 / 0.04);
    --fl-sombra-xl: 0 20px 25px -5px rgb(0 0 0 / 0.10), 0 8px 10px -6px rgb(0 0 0 / 0.04);
    --fl-sombra-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25);
    --fl-sombra-interna: inset 0 2px 4px 0 rgb(0 0 0 / 0.04);

    /* Anillo de foco (usa el acento activo) */
    --fl-foco-ancho: 3px;
    --fl-foco-offset: 2px;

    /* Transiciones */
    --fl-t-rapido: 120ms;
    --fl-t-medio: 200ms;
    --fl-t-lento: 320ms;

    --fl-ease-salida: cubic-bezier(0.16, 1, 0.3, 1);
    --fl-ease-entrada: cubic-bezier(0.7, 0, 0.84, 0);
    --fl-ease-inout: cubic-bezier(0.65, 0, 0.35, 1);
    /* Resorte suavizado — overshoot reducido (1.15 vs 1.56 original) para
       evitar el "trabón" visual en hovers/scales. El nombre histórico se
       mantiene porque muchos componentes lo referencian. */
    --fl-ease-resorte: cubic-bezier(0.34, 1.15, 0.64, 1);
    --fl-ease-resorte-fuerte: cubic-bezier(0.34, 1.56, 0.64, 1);

    /* Capas z-index — ordenadas y con nombres semánticos */
    --fl-z-base: 0;
    --fl-z-elevado: 10;
    --fl-z-pegajoso: 100;      /* sticky headers */
    --fl-z-dropdown: 1000;
    --fl-z-menu-contextual: 1100;
    --fl-z-overlay: 1200;       /* backdrop de modales */
    --fl-z-modal: 1300;
    --fl-z-popover: 1400;
    --fl-z-tooltip: 1500;
    --fl-z-aviso: 1600;         /* toasts */
    --fl-z-maximo: 9999;

    /* Breakpoints (referencia — también hay utilidades @media) */
    --fl-bp-sm: 640px;
    --fl-bp-md: 768px;
    --fl-bp-lg: 1024px;
    --fl-bp-xl: 1280px;
    --fl-bp-2xl: 1536px;

    /* Tipografía — familias.
       Sans para UI, Serif para títulos-display (carácter editorial),
       Mono para código. Todas fallback a system fonts. */
    --fl-fuente-sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI",
        Roboto, "Helvetica Neue", Arial, sans-serif;
    --fl-fuente-display: "New York", "Iowan Old Style", "Palatino Linotype",
        Palatino, "URW Palladio L", P052, "Hoefler Text", Georgia, serif;
    --fl-fuente-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo,
        Monaco, Consolas, "Liberation Mono", monospace;

    /* Escala tipográfica — tamaños */
    --fl-texto-2xs: 0.6875rem;  /* 11px */
    --fl-texto-xs: 0.75rem;     /* 12px */
    --fl-texto-sm: 0.875rem;    /* 14px */
    --fl-texto-base: 1rem;      /* 16px */
    --fl-texto-lg: 1.125rem;    /* 18px */
    --fl-texto-xl: 1.25rem;     /* 20px */
    --fl-texto-2xl: 1.5rem;     /* 24px */
    --fl-texto-3xl: 1.875rem;   /* 30px */
    --fl-texto-4xl: 2.25rem;    /* 36px */
    --fl-texto-5xl: 3rem;       /* 48px */

    /* Line-height */
    --fl-lh-compacta: 1.2;
    --fl-lh-ajustada: 1.375;
    --fl-lh-normal: 1.5;
    --fl-lh-relajada: 1.75;

    /* Pesos */
    --fl-peso-regular: 400;
    --fl-peso-medio: 500;
    --fl-peso-semibold: 600;
    --fl-peso-bold: 700;

    /* Letter-spacing */
    --fl-ls-compacto: -0.02em;
    --fl-ls-normal: 0;
    --fl-ls-amplio: 0.02em;
    --fl-ls-mayus: 0.06em;

    /* Tamaños de control — altura de botones, inputs, etc. */
    --fl-alto-control-xs: 24px;
    --fl-alto-control-sm: 32px;
    --fl-alto-control-md: 40px;
    --fl-alto-control-lg: 48px;

    /* Densidad de componentes — compacto vs. cómodo */
    --fl-densidad-fila: 44px;   /* filas de tabla */
    --fl-densidad-fila-compacta: 36px;
}


/* ===== resources/css/03-tokens-neutros.css ===== */
/* ==========================================================================
   Flora · Neutros
   Escala de grises fija + tokens semánticos SÓLO en modo claro.
   El modo oscuro dejó de ser un eje independiente: ahora vive como la
   8ª paleta `oscuro` en 04-tokens-enfasis.css. Elegir esa paleta activa
   los neutros invertidos.
   ========================================================================== */

:root {
    /* Escala gris neutra — valores crudos */
    --fl-neutro-0: #ffffff;
    --fl-neutro-50: #fafafa;
    --fl-neutro-100: #f5f5f5;
    --fl-neutro-150: #ededed;
    --fl-neutro-200: #e5e5e5;
    --fl-neutro-300: #d4d4d4;
    --fl-neutro-400: #a3a3a3;
    --fl-neutro-500: #737373;
    --fl-neutro-600: #525252;
    --fl-neutro-700: #404040;
    --fl-neutro-800: #262626;
    --fl-neutro-850: #1c1c1c;
    --fl-neutro-900: #171717;
    --fl-neutro-950: #0a0a0a;
    --fl-neutro-1000: #000000;
}

/* --------------------------------------------------------------------------
   Tokens semánticos — modo claro (default para las 7 paletas claras)
   -------------------------------------------------------------------------- */
:root {
    /* Fondos */
    --fl-fondo: var(--fl-neutro-0);
    --fl-fondo-sutil: var(--fl-neutro-50);
    --fl-fondo-tenue: var(--fl-neutro-100);

    /* Superficies — cards, tablas, modales */
    --fl-superficie: var(--fl-neutro-0);
    --fl-superficie-elevada: var(--fl-neutro-0);
    --fl-superficie-hover: var(--fl-neutro-50);
    --fl-superficie-activa: var(--fl-neutro-100);
    --fl-superficie-muda: var(--fl-neutro-100);
    --fl-superficie-invertida: var(--fl-neutro-900);

    /* Bordes */
    --fl-borde: var(--fl-neutro-200);
    --fl-borde-sutil: var(--fl-neutro-150);
    --fl-borde-fuerte: var(--fl-neutro-300);
    --fl-borde-intenso: var(--fl-neutro-400);

    /* Textos */
    --fl-texto: var(--fl-neutro-900);
    --fl-texto-fuerte: var(--fl-neutro-950);
    --fl-texto-suave: var(--fl-neutro-600);
    --fl-texto-tenue: var(--fl-neutro-500);
    --fl-texto-deshabilitado: var(--fl-neutro-400);
    --fl-texto-invertido: var(--fl-neutro-0);
    --fl-texto-enlace: var(--fl-acento);

    /* Overlays */
    --fl-overlay: rgb(0 0 0 / 0.5);
    --fl-overlay-sutil: rgb(0 0 0 / 0.2);

    color-scheme: light;
}

/* --------------------------------------------------------------------------
   Paleta "oscuro" — invierte los neutros semánticos. La única paleta que
   cambia el fondo al oscuro. El resto vive siempre en claro.
   -------------------------------------------------------------------------- */
[data-fl-enfasis="oscuro"] {
    /* Fondos */
    --fl-fondo: var(--fl-neutro-950);
    --fl-fondo-sutil: var(--fl-neutro-900);
    --fl-fondo-tenue: var(--fl-neutro-850);

    /* Superficies */
    --fl-superficie: var(--fl-neutro-900);
    --fl-superficie-elevada: var(--fl-neutro-850);
    --fl-superficie-hover: var(--fl-neutro-800);
    --fl-superficie-activa: var(--fl-neutro-700);
    --fl-superficie-muda: var(--fl-neutro-800);
    --fl-superficie-invertida: var(--fl-neutro-50);

    /* Bordes */
    --fl-borde: var(--fl-neutro-800);
    --fl-borde-sutil: var(--fl-neutro-850);
    --fl-borde-fuerte: var(--fl-neutro-700);
    --fl-borde-intenso: var(--fl-neutro-600);

    /* Textos */
    --fl-texto: var(--fl-neutro-50);
    --fl-texto-fuerte: var(--fl-neutro-0);
    --fl-texto-suave: var(--fl-neutro-400);
    --fl-texto-tenue: var(--fl-neutro-500);
    --fl-texto-deshabilitado: var(--fl-neutro-600);
    --fl-texto-invertido: var(--fl-neutro-950);

    /* Overlays */
    --fl-overlay: rgb(0 0 0 / 0.7);
    --fl-overlay-sutil: rgb(0 0 0 / 0.4);

    color-scheme: dark;
}


/* ===== resources/css/04-tokens-enfasis.css ===== */
/* ==========================================================================
   Flora · Énfasis
   8 énfasis — 7 de color sobre fondo claro + 1 especial `oscuro` que es el
   único con fondo oscuro. El usuario elige UNA paleta y esa define tanto
   el acento como el modo (claro/oscuro). Sin eje tema separado.

   Mapeo Tailwind → nombre Flora:
     blue    → azul        (default claro)
     emerald → verde
     amber   → naranja     (ámbar dorado — el naranja de mate cocido)
     red     → rojo
     pink    → rosa
     violet  → violeta
     neutral → gris
     indigo  → oscuro      (única paleta con fondo negro + acentos indigo)

   Los tokens semánticos (--fl-acento, --fl-acento-hover, etc.) se mapean
   en 05-tokens-acento.css — no repetimos código por énfasis.
   Activación: atributo [data-fl-enfasis="nombre"] en <html>.
   Énfasis por defecto: azul. Si el OS es dark al primer carga, se aplica
   automáticamente "oscuro" (ver 02-tema.js).
   ========================================================================== */

/* AZUL — blue. Default. Saturado, ni pastel ni industrial. */
:root,
[data-fl-enfasis="azul"] {
    --fl-acento-50:  #eff6ff;
    --fl-acento-100: #dbeafe;
    --fl-acento-200: #bfdbfe;
    --fl-acento-300: #93c5fd;
    --fl-acento-400: #60a5fa;
    --fl-acento-500: #3b82f6;
    --fl-acento-600: #2563eb;
    --fl-acento-700: #1d4ed8;
    --fl-acento-800: #1e40af;
    --fl-acento-900: #1e3a8a;
    --fl-acento-950: #172554;
}

/* VERDE — emerald. Verde limpio, vegetal, ácido en tonos claros. */
[data-fl-enfasis="verde"] {
    --fl-acento-50:  #ecfdf5;
    --fl-acento-100: #d1fae5;
    --fl-acento-200: #a7f3d0;
    --fl-acento-300: #6ee7b7;
    --fl-acento-400: #34d399;
    --fl-acento-500: #10b981;
    --fl-acento-600: #059669;
    --fl-acento-700: #047857;
    --fl-acento-800: #065f46;
    --fl-acento-900: #064e3b;
    --fl-acento-950: #022c22;
}

/* NARANJA — amber. Ámbar dorado cálido. El "naranja" de la calle. */
[data-fl-enfasis="naranja"] {
    --fl-acento-50:  #fffbeb;
    --fl-acento-100: #fef3c7;
    --fl-acento-200: #fde68a;
    --fl-acento-300: #fcd34d;
    --fl-acento-400: #fbbf24;
    --fl-acento-500: #f59e0b;
    --fl-acento-600: #d97706;
    --fl-acento-700: #b45309;
    --fl-acento-800: #92400e;
    --fl-acento-900: #78350f;
    --fl-acento-950: #451a03;
}

/* ROJO — red. Rojo-rosa tierra, coral y ladrillo. */
[data-fl-enfasis="rojo"] {
    --fl-acento-50:  #fef2f2;
    --fl-acento-100: #fee2e2;
    --fl-acento-200: #fecaca;
    --fl-acento-300: #fca5a5;
    --fl-acento-400: #f87171;
    --fl-acento-500: #ef4444;
    --fl-acento-600: #dc2626;
    --fl-acento-700: #b91c1c;
    --fl-acento-800: #991b1b;
    --fl-acento-900: #7f1d1d;
    --fl-acento-950: #450a0a;
}

/* ROSA — pink. Rosa saturado, magenta que se acerca. */
[data-fl-enfasis="rosa"] {
    --fl-acento-50:  #fdf2f8;
    --fl-acento-100: #fce7f3;
    --fl-acento-200: #fbcfe8;
    --fl-acento-300: #f9a8d4;
    --fl-acento-400: #f472b6;
    --fl-acento-500: #ec4899;
    --fl-acento-600: #db2777;
    --fl-acento-700: #be185d;
    --fl-acento-800: #9d174d;
    --fl-acento-900: #831843;
    --fl-acento-950: #500724;
}

/* VIOLETA — violet. Eléctrico, más vivo que el estándar. */
[data-fl-enfasis="violeta"] {
    --fl-acento-50:  #f5f3ff;
    --fl-acento-100: #ede9fe;
    --fl-acento-200: #ddd6fe;
    --fl-acento-300: #c4b5fd;
    --fl-acento-400: #a78bfa;
    --fl-acento-500: #8b5cf6;
    --fl-acento-600: #7c3aed;
    --fl-acento-700: #6d28d9;
    --fl-acento-800: #5b21b6;
    --fl-acento-900: #4c1d95;
    --fl-acento-950: #2e1065;
}

/* GRIS — neutral. Gris puro, para productos que rechazan el color. */
[data-fl-enfasis="gris"] {
    --fl-acento-50:  #fafafa;
    --fl-acento-100: #f5f5f5;
    --fl-acento-200: #e5e5e5;
    --fl-acento-300: #d4d4d4;
    --fl-acento-400: #a3a3a3;
    --fl-acento-500: #737373;
    --fl-acento-600: #525252;
    --fl-acento-700: #404040;
    --fl-acento-800: #262626;
    --fl-acento-900: #171717;
    --fl-acento-950: #0a0a0a;
}

/* OSCURO — indigo Tailwind sobre fondo casi negro. La única paleta con
   modo oscuro. Diseñada para que el indigo se encienda en el dark. */
[data-fl-enfasis="oscuro"] {
    --fl-acento-50:  #eef2ff;
    --fl-acento-100: #e0e7ff;
    --fl-acento-200: #c7d2fe;
    --fl-acento-300: #a5b4fc;
    --fl-acento-400: #818cf8;
    --fl-acento-500: #6366f1;
    --fl-acento-600: #4f46e5;
    --fl-acento-700: #4338ca;
    --fl-acento-800: #3730a3;
    --fl-acento-900: #312e81;
    --fl-acento-950: #1e1b4b;
}


/* ===== resources/css/05-tokens-acento.css ===== */
/* ==========================================================================
   Flora · Tokens semánticos del acento
   Mapea la escala cruda de la paleta activa a tokens de uso (acento,
   hover, activo, suave, borde, etc.). El mapeo default sirve para las
   7 paletas claras. La paleta "oscuro" tiene su propio override para que
   el acento se aclare y contraste con el fondo negro.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Default — 7 paletas claras
   -------------------------------------------------------------------------- */
:root {
    --fl-acento:               var(--fl-acento-600);
    --fl-acento-hover:         var(--fl-acento-700);
    --fl-acento-activo:        var(--fl-acento-800);
    --fl-acento-suave:         var(--fl-acento-50);
    --fl-acento-suave-hover:   var(--fl-acento-100);
    --fl-acento-borde:         var(--fl-acento-200);
    --fl-acento-borde-fuerte:  var(--fl-acento-400);
    --fl-acento-enlace:        var(--fl-acento-600);
    --fl-acento-texto:         var(--fl-acento-700);
    --fl-acento-texto-sobre:   var(--fl-neutro-0);
    --fl-acento-foco:          color-mix(in srgb, var(--fl-acento) 35%, transparent);

    /* Destaque — patrón de resalte de alto contraste inspirado en flora vieja.
       El color más fuerte y oscuro de la paleta + texto blanco.
       Se usa con las utilidades .u-destaque* y en componentes de énfasis
       (heros, badges sólidos, banners informativos, headers premium). */
    --fl-destaque-fondo:       var(--fl-acento-900);
    --fl-destaque-fondo-hover: var(--fl-acento-800);
    --fl-destaque-texto:       var(--fl-neutro-0);
    --fl-destaque-borde:       var(--fl-acento-700);
    --fl-destaque-gradiente:   linear-gradient(
                                   135deg,
                                   var(--fl-acento-900) 0%,
                                   var(--fl-acento-700) 55%,
                                   var(--fl-acento-800) 100%
                               );
}

/* --------------------------------------------------------------------------
   Paleta "oscuro" — acento aclarado para contrastar con fondo negro.
   Destaque NO se invierte al extremo pastel (eso era el bug clásico de
   flora vieja — se veía todo claritongo). Usa shades profundos saturados
   (800/900) que mantienen color sin blanquearse contra el fondo oscuro.
   Texto siempre blanco — el mismo patrón bandera: color fuerte + blanco.
   -------------------------------------------------------------------------- */
[data-fl-enfasis="oscuro"] {
    --fl-acento:               var(--fl-acento-500);
    --fl-acento-hover:         var(--fl-acento-400);
    --fl-acento-activo:        var(--fl-acento-300);
    --fl-acento-suave:         color-mix(in srgb, var(--fl-acento-500) 16%, transparent);
    --fl-acento-suave-hover:   color-mix(in srgb, var(--fl-acento-500) 26%, transparent);
    --fl-acento-borde:         var(--fl-acento-800);
    --fl-acento-borde-fuerte:  var(--fl-acento-600);
    --fl-acento-enlace:        var(--fl-acento-400);
    --fl-acento-texto:         var(--fl-acento-300);
    --fl-acento-texto-sobre:   var(--fl-neutro-0);
    --fl-acento-foco:          color-mix(in srgb, var(--fl-acento) 45%, transparent);

    /* Destaque saturado profundo — color fuerte + blanco. Consistente con
       las 7 paletas claras que también usan acento-800/900 como destaque. */
    --fl-destaque-fondo:       var(--fl-acento-800);
    --fl-destaque-fondo-hover: var(--fl-acento-700);
    --fl-destaque-texto:       var(--fl-neutro-0);
    --fl-destaque-borde:       var(--fl-acento-600);
    --fl-destaque-gradiente:   linear-gradient(
                                   135deg,
                                   var(--fl-acento-900) 0%,
                                   var(--fl-acento-700) 55%,
                                   var(--fl-acento-800) 100%
                               );
}

/* --------------------------------------------------------------------------
   Paleta "gris" — texto sobre acento ajustado porque el "acento" gris
   puede tener bajo contraste con blanco.
   -------------------------------------------------------------------------- */
[data-fl-enfasis="gris"] {
    --fl-acento-texto-sobre:   var(--fl-neutro-0);
}


/* ===== resources/css/06-tokens-semanticos.css ===== */
/* ==========================================================================
   Flora · Tokens semánticos fijos
   Colores de estado (éxito, error, advertencia, info) INDEPENDIENTES de la
   paleta elegida. Una alerta de error siempre es roja aunque el usuario
   haya elegido la paleta violeta. Son señales, no estilo.

   Default = paletas claras. Override para [data-fl-enfasis="oscuro"] que
   aclara los semánticos para contrastar con el fondo negro.
   ========================================================================== */

:root {
    /* Éxito — verde */
    --fl-exito:              #059669;
    --fl-exito-hover:        #047857;
    --fl-exito-suave:        #ecfdf5;
    --fl-exito-borde:        #a7f3d0;
    --fl-exito-texto:        #065f46;
    --fl-exito-texto-sobre:  #ffffff;

    /* Error — rojo */
    --fl-error:              #dc2626;
    --fl-error-hover:        #b91c1c;
    --fl-error-suave:        #fef2f2;
    --fl-error-borde:        #fecaca;
    --fl-error-texto:        #991b1b;
    --fl-error-texto-sobre:  #ffffff;

    /* Advertencia — ámbar */
    --fl-advertencia:              #d97706;
    --fl-advertencia-hover:        #b45309;
    --fl-advertencia-suave:        #fffbeb;
    --fl-advertencia-borde:        #fde68a;
    --fl-advertencia-texto:        #92400e;
    --fl-advertencia-texto-sobre:  #ffffff;

    /* Info — azul */
    --fl-info:              #2563eb;
    --fl-info-hover:        #1d4ed8;
    --fl-info-suave:        #eff6ff;
    --fl-info-borde:        #bfdbfe;
    --fl-info-texto:        #1e40af;
    --fl-info-texto-sobre:  #ffffff;
}

/* Override para la paleta "oscuro" — colores aclarados para el fondo negro */
[data-fl-enfasis="oscuro"] {
    --fl-exito:              #10b981;
    --fl-exito-hover:        #34d399;
    --fl-exito-suave:        color-mix(in srgb, #10b981 16%, transparent);
    --fl-exito-borde:        #065f46;
    --fl-exito-texto:        #6ee7b7;
    --fl-exito-texto-sobre:  #022c22;

    --fl-error:              #ef4444;
    --fl-error-hover:        #f87171;
    --fl-error-suave:        color-mix(in srgb, #ef4444 16%, transparent);
    --fl-error-borde:        #7f1d1d;
    --fl-error-texto:        #fca5a5;
    --fl-error-texto-sobre:  #450a0a;

    --fl-advertencia:              #f59e0b;
    --fl-advertencia-hover:        #fbbf24;
    --fl-advertencia-suave:        color-mix(in srgb, #f59e0b 16%, transparent);
    --fl-advertencia-borde:        #78350f;
    --fl-advertencia-texto:        #fcd34d;
    --fl-advertencia-texto-sobre:  #451a03;

    --fl-info:              #3b82f6;
    --fl-info-hover:        #60a5fa;
    --fl-info-suave:        color-mix(in srgb, #3b82f6 16%, transparent);
    --fl-info-borde:        #1e3a8a;
    --fl-info-texto:        #93c5fd;
    --fl-info-texto-sobre:  #172554;
}


/* ===== resources/css/06b-intensidad.css ===== */
/* ==========================================================================
   Flora · Intensidad cromática
   Tiñe las superficies, fondos y bordes neutros con el acento activo.
   Sin esto la app queda blanca/negra y el color sólo aparece en botones.
   Con esto el énfasis "invade" la pantalla.

   Arquitectura: NO hay eje tema separado. Las 7 paletas claras comparten
   las mismas fórmulas. La 8ª paleta "oscuro" tiene sus propios valores
   porque el fondo base es casi negro y la lógica de luminancia cambia.

   Activación: atributo [data-fl-intensidad="vivida|media|suave|neutro"] en
   <html>. Default: vivida. Rollback: data-fl-intensidad="neutro".
   ========================================================================== */

/* --------------------------------------------------------------------------
   VÍVIDA — default. Contrastado: las superficies "en reposo" son más
   tenues (menos tintadas) para que los destaques y estados activos
   resalten con fuerza. Flora vieja usaba esta tensión.
   -------------------------------------------------------------------------- */
:root,
:root[data-fl-intensidad="vivida"] {
    /* Fondos — tenue para que todo lo destacado sobresalga */
    --fl-fondo:              color-mix(in srgb, var(--fl-acento) 10%, var(--fl-neutro-0));
    --fl-fondo-sutil:        color-mix(in srgb, var(--fl-acento) 16%, var(--fl-neutro-50));
    --fl-fondo-tenue:        color-mix(in srgb, var(--fl-acento) 22%, var(--fl-neutro-100));

    /* Superficies — cards al reposo casi blancas. Hover/activa saltan fuerte. */
    --fl-superficie:         color-mix(in srgb, var(--fl-acento) 6%,  var(--fl-neutro-0));
    --fl-superficie-elevada: color-mix(in srgb, var(--fl-acento) 3%,  var(--fl-neutro-0));
    --fl-superficie-hover:   color-mix(in srgb, var(--fl-acento) 32%, var(--fl-neutro-0));
    --fl-superficie-activa:  color-mix(in srgb, var(--fl-acento) 48%, var(--fl-neutro-0));
    --fl-superficie-muda:    color-mix(in srgb, var(--fl-acento) 20%, var(--fl-neutro-100));

    /* Bordes — base tenue, fuerte muy marcado. Genera dos niveles claros. */
    --fl-borde:              color-mix(in srgb, var(--fl-acento) 28%, var(--fl-neutro-200));
    --fl-borde-sutil:        color-mix(in srgb, var(--fl-acento) 18%, var(--fl-neutro-150));
    --fl-borde-fuerte:       color-mix(in srgb, var(--fl-acento) 70%, var(--fl-neutro-300));
    --fl-borde-intenso:      color-mix(in srgb, var(--fl-acento) 90%, var(--fl-neutro-400));
}

/* VÍVIDA — paleta "oscuro". Misma lógica invertida: fondo muy oscuro y
   cards que se "encienden" al activarse. Cards al reposo casi negras. */
[data-fl-enfasis="oscuro"],
[data-fl-enfasis="oscuro"][data-fl-intensidad="vivida"] {
    --fl-fondo:              color-mix(in srgb, var(--fl-acento) 10%, var(--fl-neutro-950));
    --fl-fondo-sutil:        color-mix(in srgb, var(--fl-acento) 14%, var(--fl-neutro-900));
    --fl-fondo-tenue:        color-mix(in srgb, var(--fl-acento) 20%, var(--fl-neutro-850));

    --fl-superficie:         color-mix(in srgb, var(--fl-acento) 22%, var(--fl-neutro-900));
    --fl-superficie-elevada: color-mix(in srgb, var(--fl-acento) 30%, var(--fl-neutro-850));
    --fl-superficie-hover:   color-mix(in srgb, var(--fl-acento) 48%, var(--fl-neutro-800));
    --fl-superficie-activa:  color-mix(in srgb, var(--fl-acento) 68%, var(--fl-neutro-700));
    --fl-superficie-muda:    color-mix(in srgb, var(--fl-acento) 28%, var(--fl-neutro-800));

    --fl-borde:              color-mix(in srgb, var(--fl-acento) 36%, var(--fl-neutro-800));
    --fl-borde-sutil:        color-mix(in srgb, var(--fl-acento) 24%, var(--fl-neutro-850));
    --fl-borde-fuerte:       color-mix(in srgb, var(--fl-acento) 72%, var(--fl-neutro-700));
    --fl-borde-intenso:      color-mix(in srgb, var(--fl-acento) 92%, var(--fl-neutro-600));
}

/* --------------------------------------------------------------------------
   MEDIA — presencia perceptible del color pero sin invadir. Punto intermedio
   real entre vívida (fuerte) y suave (apenas). Diferenciación clara.
   -------------------------------------------------------------------------- */
[data-fl-intensidad="media"]:not([data-fl-enfasis="oscuro"]) {
    --fl-fondo:              color-mix(in srgb, var(--fl-acento) 4%,  var(--fl-neutro-0));
    --fl-fondo-sutil:        color-mix(in srgb, var(--fl-acento) 7%,  var(--fl-neutro-50));
    --fl-fondo-tenue:        color-mix(in srgb, var(--fl-acento) 10%, var(--fl-neutro-100));
    --fl-superficie:         color-mix(in srgb, var(--fl-acento) 2%,  var(--fl-neutro-0));
    --fl-superficie-elevada: var(--fl-neutro-0);
    --fl-superficie-hover:   color-mix(in srgb, var(--fl-acento) 10%, var(--fl-neutro-0));
    --fl-superficie-activa:  color-mix(in srgb, var(--fl-acento) 18%, var(--fl-neutro-0));
    --fl-superficie-muda:    color-mix(in srgb, var(--fl-acento) 10%, var(--fl-neutro-100));
    --fl-borde:              color-mix(in srgb, var(--fl-acento) 16%, var(--fl-neutro-200));
    --fl-borde-sutil:        color-mix(in srgb, var(--fl-acento) 10%, var(--fl-neutro-150));
    --fl-borde-fuerte:       color-mix(in srgb, var(--fl-acento) 28%, var(--fl-neutro-300));
    --fl-borde-intenso:      color-mix(in srgb, var(--fl-acento) 42%, var(--fl-neutro-400));
}

[data-fl-enfasis="oscuro"][data-fl-intensidad="media"] {
    --fl-fondo:              color-mix(in srgb, var(--fl-acento) 5%,  var(--fl-neutro-950));
    --fl-fondo-sutil:        color-mix(in srgb, var(--fl-acento) 8%,  var(--fl-neutro-900));
    --fl-fondo-tenue:        color-mix(in srgb, var(--fl-acento) 12%, var(--fl-neutro-850));
    --fl-superficie:         color-mix(in srgb, var(--fl-acento) 12%, var(--fl-neutro-900));
    --fl-superficie-elevada: color-mix(in srgb, var(--fl-acento) 18%, var(--fl-neutro-850));
    --fl-superficie-hover:   color-mix(in srgb, var(--fl-acento) 24%, var(--fl-neutro-800));
    --fl-superficie-activa:  color-mix(in srgb, var(--fl-acento) 36%, var(--fl-neutro-700));
    --fl-superficie-muda:    color-mix(in srgb, var(--fl-acento) 14%, var(--fl-neutro-800));
    --fl-borde:              color-mix(in srgb, var(--fl-acento) 22%, var(--fl-neutro-800));
    --fl-borde-sutil:        color-mix(in srgb, var(--fl-acento) 14%, var(--fl-neutro-850));
    --fl-borde-fuerte:       color-mix(in srgb, var(--fl-acento) 40%, var(--fl-neutro-700));
    --fl-borde-intenso:      color-mix(in srgb, var(--fl-acento) 58%, var(--fl-neutro-600));
}

/* --------------------------------------------------------------------------
   SUAVE — el color apenas se insinúa.
   -------------------------------------------------------------------------- */
[data-fl-intensidad="suave"]:not([data-fl-enfasis="oscuro"]) {
    --fl-fondo:              var(--fl-neutro-0);
    --fl-fondo-sutil:        color-mix(in srgb, var(--fl-acento) 4%,  var(--fl-neutro-50));
    --fl-fondo-tenue:        color-mix(in srgb, var(--fl-acento) 6%,  var(--fl-neutro-100));
    --fl-superficie:         var(--fl-neutro-0);
    --fl-superficie-elevada: var(--fl-neutro-0);
    --fl-superficie-hover:   color-mix(in srgb, var(--fl-acento) 6%,  var(--fl-neutro-50));
    --fl-superficie-activa:  color-mix(in srgb, var(--fl-acento) 10%, var(--fl-neutro-100));
    --fl-superficie-muda:    color-mix(in srgb, var(--fl-acento) 5%,  var(--fl-neutro-100));
    --fl-borde:              color-mix(in srgb, var(--fl-acento) 10%, var(--fl-neutro-200));
    --fl-borde-sutil:        color-mix(in srgb, var(--fl-acento) 7%,  var(--fl-neutro-150));
    --fl-borde-fuerte:       color-mix(in srgb, var(--fl-acento) 16%, var(--fl-neutro-300));
    --fl-borde-intenso:      color-mix(in srgb, var(--fl-acento) 22%, var(--fl-neutro-400));
}

[data-fl-enfasis="oscuro"][data-fl-intensidad="suave"] {
    --fl-fondo:              color-mix(in srgb, var(--fl-acento) 4%,  var(--fl-neutro-950));
    --fl-fondo-sutil:        color-mix(in srgb, var(--fl-acento) 6%,  var(--fl-neutro-900));
    --fl-fondo-tenue:        color-mix(in srgb, var(--fl-acento) 8%,  var(--fl-neutro-850));
    --fl-superficie:         color-mix(in srgb, var(--fl-acento) 8%,  var(--fl-neutro-900));
    --fl-superficie-elevada: color-mix(in srgb, var(--fl-acento) 12%, var(--fl-neutro-850));
    --fl-superficie-hover:   color-mix(in srgb, var(--fl-acento) 16%, var(--fl-neutro-800));
    --fl-superficie-activa:  color-mix(in srgb, var(--fl-acento) 22%, var(--fl-neutro-700));
    --fl-superficie-muda:    color-mix(in srgb, var(--fl-acento) 10%, var(--fl-neutro-800));
    --fl-borde:              color-mix(in srgb, var(--fl-acento) 18%, var(--fl-neutro-800));
    --fl-borde-sutil:        color-mix(in srgb, var(--fl-acento) 12%, var(--fl-neutro-850));
    --fl-borde-fuerte:       color-mix(in srgb, var(--fl-acento) 26%, var(--fl-neutro-700));
    --fl-borde-intenso:      color-mix(in srgb, var(--fl-acento) 36%, var(--fl-neutro-600));
}

/* --------------------------------------------------------------------------
   NEUTRO — rollback total. Vuelve a los neutros puros sin tinte.
   -------------------------------------------------------------------------- */
[data-fl-intensidad="neutro"]:not([data-fl-enfasis="oscuro"]) {
    --fl-fondo:              var(--fl-neutro-0);
    --fl-fondo-sutil:        var(--fl-neutro-50);
    --fl-fondo-tenue:        var(--fl-neutro-100);
    --fl-superficie:         var(--fl-neutro-0);
    --fl-superficie-elevada: var(--fl-neutro-0);
    --fl-superficie-hover:   var(--fl-neutro-50);
    --fl-superficie-activa:  var(--fl-neutro-100);
    --fl-superficie-muda:    var(--fl-neutro-100);
    --fl-borde:              var(--fl-neutro-200);
    --fl-borde-sutil:        var(--fl-neutro-150);
    --fl-borde-fuerte:       var(--fl-neutro-300);
    --fl-borde-intenso:      var(--fl-neutro-400);
}

[data-fl-enfasis="oscuro"][data-fl-intensidad="neutro"] {
    --fl-fondo:              var(--fl-neutro-950);
    --fl-fondo-sutil:        var(--fl-neutro-900);
    --fl-fondo-tenue:        var(--fl-neutro-850);
    --fl-superficie:         var(--fl-neutro-900);
    --fl-superficie-elevada: var(--fl-neutro-850);
    --fl-superficie-hover:   var(--fl-neutro-800);
    --fl-superficie-activa:  var(--fl-neutro-700);
    --fl-superficie-muda:    var(--fl-neutro-800);
    --fl-borde:              var(--fl-neutro-800);
    --fl-borde-sutil:        var(--fl-neutro-850);
    --fl-borde-fuerte:       var(--fl-neutro-700);
    --fl-borde-intenso:      var(--fl-neutro-600);
}

/* --------------------------------------------------------------------------
   Fondo del body — dos radiales de acento que inundan el viewport.
   La paleta "oscuro" usa valores más moderados (el fondo ya viene oscuro).
   -------------------------------------------------------------------------- */
body {
    background-color: var(--fl-fondo);
    background-image:
        radial-gradient(ellipse 90% 65% at 15% 0%,
            color-mix(in srgb, var(--fl-acento) 36%, transparent) 0%,
            transparent 70%),
        radial-gradient(ellipse 80% 70% at 85% 100%,
            color-mix(in srgb, var(--fl-acento) 28%, transparent) 0%,
            transparent 65%);
    background-attachment: fixed;
}

[data-fl-enfasis="oscuro"] body {
    background-image:
        radial-gradient(ellipse 90% 65% at 15% 0%,
            color-mix(in srgb, var(--fl-acento) 22%, transparent) 0%,
            transparent 70%),
        radial-gradient(ellipse 80% 70% at 85% 100%,
            color-mix(in srgb, var(--fl-acento) 16%, transparent) 0%,
            transparent 65%);
}

[data-fl-intensidad="media"] body {
    background-image:
        radial-gradient(ellipse 80% 50% at 15% 0%,
            color-mix(in srgb, var(--fl-acento) 6%, transparent) 0%,
            transparent 55%);
}

[data-fl-intensidad="suave"] body {
    background-image:
        radial-gradient(ellipse 80% 50% at 15% 0%,
            color-mix(in srgb, var(--fl-acento) 5%, transparent) 0%,
            transparent 50%);
}

[data-fl-intensidad="neutro"] body {
    background-image: none;
}


/* ===== resources/css/07-tipografia.css ===== */
/* ==========================================================================
   Flora · Tipografía
   IBM Plex Sans como familia principal. Fuente variable con eje de peso,
   Latin subset (soporta español/portugués perfecto).
   ========================================================================== */

@font-face {
    font-family: "IBM Plex Sans";
    font-style: normal;
    font-display: swap;
    font-weight: 100 700;
    src: url("./fuentes/ibm-plex-sans-latin-wght-normal.woff2") format("woff2-variations"),
         url("./fuentes/ibm-plex-sans-latin-wght-normal.woff2") format("woff2");
}

@font-face {
    font-family: "IBM Plex Sans";
    font-style: italic;
    font-display: swap;
    font-weight: 100 700;
    src: url("./fuentes/ibm-plex-sans-latin-wght-italic.woff2") format("woff2-variations"),
         url("./fuentes/ibm-plex-sans-latin-wght-italic.woff2") format("woff2");
}

/* --------------------------------------------------------------------------
   Defaults globales
   -------------------------------------------------------------------------- */
html {
    font-family: var(--fl-fuente-sans);
    font-size: 16px;
    font-weight: var(--fl-peso-regular);
    line-height: var(--fl-lh-normal);
    color: var(--fl-texto);
    /* La página completa se tinta muy sutilmente con el acento — da la
       "temperatura" del color elegido a todo el contexto sin gritar. */
    background-color: color-mix(in srgb, var(--fl-acento) 2.5%, var(--fl-fondo));
    font-feature-settings: "cv11" on, "ss01" on;
}

/* Textura de fondo — opt-in mediante [data-fl-textura="puntos"] en <body>
   o en cualquier contenedor. Grid sutil de puntos acento, 32px de paso.
   Sin background-attachment: fixed (causa jank de scroll en mobile). */
[data-fl-textura="puntos"] {
    background-image: radial-gradient(
        circle at 1px 1px,
        color-mix(in srgb, var(--fl-acento) 18%, transparent) 1px,
        transparent 0
    );
    background-size: 32px 32px;
}

[data-fl-textura="grilla"] {
    background-image:
        linear-gradient(to right,  color-mix(in srgb, var(--fl-acento) 8%, transparent) 1px, transparent 1px),
        linear-gradient(to bottom, color-mix(in srgb, var(--fl-acento) 8%, transparent) 1px, transparent 1px);
    background-size: 48px 48px;
}

body {
    font-size: var(--fl-texto-base);
    letter-spacing: var(--fl-ls-normal);
}

/* --------------------------------------------------------------------------
   Jerarquía de headings — clases, no tags. Evitamos imponer estilo al
   elemento crudo para que los tags mantengan significado semántico sin
   obligar a un look específico.
   -------------------------------------------------------------------------- */
.fl-titulo-1 {
    font-family: var(--fl-fuente-display);
    font-size: var(--fl-texto-4xl);
    font-weight: var(--fl-peso-regular);
    line-height: 1.05;
    letter-spacing: -0.025em;
    color: var(--fl-texto-fuerte);
}

/* Modificador opcional para cualquier titulo: barra de acento a la izquierda */
.fl-titulo-1--acento,
.fl-titulo-2--acento,
.fl-titulo-3--acento,
.fl-titulo-4--acento,
.fl-titulo-5--acento,
.fl-titulo-6--acento {
    padding-left: var(--fl-sp-3);
    border-left: 3px solid var(--fl-acento);
}

.fl-titulo-2 {
    font-family: var(--fl-fuente-display);
    font-size: var(--fl-texto-3xl);
    font-weight: var(--fl-peso-regular);
    line-height: 1.1;
    letter-spacing: -0.02em;
    color: var(--fl-texto-fuerte);
}

.fl-titulo-3 {
    font-size: var(--fl-texto-2xl);
    font-weight: var(--fl-peso-semibold);
    line-height: var(--fl-lh-ajustada);
    color: var(--fl-texto-fuerte);
}

.fl-titulo-4 {
    font-size: var(--fl-texto-xl);
    font-weight: var(--fl-peso-semibold);
    line-height: var(--fl-lh-ajustada);
    color: var(--fl-texto-fuerte);
}

.fl-titulo-5 {
    font-size: var(--fl-texto-lg);
    font-weight: var(--fl-peso-semibold);
    line-height: var(--fl-lh-ajustada);
    color: var(--fl-texto-fuerte);
}

.fl-titulo-6 {
    font-size: var(--fl-texto-base);
    font-weight: var(--fl-peso-semibold);
    line-height: var(--fl-lh-ajustada);
    color: var(--fl-texto-fuerte);
}

/* Display — para landings, heros. Serif editorial, italic opcional. */
.fl-display {
    font-family: var(--fl-fuente-display);
    font-size: var(--fl-texto-5xl);
    font-weight: var(--fl-peso-regular);
    line-height: 1;
    letter-spacing: -0.035em;
    color: var(--fl-texto-fuerte);
}

.fl-display--italic,
.fl-titulo-1--italic,
.fl-titulo-2--italic {
    font-style: italic;
    letter-spacing: -0.03em;
}

/* Texto corporal */
.fl-texto-cuerpo {
    font-size: var(--fl-texto-base);
    line-height: var(--fl-lh-normal);
    color: var(--fl-texto);
}

.fl-texto-pie {
    font-size: var(--fl-texto-sm);
    line-height: var(--fl-lh-normal);
    color: var(--fl-texto-suave);
}

.fl-texto-mini {
    font-size: var(--fl-texto-xs);
    line-height: var(--fl-lh-normal);
    color: var(--fl-texto-tenue);
}

/* Mayúsculas tipo label — "ACTIVIDAD RECIENTE" */
.fl-texto-etiqueta {
    font-size: var(--fl-texto-xs);
    font-weight: var(--fl-peso-semibold);
    line-height: var(--fl-lh-compacta);
    letter-spacing: var(--fl-ls-mayus);
    text-transform: uppercase;
    color: var(--fl-texto-suave);
}

/* Cita — para blockquote o citas tipográficas */
.fl-cita {
    font-size: var(--fl-texto-lg);
    font-style: italic;
    line-height: var(--fl-lh-relajada);
    color: var(--fl-texto-suave);
    border-left: 3px solid var(--fl-acento-borde);
    padding-left: var(--fl-sp-4);
}

/* Números tabulares — para columnas de datos */
.fl-numero-tabular {
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
}

/* Código inline y bloques */
code,
kbd,
samp,
pre,
.fl-codigo {
    font-family: var(--fl-fuente-mono);
    font-size: 0.925em;
}

.fl-codigo-inline {
    background: var(--fl-superficie-muda);
    padding: 0.125em 0.375em;
    border-radius: var(--fl-r-sm);
    font-size: 0.9em;
    color: var(--fl-texto-fuerte);
    border: 1px solid var(--fl-borde-sutil);
}

/* Enlace estándar */
.fl-enlace {
    color: var(--fl-acento-enlace);
    font-weight: var(--fl-peso-medio);
    text-decoration: underline;
    text-decoration-color: color-mix(in srgb, currentColor 60%, transparent);
    text-decoration-thickness: 1.5px;
    text-underline-offset: 0.22em;
    transition: color var(--fl-t-rapido) var(--fl-ease-salida),
                text-decoration-color var(--fl-t-rapido) var(--fl-ease-salida),
                text-decoration-thickness var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-enlace:hover {
    color: var(--fl-acento-hover);
    text-decoration-color: currentColor;
    text-decoration-thickness: 2px;
}

.fl-enlace:focus-visible {
    outline: 2px solid var(--fl-acento-foco);
    outline-offset: 2px;
    border-radius: var(--fl-r-xs);
}


/* ===== resources/css/08-layout.css ===== */
/* ==========================================================================
   Flora · Layout
   Primitivas de composición: contenedores, pilas, filas, grillas.
   ========================================================================== */

/* Contenedor centrado con max-width responsivo.
   Escala suavemente hasta 1680px por default para aprovechar pantallas
   grandes (1920+) sin estirar texto a líneas ilegibles. Variantes cubren
   desde lectura (estrecho) hasta dashboards full-bleed (gigante/fluido). */
.fl-contenedor {
    width: 100%;
    max-width: 1440px;
    margin-left: auto;
    margin-right: auto;
    padding-left: var(--fl-sp-4);
    padding-right: var(--fl-sp-4);
    box-sizing: border-box;
}

.fl-contenedor--estrecho { max-width: 768px; }    /* lectura larga */
.fl-contenedor--medio    { max-width: 1024px; }   /* formularios */
.fl-contenedor--ancho    { max-width: 1680px; }   /* admin/dashboards */
.fl-contenedor--gigante  { max-width: 1920px; }   /* tablas anchas */
.fl-contenedor--fluido   { max-width: none; }     /* full-bleed */

/* En mobile chiquito bajamos padding para ganar píxeles útiles */
@media (max-width: 480px) {
    .fl-contenedor {
        padding-left: var(--fl-sp-3);
        padding-right: var(--fl-sp-3);
    }
}

@media (min-width: 768px) {
    .fl-contenedor {
        padding-left: var(--fl-sp-6);
        padding-right: var(--fl-sp-6);
    }
}

@media (min-width: 1280px) {
    .fl-contenedor {
        padding-left: var(--fl-sp-8);
        padding-right: var(--fl-sp-8);
    }
}

@media (min-width: 1680px) {
    .fl-contenedor {
        padding-left: var(--fl-sp-10);
        padding-right: var(--fl-sp-10);
    }
}

/* Pila vertical con gap uniforme */
.fl-apilar {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-4);
}

.fl-apilar--xs { gap: var(--fl-sp-1); }
.fl-apilar--sm { gap: var(--fl-sp-2); }
.fl-apilar--md { gap: var(--fl-sp-4); }
.fl-apilar--lg { gap: var(--fl-sp-6); }
.fl-apilar--xl { gap: var(--fl-sp-8); }
.fl-apilar--2xl { gap: var(--fl-sp-12); }

/* Fila horizontal con gap */
.fl-fila {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--fl-sp-3);
    flex-wrap: wrap;
}

.fl-fila--xs { gap: var(--fl-sp-1); }
.fl-fila--sm { gap: var(--fl-sp-2); }
.fl-fila--md { gap: var(--fl-sp-3); }
.fl-fila--lg { gap: var(--fl-sp-4); }
.fl-fila--xl { gap: var(--fl-sp-6); }

.fl-fila--nowrap { flex-wrap: nowrap; }
.fl-fila--top    { align-items: flex-start; }
.fl-fila--centro { align-items: center; }
.fl-fila--base   { align-items: baseline; }
.fl-fila--stretch { align-items: stretch; }

.fl-fila--separar { justify-content: space-between; }
.fl-fila--centrada { justify-content: center; }
.fl-fila--derecha { justify-content: flex-end; }
.fl-fila--izquierda { justify-content: flex-start; }

/* Grilla responsiva de columnas */
.fl-grilla {
    display: grid;
    gap: var(--fl-sp-4);
    grid-template-columns: repeat(12, minmax(0, 1fr));
}

.fl-grilla--auto {
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}

.fl-col-1  { grid-column: span 1; }
.fl-col-2  { grid-column: span 2; }
.fl-col-3  { grid-column: span 3; }
.fl-col-4  { grid-column: span 4; }
.fl-col-5  { grid-column: span 5; }
.fl-col-6  { grid-column: span 6; }
.fl-col-7  { grid-column: span 7; }
.fl-col-8  { grid-column: span 8; }
.fl-col-9  { grid-column: span 9; }
.fl-col-10 { grid-column: span 10; }
.fl-col-11 { grid-column: span 11; }
.fl-col-12 { grid-column: span 12; }

@media (max-width: 1023px) {
    .fl-col-md-1  { grid-column: span 1; }
    .fl-col-md-2  { grid-column: span 2; }
    .fl-col-md-3  { grid-column: span 3; }
    .fl-col-md-4  { grid-column: span 4; }
    .fl-col-md-6  { grid-column: span 6; }
    .fl-col-md-12 { grid-column: span 12; }
}

@media (max-width: 639px) {
    .fl-col-sm-12,
    .fl-col-1, .fl-col-2, .fl-col-3, .fl-col-4, .fl-col-5, .fl-col-6,
    .fl-col-7, .fl-col-8, .fl-col-9, .fl-col-10, .fl-col-11 {
        grid-column: span 12;
    }
}

/* Separador horizontal — usamos el borde "fuerte" para garantizar
   visibilidad en las 8 paletas (el --fl-borde base era demasiado sutil). */
.fl-separador {
    display: block;
    width: 100%;
    height: 1px;
    background: var(--fl-borde-fuerte);
    border: 0;
    margin: var(--fl-sp-4) 0;
}

.fl-separador--vertical {
    width: 1px;
    height: auto;
    align-self: stretch;
    margin: 0;
    background: var(--fl-borde-fuerte);
}

/* Centro absoluto en viewport */
.fl-centrado-pantalla {
    min-height: 100vh;
    display: grid;
    place-items: center;
    padding: var(--fl-sp-4);
}

/* Espaciador flexible — empuja elementos al otro lado de un flex/grid */
.fl-espaciador {
    flex: 1 1 auto;
    min-height: 1px;
}

/* Panel — envoltura genérica para secciones de página */
.fl-panel {
    padding: var(--fl-sp-6);
    background: var(--fl-superficie);
    border: 1px solid var(--fl-borde);
    border-radius: var(--fl-r-lg);
}

.fl-panel--tenue {
    background: var(--fl-fondo-sutil);
    border-color: var(--fl-borde-sutil);
}


/* ===== resources/css/08b-scrollbar.css ===== */
/* ==========================================================================
   Flora · Scrollbar
   Barra de scroll tintada con el acento activo. Usa variables — cambia sola
   con énfasis, tema e intensidad. Firefox (scrollbar-color) + Webkit
   (pseudo-elementos ::-webkit-scrollbar-*).

   Ubicado en 08b-* para que el concatenador natural-sort lo inserte entre
   08-layout.css y 09-utilidades.css.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Scrollbar global — afecta al documento y a todos los contenedores con scroll
   -------------------------------------------------------------------------- */

/* Firefox */
html {
    scrollbar-width: thin;
    scrollbar-color:
        color-mix(in srgb, var(--fl-acento) 55%, transparent)
        var(--fl-fondo-sutil);
    /* Scrollbar vertical SIEMPRE presente — evita que aparezca/desaparezca
       según la altura del contenido y genere reflow horizontal (contenidos
       centrados/flex se corrían al abrir overlays, dropdowns, etc.). */
    overflow-y: scroll;
}

/* Aseguramos que body NO compite con html por el scroll — si body tiene
   overflow (incluyendo overflow-x: hidden), algunos browsers propagan
   el scroll a html y a body simultáneamente = doble scrollbar. */
body {
    overflow-x: clip;
}

/* Webkit — Chrome, Safari, Edge, Opera */
::-webkit-scrollbar {
    width: 12px;
    height: 12px;
}

::-webkit-scrollbar-track {
    background: var(--fl-fondo-sutil);
    border-radius: var(--fl-r-full);
}

::-webkit-scrollbar-thumb {
    background: color-mix(in srgb, var(--fl-acento) 45%, transparent);
    border: 3px solid var(--fl-fondo);
    border-radius: var(--fl-r-full);
    background-clip: padding-box;
    transition: background-color var(--fl-t-rapido) var(--fl-ease-salida);
}

::-webkit-scrollbar-thumb:hover {
    background: color-mix(in srgb, var(--fl-acento) 70%, transparent);
    background-clip: padding-box;
}

::-webkit-scrollbar-thumb:active {
    background: var(--fl-acento);
    background-clip: padding-box;
}

::-webkit-scrollbar-corner {
    background: var(--fl-fondo-sutil);
}

/* --------------------------------------------------------------------------
   Variante sutil — para contenedores internos (sidebars, listas, tablas)
   donde no querés que la barra domine. Track transparente, pulgar fino.
   Uso: agregar la clase .fl-scroll-sutil al contenedor que tiene overflow.
   -------------------------------------------------------------------------- */
.fl-scroll-sutil {
    scrollbar-width: thin;
    scrollbar-color:
        color-mix(in srgb, var(--fl-acento) 40%, transparent)
        transparent;
}

.fl-scroll-sutil::-webkit-scrollbar {
    width: 8px;
    height: 8px;
}

.fl-scroll-sutil::-webkit-scrollbar-track {
    background: transparent;
}

.fl-scroll-sutil::-webkit-scrollbar-thumb {
    border-width: 2px;
    background: color-mix(in srgb, var(--fl-acento) 35%, transparent);
    background-clip: padding-box;
}

.fl-scroll-sutil::-webkit-scrollbar-thumb:hover {
    background: color-mix(in srgb, var(--fl-acento) 60%, transparent);
    background-clip: padding-box;
}

/* --------------------------------------------------------------------------
   Variante overlay — se muestra sólo al hacer scroll, desaparece en reposo.
   Uso: .fl-scroll-overlay en el contenedor con overflow.
   -------------------------------------------------------------------------- */
.fl-scroll-overlay {
    scrollbar-gutter: stable;
}

.fl-scroll-overlay::-webkit-scrollbar-thumb {
    background: transparent;
    background-clip: padding-box;
    transition: background-color 160ms var(--fl-ease-salida);
}

.fl-scroll-overlay:hover::-webkit-scrollbar-thumb,
.fl-scroll-overlay:focus-within::-webkit-scrollbar-thumb {
    background: color-mix(in srgb, var(--fl-acento) 55%, transparent);
    background-clip: padding-box;
}


/* ===== resources/css/09-utilidades.css ===== */
/* ==========================================================================
   Flora · Utilidades
   Clases de un solo propósito con prefijo u-*. Sólo para micro-ajustes.
   NO son reemplazo de componentes — son pegamento.

   Convención: u-{propiedad}-{valor}
   ========================================================================== */

/* --------------------------------------------------------------------------
   Espaciado — margin
   -------------------------------------------------------------------------- */
.u-m-0  { margin: 0; }
.u-m-1  { margin: var(--fl-sp-1); }
.u-m-2  { margin: var(--fl-sp-2); }
.u-m-3  { margin: var(--fl-sp-3); }
.u-m-4  { margin: var(--fl-sp-4); }
.u-m-6  { margin: var(--fl-sp-6); }
.u-m-8  { margin: var(--fl-sp-8); }
.u-m-auto { margin: auto; }

.u-mt-0 { margin-top: 0; }
.u-mt-1 { margin-top: var(--fl-sp-1); }
.u-mt-2 { margin-top: var(--fl-sp-2); }
.u-mt-3 { margin-top: var(--fl-sp-3); }
.u-mt-4 { margin-top: var(--fl-sp-4); }
.u-mt-6 { margin-top: var(--fl-sp-6); }
.u-mt-8 { margin-top: var(--fl-sp-8); }

.u-mb-0 { margin-bottom: 0; }
.u-mb-1 { margin-bottom: var(--fl-sp-1); }
.u-mb-2 { margin-bottom: var(--fl-sp-2); }
.u-mb-3 { margin-bottom: var(--fl-sp-3); }
.u-mb-4 { margin-bottom: var(--fl-sp-4); }
.u-mb-6 { margin-bottom: var(--fl-sp-6); }
.u-mb-8 { margin-bottom: var(--fl-sp-8); }

.u-mx-auto { margin-left: auto; margin-right: auto; }
.u-my-auto { margin-top: auto; margin-bottom: auto; }

/* --------------------------------------------------------------------------
   Espaciado — padding
   -------------------------------------------------------------------------- */
.u-p-0 { padding: 0; }
.u-p-1 { padding: var(--fl-sp-1); }
.u-p-2 { padding: var(--fl-sp-2); }
.u-p-3 { padding: var(--fl-sp-3); }
.u-p-4 { padding: var(--fl-sp-4); }
.u-p-6 { padding: var(--fl-sp-6); }
.u-p-8 { padding: var(--fl-sp-8); }

.u-px-1 { padding-left: var(--fl-sp-1); padding-right: var(--fl-sp-1); }
.u-px-2 { padding-left: var(--fl-sp-2); padding-right: var(--fl-sp-2); }
.u-px-3 { padding-left: var(--fl-sp-3); padding-right: var(--fl-sp-3); }
.u-px-4 { padding-left: var(--fl-sp-4); padding-right: var(--fl-sp-4); }
.u-px-6 { padding-left: var(--fl-sp-6); padding-right: var(--fl-sp-6); }

.u-py-1 { padding-top: var(--fl-sp-1); padding-bottom: var(--fl-sp-1); }
.u-py-2 { padding-top: var(--fl-sp-2); padding-bottom: var(--fl-sp-2); }
.u-py-3 { padding-top: var(--fl-sp-3); padding-bottom: var(--fl-sp-3); }
.u-py-4 { padding-top: var(--fl-sp-4); padding-bottom: var(--fl-sp-4); }
.u-py-6 { padding-top: var(--fl-sp-6); padding-bottom: var(--fl-sp-6); }

/* --------------------------------------------------------------------------
   Tipografía
   -------------------------------------------------------------------------- */
.u-texto-2xs  { font-size: var(--fl-texto-2xs); }
.u-texto-xs   { font-size: var(--fl-texto-xs); }
.u-texto-sm   { font-size: var(--fl-texto-sm); }
.u-texto-base { font-size: var(--fl-texto-base); }
.u-texto-lg   { font-size: var(--fl-texto-lg); }
.u-texto-xl   { font-size: var(--fl-texto-xl); }
.u-texto-2xl  { font-size: var(--fl-texto-2xl); }

.u-peso-regular  { font-weight: var(--fl-peso-regular); }
.u-peso-medio    { font-weight: var(--fl-peso-medio); }
.u-peso-semibold { font-weight: var(--fl-peso-semibold); }
.u-peso-bold     { font-weight: var(--fl-peso-bold); }

.u-texto-izquierda { text-align: left; }
.u-texto-centro    { text-align: center; }
.u-texto-derecha   { text-align: right; }

.u-mayusculas  { text-transform: uppercase; letter-spacing: var(--fl-ls-mayus); }
.u-minusculas  { text-transform: lowercase; }
.u-capitalizar { text-transform: capitalize; }

.u-italica       { font-style: italic; }
.u-subrayado     { text-decoration: underline; }
.u-tachado       { text-decoration: line-through; }
.u-sin-decor     { text-decoration: none; }

.u-truncar {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.u-cortar-2-lineas {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.u-mono { font-family: var(--fl-fuente-mono); }
.u-nums-tabular { font-variant-numeric: tabular-nums; }

/* --------------------------------------------------------------------------
   Colores de texto y fondo
   -------------------------------------------------------------------------- */
.u-texto-base        { color: var(--fl-texto); }
.u-texto-fuerte      { color: var(--fl-texto-fuerte); }
.u-texto-suave       { color: var(--fl-texto-suave); }
.u-texto-tenue       { color: var(--fl-texto-tenue); }
.u-texto-acento      { color: var(--fl-acento-texto); }
.u-texto-exito       { color: var(--fl-exito-texto); }
.u-texto-error       { color: var(--fl-error-texto); }
.u-texto-advertencia { color: var(--fl-advertencia-texto); }
.u-texto-info        { color: var(--fl-info-texto); }
.u-texto-invertido   { color: var(--fl-texto-invertido); }

.u-fondo            { background: var(--fl-fondo); }
.u-fondo-sutil      { background: var(--fl-fondo-sutil); }
.u-fondo-tenue      { background: var(--fl-fondo-tenue); }
.u-fondo-superficie { background: var(--fl-superficie); }
.u-fondo-muda       { background: var(--fl-superficie-muda); }
.u-fondo-acento     { background: var(--fl-acento); color: var(--fl-acento-texto-sobre); }
.u-fondo-acento-suave { background: var(--fl-acento-suave); color: var(--fl-acento-texto); }

/* --------------------------------------------------------------------------
   Bordes y radios
   -------------------------------------------------------------------------- */
.u-borde         { border: 1px solid var(--fl-borde); }
.u-borde-sutil   { border: 1px solid var(--fl-borde-sutil); }
.u-borde-fuerte  { border: 1px solid var(--fl-borde-fuerte); }
.u-borde-acento  { border: 1px solid var(--fl-acento-borde); }
.u-borde-top     { border-top: 1px solid var(--fl-borde); }
.u-borde-bottom  { border-bottom: 1px solid var(--fl-borde); }
.u-borde-left    { border-left: 1px solid var(--fl-borde); }
.u-borde-right   { border-right: 1px solid var(--fl-borde); }
.u-sin-borde     { border: 0; }

.u-r-0    { border-radius: 0; }
.u-r-xs   { border-radius: var(--fl-r-xs); }
.u-r-sm   { border-radius: var(--fl-r-sm); }
.u-r-md   { border-radius: var(--fl-r-md); }
.u-r-lg   { border-radius: var(--fl-r-lg); }
.u-r-xl   { border-radius: var(--fl-r-xl); }
.u-r-2xl  { border-radius: var(--fl-r-2xl); }
.u-r-full { border-radius: var(--fl-r-full); }

.u-sombra-xs  { box-shadow: var(--fl-sombra-xs); }
.u-sombra-sm  { box-shadow: var(--fl-sombra-sm); }
.u-sombra-md  { box-shadow: var(--fl-sombra-md); }
.u-sombra-lg  { box-shadow: var(--fl-sombra-lg); }
.u-sombra-xl  { box-shadow: var(--fl-sombra-xl); }
.u-sin-sombra { box-shadow: none; }

/* --------------------------------------------------------------------------
   Display y posicionamiento
   -------------------------------------------------------------------------- */
.u-bloque       { display: block; }
.u-inline       { display: inline; }
.u-inline-bloque { display: inline-block; }
.u-flex         { display: flex; }
.u-inline-flex  { display: inline-flex; }
.u-grid         { display: grid; }
.u-oculto       { display: none; }

.u-flex-col      { flex-direction: column; }
.u-flex-row      { flex-direction: row; }
.u-flex-1        { flex: 1 1 0%; }
.u-flex-auto     { flex: 1 1 auto; }
.u-flex-ninguno  { flex: none; }
.u-flex-wrap     { flex-wrap: wrap; }
.u-flex-nowrap   { flex-wrap: nowrap; }

.u-items-inicio  { align-items: flex-start; }
.u-items-centro  { align-items: center; }
.u-items-fin     { align-items: flex-end; }
.u-items-stretch { align-items: stretch; }

.u-justify-inicio  { justify-content: flex-start; }
.u-justify-centro  { justify-content: center; }
.u-justify-fin     { justify-content: flex-end; }
.u-justify-entre   { justify-content: space-between; }
.u-justify-alrededor { justify-content: space-around; }

.u-gap-0 { gap: 0; }
.u-gap-1 { gap: var(--fl-sp-1); }
.u-gap-2 { gap: var(--fl-sp-2); }
.u-gap-3 { gap: var(--fl-sp-3); }
.u-gap-4 { gap: var(--fl-sp-4); }
.u-gap-6 { gap: var(--fl-sp-6); }
.u-gap-8 { gap: var(--fl-sp-8); }

.u-w-full   { width: 100%; }
.u-w-auto   { width: auto; }
.u-w-min    { width: min-content; }
.u-w-max    { width: max-content; }
.u-w-fit    { width: fit-content; }
.u-h-full   { height: 100%; }
.u-h-auto   { height: auto; }
.u-min-h-pantalla { min-height: 100vh; }

/* Ancho máximo con centrado — para limitar contenedores en pantallas grandes.
   Por default los componentes son full-width; usa estas utilidades cuando
   quieras restringir (lectura larga, formularios angostos, etc.) */
.u-max-w-xs       { max-width: 20rem;  margin-left: auto; margin-right: auto; }    /* 320px */
.u-max-w-sm       { max-width: 24rem;  margin-left: auto; margin-right: auto; }    /* 384px */
.u-max-w-md       { max-width: 28rem;  margin-left: auto; margin-right: auto; }    /* 448px */
.u-max-w-lg       { max-width: 32rem;  margin-left: auto; margin-right: auto; }    /* 512px */
.u-max-w-xl       { max-width: 40rem;  margin-left: auto; margin-right: auto; }    /* 640px */
.u-max-w-2xl      { max-width: 48rem;  margin-left: auto; margin-right: auto; }    /* 768px */
.u-max-w-3xl      { max-width: 56rem;  margin-left: auto; margin-right: auto; }    /* 896px */
.u-max-w-4xl      { max-width: 64rem;  margin-left: auto; margin-right: auto; }    /* 1024px */
.u-max-w-5xl      { max-width: 72rem;  margin-left: auto; margin-right: auto; }    /* 1152px */
.u-max-w-6xl      { max-width: 80rem;  margin-left: auto; margin-right: auto; }    /* 1280px */
.u-max-w-7xl      { max-width: 96rem;  margin-left: auto; margin-right: auto; }    /* 1536px */
.u-max-w-prosa    { max-width: 65ch;   margin-left: auto; margin-right: auto; }    /* lectura 65ch */

/* Variantes sin auto-centrar (se pegan a la izquierda) */
.u-max-w-xs-izq   { max-width: 20rem; }
.u-max-w-sm-izq   { max-width: 24rem; }
.u-max-w-md-izq   { max-width: 28rem; }
.u-max-w-lg-izq   { max-width: 32rem; }
.u-max-w-xl-izq   { max-width: 40rem; }
.u-max-w-2xl-izq  { max-width: 48rem; }
.u-max-w-3xl-izq  { max-width: 56rem; }
.u-max-w-4xl-izq  { max-width: 64rem; }
.u-max-w-5xl-izq  { max-width: 72rem; }
.u-max-w-6xl-izq  { max-width: 80rem; }
.u-max-w-7xl-izq  { max-width: 96rem; }

.u-relativo { position: relative; }
.u-absoluto { position: absolute; }
.u-fijo     { position: fixed; }
.u-pegajoso { position: sticky; }
.u-estatico { position: static; }

.u-overflow-oculto { overflow: hidden; }
.u-overflow-auto   { overflow: auto; }
.u-overflow-x-auto { overflow-x: auto; }
.u-overflow-y-auto { overflow-y: auto; }

/* --------------------------------------------------------------------------
   Accesibilidad
   -------------------------------------------------------------------------- */
.u-lector-pantalla {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.u-no-seleccionable { user-select: none; }
.u-cursor-puntero   { cursor: pointer; }
.u-cursor-ayuda     { cursor: help; }
.u-cursor-espera    { cursor: wait; }
.u-cursor-prohibido { cursor: not-allowed; }

/* --------------------------------------------------------------------------
   Visibilidad responsiva
   -------------------------------------------------------------------------- */
@media (max-width: 767px) {
    .u-oculto-movil { display: none !important; }
}

@media (min-width: 768px) {
    .u-solo-movil { display: none !important; }
}

@media (max-width: 1023px) {
    .u-oculto-tablet { display: none !important; }
}

@media (min-width: 1024px) {
    .u-solo-tablet { display: none !important; }
}

/* --------------------------------------------------------------------------
   Responsive helpers — para que componentes grandes entren en mobile.
   Garantizan scroll horizontal aislado y flex-wrap cuando falta espacio.
   -------------------------------------------------------------------------- */
.u-scroll-x        { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.u-scroll-x-movil  { }

@media (max-width: 767px) {
    .u-scroll-x-movil { overflow-x: auto; -webkit-overflow-scrolling: touch; }
    /* En mobile, los flex rows típicos se apilan */
    .u-apilar-movil   { flex-direction: column !important; align-items: stretch !important; }
    /* Ancho full en mobile: sobre-escribe max-width para que nada quede chico */
    .u-full-movil     { width: 100% !important; max-width: 100% !important; }
    /* Wrap forzado en mobile */
    .u-wrap-movil     { flex-wrap: wrap !important; }
}

/* Garantía absoluta: ningún componente debe desbordar su padre en mobile.
   Aplicá .u-contenedor-movil al wrapper del contenido principal. */
@media (max-width: 767px) {
    .u-contenedor-movil > * {
        max-width: 100%;
    }
}

/* --------------------------------------------------------------------------
   Columnas responsivas adicionales — breakpoints sm/md ya en 08-layout.css.
   Acá agregamos breakpoint XS (≤480px) para phones chicos. */
@media (max-width: 480px) {
    .fl-grilla {
        gap: var(--fl-sp-3);
    }
}

/* --------------------------------------------------------------------------
   Movimiento — hover-lift y glow reutilizables.
   La "sensación de vida" que aporta feedback táctil sin estridencia.
   Respetan prefers-reduced-motion.
   -------------------------------------------------------------------------- */
.u-lift {
    transition: transform var(--fl-t-rapido) var(--fl-ease-salida),
                box-shadow var(--fl-t-rapido) var(--fl-ease-salida);
    will-change: transform;
}
.u-lift:hover {
    transform: translateY(-1px);
    box-shadow: var(--fl-sombra-md);
}
.u-lift:active { transform: translateY(0); }

.u-lift-fuerte {
    transition: transform var(--fl-t-medio) var(--fl-ease-resorte),
                box-shadow var(--fl-t-medio) var(--fl-ease-salida);
    will-change: transform;
}
.u-lift-fuerte:hover {
    transform: translateY(-2px);
    box-shadow: var(--fl-sombra-lg);
}
.u-lift-fuerte:active { transform: translateY(0); }

.u-glow {
    box-shadow: 0 0 0 var(--fl-foco-ancho) var(--fl-acento-foco);
}

@media (prefers-reduced-motion: reduce) {
    .u-lift, .u-lift-fuerte { transition: none; }
    .u-lift:hover, .u-lift-fuerte:hover { transform: none; }
}

/* --------------------------------------------------------------------------
   Destaque — patrón de resalte de alto contraste inspirado en flora vieja.
   Usa los tokens --fl-destaque-* (definidos en 05-tokens-acento.css):
     · En paletas claras: color más oscuro de la paleta + texto blanco.
     · En paleta "oscuro": invertido — color más claro + texto oscuro.
   La inversión es automática gracias a los tokens.
   -------------------------------------------------------------------------- */

/* Solo bg/color — para componer sobre otros elementos (botón, chip, card).
   Respeta padding y radius ya existentes del elemento base. */
.u-destaque {
    background: var(--fl-destaque-fondo);
    color: var(--fl-destaque-texto);
}

.u-destaque-hover:hover {
    background: var(--fl-destaque-fondo-hover);
    color: var(--fl-destaque-texto);
}

/* Bloque destacado — listo para usar: padding + radius + tipografía.
   Ideal para callouts, alertas premium, banners informativos. */
.u-bloque-destaque {
    background: var(--fl-destaque-fondo);
    color: var(--fl-destaque-texto);
    padding: var(--fl-sp-4) var(--fl-sp-5);
    border-radius: var(--fl-r-lg);
    border: 1px solid var(--fl-destaque-borde);
}

/* Hero destacado — gradiente diagonal 135deg con tres paradas de la paleta.
   Patrón de flora vieja en headers principales. */
.u-hero-destaque {
    background: var(--fl-destaque-gradiente);
    color: var(--fl-destaque-texto);
    padding: var(--fl-sp-8) var(--fl-sp-6);
    border-radius: var(--fl-r-xl);
    position: relative;
    overflow: hidden;
}

/* Highlight sutil arriba — efecto "vidrio" opcional para hero */
.u-hero-destaque::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 1px;
    background: linear-gradient(
        to right,
        transparent 10%,
        rgb(255 255 255 / 0.2),
        transparent 90%
    );
    pointer-events: none;
}

/* Chip destacado — inline, pequeño, con todo el peso visual.
   Ideal para badges "PRO", "NUEVO", contadores destacados, etc. */
.u-chip-destaque {
    display: inline-flex;
    align-items: center;
    gap: var(--fl-sp-1);
    background: var(--fl-destaque-fondo);
    color: var(--fl-destaque-texto);
    padding: var(--fl-sp-0-5) var(--fl-sp-2);
    border-radius: var(--fl-r-sm);
    font-size: var(--fl-texto-2xs);
    font-weight: var(--fl-peso-semibold);
    letter-spacing: var(--fl-ls-amplio);
    text-transform: uppercase;
    line-height: 1;
    height: 20px;
}

/* Borde destaque — para tarjetas/cards que quieras marcar con la paleta */
.u-borde-destaque {
    border: 2px solid var(--fl-destaque-borde);
}


/* ===== resources/css/componentes/a11y-toggles.css ===== */
/* ==========================================================================
   Flora · A11y Toggles (tamaño fuente, contraste alto, reducir movimiento)
   Overrides en <html> por atributos data-fl-*:
     data-fl-fuente="sm|md|lg|xl"
     data-fl-contraste="alto"
     data-fl-mov="reducir"
   ========================================================================== */

/* Escala de fuente global */
html[data-fl-fuente="sm"]  { font-size: 93.75%; }
html[data-fl-fuente="md"]  { font-size: 100%; }
html[data-fl-fuente="lg"]  { font-size: 112.5%; }
html[data-fl-fuente="xl"]  { font-size: 125%; }

/* Contraste alto */
html[data-fl-contraste="alto"] {
    --fl-borde: #000;
    --fl-borde-intenso: #000;
    --fl-borde-sutil: #666;
    --fl-texto-tenue: #000;
    --fl-texto-suave: #000;
    --fl-texto: #000;
    --fl-texto-fuerte: #000;
    --fl-fondo: #fff;
    --fl-superficie: #fff;
    --fl-superficie-elevada: #fff;
    --fl-fondo-sutil: #f4f4f4;
}
html[data-fl-contraste="alto"][data-fl-enfasis="oscuro"] {
    --fl-borde: #fff;
    --fl-borde-intenso: #fff;
    --fl-borde-sutil: #999;
    --fl-texto-tenue: #fff;
    --fl-texto-suave: #fff;
    --fl-texto: #fff;
    --fl-texto-fuerte: #fff;
    --fl-fondo: #000;
    --fl-superficie: #000;
    --fl-superficie-elevada: #000;
    --fl-fondo-sutil: #111;
}
html[data-fl-contraste="alto"] *:focus-visible {
    outline: 3px solid currentColor !important;
    outline-offset: 2px;
}

/* Reducir movimiento (override manual por sobre el prefers-reduced-motion del SO) */
html[data-fl-mov="reducir"] *,
html[data-fl-mov="reducir"] *::before,
html[data-fl-mov="reducir"] *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
}

/* Panel de preferencias (opcional) */
.fl-a11y-panel {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-3);
    padding: var(--fl-sp-4);
    background: var(--fl-superficie);
    border: 1px solid var(--fl-borde);
    border-radius: var(--fl-r-lg);
    max-width: 340px;
}

.fl-a11y-panel-grupo {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.fl-a11y-panel-etiqueta {
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-suave);
    font-weight: var(--fl-peso-semibold);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.fl-a11y-panel-fuente {
    display: inline-flex;
    gap: 4px;
}
.fl-a11y-panel-fuente button {
    padding: 6px 12px;
    background: var(--fl-superficie);
    border: 1px solid var(--fl-borde);
    border-radius: var(--fl-r-sm);
    cursor: pointer;
    font-family: inherit;
}
.fl-a11y-panel-fuente button[data-fl-activo="true"] {
    background: var(--fl-destaque-fondo);
    color: var(--fl-destaque-texto);
    border-color: var(--fl-destaque-fondo);
}
.fl-a11y-panel-fuente button[data-fl-tamano="sm"] { font-size: 12px; }
.fl-a11y-panel-fuente button[data-fl-tamano="md"] { font-size: 14px; }
.fl-a11y-panel-fuente button[data-fl-tamano="lg"] { font-size: 17px; }
.fl-a11y-panel-fuente button[data-fl-tamano="xl"] { font-size: 20px; }


/* ===== resources/css/componentes/accion-sheet.css ===== */
/* ==========================================================================
   Flora · Accion-Sheet (bottom sheet iOS-style con lista de acciones)
   ========================================================================== */

.fl-accion-sheet-fondo {
    position: fixed; inset: 0;
    background: rgba(0 0 0 / 0.4);
    z-index: var(--fl-z-modal);
    opacity: 0; visibility: hidden;
    transition: opacity 220ms, visibility 220ms;
}
.fl-accion-sheet-fondo[data-fl-abierto="true"] { opacity: 1; visibility: visible; }

.fl-accion-sheet {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: calc(var(--fl-z-modal) + 1);
    padding: 8px;
    padding-bottom: max(var(--fl-sp-3), env(safe-area-inset-bottom));
    transform: translateY(100%);
    transition: transform 280ms var(--fl-ease-salida);
    display: flex;
    flex-direction: column;
    gap: 8px;
    font-size: var(--fl-texto-base);
}
.fl-accion-sheet[data-fl-abierto="true"] { transform: translateY(0); }

.fl-accion-sheet-grupo {
    background: var(--fl-superficie-elevada);
    border-radius: var(--fl-r-lg);
    overflow: hidden;
    box-shadow: var(--fl-sombra-lg);
}

.fl-accion-sheet-titulo {
    padding: 12px var(--fl-sp-4);
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-tenue);
    text-align: center;
    border-bottom: 1px solid var(--fl-borde-sutil);
}

.fl-accion-sheet-accion {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
    width: 100%;
    padding: 14px var(--fl-sp-4);
    background: transparent;
    border: 0;
    cursor: pointer;
    font-size: var(--fl-texto-base);
    color: var(--fl-texto-fuerte);
    text-align: left;
    transition: background 120ms;
    min-height: 52px;
    font-family: inherit;
}
.fl-accion-sheet-accion + .fl-accion-sheet-accion { border-top: 1px solid var(--fl-borde-sutil); }
.fl-accion-sheet-accion:hover, .fl-accion-sheet-accion:active { background: var(--fl-superficie-hover); }
.fl-accion-sheet-accion[data-fl-variante="peligro"] { color: var(--fl-error); }
.fl-accion-sheet-accion[data-fl-variante="acento"] { color: var(--fl-acento); font-weight: var(--fl-peso-semibold); }
.fl-accion-sheet-accion .fl-icono { width: 20px; height: 20px; }
.fl-accion-sheet-accion-descripcion {
    display: block;
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-tenue);
    margin-top: 2px;
    font-weight: var(--fl-peso-regular);
}

.fl-accion-sheet-cancelar {
    width: 100%;
    padding: 14px;
    background: var(--fl-superficie-elevada);
    border-radius: var(--fl-r-lg);
    border: 0;
    cursor: pointer;
    font-size: var(--fl-texto-base);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-fuerte);
    box-shadow: var(--fl-sombra-lg);
    font-family: inherit;
}

@media (prefers-reduced-motion: reduce) {
    .fl-accion-sheet { transition: none; }
}


/* ===== resources/css/componentes/acordeon.css ===== */
/* ==========================================================================
   Flora · Acordeón
   Header con gradient dark del acento (siempre visible como "lomo" fuerte),
   cuerpo con acento-suave cuando se despliega. Animación vía grid-template-rows.
   ========================================================================== */

.fl-acordeon {
    display: flex;
    width: 100%;
    flex-direction: column;
    gap: var(--fl-sp-2);
}

/* Variante bordeada: todos los items en un bloque continuo */
.fl-acordeon--bordeado {
    border: 1px solid color-mix(in srgb, var(--fl-acento) 30%, transparent);
    border-radius: var(--fl-r-lg);
    overflow: hidden;
    gap: 0;
    box-shadow: 0 4px 14px -4px color-mix(in srgb, var(--fl-acento) 25%, transparent);
}

.fl-acordeon--bordeado .fl-acordeon-item + .fl-acordeon-item {
    border-top: 1px solid color-mix(in srgb, white 12%, transparent);
}

.fl-acordeon-item {
    background: transparent;
    border-radius: var(--fl-r-md);
    overflow: hidden;
}

.fl-acordeon:not(.fl-acordeon--bordeado) .fl-acordeon-item {
    box-shadow: 0 2px 10px -3px color-mix(in srgb, var(--fl-acento) 30%, transparent);
}

.fl-acordeon--bordeado .fl-acordeon-item {
    border-radius: 0;
}

/* Header — gradient dark del acento con texto blanco */
.fl-acordeon-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--fl-sp-3);
    width: 100%;
    padding: var(--fl-sp-3) var(--fl-sp-4);
    background: linear-gradient(
        135deg,
        var(--fl-acento-600) 0%,
        var(--fl-acento-900) 100%
    );
    border: 0;
    font-family: inherit;
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-semibold);
    color: white;
    text-align: left;
    cursor: pointer;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida),
                box-shadow var(--fl-t-rapido) var(--fl-ease-salida);
    box-shadow: inset 0 1px 0 color-mix(in srgb, white 18%, transparent);
    position: relative;
}

.fl-acordeon-header:hover {
    background: linear-gradient(
        135deg,
        var(--fl-acento-500) 0%,
        var(--fl-acento-800) 100%
    );
}

.fl-acordeon-header:focus-visible {
    outline: none;
    box-shadow:
        inset 0 0 0 2px white,
        inset 0 1px 0 color-mix(in srgb, white 18%, transparent);
}

.fl-acordeon-header-texto {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
    flex: 1;
    min-width: 0;
}

.fl-acordeon-header-texto .fl-icono {
    width: 16px;
    height: 16px;
    color: color-mix(in srgb, white 88%, transparent);
    flex: none;
}

/* Chevron indicador */
.fl-acordeon-chevron {
    flex: none;
    width: 16px;
    height: 16px;
    color: color-mix(in srgb, white 75%, transparent);
    transition: transform 260ms var(--fl-ease-resorte),
                color var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-acordeon-item[data-fl-abierto="true"] .fl-acordeon-chevron {
    transform: rotate(180deg);
    color: white;
}

/* Cuerpo colapsable — usamos grid-template-rows para animar altura */
.fl-acordeon-contenedor {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows 300ms var(--fl-ease-salida);
}

.fl-acordeon-item[data-fl-abierto="true"] .fl-acordeon-contenedor {
    grid-template-rows: 1fr;
}

.fl-acordeon-cuerpo {
    overflow: hidden;
    min-height: 0;
    background: var(--fl-acento-suave);
}

.fl-acordeon-cuerpo-contenido {
    padding: var(--fl-sp-4);
    color: var(--fl-texto-fuerte);
    font-size: var(--fl-texto-sm);
    line-height: var(--fl-lh-relajada);
}

@media (prefers-reduced-motion: reduce) {
    .fl-acordeon-contenedor,
    .fl-acordeon-chevron,
    .fl-acordeon-header {
        transition: none;
    }
}


/* ===== resources/css/componentes/alerta.css ===== */
/* ==========================================================================
   Flora · Alerta
   Inline notification. Cuatro variantes semánticas: éxito, error, advertencia,
   info. Estructura: icono + contenido (título + mensaje) + cerrar opcional.
   ========================================================================== */

.fl-alerta {
    display: flex;
    align-items: center;
    width: 100%;
    max-width: 100%;
    gap: var(--fl-sp-3);
    padding: var(--fl-sp-3) var(--fl-sp-4);
    border: 1px solid;
    border-left-width: 4px;
    border-radius: var(--fl-r-md);
    /* Fondo mezclado con acento para cohesión de paleta.
       La border-left (stripe de severidad) mantiene el color semántico puro
       para reconocimiento inmediato, pero el fondo queda matizado. */
    background: color-mix(in srgb, var(--fl-info-suave) 70%, var(--fl-acento-suave));
    border-color: color-mix(in srgb, var(--fl-info-borde) 60%, var(--fl-acento-borde));
    border-left-color: var(--fl-info);
    color: var(--fl-info-texto);
    font-size: var(--fl-texto-sm);
    line-height: var(--fl-lh-ajustada);
    position: relative;
    animation: fl-alerta-entrada 1800ms var(--fl-ease-salida) both;
}

/* --------------------------------------------------------------------------
   Variantes semánticas — fondo mezclado con acento, stripe pura
   -------------------------------------------------------------------------- */
.fl-alerta--exito {
    background: color-mix(in srgb, var(--fl-exito-suave) 70%, var(--fl-acento-suave));
    border-color: color-mix(in srgb, var(--fl-exito-borde) 60%, var(--fl-acento-borde));
    border-left-color: var(--fl-exito);
    color: var(--fl-exito-texto);
}

.fl-alerta--error {
    background: color-mix(in srgb, var(--fl-error-suave) 70%, var(--fl-acento-suave));
    border-color: color-mix(in srgb, var(--fl-error-borde) 60%, var(--fl-acento-borde));
    border-left-color: var(--fl-error);
    color: var(--fl-error-texto);
}

.fl-alerta--advertencia {
    background: color-mix(in srgb, var(--fl-advertencia-suave) 70%, var(--fl-acento-suave));
    border-color: color-mix(in srgb, var(--fl-advertencia-borde) 60%, var(--fl-acento-borde));
    border-left-color: var(--fl-advertencia);
    color: var(--fl-advertencia-texto);
}

.fl-alerta--info {
    background: color-mix(in srgb, var(--fl-info-suave) 70%, var(--fl-acento-suave));
    border-color: color-mix(in srgb, var(--fl-info-borde) 60%, var(--fl-acento-borde));
    border-left-color: var(--fl-info);
    color: var(--fl-info-texto);
}

/* Neutral — para mensajes sin semántica específica */
.fl-alerta--neutral {
    background: var(--fl-fondo-sutil);
    border-color: var(--fl-borde);
    border-left-color: var(--fl-borde-intenso);
    color: var(--fl-texto);
}

/* --------------------------------------------------------------------------
   Partes
   -------------------------------------------------------------------------- */
.fl-alerta-icono {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    color: inherit;
    transform-origin: center;
    animation: fl-alerta-icono-zoom 1900ms var(--fl-ease-resorte) 80ms both;
}

.fl-alerta-icono .fl-icono {
    width: 22px;
    height: 22px;
    display: block;
}

/* Por variante, el ícono usa el color semántico sólido (contraste fuerte
   contra el fondo suave) — así la alerta info se lee azul clara, la
   advertencia amarilla/naranja, error rojo, éxito verde. */
.fl-alerta .fl-alerta-icono { color: var(--fl-info); }
.fl-alerta--exito .fl-alerta-icono       { color: var(--fl-exito); }
.fl-alerta--error .fl-alerta-icono       { color: var(--fl-error); }
.fl-alerta--advertencia .fl-alerta-icono { color: var(--fl-advertencia); }
.fl-alerta--info .fl-alerta-icono        { color: var(--fl-info); }
.fl-alerta--neutral .fl-alerta-icono     { color: var(--fl-texto-suave); }

.fl-alerta-contenido {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-1);
}

.fl-alerta-titulo {
    font-weight: var(--fl-peso-semibold);
    line-height: var(--fl-lh-compacta);
    color: inherit;
}

.fl-alerta-mensaje {
    color: inherit;
    opacity: 0.92;
}

.fl-alerta-mensaje p {
    margin: 0;
}

.fl-alerta-mensaje p + p {
    margin-top: var(--fl-sp-2);
}

.fl-alerta-acciones {
    display: flex;
    gap: var(--fl-sp-2);
    margin-top: var(--fl-sp-2);
}

/* Los botones fantasma dentro de las acciones heredan el color semántico
   de la variante de la alerta (base + hover) para que el gesto de cada
   acción se sienta coherente con el contexto. El SECUNDARIO mantiene su
   color de paleta — es neutro frente al intent semántico. */
.fl-alerta--error .fl-alerta-acciones .fl-boton--fantasma {
    color: var(--fl-error);
}
.fl-alerta--exito .fl-alerta-acciones .fl-boton--fantasma {
    color: var(--fl-exito);
}
.fl-alerta--advertencia .fl-alerta-acciones .fl-boton--fantasma {
    color: var(--fl-advertencia);
}
.fl-alerta--info .fl-alerta-acciones .fl-boton--fantasma {
    color: var(--fl-info);
}

.fl-alerta--error .fl-alerta-acciones .fl-boton--fantasma:hover:not(:disabled) {
    background: color-mix(in srgb, var(--fl-error) 7%, transparent);
    border-color: var(--fl-error);
    color: var(--fl-error);
}
.fl-alerta--exito .fl-alerta-acciones .fl-boton--fantasma:hover:not(:disabled) {
    background: color-mix(in srgb, var(--fl-exito) 7%, transparent);
    border-color: var(--fl-exito);
    color: var(--fl-exito);
}
.fl-alerta--advertencia .fl-alerta-acciones .fl-boton--fantasma:hover:not(:disabled) {
    background: color-mix(in srgb, var(--fl-advertencia) 7%, transparent);
    border-color: var(--fl-advertencia);
    color: var(--fl-advertencia);
}
.fl-alerta--info .fl-alerta-acciones .fl-boton--fantasma:hover:not(:disabled) {
    background: color-mix(in srgb, var(--fl-info) 7%, transparent);
    border-color: var(--fl-info);
    color: var(--fl-info);
}

.fl-alerta-cerrar {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    margin-top: -2px;
    margin-right: -4px;
    padding: 0;
    background: transparent;
    border: 0;
    border-radius: var(--fl-r-sm);
    color: inherit;
    opacity: 0.6;
    cursor: pointer;
    transition: opacity var(--fl-t-rapido) var(--fl-ease-salida),
                background var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-alerta-cerrar:hover {
    opacity: 1;
    background: color-mix(in srgb, currentColor 10%, transparent);
}

.fl-alerta-cerrar:focus-visible {
    outline: none;
    opacity: 1;
    box-shadow: 0 0 0 2px color-mix(in srgb, currentColor 40%, transparent);
}

.fl-alerta-cerrar .fl-icono {
    width: 16px;
    height: 16px;
}

/* --------------------------------------------------------------------------
   Modificadores
   -------------------------------------------------------------------------- */
.fl-alerta--solido.fl-alerta--exito {
    background: var(--fl-exito);
    border-color: var(--fl-exito);
    color: var(--fl-exito-texto-sobre);
}

.fl-alerta--solido.fl-alerta--error {
    background: var(--fl-error);
    border-color: var(--fl-error);
    color: var(--fl-error-texto-sobre);
}

.fl-alerta--solido.fl-alerta--advertencia {
    background: var(--fl-advertencia);
    border-color: var(--fl-advertencia);
    color: var(--fl-advertencia-texto-sobre);
}

.fl-alerta--solido.fl-alerta--info {
    background: var(--fl-info);
    border-color: var(--fl-info);
    color: var(--fl-info-texto-sobre);
}

/* En variante sólida el fondo es el color semántico — el ícono no puede
   usar el mismo color (se perdería). Forzamos que herede el color del
   texto-sobre (típicamente blanco) para que quede visible y contrastado. */
.fl-alerta--solido .fl-alerta-icono { color: inherit; }

/* Variante destaque — color de paleta más oscuro + texto blanco (flora vieja) */
.fl-alerta--destaque {
    background: var(--fl-destaque-fondo);
    border-color: var(--fl-destaque-fondo);
    color: var(--fl-destaque-texto);
}

.fl-alerta--destaque .fl-alerta-icono,
.fl-alerta--destaque .fl-alerta-titulo,
.fl-alerta--destaque .fl-alerta-cerrar {
    color: var(--fl-destaque-texto);
}

/* Compacta — menos padding, una sola línea */
.fl-alerta--compacta {
    padding: var(--fl-sp-2) var(--fl-sp-3);
    gap: var(--fl-sp-2);
    font-size: var(--fl-texto-xs);
    align-items: center;
}

.fl-alerta--compacta .fl-alerta-icono {
    width: 18px;
    height: 18px;
    margin-top: 0;
}

.fl-alerta--compacta .fl-alerta-icono .fl-icono {
    width: 18px;
    height: 18px;
}

/* Sin borde izquierdo enfatizado */
.fl-alerta--plana {
    border-left-width: 1px;
}

@keyframes fl-alerta-entrada {
    from {
        opacity: 0;
        transform: translateY(-14px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

@keyframes fl-alerta-icono-zoom {
    0%   { opacity: 0; transform: scale(2); }
    60%  { opacity: 1; transform: scale(0.92); }
    100% { opacity: 1; transform: scale(1); }
}

/* Salida al cerrar — fade + slide up + colapso vertical.
   height, padding y margin se animan para que el contenido de abajo
   suba suave en vez de saltar. overflow:hidden evita que el contenido
   se vea mientras se colapsa. */
.fl-alerta--cerrando {
    animation: none;
    overflow: hidden;
    pointer-events: none;
    transition:
        opacity 260ms var(--fl-ease-salida),
        transform 260ms var(--fl-ease-salida),
        height 320ms var(--fl-ease-salida) 60ms,
        padding 320ms var(--fl-ease-salida) 60ms,
        margin 320ms var(--fl-ease-salida) 60ms,
        border-width 320ms var(--fl-ease-salida) 60ms;
    opacity: 0;
    transform: translateY(-6px);
    padding-top: 0;
    padding-bottom: 0;
    margin-top: 0;
    margin-bottom: 0;
    border-top-width: 0;
    border-bottom-width: 0;
}

/* Respetar preferencia reduced-motion */
@media (prefers-reduced-motion: reduce) {
    .fl-alerta,
    .fl-alerta-icono { animation: none; }
    .fl-alerta--cerrando { transition: none; }
}


/* ===== resources/css/componentes/animaciones.css ===== */
/* ==========================================================================
   Flora · Animaciones (reemplazo minimal de Animate.css)
   15 animaciones CSS-only más comunes + data-fl-animar para entrar al scroll.
   Uso: <div class="fl-anim fl-anim--fade-up">...</div>
   O:    <div data-fl-animar="fade-up">...</div> (IntersectionObserver)
   ========================================================================== */

.fl-anim { animation-duration: 600ms; animation-fill-mode: both; animation-timing-function: var(--fl-ease-salida); }
.fl-anim--rapida { animation-duration: 360ms; }
.fl-anim--lenta { animation-duration: 1000ms; }
.fl-anim--retraso-1 { animation-delay: 120ms; }
.fl-anim--retraso-2 { animation-delay: 240ms; }
.fl-anim--retraso-3 { animation-delay: 360ms; }

/* Fade */
@keyframes fl-fade-in      { from { opacity: 0; } to { opacity: 1; } }
@keyframes fl-fade-up      { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
@keyframes fl-fade-down    { from { opacity: 0; transform: translateY(-16px); } to { opacity: 1; transform: none; } }
@keyframes fl-fade-left    { from { opacity: 0; transform: translateX(16px); } to { opacity: 1; transform: none; } }
@keyframes fl-fade-right   { from { opacity: 0; transform: translateX(-16px); } to { opacity: 1; transform: none; } }

.fl-anim--fade-in    { animation-name: fl-fade-in; }
.fl-anim--fade-up    { animation-name: fl-fade-up; }
.fl-anim--fade-down  { animation-name: fl-fade-down; }
.fl-anim--fade-left  { animation-name: fl-fade-left; }
.fl-anim--fade-right { animation-name: fl-fade-right; }

/* Scale */
@keyframes fl-zoom-in   { from { opacity: 0; transform: scale(0.9); } to { opacity: 1; transform: none; } }
@keyframes fl-zoom-out  { from { opacity: 0; transform: scale(1.1); } to { opacity: 1; transform: none; } }
@keyframes fl-pop       { 0% { transform: scale(0.3); opacity: 0; } 60% { transform: scale(1.08); opacity: 1; } 100% { transform: scale(1); } }

.fl-anim--zoom-in  { animation-name: fl-zoom-in; }
.fl-anim--zoom-out { animation-name: fl-zoom-out; }
.fl-anim--pop      { animation-name: fl-pop; animation-timing-function: var(--fl-ease-resorte); }

/* Slide (sin fade) */
@keyframes fl-slide-up    { from { transform: translateY(100%); } to { transform: none; } }
@keyframes fl-slide-down  { from { transform: translateY(-100%); } to { transform: none; } }
@keyframes fl-slide-left  { from { transform: translateX(100%); } to { transform: none; } }
@keyframes fl-slide-right { from { transform: translateX(-100%); } to { transform: none; } }

.fl-anim--slide-up    { animation-name: fl-slide-up; }
.fl-anim--slide-down  { animation-name: fl-slide-down; }
.fl-anim--slide-left  { animation-name: fl-slide-left; }
.fl-anim--slide-right { animation-name: fl-slide-right; }

/* Attention seekers */
@keyframes fl-shake   { 0%,100% { transform: none; } 20% { transform: translateX(-8px); } 40% { transform: translateX(8px); } 60% { transform: translateX(-6px); } 80% { transform: translateX(6px); } }
@keyframes fl-bounce  { 0%,100% { transform: none; } 30% { transform: translateY(-20px); } 60% { transform: translateY(-10px); } }
@keyframes fl-pulse   { 0%,100% { transform: scale(1); } 50% { transform: scale(1.05); } }
@keyframes fl-spin    { to { transform: rotate(360deg); } }
@keyframes fl-flash   { 0%,50%,100% { opacity: 1; } 25%,75% { opacity: 0; } }

.fl-anim--shake  { animation-name: fl-shake; }
.fl-anim--bounce { animation-name: fl-bounce; }
.fl-anim--pulse  { animation-name: fl-pulse; animation-iteration-count: infinite; }
.fl-anim--spin   { animation-name: fl-spin; animation-iteration-count: infinite; animation-timing-function: linear; }
.fl-anim--flash  { animation-name: fl-flash; }

/* Scroll-triggered via data-fl-animar — inicial oculto, se revela al entrar en viewport */
[data-fl-animar] { opacity: 0; }
[data-fl-animar][data-fl-visto="true"] { opacity: 1; animation-duration: 700ms; animation-fill-mode: both; animation-timing-function: var(--fl-ease-salida); }
[data-fl-animar="fade-up"][data-fl-visto="true"]    { animation-name: fl-fade-up; }
[data-fl-animar="fade-down"][data-fl-visto="true"]  { animation-name: fl-fade-down; }
[data-fl-animar="fade-left"][data-fl-visto="true"]  { animation-name: fl-fade-left; }
[data-fl-animar="fade-right"][data-fl-visto="true"] { animation-name: fl-fade-right; }
[data-fl-animar="fade-in"][data-fl-visto="true"]    { animation-name: fl-fade-in; }
[data-fl-animar="zoom-in"][data-fl-visto="true"]    { animation-name: fl-zoom-in; }
[data-fl-animar="pop"][data-fl-visto="true"]        { animation-name: fl-pop; animation-timing-function: var(--fl-ease-resorte); }

@media (prefers-reduced-motion: reduce) {
    .fl-anim, [data-fl-animar] { animation: none !important; opacity: 1 !important; }
}


/* ===== resources/css/componentes/avatar.css ===== */
/* ==========================================================================
   Flora · Avatar
   Círculo con imagen, iniciales o ícono fallback. 7 tamaños, 6 colores
   determinísticos por nombre (hash del string → paleta de fondo).
   ========================================================================== */

.fl-avatar {
    --_size: 40px;
    --_font: var(--fl-texto-sm);

    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: var(--_size);
    height: var(--_size);
    font-size: var(--_font);
    font-weight: var(--fl-peso-semibold);
    letter-spacing: -0.02em;
    border-radius: var(--fl-r-full);
    /* Fondo con más presencia contra --fl-fondo en paletas claras:
       usamos superficie-muda + borde sutil para garantizar contraste en las
       8 paletas. El texto usa color semántico fuerte. */
    background: var(--fl-superficie-muda);
    color: var(--fl-texto-fuerte);
    border: 1px solid var(--fl-borde);
    position: relative;
    user-select: none;
    text-transform: uppercase;
}

/* Cuando hay imagen, el borde se hace sutil para no competir con el contenido. */
.fl-avatar:has(img) {
    border-color: var(--fl-borde-sutil);
}

/* La imagen se recorta con su propio border-radius (evita que overflow:hidden
   en el avatar corte el indicador de estado que vive fuera del círculo). */
.fl-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    border-radius: inherit;
}

.fl-avatar .fl-icono {
    width: 55%;
    height: 55%;
}

/* --------------------------------------------------------------------------
   Tamaños
   -------------------------------------------------------------------------- */
.fl-avatar--xs { --_size: 20px; --_font: 9px;  }
.fl-avatar--sm { --_size: 28px; --_font: 11px; }
.fl-avatar--md { --_size: 40px; --_font: var(--fl-texto-sm); }
.fl-avatar--lg { --_size: 56px; --_font: var(--fl-texto-lg); }
.fl-avatar--xl { --_size: 72px; --_font: var(--fl-texto-xl); }
.fl-avatar--2xl { --_size: 96px; --_font: var(--fl-texto-2xl); }
.fl-avatar--3xl { --_size: 128px; --_font: var(--fl-texto-3xl); }

/* --------------------------------------------------------------------------
   Cuadrado (con radio sutil en vez de círculo)
   -------------------------------------------------------------------------- */
.fl-avatar--cuadrado {
    border-radius: var(--fl-r-lg);
}

/* --------------------------------------------------------------------------
   Paletas determinísticas — aplicadas según [data-fl-avatar-color="N"] de 1-6
   Elegí un valor estable por usuario (ej: hash del nombre mod 6 + 1).
   -------------------------------------------------------------------------- */
.fl-avatar[data-fl-avatar-color="1"] { background: #eef2ff; color: #3730a3; }
.fl-avatar[data-fl-avatar-color="2"] { background: #fdf2f8; color: #9d174d; }
.fl-avatar[data-fl-avatar-color="3"] { background: #ecfdf5; color: #065f46; }
.fl-avatar[data-fl-avatar-color="4"] { background: #fff7ed; color: #9a3412; }
.fl-avatar[data-fl-avatar-color="5"] { background: #f5f3ff; color: #5b21b6; }
.fl-avatar[data-fl-avatar-color="6"] { background: #f0fdfa; color: #115e59; }

[data-fl-enfasis="oscuro"] .fl-avatar[data-fl-avatar-color="1"] { background: color-mix(in srgb, #6366f1 18%, transparent); color: #c7d2fe; }
[data-fl-enfasis="oscuro"] .fl-avatar[data-fl-avatar-color="2"] { background: color-mix(in srgb, #ec4899 18%, transparent); color: #fbcfe8; }
[data-fl-enfasis="oscuro"] .fl-avatar[data-fl-avatar-color="3"] { background: color-mix(in srgb, #10b981 18%, transparent); color: #a7f3d0; }
[data-fl-enfasis="oscuro"] .fl-avatar[data-fl-avatar-color="4"] { background: color-mix(in srgb, #f97316 18%, transparent); color: #fed7aa; }
[data-fl-enfasis="oscuro"] .fl-avatar[data-fl-avatar-color="5"] { background: color-mix(in srgb, #8b5cf6 18%, transparent); color: #ddd6fe; }
[data-fl-enfasis="oscuro"] .fl-avatar[data-fl-avatar-color="6"] { background: color-mix(in srgb, #14b8a6 18%, transparent); color: #99f6e4; }

/* --------------------------------------------------------------------------
   Indicador de estado (punto en esquina inferior derecha)
   -------------------------------------------------------------------------- */
.fl-avatar--con-estado {
    position: relative;
}

.fl-avatar-estado {
    position: absolute;
    right: 0;
    bottom: 0;
    width: 28%;
    height: 28%;
    min-width: 8px;
    min-height: 8px;
    border-radius: var(--fl-r-full);
    border: 2px solid var(--fl-superficie);
    background: var(--fl-texto-tenue);
}

.fl-avatar-estado--online    { background: var(--fl-exito); }
.fl-avatar-estado--ocupado   { background: var(--fl-error); }
.fl-avatar-estado--ausente   { background: var(--fl-advertencia); }
.fl-avatar-estado--offline   { background: var(--fl-texto-tenue); }

/* --------------------------------------------------------------------------
   Grupo — avatares superpuestos (stack)
   -------------------------------------------------------------------------- */
.fl-avatares-grupo {
    display: inline-flex;
    align-items: center;
}

.fl-avatares-grupo > .fl-avatar {
    border: 2px solid var(--fl-superficie);
    margin-left: -10px;
    transition: transform 180ms var(--fl-ease-resorte);
}

.fl-avatares-grupo > .fl-avatar:first-child {
    margin-left: 0;
}

.fl-avatares-grupo > .fl-avatar:hover {
    transform: translateY(-3px);
    z-index: 1;
}

.fl-avatares-grupo--sm > .fl-avatar { margin-left: -6px; }
.fl-avatares-grupo--lg > .fl-avatar { margin-left: -14px; }

/* Avatar "+N" al final del stack */
.fl-avatar--contador {
    background: var(--fl-superficie-muda);
    color: var(--fl-texto-suave);
    font-weight: var(--fl-peso-medio);
}


/* ===== resources/css/componentes/badge.css ===== */
/* ==========================================================================
   Flora · Badge
   Pill pequeño para estado, conteo, etiqueta. Inerte (no clickeable).
   Para interactivos usar Chip.

   Paleta: TODAS las variantes usan profundidades de acento, no colores
   semánticos externos. Las variantes "exito/error/adv/info" son aliases
   que apuntan a distintas intensidades de la misma paleta — el texto del
   badge ("Activo", "Rechazado") carga el significado, el color sólo
   refuerza la jerarquía.
   ========================================================================== */

.fl-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--fl-sp-1);
    padding: 1px var(--fl-sp-2);
    font-size: var(--fl-texto-2xs);
    font-weight: var(--fl-peso-medio);
    line-height: 1.5;
    letter-spacing: 0.01em;
    color: var(--fl-texto);
    background: var(--fl-superficie-muda);
    border: 1px solid var(--fl-borde-sutil);
    border-radius: var(--fl-r-full);
    white-space: nowrap;
    vertical-align: middle;
}

.fl-badge .fl-icono {
    width: 10px;
    height: 10px;
}

/* Punto decorativo al inicio — status indicator */
.fl-badge-punto {
    width: 6px;
    height: 6px;
    border-radius: var(--fl-r-full);
    background: currentColor;
    flex: none;
}

.fl-badge-texto {
    position: relative;
    top: -1px;
}

/* --------------------------------------------------------------------------
   Tamaños
   -------------------------------------------------------------------------- */
.fl-badge--sm {
    padding: 1px var(--fl-sp-1-5);
    font-size: 10px;
}

.fl-badge--lg {
    padding: 3px var(--fl-sp-2-5);
    font-size: var(--fl-texto-xs);
}

/* --------------------------------------------------------------------------
   Variantes — profundidades de paleta (no semántico externo)
   Cada variante = una intensidad distinta de acento. El texto da el contexto.
   -------------------------------------------------------------------------- */
.fl-badge--acento,
.fl-badge--info {
    background: color-mix(in srgb, var(--fl-acento) 12%, var(--fl-superficie));
    border-color: color-mix(in srgb, var(--fl-acento) 30%, transparent);
    color: var(--fl-acento-texto);
}

.fl-badge--adv {
    background: color-mix(in srgb, var(--fl-acento) 20%, var(--fl-superficie));
    border-color: color-mix(in srgb, var(--fl-acento) 40%, transparent);
    color: var(--fl-acento-texto);
}

.fl-badge--exito {
    background: color-mix(in srgb, var(--fl-acento-700) 16%, var(--fl-superficie));
    border-color: color-mix(in srgb, var(--fl-acento-700) 40%, transparent);
    color: var(--fl-acento-texto);
}

.fl-badge--error {
    background: color-mix(in srgb, var(--fl-acento-900) 20%, var(--fl-superficie));
    border-color: color-mix(in srgb, var(--fl-acento-900) 45%, transparent);
    color: var(--fl-acento-texto);
}

/* Sólidos — alto contraste con paleta, texto siempre blanco */
.fl-badge--solido {
    background: var(--fl-texto-fuerte);
    border-color: transparent;
    color: var(--fl-texto-invertido);
}

.fl-badge--solido.fl-badge--acento,
.fl-badge--solido.fl-badge--info  { background: var(--fl-acento);     color: var(--fl-acento-texto-sobre); }
.fl-badge--solido.fl-badge--adv   { background: var(--fl-acento-700); color: var(--fl-acento-texto-sobre); }
.fl-badge--solido.fl-badge--exito { background: var(--fl-acento-800); color: var(--fl-acento-texto-sobre); }
.fl-badge--solido.fl-badge--error { background: var(--fl-acento-950); color: var(--fl-acento-texto-sobre); }

/* Variante destaque explícita — el color más fuerte + blanco */
.fl-badge--destaque {
    background: var(--fl-destaque-fondo);
    color: var(--fl-destaque-texto);
    border-color: transparent;
    font-weight: var(--fl-peso-semibold);
    text-transform: uppercase;
    letter-spacing: var(--fl-ls-mayus);
}

/* Outline — borde en acento, sin fondo */
.fl-badge--outline {
    background: transparent;
    border-color: var(--fl-borde-fuerte);
}

.fl-badge--outline.fl-badge--acento,
.fl-badge--outline.fl-badge--info  { border-color: var(--fl-acento);     color: var(--fl-acento-texto); }
.fl-badge--outline.fl-badge--adv   { border-color: var(--fl-acento-600); color: var(--fl-acento-texto); }
.fl-badge--outline.fl-badge--exito { border-color: var(--fl-acento-700); color: var(--fl-acento-texto); }
.fl-badge--outline.fl-badge--error { border-color: var(--fl-acento-900); color: var(--fl-acento-texto); }

/* Conteo — pastilla numérica muy chica, típicamente sobre un ícono */
.fl-badge--conteo {
    min-width: 18px;
    padding: 1px 5px;
    font-size: 10px;
    font-weight: var(--fl-peso-semibold);
}


/* ===== resources/css/componentes/barra-carga.css ===== */
/* ==========================================================================
   Flora · Barra-Carga (top loading bar tipo NProgress)
   Barra fina arriba de la página para operaciones de carga/nav SPA.
   ========================================================================== */

.fl-barra-carga {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
    background: var(--fl-destaque-fondo);
    z-index: var(--fl-z-toast, 1050);
    width: 0;
    opacity: 0;
    transform-origin: left;
    transition: width 240ms var(--fl-ease-salida),
                opacity 200ms var(--fl-ease-salida);
    box-shadow: 0 0 12px var(--fl-destaque-fondo);
    pointer-events: none;
}

.fl-barra-carga[data-fl-activa="true"] { opacity: 1; }

.fl-barra-carga::after {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    width: 80px;
    height: 100%;
    background: linear-gradient(to right, transparent, rgba(255 255 255 / 0.6));
    animation: fl-barra-carga-sheen 1.4s linear infinite;
}

.fl-barra-carga[data-fl-activa="false"]::after { display: none; }

@keyframes fl-barra-carga-sheen {
    0%   { transform: translateX(-80px); }
    100% { transform: translateX(80px); }
}

@media (prefers-reduced-motion: reduce) {
    .fl-barra-carga::after { animation: none; }
}


/* ===== resources/css/componentes/boton.css ===== */
/* ==========================================================================
   Flora · Botón
   Base + variantes (primario, secundario, fantasma, peligro, suave, enlace)
   + tamaños (xs, sm, md, lg) + estados (hover, activo, foco, loading).
   ========================================================================== */

.fl-boton {
    --_alto: var(--fl-alto-control-md);
    --_px: var(--fl-sp-4);
    --_texto: var(--fl-texto-sm);
    /* Gap = espacio a los lados del ícono (tanto entre ícono-texto como
       entre ícono-borde vía la regla :has() más abajo que usa este token).
       13px de cada lado — hardcoded (no hay token intermedio). */
    --_gap: 13px;

    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--_gap);
    height: var(--_alto);
    padding: 0 var(--_px);
    font-family: inherit;
    font-size: var(--_texto);
    font-weight: var(--fl-peso-medio);
    /* 1.5 en lugar de 1 para que el leading extra compense la asimetría
       de la métrica del font (mismo truco que chip/badge/breadcrumb-pasos). */
    line-height: 1.5;
    letter-spacing: 0;
    text-decoration: none;
    white-space: nowrap;
    border-radius: var(--fl-r-md);
    border: 1px solid transparent;
    background: transparent;
    color: inherit;
    cursor: pointer;
    user-select: none;
    /* Botón y su ícono comparten duración/easing para que el hover se
       perciba como UN solo movimiento coordinado (sin "dos tiempos"). */
    transition: background var(--fl-t-rapido) var(--fl-ease-salida),
                color var(--fl-t-rapido) var(--fl-ease-salida),
                border-color var(--fl-t-rapido) var(--fl-ease-salida),
                box-shadow var(--fl-t-medio) var(--fl-ease-salida),
                transform var(--fl-t-medio) var(--fl-ease-salida);
}

/* Cuando el botón tiene un ícono al inicio o al final, el padding de ese
   lado se reduce al valor del gap. Motivo: con padding=16 y gap=8, el
   ícono queda más lejos del borde que del texto, desbalanceado. Igualando
   ambos espacios el ícono se lee "ópticamente centrado" entre el borde
   y el texto. Patrón clásico tipo Material Design para botones icon+text. */
.fl-boton:has(> .fl-icono:first-child:not(:last-child)) {
    padding-left: var(--_gap);
}

.fl-boton:has(> .fl-icono:last-child:not(:first-child)) {
    padding-right: var(--_gap);
    will-change: transform;
}

.fl-boton:focus {
    outline: none;
}

.fl-boton:focus-visible {
    box-shadow: 0 0 0 var(--fl-foco-ancho) var(--fl-acento-foco);
}

/* Press-bounce — feedback táctil cuando hacés click */
.fl-boton:not(:disabled):not([aria-busy="true"]):active {
    transform: scale(0.97);
    transition-duration: 60ms;
}

.fl-boton:disabled,
.fl-boton[aria-disabled="true"] {
    opacity: 0.5;
    cursor: not-allowed;
    pointer-events: none;
}

/* Ícono dentro de botón — micro-interacción en hover.
   · Scale 1.45 con ease-salida, coordinado al mismo timing que el lift
     del botón para que se lea como UN solo movimiento.
   · IMPORTANTE: NO promovemos a capa GPU (nada de will-change ni
     backface-visibility) — eso cacheaba el SVG como raster y lo escalaba
     como bitmap, produciendo el "blur mientras crece + pop de nitidez al
     final" que se veía como dos tiempos. Sin promoción, el browser
     re-renderiza el SVG vectorialmente frame a frame = nítido siempre. */
.fl-boton > .fl-icono {
    /* Ícono un poco más grande que el texto para que tenga presencia
       visual clara (1.25em ≈ 17.5px cuando el botón es text-sm 14px).
       Antes era 1em — se leía como un adorno; ahora pesa como elemento. */
    width: 1.25em;
    height: 1.25em;
    flex: none;
    transform-origin: center;
    /* Zoom-in muy pausado — 520ms. El ícono crece lento y deliberado,
       como respirando. Mucho más perceptible que un hover estándar. */
    transition: transform 520ms var(--fl-ease-salida);
}

.fl-boton:hover:not(:disabled) > .fl-icono {
    /* Hover: escala proporcional al nuevo tamaño base. Antes 1.25, ahora
       1.4 — mantiene el "pop" más marcado en hover. */
    transform: scale(1.4);
}

.fl-boton:active:not(:disabled) > .fl-icono {
    transform: scale(0.92);
    transition: transform 90ms var(--fl-ease-salida);
}

@media (prefers-reduced-motion: reduce) {
    .fl-boton > .fl-icono { transition: none; }
    .fl-boton:hover:not(:disabled) > .fl-icono,
    .fl-boton:active:not(:disabled) > .fl-icono { transform: none; }
}

/* --------------------------------------------------------------------------
   Tamaños
   -------------------------------------------------------------------------- */
.fl-boton--xs {
    --_alto: var(--fl-alto-control-xs);
    --_px: var(--fl-sp-2);
    --_texto: var(--fl-texto-2xs);
    --_gap: var(--fl-sp-1);
    border-radius: var(--fl-r-sm);
}

.fl-boton--sm {
    --_alto: var(--fl-alto-control-sm);
    --_px: var(--fl-sp-3);
    --_texto: var(--fl-texto-sm);
    --_gap: var(--fl-sp-1-5);
}

.fl-boton--lg {
    --_alto: var(--fl-alto-control-lg);
    --_px: var(--fl-sp-5);
    --_texto: var(--fl-texto-base);
    --_gap: var(--fl-sp-2-5);
    border-radius: var(--fl-r-lg);
}

/* --------------------------------------------------------------------------
   Variante: primario (destaque — color MÁS OSCURO de la paleta + texto blanco)
   Inspirado directo en flora vieja: máximo contraste para que la acción
   primaria grite en la pantalla. En la paleta "oscuro" se invierte
   automáticamente gracias a los tokens --fl-destaque-*.
   -------------------------------------------------------------------------- */
.fl-boton--primario {
    background: var(--fl-destaque-fondo);
    color: var(--fl-destaque-texto);
    border-color: var(--fl-destaque-fondo);
}

.fl-boton--primario:hover:not(:disabled) {
    background: var(--fl-destaque-fondo-hover);
    border-color: var(--fl-destaque-fondo-hover);
    transform: translateY(-1px);
    box-shadow: 0 6px 14px -6px color-mix(in srgb, var(--fl-destaque-fondo) 60%, transparent);
}

.fl-boton--primario:active:not(:disabled) {
    background: var(--fl-destaque-borde);
    border-color: var(--fl-destaque-borde);
    transform: translateY(0);
    box-shadow: none;
}

/* --------------------------------------------------------------------------
   Variante: secundario (outline con borde)
   -------------------------------------------------------------------------- */
.fl-boton--secundario {
    background: var(--fl-superficie);
    color: var(--fl-acento-texto);
    border-color: var(--fl-borde-fuerte);
}

.fl-boton--secundario:hover:not(:disabled) {
    /* Wash sobrio con acento. Usamos --fl-acento-texto para el color del
       texto porque es el token pensado para ir sobre --fl-acento-suave en
       ambas paletas (light: acento-700, dark: acento-300) — así siempre
       contrasta. Antes usaba --fl-destaque-fondo que en dark (= acento-800)
       se mimetizaba con el fondo oscuro y el texto desaparecía. */
    background: var(--fl-acento-suave);
    border-color: var(--fl-acento);
    color: var(--fl-acento-texto);
    transform: translateY(-1px);
    box-shadow: 0 2px 6px -2px color-mix(in srgb, var(--fl-acento) 30%, transparent);
}

.fl-boton--secundario:active:not(:disabled) {
    background: var(--fl-acento-suave-hover);
    color: var(--fl-acento-texto);
    transform: translateY(0);
    box-shadow: none;
}

/* --------------------------------------------------------------------------
   Variante: fantasma (sin relleno ni borde, hover sutil)
   -------------------------------------------------------------------------- */
.fl-boton--fantasma {
    background: transparent;
    color: var(--fl-acento-texto);
    border-color: transparent;
}

.fl-boton--fantasma:hover:not(:disabled) {
    /* Fondo suave del acento, sin cambiar border-color (quedaba como shift
       sub-pixel en soloIcono al alternar transparent↔visible). */
    background: color-mix(in srgb, var(--fl-acento) 10%, transparent);
    color: var(--fl-acento-texto);
}

.fl-boton--fantasma:active:not(:disabled) {
    background: color-mix(in srgb, var(--fl-acento) 16%, transparent);
    color: var(--fl-acento-texto);
}

/* --------------------------------------------------------------------------
   Variante: suave (acento con baja saturación, fondo suave)
   -------------------------------------------------------------------------- */
.fl-boton--suave {
    background: var(--fl-acento-suave);
    color: var(--fl-acento-texto);
    border-color: transparent;
}

.fl-boton--suave:hover:not(:disabled) {
    background: var(--fl-acento-suave-hover);
    transform: translateY(-1px);
    box-shadow: 0 4px 10px -4px color-mix(in srgb, var(--fl-acento) 35%, transparent);
}

.fl-boton--suave:active:not(:disabled) {
    transform: translateY(0);
    box-shadow: none;
}

/* --------------------------------------------------------------------------
   Variante: peligro (rojo sólido)
   -------------------------------------------------------------------------- */
.fl-boton--peligro {
    background: var(--fl-error);
    color: var(--fl-error-texto-sobre);
    border-color: var(--fl-error);
}

.fl-boton--peligro:hover:not(:disabled) {
    background: var(--fl-error-hover);
    border-color: var(--fl-error-hover);
    transform: translateY(-1px);
    box-shadow: 0 6px 14px -6px color-mix(in srgb, var(--fl-error) 60%, transparent);
}

.fl-boton--peligro:active:not(:disabled) {
    transform: translateY(0);
    box-shadow: none;
}

.fl-boton--peligro:focus-visible {
    box-shadow: 0 0 0 var(--fl-foco-ancho)
        color-mix(in srgb, var(--fl-error) 35%, transparent);
}

/* --------------------------------------------------------------------------
   Variante: éxito (verde sólido) — espejo de peligro para acciones positivas.
   Usa siempre los tokens semánticos (--fl-exito) así no depende de la paleta.
   -------------------------------------------------------------------------- */
.fl-boton--exito {
    background: var(--fl-exito);
    color: var(--fl-exito-texto-sobre);
    border-color: var(--fl-exito);
}

.fl-boton--exito:hover:not(:disabled) {
    background: var(--fl-exito-hover);
    border-color: var(--fl-exito-hover);
    transform: translateY(-1px);
    box-shadow: 0 6px 14px -6px color-mix(in srgb, var(--fl-exito) 60%, transparent);
}

.fl-boton--exito:active:not(:disabled) {
    transform: translateY(0);
    box-shadow: none;
}

.fl-boton--exito:focus-visible {
    box-shadow: 0 0 0 var(--fl-foco-ancho)
        color-mix(in srgb, var(--fl-exito) 35%, transparent);
}

/* --------------------------------------------------------------------------
   Variante: advertencia (amarillo/naranja sólido)
   -------------------------------------------------------------------------- */
.fl-boton--advertencia {
    background: var(--fl-advertencia);
    color: var(--fl-advertencia-texto-sobre);
    border-color: var(--fl-advertencia);
}

.fl-boton--advertencia:hover:not(:disabled) {
    background: var(--fl-advertencia-hover);
    border-color: var(--fl-advertencia-hover);
    transform: translateY(-1px);
    box-shadow: 0 6px 14px -6px color-mix(in srgb, var(--fl-advertencia) 60%, transparent);
}

.fl-boton--advertencia:active:not(:disabled) {
    transform: translateY(0);
    box-shadow: none;
}

.fl-boton--advertencia:focus-visible {
    box-shadow: 0 0 0 var(--fl-foco-ancho)
        color-mix(in srgb, var(--fl-advertencia) 35%, transparent);
}

/* --------------------------------------------------------------------------
   Variante: info (azul sólido)
   -------------------------------------------------------------------------- */
.fl-boton--info {
    background: var(--fl-info);
    color: var(--fl-info-texto-sobre);
    border-color: var(--fl-info);
}

.fl-boton--info:hover:not(:disabled) {
    background: var(--fl-info-hover);
    border-color: var(--fl-info-hover);
    transform: translateY(-1px);
    box-shadow: 0 6px 14px -6px color-mix(in srgb, var(--fl-info) 60%, transparent);
}

.fl-boton--info:active:not(:disabled) {
    transform: translateY(0);
    box-shadow: none;
}

.fl-boton--info:focus-visible {
    box-shadow: 0 0 0 var(--fl-foco-ancho)
        color-mix(in srgb, var(--fl-info) 35%, transparent);
}

/* --------------------------------------------------------------------------
   Variante: enlace (parece un link, pero es botón)
   -------------------------------------------------------------------------- */
.fl-boton--enlace {
    height: auto;
    padding: 0;
    background: transparent;
    color: var(--fl-acento-enlace);
    border-color: transparent;
    border-radius: var(--fl-r-xs);
}

.fl-boton--enlace:hover:not(:disabled) {
    color: var(--fl-acento-hover);
    text-decoration: underline;
    text-underline-offset: 0.2em;
}

/* --------------------------------------------------------------------------
   Modificadores
   -------------------------------------------------------------------------- */
.fl-boton--solo-icono {
    width: var(--_alto);
    padding: 0;
}

.fl-boton--bloque {
    width: 100%;
}

.fl-boton--redondeado {
    border-radius: var(--fl-r-full);
}

/* Estado cargando — agrega un spinner y deshabilita */
.fl-boton[aria-busy="true"] {
    cursor: wait;
    pointer-events: none;
}

.fl-boton[aria-busy="true"] > .fl-boton-contenido {
    opacity: 0.0;
}

.fl-boton[aria-busy="true"]::after {
    content: "";
    position: absolute;
    width: 1em;
    height: 1em;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: var(--fl-r-full);
    animation: fl-spinner 0.7s linear infinite;
}

.fl-boton[aria-busy="true"] {
    position: relative;
}

@keyframes fl-spinner {
    to { transform: rotate(360deg); }
}

/* --------------------------------------------------------------------------
   Grupo de botones (segmented control / split button)
   -------------------------------------------------------------------------- */
.fl-grupo-botones {
    display: inline-flex;
    align-items: stretch;
}

.fl-grupo-botones > .fl-boton {
    border-radius: 0;
    margin-left: -1px;
}

.fl-grupo-botones > .fl-boton:first-child {
    border-top-left-radius: var(--fl-r-md);
    border-bottom-left-radius: var(--fl-r-md);
    margin-left: 0;
}

.fl-grupo-botones > .fl-boton:last-child {
    border-top-right-radius: var(--fl-r-md);
    border-bottom-right-radius: var(--fl-r-md);
}

.fl-grupo-botones > .fl-boton:focus-visible {
    z-index: 1;
}


/* ===== resources/css/componentes/breadcrumb.css ===== */
/* ==========================================================================
   Flora · Breadcrumb
   Lista horizontal de enlaces jerárquicos con separador. Último = actual.
   ========================================================================== */

.fl-breadcrumb {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--fl-sp-1);
    padding: 0;
    margin: 0;
    list-style: none;
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto-suave);
    /* 1.5 para que los caps queden ópticamente centrados (igual que chip/boton). */
    line-height: 1.5;
}

.fl-breadcrumb-item {
    display: inline-flex;
    align-items: center;
    gap: var(--fl-sp-1);
    min-width: 0;
}

.fl-breadcrumb-enlace {
    /* Más fuerte que texto-suave para que se lea mejor sobre fondos tintados
       de vívida (especialmente en la paleta oscuro donde el contraste baja). */
    color: var(--fl-texto);
    text-decoration: none;
    padding: 6px var(--fl-sp-3);
    border-radius: var(--fl-r-sm);
    line-height: 1;
    transition: color var(--fl-t-rapido) var(--fl-ease-salida),
                background var(--fl-t-rapido) var(--fl-ease-salida);
    display: inline-flex;
    align-items: center;
    gap: var(--fl-sp-1);
}

.fl-breadcrumb-enlace:hover {
    /* --fl-acento-texto se auto-invierte: en claras = acento-700 (dark),
       en oscuro = acento-300 (bright). Legible en ambos modos. */
    color: var(--fl-acento-texto);
    background: color-mix(in srgb, var(--fl-acento) 8%, transparent);
}

.fl-breadcrumb-enlace:focus-visible {
    outline: none;
    color: var(--fl-acento-texto);
    background: color-mix(in srgb, var(--fl-acento) 8%, transparent);
    box-shadow: 0 0 0 2px var(--fl-acento-foco);
}

.fl-breadcrumb-enlace .fl-icono,
.fl-breadcrumb-actual .fl-icono,
.fl-breadcrumb [aria-current="page"] .fl-icono {
    width: 14px;
    height: 14px;
    vertical-align: 0;
    flex: none;
}

/* Actual (último item) — no clickeable, más fuerte. Aplicamos también
   por atributo aria-current="page" para robustez semántica. */
.fl-breadcrumb-actual,
.fl-breadcrumb [aria-current="page"] {
    color: var(--fl-texto-fuerte);
    font-weight: var(--fl-peso-semibold);
    padding: 6px var(--fl-sp-3);
    line-height: 1;
    max-width: 260px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    display: inline-flex;
    align-items: center;
    gap: var(--fl-sp-1);
}

.fl-breadcrumb-actual .fl-icono,
.fl-breadcrumb [aria-current="page"] .fl-icono {
    /* Hereda color del texto para que ícono y palabra vayan del mismo tono. */
    color: inherit;
}

/* Separador entre items */
.fl-breadcrumb-separador {
    color: var(--fl-borde-intenso);
    display: inline-flex;
    align-items: center;
    user-select: none;
    pointer-events: none;
}

.fl-breadcrumb-separador .fl-icono {
    width: 14px;
    height: 14px;
}

/* Collapse — muestra "..." cuando hay muchos niveles */
.fl-breadcrumb-colapsado {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 22px;
    padding: 0;
    background: transparent;
    border: 0;
    border-radius: var(--fl-r-sm);
    color: var(--fl-texto-tenue);
    cursor: pointer;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-breadcrumb-colapsado:hover {
    background: var(--fl-superficie-hover);
    color: var(--fl-texto);
}

/* Variantes de tamaño */
.fl-breadcrumb--sm { font-size: var(--fl-texto-xs); }
.fl-breadcrumb--lg { font-size: var(--fl-texto-base); }

/* ==========================================================================
   Variante "pasos" — híbrido con la estética de Flora antigua (Resonum):
   pills conectadas side-by-side, uppercase, color progresivo del acento.
   Cada paso es un segmento continuo. El último destaca con el acento.
   ========================================================================== */

.fl-breadcrumb--pasos {
    gap: 0;
    font-size: var(--fl-texto-2xs);
    font-weight: var(--fl-peso-semibold);
    letter-spacing: var(--fl-ls-mayus);
    text-transform: uppercase;
    line-height: 1;
}

/* Sin chevron entre items — los bordes de las pills los dividen visualmente */
.fl-breadcrumb--pasos .fl-breadcrumb-separador {
    display: none;
}

.fl-breadcrumb--pasos .fl-breadcrumb-item {
    gap: 0;
}

.fl-breadcrumb--pasos .fl-breadcrumb-enlace,
.fl-breadcrumb--pasos .fl-breadcrumb-actual {
    display: inline-flex;
    align-items: center;
    gap: var(--fl-sp-1-5);
    height: 32px;
    /* line-height = height es el truco clásico: el line-box del texto
       ocupa toda la altura, y los caps quedan centrados por las propias
       métricas del font renderizadas por el browser (más robusto que
       padding/line-height 1). */
    line-height: 32px;
    padding: 0 var(--fl-sp-4);
    border: 1px solid var(--fl-borde-fuerte);
    border-right: 0;
    background: var(--fl-superficie);
    color: var(--fl-texto-suave);
    border-radius: 0;
    max-width: none;
    overflow: visible;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida),
                color var(--fl-t-rapido) var(--fl-ease-salida),
                border-color var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-breadcrumb--pasos .fl-breadcrumb-enlace .fl-icono,
.fl-breadcrumb--pasos .fl-breadcrumb-actual .fl-icono {
    width: 14px;
    height: 14px;
    flex: none;
    vertical-align: 0;
}

/* Span del texto — hereda line-height del enlace (= height del pill),
   así el line-box del texto ocupa toda la altura y el baseline queda
   en la posición natural (centrada con el ícono). */
.fl-breadcrumb--pasos .fl-breadcrumb-texto {
    display: inline;
}

/* Primer segmento → rounded a la izquierda */
.fl-breadcrumb--pasos .fl-breadcrumb-item:first-child .fl-breadcrumb-enlace,
.fl-breadcrumb--pasos .fl-breadcrumb-item:first-child .fl-breadcrumb-actual {
    border-radius: var(--fl-r-full) 0 0 var(--fl-r-full);
    padding-left: var(--fl-sp-5);
}

/* Último (actual) → rounded a la derecha + destaque sólido */
.fl-breadcrumb--pasos .fl-breadcrumb-item:last-child .fl-breadcrumb-actual {
    border-radius: 0 var(--fl-r-full) var(--fl-r-full) 0;
    border-right: 1px solid var(--fl-destaque-fondo);
    padding-right: var(--fl-sp-5);
    background: var(--fl-destaque-fondo);
    color: var(--fl-destaque-texto);
    border-color: var(--fl-destaque-fondo);
    cursor: default;
    font-weight: var(--fl-peso-semibold);
}

/* Hover en clickeables — sólo cambio de color y fondo, borde sin cambio.
   Fondo muy tenue para no dominar — sólo un toque de acento. */
.fl-breadcrumb--pasos .fl-breadcrumb-enlace:hover {
    background: color-mix(in srgb, var(--fl-acento) 8%, transparent);
    color: var(--fl-acento-texto);
}

.fl-breadcrumb--pasos .fl-breadcrumb-enlace:hover .fl-icono {
    color: var(--fl-acento);
}

.fl-breadcrumb--pasos .fl-breadcrumb-enlace:focus-visible {
    outline: none;
    background: var(--fl-superficie-hover);
    color: var(--fl-acento);
    box-shadow: inset 0 0 0 2px var(--fl-acento-foco);
    z-index: 1;
}

/* Sin separador horizontal visual, conectados por borde */
.fl-breadcrumb--pasos .fl-breadcrumb-item + .fl-breadcrumb-item .fl-breadcrumb-enlace,
.fl-breadcrumb--pasos .fl-breadcrumb-item + .fl-breadcrumb-item .fl-breadcrumb-actual {
    position: relative;
}

/* Variante "pasos" en tamaños */
.fl-breadcrumb--pasos.fl-breadcrumb--sm .fl-breadcrumb-enlace,
.fl-breadcrumb--pasos.fl-breadcrumb--sm .fl-breadcrumb-actual {
    height: 24px;
    line-height: 24px;
    padding: 0 var(--fl-sp-3);
    font-size: 10px;
}

.fl-breadcrumb--pasos.fl-breadcrumb--lg .fl-breadcrumb-enlace,
.fl-breadcrumb--pasos.fl-breadcrumb--lg .fl-breadcrumb-actual {
    height: 38px;
    line-height: 38px;
    padding: 0 var(--fl-sp-5);
    font-size: var(--fl-texto-xs);
}

/* Medium (default): a 11px IBM Plex el texto queda visualmente pegado al
   borde inferior. Añadimos padding-bottom para empujar el contenido hacia
   arriba dejando más aire debajo (box-sizing mantiene height en 32px). */
.fl-breadcrumb--pasos:not(.fl-breadcrumb--sm):not(.fl-breadcrumb--lg) .fl-breadcrumb-enlace,
.fl-breadcrumb--pasos:not(.fl-breadcrumb--sm):not(.fl-breadcrumb--lg) .fl-breadcrumb-actual {
    padding-bottom: 2px;
}

/* ==========================================================================
   Mobile (< 640px) — aplanamos la variante "pasos".
   Razones:
   1. flex-wrap: wrap mandaba los pills a múltiples filas → cada fila con
      altura visual distinta (especialmente el actual que es bg sólido).
   2. El truco de pills conectadas usa border-right: 0 + border en otros
      lados con color borde-fuerte (visible) en enlaces, vs border-color
      destaque-fondo (invisible) en el actual. Misma altura física (32px
      con border-box), pero la silueta visual del enlace tiene 1px de
      ribete visible arriba y abajo que no tiene el actual → percepción de
      "enlaces más altos que el último".
   Solución mobile: scroll horizontal nowrap + sacar el truco de pills,
   render como texto plano con chevrons entre items. Más limpio en pantalla
   chica y evita la incongruencia visual.
   ========================================================================== */
@media (max-width: 640px) {
    .fl-breadcrumb {
        flex-wrap: nowrap;
        overflow-x: auto;
        overflow-y: hidden;
        scrollbar-width: none;            /* Firefox */
        -ms-overflow-style: none;         /* IE/Edge legacy */
        -webkit-overflow-scrolling: touch;
        gap: 2px;
        align-items: center;
    }
    .fl-breadcrumb::-webkit-scrollbar {
        display: none;                    /* Safari / Chrome */
    }
    .fl-breadcrumb-item {
        flex: none;
        align-items: center;
    }
    /* Aplanamos pills → texto plano con misma height/padding para todos.
       Sin border, sin background, mismo line-height. Garantiza que enlace
       y actual sean visualmente idénticos en altura. */
    .fl-breadcrumb--pasos .fl-breadcrumb-enlace,
    .fl-breadcrumb--pasos .fl-breadcrumb-actual {
        height: 28px;
        line-height: 28px;
        padding: 0 8px;
        padding-bottom: 0;
        border: 0;
        background: transparent;
        border-radius: var(--fl-r-sm);
    }
    .fl-breadcrumb--pasos .fl-breadcrumb-item:first-child .fl-breadcrumb-enlace,
    .fl-breadcrumb--pasos .fl-breadcrumb-item:first-child .fl-breadcrumb-actual {
        padding-left: 8px;
    }
    .fl-breadcrumb--pasos .fl-breadcrumb-item:last-child .fl-breadcrumb-actual {
        padding-right: 8px;
        background: transparent;
        color: var(--fl-texto-fuerte);
        border-color: transparent;
    }
    /* Chevron entre items — la variante "pasos" lo escondía con display: none.
       En mobile lo necesitamos para separar visualmente los items aplanados. */
    .fl-breadcrumb--pasos .fl-breadcrumb-item + .fl-breadcrumb-item::before {
        content: '';
        display: inline-block;
        width: 14px;
        height: 14px;
        background-color: var(--fl-borde-intenso);
        -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='9 18 15 12 9 6'/></svg>") no-repeat center / contain;
                mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='9 18 15 12 9 6'/></svg>") no-repeat center / contain;
        margin-right: 2px;
        align-self: center;
        flex: none;
    }
    /* En default (no-pasos) el item actual permite hasta 260px y trunca con
       ellipsis. En mobile bajamos el cap para que un nombre largo no domine
       el row y deje ver el resto al scrollear. */
    .fl-breadcrumb-actual {
        max-width: 180px;
    }
}





/* ===== resources/css/componentes/calendario.css ===== */
/* ==========================================================================
   Flora · Calendario
   Reemplazo de FullCalendar. Vistas mes / semana / día. Eventos coloreados.
   Drag & drop de eventos entre días. Locale es-AR (semana arranca lunes).
   ========================================================================== */

.fl-calendario {
    display: flex;
    flex-direction: column;
    width: 100%;
    background: var(--fl-superficie);
    border: 1px solid var(--fl-borde);
    border-radius: var(--fl-r-lg);
    overflow: hidden;
    min-height: 400px;
}

/* --------------------------------------------------------------------------
   Toolbar: navegación + título + cambio de vista
   -------------------------------------------------------------------------- */
.fl-calendario-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--fl-sp-3);
    padding: var(--fl-sp-3) var(--fl-sp-4);
    border-bottom: 1px solid var(--fl-borde-sutil);
    flex-wrap: wrap;
}

.fl-calendario-toolbar-izq,
.fl-calendario-toolbar-der {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
}

.fl-calendario-titulo {
    font-size: var(--fl-texto-lg);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-fuerte);
    line-height: 1.2;
    letter-spacing: var(--fl-ls-compacto);
    text-transform: capitalize;
    min-width: 180px;
    text-align: center;
}

/* --------------------------------------------------------------------------
   Grilla del mes (7 columnas de días)
   -------------------------------------------------------------------------- */
.fl-calendario-cuerpo {
    flex: 1;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.fl-calendario-dias-semana {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    background: color-mix(in srgb, var(--fl-acento) 8%, var(--fl-fondo-sutil));
    border-bottom: 1px solid var(--fl-borde);
}

.fl-calendario-dia-semana {
    padding: var(--fl-sp-2);
    text-align: center;
    font-size: var(--fl-texto-2xs);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-acento-texto);
    text-transform: uppercase;
    letter-spacing: var(--fl-ls-mayus);
    border-right: 1px solid var(--fl-borde-sutil);
}

.fl-calendario-dia-semana:last-child {
    border-right: 0;
}

/* Vista de mes — 6 filas de 7 días */
.fl-calendario-mes {
    flex: 1;
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    grid-template-rows: repeat(6, minmax(0, 1fr));
    min-height: 340px;
}

.fl-calendario-dia {
    border-right: 1px solid var(--fl-borde-sutil);
    border-bottom: 1px solid var(--fl-borde-sutil);
    padding: 6px;
    display: flex;
    flex-direction: column;
    gap: 3px;
    overflow: hidden;
    position: relative;
    cursor: pointer;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-calendario-dia:nth-child(7n) {
    border-right: 0;
}

.fl-calendario-dia:hover {
    background: color-mix(in srgb, var(--fl-acento) 4%, transparent);
}

/* Hover unificado para TODAS las variantes (otro-mes, finde y combinación).
   Sin esto, los selectores de variante con 2-3 clases (.--otro-mes, .--finde,
   .--otro-mes.--finde) tienen mayor especificidad que `.fl-calendario-dia:hover`
   y "ganan" sobre el hover → algunos días (típicamente los del mes siguiente
   en finde) no se iluminan al pasar por encima. Re-declaramos el hover con
   misma o mayor especificidad para garantizar feedback visual en todos. */
.fl-calendario-dia.fl-calendario-dia--otro-mes:hover,
.fl-calendario-dia.fl-calendario-dia--finde:hover,
.fl-calendario-dia.fl-calendario-dia--otro-mes.fl-calendario-dia--finde:hover {
    background: color-mix(in srgb, var(--fl-acento) 10%, var(--fl-fondo));
}

.fl-calendario-dia[data-fl-arrastrando-sobre="true"] {
    background: var(--fl-acento-suave);
    box-shadow: inset 0 0 0 2px var(--fl-acento);
}

.fl-calendario-dia-numero {
    font-size: var(--fl-texto-xs);
    font-weight: var(--fl-peso-medio);
    color: var(--fl-texto);
    text-align: right;
    padding: 2px 4px;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    align-self: flex-end;
}

/* Días de meses adyacentes */
.fl-calendario-dia--otro-mes {
    background: var(--fl-fondo-sutil);
}

.fl-calendario-dia--otro-mes .fl-calendario-dia-numero {
    color: var(--fl-texto-tenue);
}

/* Hoy — badge circular destaque (color más fuerte de la paleta) */
.fl-calendario-dia--hoy .fl-calendario-dia-numero {
    align-self: flex-end;
    width: 26px;
    height: 26px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--fl-destaque-fondo);
    color: var(--fl-destaque-texto);
    border-radius: var(--fl-r-full);
    font-weight: var(--fl-peso-semibold);
    padding: 0;
}

/* Fin de semana (sábado/domingo) — apenas un toque más oscuro que los días
   normales. Más sutil que antes (15% en vez de 30% del fondo-sutil) para
   marcar contraste claro contra los días de "otro mes" que son 100% sutil.
   Queda casi como un día normal pero con un leve gris perceptible. */
.fl-calendario-dia--finde {
    background: color-mix(in srgb, var(--fl-fondo-sutil) 3%, var(--fl-fondo));
}
/* Combinación: día de OTRO mes Y fin de semana → mantenemos el gris de
   "otro mes" para que no compita visualmente con findes del mes actual. */
.fl-calendario-dia--otro-mes.fl-calendario-dia--finde {
    background: var(--fl-fondo-sutil);
}

/* --------------------------------------------------------------------------
   Evento en la grilla
   -------------------------------------------------------------------------- */
.fl-calendario-evento {
    --_color: var(--fl-acento);

    display: flex;
    align-items: center;
    gap: 4px;
    padding: 2px 6px;
    font-size: 11px;
    font-weight: var(--fl-peso-medio);
    line-height: 1.2;
    color: var(--fl-acento-texto-sobre);
    background: var(--_color);
    border-radius: var(--fl-r-sm);
    cursor: grab;
    user-select: none;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    transition: transform 120ms var(--fl-ease-resorte),
                box-shadow var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-calendario-evento:hover {
    transform: translateY(-1px);
    box-shadow: 0 2px 6px -2px color-mix(in srgb, var(--_color) 60%, transparent);
}

.fl-calendario-evento:active {
    cursor: grabbing;
}

.fl-calendario-evento[data-fl-arrastrando="true"] {
    opacity: 0.4;
    transform: scale(0.98);
}

.fl-calendario-evento-hora {
    font-variant-numeric: tabular-nums;
    font-size: 10px;
    opacity: 0.9;
    flex: none;
    /* Sin line-height el span heredaba 1.2 y el box de dígitos (con
       tabular-nums) no coincidía ópticamente con el del título — el
       horario quedaba levantado. line-height:1 + inline-flex centrado
       alinea la caja numérica con el texto al centro del chip. */
    line-height: 1;
    display: inline-flex;
    align-items: center;
}

.fl-calendario-evento-titulo {
    overflow: hidden;
    text-overflow: ellipsis;
    flex: 1;
    min-width: 0;
    line-height: 1;
    display: inline-flex;
    align-items: center;
}

/* Variante tenue: evento con sólo borde izquierdo del color */
.fl-calendario-evento--tenue {
    background: color-mix(in srgb, var(--_color) 15%, var(--fl-superficie));
    color: var(--fl-texto-fuerte);
    border-left: 3px solid var(--_color);
    padding-left: 4px;
}

/* Contador de eventos extra cuando no caben */
.fl-calendario-mas {
    font-size: 10px;
    color: var(--fl-texto-suave);
    padding: 0 4px;
    cursor: pointer;
    border-radius: var(--fl-r-sm);
    transition: background var(--fl-t-rapido) var(--fl-ease-salida),
                color var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-calendario-mas:hover {
    background: var(--fl-acento-suave);
    color: var(--fl-acento-texto);
}

/* Modal "día completo" — lista de todos los eventos cuando hay desborde */
.fl-cal-dia-lista {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: var(--fl-sp-1) 0;
}
.fl-cal-dia-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 14px;
    border: none;
    background: transparent;
    border-radius: var(--fl-r-md);
    cursor: pointer;
    text-align: left;
    width: 100%;
    font-family: inherit;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida);
}
.fl-cal-dia-item:hover {
    background: var(--fl-fondo-sutil);
}
.fl-cal-dia-item-punto {
    width: 10px;
    height: 10px;
    border-radius: var(--fl-r-full);
    flex-shrink: 0;
}
.fl-cal-dia-item-titulo {
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-medio);
    color: var(--fl-texto-fuerte);
}


/* --------------------------------------------------------------------------
   Vista SEMANA: 7 columnas de días con horarios
   -------------------------------------------------------------------------- */
.fl-calendario-semana {
    flex: 1;
    display: grid;
    grid-template-columns: 56px repeat(7, 1fr);
    overflow-y: auto;
    max-height: 640px;
}

.fl-calendario-semana-horas {
    display: flex;
    flex-direction: column;
    border-right: 1px solid var(--fl-borde-sutil);
    background: var(--fl-fondo-sutil);
}

.fl-calendario-semana-hora {
    height: 48px;
    padding: 4px 6px 0 0;
    font-size: 10px;
    color: var(--fl-texto-tenue);
    text-align: right;
    font-variant-numeric: tabular-nums;
    border-bottom: 1px solid var(--fl-borde-sutil);
}

.fl-calendario-semana-col {
    display: flex;
    flex-direction: column;
    border-right: 1px solid var(--fl-borde-sutil);
    position: relative;
}

.fl-calendario-semana-col:last-child {
    border-right: 0;
}

.fl-calendario-semana-celda {
    height: 48px;
    border-bottom: 1px solid var(--fl-borde-sutil);
    cursor: pointer;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-calendario-semana-celda:hover {
    background: color-mix(in srgb, var(--fl-acento) 3%, transparent);
}

/* Evento en vista semana — posicionado absoluto por hora */
.fl-calendario-semana-evento {
    --_color: var(--fl-acento);
    position: absolute;
    left: 4px;
    right: 4px;
    padding: 4px 6px;
    background: var(--_color);
    color: var(--fl-acento-texto-sobre);
    border-radius: var(--fl-r-sm);
    font-size: 11px;
    font-weight: var(--fl-peso-medio);
    line-height: 1.3;
    overflow: hidden;
    cursor: pointer;
    box-shadow: 0 2px 6px -2px color-mix(in srgb, var(--_color) 40%, transparent);
    transition: transform 140ms var(--fl-ease-resorte);
}

.fl-calendario-semana-evento:hover {
    /* Sólo un pequeño "lift" vertical — no escalamos porque el evento
       está positioned:absolute al lado de la columna de horas y el
       crecimiento horizontal lo pisaba. */
    transform: translateY(-1px);
    box-shadow: 0 6px 14px -4px color-mix(in srgb, var(--_color) 45%, transparent);
    z-index: 2;
}

.fl-calendario-semana-evento-titulo {
    font-weight: var(--fl-peso-semibold);
}

.fl-calendario-semana-evento-hora {
    font-size: 10px;
    opacity: 0.9;
    margin-top: 1px;
    font-variant-numeric: tabular-nums;
}

/* Header de días (arriba de la grilla semana) */
.fl-calendario-semana-cabecera {
    display: grid;
    grid-template-columns: 56px repeat(7, 1fr);
    border-bottom: 1px solid var(--fl-borde);
    background: color-mix(in srgb, var(--fl-acento) 8%, var(--fl-fondo-sutil));
    position: sticky;
    top: 0;
    z-index: 2;
}

.fl-calendario-semana-cabecera-dia {
    padding: var(--fl-sp-2);
    text-align: center;
    border-right: 1px solid var(--fl-borde-sutil);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
}

.fl-calendario-semana-cabecera-dia:last-child {
    border-right: 0;
}

.fl-calendario-semana-cabecera-label {
    font-size: var(--fl-texto-2xs);
    font-weight: var(--fl-peso-semibold);
    text-transform: uppercase;
    letter-spacing: var(--fl-ls-mayus);
    color: var(--fl-acento-texto);
}

.fl-calendario-semana-cabecera-num {
    font-size: var(--fl-texto-lg);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-fuerte);
    font-variant-numeric: tabular-nums;
}

.fl-calendario-semana-cabecera-dia--hoy .fl-calendario-semana-cabecera-num {
    background: var(--fl-acento);
    color: var(--fl-acento-texto-sobre);
    width: 34px;
    height: 34px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--fl-r-full);
}

/* --------------------------------------------------------------------------
   Vista SEMANA · modo lista (sin grilla de horas).
   Cada columna es un día con la lista cronológica de sus eventos.
   -------------------------------------------------------------------------- */
.fl-calendario-semana-cabecera--lista {
    grid-template-columns: repeat(7, 1fr);
}

.fl-calendario-semana-lista {
    flex: 1;
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    overflow-y: auto;
    max-height: 640px;
    min-height: 320px;
}

.fl-calendario-semana-lista-col {
    border-right: 1px solid var(--fl-borde-sutil);
    padding: var(--fl-sp-2);
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-1-5);
    min-height: 100%;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-calendario-semana-lista-col:last-child {
    border-right: 0;
}

.fl-calendario-semana-lista-col:hover {
    background: color-mix(in srgb, var(--fl-acento) 3%, transparent);
}

/* Columna del día actual — fondo muy sutil para referencia visual */
.fl-calendario-semana-lista-col--hoy {
    background: color-mix(in srgb, var(--fl-acento) 5%, transparent);
}

.fl-calendario-semana-lista-col--hoy:hover {
    background: color-mix(in srgb, var(--fl-acento) 8%, transparent);
}

.fl-calendario-semana-evento-item {
    --_color: var(--fl-acento);
    padding: var(--fl-sp-1-5) var(--fl-sp-2);
    background: color-mix(in srgb, var(--_color) 10%, var(--fl-superficie));
    border-left: 3px solid var(--_color);
    border-radius: var(--fl-r-sm);
    cursor: pointer;
    display: flex;
    flex-direction: column;
    gap: 2px;
    transition: background 140ms var(--fl-ease-salida),
                transform 140ms var(--fl-ease-resorte);
}

.fl-calendario-semana-evento-item:hover {
    background: color-mix(in srgb, var(--_color) 18%, var(--fl-superficie));
    transform: translateX(2px);
}

.fl-calendario-semana-evento-item-hora {
    font-size: 10px;
    color: var(--fl-texto-suave);
    font-variant-numeric: tabular-nums;
    line-height: 1.2;
}

.fl-calendario-semana-evento-item-titulo {
    font-size: var(--fl-texto-xs);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-fuerte);
    line-height: 1.3;
    word-break: break-word;
}

.fl-calendario-semana-vacio {
    color: var(--fl-texto-tenue);
    font-size: var(--fl-texto-2xs);
    text-align: center;
    padding: var(--fl-sp-3) var(--fl-sp-2);
    font-style: italic;
}

/* --------------------------------------------------------------------------
   Vista DÍA: columna única + horarios
   -------------------------------------------------------------------------- */
.fl-calendario-dia-vista {
    flex: 1;
    display: grid;
    grid-template-columns: 64px 1fr;
    overflow-y: auto;
    max-height: 640px;
}

.fl-calendario-dia-vista .fl-calendario-semana-hora {
    height: 72px;
}

.fl-calendario-dia-vista .fl-calendario-semana-celda {
    height: 72px;
}

/* --------------------------------------------------------------------------
   Leyenda de categorías/calendarios
   -------------------------------------------------------------------------- */
.fl-calendario-leyenda {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-3);
    padding: var(--fl-sp-2) var(--fl-sp-4);
    border-top: 1px solid var(--fl-borde-sutil);
    background: var(--fl-fondo-sutil);
    flex-wrap: wrap;
    font-size: var(--fl-texto-xs);
}

.fl-calendario-leyenda-item {
    display: inline-flex;
    align-items: center;
    gap: var(--fl-sp-1-5);
    color: var(--fl-texto-suave);
    cursor: pointer;
    padding: 2px 6px;
    border-radius: var(--fl-r-sm);
    transition: background var(--fl-t-rapido);
}

.fl-calendario-leyenda-item:hover {
    background: var(--fl-superficie-hover);
    color: var(--fl-texto);
}

.fl-calendario-leyenda-item[data-fl-oculto="true"] {
    opacity: 0.4;
}

.fl-calendario-leyenda-punto {
    width: 10px;
    height: 10px;
    border-radius: var(--fl-r-sm);
    flex: none;
}

/* --------------------------------------------------------------------------
   Vista ANUAL — 12 meses con lista de eventos por mes
   -------------------------------------------------------------------------- */
.fl-calendario-anio {
    flex: 1;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--fl-sp-3);
    padding: var(--fl-sp-3);
    overflow-y: auto;
    align-content: start;
}

@media (max-width: 1200px) {
    .fl-calendario-anio {
        grid-template-columns: repeat(3, 1fr);
    }
}

@media (max-width: 900px) {
    .fl-calendario-anio {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (max-width: 600px) {
    .fl-calendario-anio {
        grid-template-columns: 1fr;
    }
}

.fl-calendario-anio-mes {
    background: var(--fl-superficie);
    border: 1px solid var(--fl-borde);
    border-radius: var(--fl-r-md);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    transition: border-color var(--fl-t-rapido), box-shadow var(--fl-t-rapido);
}

.fl-calendario-anio-mes:hover {
    border-color: var(--fl-acento);
    box-shadow: 0 4px 12px -4px color-mix(in srgb, var(--fl-acento) 25%, transparent);
}

.fl-calendario-anio-mes-titulo {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--fl-sp-2) var(--fl-sp-3);
    background: color-mix(in srgb, var(--fl-acento) 7%, var(--fl-fondo-sutil));
    border-bottom: 1px solid var(--fl-borde-sutil);
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-acento-texto);
    cursor: pointer;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida);
    text-transform: capitalize;
    letter-spacing: var(--fl-ls-compacto);
}

/* Hover sobre zonas clickeables (título + vacío) que disparan "nuevo evento" */
.fl-calendario-anio-mes-titulo:hover {
    background: color-mix(in srgb, var(--fl-acento) 14%, var(--fl-fondo-sutil));
}

.fl-calendario-anio-vacio:hover {
    background: color-mix(in srgb, var(--fl-acento) 5%, transparent);
    color: var(--fl-texto-suave);
}

.fl-calendario-anio-mes-acciones {
    display: inline-flex;
    align-items: center;
    gap: var(--fl-sp-1-5);
}

/* Botón "+" en la cabecera de cada mini-mes: crea evento rápido sin
   navegar a vista mes. Compacto para no competir con el título. */
.fl-calendario-anio-nuevo {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    padding: 0;
    background: transparent;
    border: 0;
    border-radius: var(--fl-r-full);
    color: var(--fl-texto-suave);
    cursor: pointer;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida),
                color var(--fl-t-rapido) var(--fl-ease-salida),
                transform 140ms var(--fl-ease-resorte);
}

.fl-calendario-anio-nuevo:hover {
    background: var(--fl-acento);
    color: var(--fl-acento-texto-sobre);
    transform: scale(1.08);
}

.fl-calendario-anio-nuevo .fl-icono {
    width: 14px;
    height: 14px;
}

.fl-calendario-anio-mes-conteo {
    font-size: var(--fl-texto-2xs);
    font-variant-numeric: tabular-nums;
    font-weight: var(--fl-peso-medio);
    color: var(--fl-texto-suave);
    background: var(--fl-superficie);
    border: 1px solid var(--fl-borde-sutil);
    border-radius: var(--fl-r-full);
    /* Pill con altura explícita + flex-center para que el número quede
       ópticamente centrado. Antes era inline-text con padding asimétrico
       y line-height heredada, y se veía levantado. */
    height: 22px;
    min-width: 26px;
    padding: 0 8px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
}

.fl-calendario-anio-lista {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
}

.fl-calendario-anio-evento {
    --_color: var(--fl-acento);
    display: grid;
    grid-template-columns: 28px 1fr auto;
    align-items: center;
    gap: var(--fl-sp-2);
    padding: 6px var(--fl-sp-3);
    border-bottom: 1px solid var(--fl-borde-sutil);
    cursor: pointer;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-calendario-anio-evento:last-child {
    border-bottom: 0;
}

.fl-calendario-anio-evento:hover {
    background: color-mix(in srgb, var(--_color) 6%, transparent);
}

.fl-calendario-anio-evento-fecha {
    font-variant-numeric: tabular-nums;
    font-size: var(--fl-texto-xs);
    font-weight: var(--fl-peso-semibold);
    color: var(--_color);
    text-align: center;
    line-height: 1;
}

.fl-calendario-anio-evento-titulo {
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-fuerte);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

.fl-calendario-anio-evento-hora {
    font-variant-numeric: tabular-nums;
    font-size: 10px;
    color: var(--fl-texto-tenue);
    flex: none;
}

.fl-calendario-anio-vacio {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 120px;
    padding: var(--fl-sp-3);
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-tenue);
    text-align: center;
    font-style: italic;
    cursor: pointer;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida),
                color var(--fl-t-rapido) var(--fl-ease-salida);
}

@media (prefers-reduced-motion: reduce) {
    .fl-calendario-evento,
    .fl-calendario-semana-evento,
    .fl-calendario-anio-mes {
        transition: none;
    }
}


/* ===== resources/css/componentes/callout.css ===== */
/* ==========================================================================
   Flora · Callout
   Bloque destacado para resaltar información con ícono + título + texto.
   Variantes: acento (default, patrón destaque), semánticas, gradiente.
   Inspirado en flora vieja (bandas destacadas con color fuerte + blanco).

   Diferencia con .fl-alerta:
     - Alerta = notificación transitoria, inline en un formulario o vista.
     - Callout = bloque estructural que resalta algo "de fondo" en la página
       (tip, disclaimer, aviso, feature highlight).
   ========================================================================== */

.fl-callout {
    display: flex;
    /* Siempre centrar vertical. Con el chip de 28px grande se lee como un
       badge al costado del contenido, funciona en single-line, 2 líneas
       (titulo + mensaje) y multi-línea. */
    align-items: center;
    gap: var(--fl-sp-3);
    padding: var(--fl-sp-4) var(--fl-sp-5);
    background: var(--fl-destaque-fondo);
    color: var(--fl-destaque-texto);
    border-radius: var(--fl-r-lg);
    border: 1px solid var(--fl-destaque-fondo);
    /* Ribbon lateral — acento visual consistente en todas las variantes.
       En el default usa el mismo destaque; en las semánticas se sobreescribe. */
    border-left: 5px solid color-mix(in srgb, var(--fl-destaque-texto) 40%, var(--fl-destaque-fondo));
    position: relative;
    overflow: hidden;
    max-width: 100%;

    /* Tokens de texto locales para que el contenido se lea claro */
    --fl-texto:          var(--fl-destaque-texto);
    --fl-texto-fuerte:   var(--fl-destaque-texto);
    --fl-texto-suave:    color-mix(in srgb, var(--fl-destaque-texto) 80%, transparent);
}

/* Highlight superior tipo "vidrio" opcional */
.fl-callout::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 1px;
    background: linear-gradient(
        to right,
        transparent 10%,
        rgb(255 255 255 / 0.18),
        transparent 90%
    );
    pointer-events: none;
}

.fl-callout-icono {
    flex: none;
    width: 28px;
    height: 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--fl-destaque-texto);
}

.fl-callout-icono .fl-icono {
    width: 28px;
    height: 28px;
    display: block;
}

.fl-callout-contenido {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-1);
}

.fl-callout-titulo {
    font-size: var(--fl-texto-base);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-destaque-texto);
    line-height: var(--fl-lh-compacta);
    margin: 0;
}

.fl-callout-mensaje {
    font-size: var(--fl-texto-sm);
    color: var(--fl-destaque-texto);
    line-height: var(--fl-lh-ajustada);
    /* Sin opacity — cuando el mensaje es el único contenido (sin título)
       no queremos que se vea washed-out. */
}

/* Cuando hay título, el mensaje secundario SÍ va atenuado para diferenciarlo */
.fl-callout:has(.fl-callout-titulo) .fl-callout-mensaje {
    opacity: 0.88;
}

.fl-callout-acciones {
    display: flex;
    gap: var(--fl-sp-2);
    margin-top: var(--fl-sp-2);
}

/* Fantasma dentro de acciones toma color semántico de la variante
   (mismo patrón que alerta/modal). Secundario se mantiene neutral. */
.fl-callout--error .fl-callout-acciones .fl-boton--fantasma {
    color: var(--fl-error);
}
.fl-callout--exito .fl-callout-acciones .fl-boton--fantasma {
    color: var(--fl-exito);
}
.fl-callout--advertencia .fl-callout-acciones .fl-boton--fantasma {
    color: var(--fl-advertencia);
}
.fl-callout--info .fl-callout-acciones .fl-boton--fantasma {
    color: var(--fl-info);
}

.fl-callout--error .fl-callout-acciones .fl-boton--fantasma:hover:not(:disabled) {
    background: color-mix(in srgb, var(--fl-error) 7%, transparent);
    border-color: var(--fl-error);
    color: var(--fl-error);
}
.fl-callout--exito .fl-callout-acciones .fl-boton--fantasma:hover:not(:disabled) {
    background: color-mix(in srgb, var(--fl-exito) 7%, transparent);
    border-color: var(--fl-exito);
    color: var(--fl-exito);
}
.fl-callout--advertencia .fl-callout-acciones .fl-boton--fantasma:hover:not(:disabled) {
    background: color-mix(in srgb, var(--fl-advertencia) 7%, transparent);
    border-color: var(--fl-advertencia);
    color: var(--fl-advertencia);
}
.fl-callout--info .fl-callout-acciones .fl-boton--fantasma:hover:not(:disabled) {
    background: color-mix(in srgb, var(--fl-info) 7%, transparent);
    border-color: var(--fl-info);
    color: var(--fl-info);
}

.fl-callout-cerrar {
    flex: none;
    background: transparent;
    border: 0;
    padding: 4px;
    border-radius: var(--fl-r-sm);
    color: color-mix(in srgb, var(--fl-destaque-texto) 70%, transparent);
    cursor: pointer;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida),
                color var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-callout-cerrar:hover {
    background: color-mix(in srgb, var(--fl-destaque-texto) 14%, transparent);
    color: var(--fl-destaque-texto);
}

.fl-callout-cerrar .fl-icono {
    width: 14px;
    height: 14px;
}

/* --------------------------------------------------------------------------
   Variante gradiente — 135deg con shades de la paleta
   -------------------------------------------------------------------------- */
.fl-callout--gradiente {
    background: var(--fl-destaque-gradiente);
    border-color: transparent;
}

/* --------------------------------------------------------------------------
   Variantes semánticas — mantienen el patrón "color fuerte + blanco"
   pero con los tokens semánticos en vez del acento.
   -------------------------------------------------------------------------- */
.fl-callout--exito {
    background: var(--fl-exito);
    border-color: var(--fl-exito);
    border-left-color: color-mix(in srgb, #000 25%, var(--fl-exito));
    color: var(--fl-exito-texto-sobre);
    --fl-texto:        var(--fl-exito-texto-sobre);
    --fl-texto-fuerte: var(--fl-exito-texto-sobre);
}

.fl-callout--exito .fl-callout-icono {
    color: var(--fl-exito-texto-sobre);
}

.fl-callout--exito .fl-callout-titulo,
.fl-callout--exito .fl-callout-mensaje {
    color: var(--fl-exito-texto-sobre);
}

.fl-callout--error {
    background: var(--fl-error);
    border-color: var(--fl-error);
    border-left-color: color-mix(in srgb, #000 25%, var(--fl-error));
    color: var(--fl-error-texto-sobre);
    --fl-texto:        var(--fl-error-texto-sobre);
    --fl-texto-fuerte: var(--fl-error-texto-sobre);
}

.fl-callout--error .fl-callout-icono {
    color: var(--fl-error-texto-sobre);
}

.fl-callout--error .fl-callout-titulo,
.fl-callout--error .fl-callout-mensaje {
    color: var(--fl-error-texto-sobre);
}

.fl-callout--advertencia {
    background: var(--fl-advertencia);
    border-color: var(--fl-advertencia);
    border-left-color: color-mix(in srgb, #000 25%, var(--fl-advertencia));
    color: var(--fl-advertencia-texto-sobre);
    --fl-texto:        var(--fl-advertencia-texto-sobre);
    --fl-texto-fuerte: var(--fl-advertencia-texto-sobre);
}

.fl-callout--advertencia .fl-callout-icono {
    color: var(--fl-advertencia-texto-sobre);
}

.fl-callout--advertencia .fl-callout-titulo,
.fl-callout--advertencia .fl-callout-mensaje {
    color: var(--fl-advertencia-texto-sobre);
}

.fl-callout--info {
    background: var(--fl-info);
    border-color: var(--fl-info);
    border-left-color: color-mix(in srgb, #000 25%, var(--fl-info));
    color: var(--fl-info-texto-sobre);
    --fl-texto:        var(--fl-info-texto-sobre);
    --fl-texto-fuerte: var(--fl-info-texto-sobre);
}

.fl-callout--info .fl-callout-icono {
    color: var(--fl-info-texto-sobre);
}

.fl-callout--info .fl-callout-titulo,
.fl-callout--info .fl-callout-mensaje {
    color: var(--fl-info-texto-sobre);
}

/* --------------------------------------------------------------------------
   Variante sobria — fondo tenue con el acento sutil, para cuando no querés
   el impacto destaque pero sí resaltar del fondo normal.
   -------------------------------------------------------------------------- */
.fl-callout--sobrio {
    background: var(--fl-acento-suave);
    border-color: var(--fl-acento-borde);
    color: var(--fl-texto);
    --fl-texto:        var(--fl-texto);
    --fl-texto-fuerte: var(--fl-texto-fuerte);
}

.fl-callout--sobrio::before { display: none; }

.fl-callout--sobrio .fl-callout-icono {
    color: var(--fl-acento);
}

.fl-callout--sobrio .fl-callout-titulo {
    color: var(--fl-texto-fuerte);
}

.fl-callout--sobrio .fl-callout-mensaje {
    color: var(--fl-texto);
    opacity: 1;
}

/* --------------------------------------------------------------------------
   Salida al cerrar — fade + slide up + colapso vertical.
   Espejo del patrón de alerta/banner para consistencia.
   -------------------------------------------------------------------------- */
.fl-callout--cerrando {
    pointer-events: none;
    transition:
        opacity 260ms var(--fl-ease-salida),
        transform 260ms var(--fl-ease-salida),
        height 320ms var(--fl-ease-salida) 60ms,
        padding 320ms var(--fl-ease-salida) 60ms,
        margin 320ms var(--fl-ease-salida) 60ms,
        border-width 320ms var(--fl-ease-salida) 60ms;
    opacity: 0;
    transform: translateY(-6px);
    padding-top: 0;
    padding-bottom: 0;
    margin-top: 0;
    margin-bottom: 0;
    border-top-width: 0;
    border-bottom-width: 0;
}

@media (prefers-reduced-motion: reduce) {
    .fl-callout--cerrando { transition: none; }
}


/* ===== resources/css/componentes/campo.css ===== */
/* ==========================================================================
   Flora · Campo (form field)
   Wrapper: etiqueta + entrada + ayuda/error.
   Cubre input, textarea, select nativo. Select2/rich selects van aparte.
   ========================================================================== */

.fl-campo {
    display: flex;
    flex-direction: column;
    /* Gap interno entre etiqueta ↔ input. sp-2-5 (10px) — el label respira
       claramente del input. Cambio global para toda la librería. */
    gap: var(--fl-sp-2-5);
    width: 100%;
}

/* --------------------------------------------------------------------------
   Etiqueta
   -------------------------------------------------------------------------- */
.fl-campo-etiqueta {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-1);
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-medio);
    color: var(--fl-texto);
    line-height: var(--fl-lh-compacta);
}

.fl-campo-etiqueta--obligatorio::after {
    content: "*";
    color: var(--fl-error);
    font-weight: var(--fl-peso-semibold);
}

.fl-campo-etiqueta-opcional {
    color: var(--fl-texto-tenue);
    font-size: var(--fl-texto-xs);
    font-weight: var(--fl-peso-regular);
    margin-left: var(--fl-sp-1);
}

/* --------------------------------------------------------------------------
   Entrada base (input, textarea, select)
   -------------------------------------------------------------------------- */
.fl-campo-entrada {
    display: block;
    width: 100%;
    min-height: var(--fl-alto-control-md);
    padding: 0 var(--fl-sp-3);
    font-family: inherit;
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-regular);
    line-height: var(--fl-lh-ajustada);
    color: var(--fl-texto-fuerte);
    background: var(--fl-superficie);
    border: 1px solid var(--fl-borde-fuerte);
    border-radius: var(--fl-r-md);
    box-shadow: var(--fl-sombra-xs);
    transition: border-color var(--fl-t-rapido) var(--fl-ease-salida),
                box-shadow var(--fl-t-rapido) var(--fl-ease-salida),
                background var(--fl-t-rapido) var(--fl-ease-salida);
    -webkit-appearance: none;
    appearance: none;
}

textarea.fl-campo-entrada {
    min-height: calc(var(--fl-alto-control-md) * 2);
    padding-top: var(--fl-sp-2);
    padding-bottom: var(--fl-sp-2);
    line-height: var(--fl-lh-normal);
    resize: vertical;
}

select.fl-campo-entrada {
    padding-right: var(--fl-sp-8);
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
    background-repeat: no-repeat;
    background-position: right var(--fl-sp-3) center;
    background-size: 16px;
    cursor: pointer;
}

.fl-campo-entrada::placeholder {
    color: var(--fl-texto-tenue);
    opacity: 1;
}

.fl-campo-entrada:hover:not(:disabled):not(:focus) {
    border-color: var(--fl-borde-intenso);
}

.fl-campo-entrada:focus {
    outline: none;
    border-color: var(--fl-destaque-fondo);
    box-shadow: 0 0 0 var(--fl-foco-ancho) var(--fl-acento-foco),
                0 4px 14px -6px color-mix(in srgb, var(--fl-destaque-fondo) 55%, transparent);
}

/* Cuando el input está focado, la etiqueta toma un color acento legible en
   ambos modos. `--fl-acento-texto` mapea a acento-700 en claro y acento-300
   en oscuro — siempre con contraste suficiente sobre el fondo. */
.fl-campo:focus-within .fl-campo-etiqueta {
    color: var(--fl-acento-texto);
}

.fl-campo-entrada:disabled {
    background: var(--fl-fondo-sutil);
    color: var(--fl-texto-deshabilitado);
    cursor: not-allowed;
    opacity: 0.8;
}

.fl-campo-entrada:read-only {
    background: var(--fl-fondo-sutil);
    cursor: default;
}

/* --------------------------------------------------------------------------
   Tamaños
   -------------------------------------------------------------------------- */
.fl-campo-entrada--sm {
    min-height: var(--fl-alto-control-sm);
    font-size: var(--fl-texto-sm);
    padding: 0 var(--fl-sp-2-5);
}

.fl-campo-entrada--lg {
    min-height: var(--fl-alto-control-lg);
    font-size: var(--fl-texto-base);
    padding: 0 var(--fl-sp-4);
}

/* --------------------------------------------------------------------------
   Estados semánticos
   -------------------------------------------------------------------------- */
.fl-campo--error .fl-campo-entrada,
.fl-campo-entrada[aria-invalid="true"] {
    border-color: var(--fl-error);
    box-shadow: 0 0 0 0 transparent;
}

.fl-campo--error .fl-campo-entrada:focus,
.fl-campo-entrada[aria-invalid="true"]:focus {
    box-shadow: 0 0 0 var(--fl-foco-ancho)
        color-mix(in srgb, var(--fl-error) 25%, transparent);
}

.fl-campo--exito .fl-campo-entrada {
    border-color: var(--fl-exito);
}

.fl-campo--exito .fl-campo-entrada:focus {
    box-shadow: 0 0 0 var(--fl-foco-ancho)
        color-mix(in srgb, var(--fl-exito) 25%, transparent);
}

/* --------------------------------------------------------------------------
   Texto de ayuda y mensaje de error
   -------------------------------------------------------------------------- */
.fl-campo-ayuda {
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-suave);
    line-height: var(--fl-lh-ajustada);
}

.fl-campo-error {
    display: flex;
    align-items: flex-start;
    gap: var(--fl-sp-1);
    font-size: var(--fl-texto-xs);
    color: var(--fl-error-texto);
    line-height: var(--fl-lh-ajustada);
}

/* El atributo [hidden] del HTML debe ganar sobre el display:flex del error,
   sino se ven siempre aunque estén marcados como ocultos. Mismas reglas
   aplicadas globalmente para cualquier .fl-campo-error con hidden. */
.fl-campo-error[hidden] {
    display: none;
}

.fl-campo-error .fl-icono {
    width: 14px;
    height: 14px;
    flex: none;
    margin-top: 1px;
}

/* --------------------------------------------------------------------------
   Campo con icono (inicio o fin)
   -------------------------------------------------------------------------- */
.fl-campo-grupo {
    position: relative;
    display: flex;
    align-items: center;
}

.fl-campo-grupo .fl-campo-entrada {
    flex: 1;
}

.fl-campo-grupo-icono {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    color: var(--fl-texto-tenue);
    pointer-events: none;
    display: flex;
    align-items: center;
    justify-content: center;
    width: var(--fl-sp-8);
    height: 100%;
}

.fl-campo-grupo-icono .fl-icono {
    width: 16px;
    height: 16px;
}

.fl-campo-grupo-icono--inicio {
    left: 0;
}

.fl-campo-grupo-icono--fin {
    right: 0;
}

.fl-campo-grupo:has(.fl-campo-grupo-icono--inicio) .fl-campo-entrada {
    padding-left: var(--fl-sp-8);
}

.fl-campo-grupo:has(.fl-campo-grupo-icono--fin) .fl-campo-entrada {
    padding-right: var(--fl-sp-8);
}

/* --------------------------------------------------------------------------
   Checkbox y radio nativos estilizados
   -------------------------------------------------------------------------- */
.fl-check {
    display: inline-flex;
    align-items: center;
    gap: var(--fl-sp-2);
    cursor: pointer;
    font-size: var(--fl-texto-sm);
    line-height: var(--fl-lh-ajustada);
    user-select: none;
}

.fl-check-control {
    flex: none;
    appearance: none;
    width: 18px;
    height: 18px;
    background: var(--fl-superficie);
    border: 1px solid var(--fl-borde-fuerte);
    border-radius: var(--fl-r-sm);
    cursor: pointer;
    position: relative;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida),
                border-color var(--fl-t-rapido) var(--fl-ease-salida),
                transform 120ms var(--fl-ease-resorte);
}

.fl-check-control:active {
    transform: scale(0.9);
}

/* Pop cuando se marca/desmarca */
.fl-check-control:checked {
    animation: fl-check-pop 240ms var(--fl-ease-resorte);
}

@keyframes fl-check-pop {
    0%   { transform: scale(1); }
    40%  { transform: scale(0.78); }
    80%  { transform: scale(1.08); }
    100% { transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
    .fl-check-control:checked { animation: none; }
    .fl-check-control:active  { transform: none; }
}

.fl-check-control[type="radio"] {
    border-radius: var(--fl-r-full);
}

.fl-check-control:hover:not(:disabled) {
    border-color: var(--fl-acento);
}

.fl-check-control:focus-visible {
    outline: none;
    box-shadow: 0 0 0 var(--fl-foco-ancho) var(--fl-acento-foco);
}

.fl-check-control:checked {
    background: var(--fl-acento);
    border-color: var(--fl-acento);
}

.fl-check-control[type="checkbox"]:checked::after {
    content: "";
    position: absolute;
    inset: 0;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><polyline points='20 6 9 17 4 12'/></svg>");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 14px;
}

.fl-check-control[type="radio"]:checked::after {
    content: "";
    position: absolute;
    inset: 4px;
    background: var(--fl-neutro-0);
    border-radius: var(--fl-r-full);
}

.fl-check-control:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}


/* ===== resources/css/componentes/cheatsheet-atajos.css ===== */
/* ==========================================================================
   Flora · Cheatsheet-Atajos (modal con lista de shortcuts registrados)
   Se abre con Flora.cheatsheet.abrir() o por default Shift+?
   ========================================================================== */

.fl-cheatsheet-fondo {
    position: fixed; inset: 0;
    background: rgba(0 0 0 / 0.5);
    z-index: var(--fl-z-modal);
    opacity: 0; visibility: hidden;
    transition: opacity 180ms, visibility 180ms;
    backdrop-filter: blur(2px);
}
.fl-cheatsheet-fondo[data-fl-abierto="true"] { opacity: 1; visibility: visible; }

.fl-cheatsheet {
    position: fixed;
    top: 15vh;
    left: 50%;
    transform: translateX(-50%) scale(0.96);
    z-index: calc(var(--fl-z-modal) + 1);
    width: min(520px, 92vw);
    max-height: 70vh;
    background: var(--fl-superficie-elevada);
    border-radius: var(--fl-r-xl);
    box-shadow: var(--fl-sombra-xl);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    opacity: 0; visibility: hidden;
    transition: opacity 200ms, transform 240ms var(--fl-ease-resorte), visibility 200ms;
}
.fl-cheatsheet[data-fl-abierto="true"] {
    opacity: 1; visibility: visible;
    transform: translateX(-50%) scale(1);
}

.fl-cheatsheet-cabecera {
    display: flex; align-items: center; justify-content: space-between;
    padding: var(--fl-sp-3) var(--fl-sp-4);
    border-bottom: 1px solid var(--fl-borde-sutil);
}
.fl-cheatsheet-titulo { font-weight: var(--fl-peso-semibold); color: var(--fl-texto-fuerte); }
.fl-cheatsheet-cerrar {
    display: inline-flex; align-items: center; justify-content: center;
    width: 32px; height: 32px;
    background: transparent; border: 0; border-radius: var(--fl-r-sm);
    color: var(--fl-texto-tenue); cursor: pointer;
}
.fl-cheatsheet-cerrar:hover { color: var(--fl-texto); background: var(--fl-superficie-hover); }
.fl-cheatsheet-cerrar .fl-icono { width: 16px; height: 16px; }

.fl-cheatsheet-lista {
    overflow-y: auto;
    padding: var(--fl-sp-2);
}

.fl-cheatsheet-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 8px var(--fl-sp-3);
    border-radius: var(--fl-r-sm);
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto);
}
.fl-cheatsheet-item:hover { background: var(--fl-superficie-hover); }

.fl-cheatsheet-item-descripcion { flex: 1; }
.fl-cheatsheet-item-combo { display: inline-flex; gap: 2px; }

.fl-cheatsheet-vacio { padding: var(--fl-sp-6); text-align: center; color: var(--fl-texto-tenue); font-size: var(--fl-texto-sm); }


/* ===== resources/css/componentes/chip.css ===== */
/* ==========================================================================
   Flora · Chip
   Pill interactivo: puede tener ícono, texto, botón de cerrar, avatar.
   Usado para filtros activos, selecciones múltiples, tags clickeables.
   ========================================================================== */

.fl-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--fl-sp-1-5);
    /* Padding simétrico compensado por el line-height 1.5.
       Altura efectiva ~28px (4 + 18 line + 4 + 2 border). */
    padding: 4px var(--fl-sp-2-5);
    font-size: var(--fl-texto-xs);
    font-weight: var(--fl-peso-medio);
    /* line-height 1.5 (no 1) para que el browser tenga leading extra que
       distribuye simétrico alrededor del text-box, compensando la asimetría
       de la métrica del font. 1.5 en vez de 1.3 porque fonts chicos
       necesitan más leading absoluto para que el compensado se note. */
    line-height: 1.5;
    /* Base con acento-texto (igual que boton--secundario) — cambia a color
       de paleta en vez de texto neutro, consistente con la familia de botones. */
    color: var(--fl-acento-texto);
    background: var(--fl-superficie);
    border: 1px solid var(--fl-borde-fuerte);
    border-radius: var(--fl-r-full);
    cursor: default;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida),
                border-color var(--fl-t-rapido) var(--fl-ease-salida),
                box-shadow var(--fl-t-rapido) var(--fl-ease-salida),
                transform 180ms var(--fl-ease-salida);
}

.fl-chip .fl-icono {
    /* Relativo (1.25em) para que el ícono sea un poco más grande que el
       texto — mismo patrón que .fl-boton. Antes fijo en 12px, ahora escala
       con el font-size del chip. */
    width: 1.25em;
    height: 1.25em;
    color: currentColor;
    flex: none;
    transform-origin: center;
    transition: transform 520ms var(--fl-ease-salida);
}

.fl-chip:hover:not(:disabled) > .fl-icono {
    transform: scale(1.2);
}

@media (prefers-reduced-motion: reduce) {
    .fl-chip .fl-icono { transition: none; }
    .fl-chip:hover > .fl-icono { transform: none; }
}


/* --------------------------------------------------------------------------
   Tamaños
   -------------------------------------------------------------------------- */
.fl-chip--sm {
    padding: 2px var(--fl-sp-2);
    font-size: 11px;
    gap: 4px;
}

.fl-chip--lg {
    padding: 5px var(--fl-sp-3);
    font-size: var(--fl-texto-sm);
}

/* --------------------------------------------------------------------------
   Clickeable / seleccionable
   -------------------------------------------------------------------------- */
.fl-chip--clickeable,
button.fl-chip,
a.fl-chip {
    cursor: pointer;
}

.fl-chip--clickeable:hover,
button.fl-chip:hover,
a.fl-chip:hover {
    /* Hover espejando boton--secundario: tinte de acento + borde acento +
       texto acento-texto. Lift + sombra del mismo color para consistencia. */
    background: var(--fl-acento-suave);
    border-color: var(--fl-acento);
    color: var(--fl-acento-texto);
    transform: translateY(-1px);
    box-shadow: 0 2px 6px -2px color-mix(in srgb, var(--fl-acento) 30%, transparent);
}

.fl-chip--clickeable:active,
button.fl-chip:active {
    transform: translateY(0) scale(0.96);
    box-shadow: none;
    transition-duration: 60ms;
}

.fl-chip--clickeable:focus-visible,
button.fl-chip:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--fl-acento-foco);
}

/* Seleccionado — destaque lleno (flora vieja style). Color fuerte + texto
   blanco (o invertido en oscuro) para máximo contraste inmediato. */
.fl-chip--seleccionado {
    background: var(--fl-destaque-fondo);
    border-color: var(--fl-destaque-fondo);
    color: var(--fl-destaque-texto);
    font-weight: var(--fl-peso-semibold);
    box-shadow: 0 2px 8px -2px color-mix(in srgb, var(--fl-destaque-fondo) 55%, transparent);
}

.fl-chip--seleccionado:hover,
button.fl-chip--seleccionado:hover,
a.fl-chip--seleccionado:hover {
    background: var(--fl-destaque-fondo-hover);
    border-color: var(--fl-destaque-fondo-hover);
    color: var(--fl-destaque-texto);
}

.fl-chip--seleccionado .fl-icono {
    color: var(--fl-destaque-texto);
}

/* --------------------------------------------------------------------------
   Variantes — profundidades de paleta (no colores semánticos externos)
   El texto del chip da el contexto; el color sólo refuerza la jerarquía.
   -------------------------------------------------------------------------- */
.fl-chip--acento,
.fl-chip--info {
    background: color-mix(in srgb, var(--fl-acento) 12%, var(--fl-superficie));
    border-color: transparent;
    color: var(--fl-acento-texto);
}

.fl-chip--adv   { background: color-mix(in srgb, var(--fl-acento) 20%, var(--fl-superficie));     border-color: transparent; color: var(--fl-acento-texto); }
.fl-chip--exito { background: color-mix(in srgb, var(--fl-acento-700) 18%, var(--fl-superficie)); border-color: transparent; color: var(--fl-acento-texto); }
.fl-chip--error { background: color-mix(in srgb, var(--fl-acento-900) 22%, var(--fl-superficie)); border-color: transparent; color: var(--fl-acento-texto); }

.fl-chip--solido {
    background: var(--fl-texto-fuerte);
    border-color: transparent;
    color: var(--fl-texto-invertido);
}

.fl-chip--solido.fl-chip--acento,
.fl-chip--solido.fl-chip--info  { background: var(--fl-acento);     color: var(--fl-acento-texto-sobre); }
.fl-chip--solido.fl-chip--adv   { background: var(--fl-acento-700); color: var(--fl-acento-texto-sobre); }
.fl-chip--solido.fl-chip--exito { background: var(--fl-acento-800); color: var(--fl-acento-texto-sobre); }
.fl-chip--solido.fl-chip--error { background: var(--fl-acento-950); color: var(--fl-acento-texto-sobre); }
.fl-chip--solido .fl-icono { color: inherit; }

/* --------------------------------------------------------------------------
   Botón cerrar embebido
   -------------------------------------------------------------------------- */
.fl-chip-cerrar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
    margin-left: 2px;
    margin-right: -4px;
    padding: 0;
    background: transparent;
    border: 0;
    border-radius: var(--fl-r-full);
    color: currentColor;
    opacity: 0.55;
    cursor: pointer;
    transition: opacity var(--fl-t-rapido) var(--fl-ease-salida),
                background var(--fl-t-rapido) var(--fl-ease-salida),
                transform 200ms var(--fl-ease-resorte);
}

.fl-chip-cerrar:hover {
    opacity: 1;
    background: color-mix(in srgb, currentColor 15%, transparent);
    transform: rotate(90deg);
}

.fl-chip-cerrar:focus-visible {
    outline: none;
    opacity: 1;
    box-shadow: 0 0 0 2px currentColor;
}

.fl-chip-cerrar .fl-icono {
    width: 10px;
    height: 10px;
    color: inherit;
}

/* --------------------------------------------------------------------------
   Avatar embebido al inicio
   -------------------------------------------------------------------------- */
.fl-chip-avatar {
    width: 20px;
    height: 20px;
    margin-left: -6px;
    margin-right: -2px;
    border-radius: var(--fl-r-full);
    background: var(--fl-acento);
    color: var(--fl-acento-texto-sobre);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 9px;
    font-weight: var(--fl-peso-semibold);
    flex: none;
    overflow: hidden;
}

.fl-chip-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Simetría óptica con ícono al inicio o al final — mismo patrón que
   .fl-boton. El padding del lado del ícono se reduce al valor del gap
   para que el ícono quede equidistante del borde y del texto. */
.fl-chip:has(> .fl-icono:first-child:not(:last-child)) {
    padding-left: var(--fl-sp-1-5);
}

.fl-chip:has(> .fl-icono:last-child:not(:first-child)) {
    padding-right: var(--fl-sp-1-5);
}


/* ===== resources/css/componentes/copiar.css ===== */
/* ==========================================================================
   Flora · Copiar (copy-to-clipboard button)
   Muestra un ícono "copiar", al click copia el valor y el ícono cambia
   a check durante 1.5s. Usa navigator.clipboard.
   ========================================================================== */

.fl-copiar {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 8px;
    background: transparent;
    color: var(--fl-texto-suave);
    border: 1px solid var(--fl-borde);
    border-radius: var(--fl-r-sm);
    font-size: var(--fl-texto-xs);
    font-family: inherit;
    cursor: pointer;
    transition: color 160ms, background 160ms, border-color 160ms, transform 120ms;
}

.fl-copiar:hover {
    color: var(--fl-texto-fuerte);
    background: var(--fl-superficie-hover);
    border-color: var(--fl-borde-intenso);
}
.fl-copiar:active { transform: scale(0.97); }

.fl-copiar .fl-icono { width: 14px; height: 14px; }

.fl-copiar[data-fl-copiado="true"] {
    color: var(--fl-exito);
    border-color: var(--fl-exito);
    background: rgba(34, 197, 94, 0.08);
}

.fl-copiar-inline {
    display: inline-flex;
    align-items: center;
    gap: var(--fl-sp-2);
    padding: 6px var(--fl-sp-3);
    background: var(--fl-fondo-sutil);
    border: 1px solid var(--fl-borde-sutil);
    border-radius: var(--fl-r-md);
    font-family: var(--fl-fuente-mono, monospace);
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto-fuerte);
}

.fl-copiar-inline code {
    flex: 1;
    background: transparent;
    padding: 0;
    border: 0;
    font-family: inherit;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.fl-copiar-inline .fl-copiar {
    margin-left: auto;
    border: 0;
    padding: 4px;
    background: transparent;
}


/* ===== resources/css/componentes/date-picker.css ===== */
/* ==========================================================================
   Flora · Date-picker
   Input de fecha + calendario popup propio. Locale es-AR por default
   (semana empieza lunes, nombres en español).
   ========================================================================== */

.fl-datepicker {
    position: relative;
    display: block;
    width: 100%;
}

/* Input trigger — se ve como fl-campo-entrada pero es readonly y abre el popup */
.fl-datepicker-trigger {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
    width: 100%;
    min-height: var(--fl-alto-control-md);
    padding: 0 var(--fl-sp-3);
    font-family: inherit;
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto-fuerte);
    text-align: left;
    background: var(--fl-superficie);
    border: 1px solid var(--fl-borde-fuerte);
    border-radius: var(--fl-r-md);
    box-shadow: var(--fl-sombra-xs);
    cursor: pointer;
    transition: border-color var(--fl-t-rapido) var(--fl-ease-salida),
                box-shadow var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-datepicker-trigger:hover:not(:disabled) {
    border-color: var(--fl-borde-intenso);
}

.fl-datepicker-trigger:focus-visible,
.fl-datepicker[data-fl-abierto="true"] .fl-datepicker-trigger {
    outline: none;
    border-color: var(--fl-acento);
    box-shadow: 0 0 0 var(--fl-foco-ancho) var(--fl-acento-foco);
}

.fl-datepicker-trigger .fl-icono {
    width: 16px;
    height: 16px;
    color: var(--fl-texto-tenue);
    flex: none;
}

.fl-datepicker-trigger .fl-icono--cal {
    margin-left: auto;
}

.fl-datepicker-trigger[data-fl-sin-valor="true"] .fl-datepicker-texto {
    color: var(--fl-texto-tenue);
}

.fl-datepicker-texto {
    flex: 1;
    font-variant-numeric: tabular-nums;
}

/* Panel del calendario — se portala al body */
.fl-datepicker-panel {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    z-index: var(--fl-z-popover);
    width: 296px;
    padding: var(--fl-sp-3);
    background: var(--fl-superficie-elevada);
    border: 1px solid var(--fl-borde);
    border-radius: var(--fl-r-lg);
    box-shadow: var(--fl-sombra-lg),
                0 0 0 1px rgb(0 0 0 / 0.03);
    opacity: 0;
    transform: translateY(-4px);
    visibility: hidden;
    pointer-events: none;
    transition: opacity 140ms var(--fl-ease-salida),
                transform 200ms var(--fl-ease-resorte),
                visibility 180ms;
}

.fl-datepicker-panel--portal {
    position: fixed !important;
    top: 0;
    left: 0;
    bottom: auto;
    right: auto;
    z-index: var(--fl-z-popover);
}

.fl-datepicker[data-fl-abierto="true"] .fl-datepicker-panel,
.fl-datepicker-panel--portal[data-fl-abierto="true"] {
    opacity: 1;
    transform: translateY(0);
    visibility: visible;
    pointer-events: auto;
}

/* Header: mes + año + navegación */
.fl-datepicker-cabecera {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--fl-sp-1);
    margin-bottom: var(--fl-sp-2);
}

.fl-datepicker-nav {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    padding: 0;
    background: transparent;
    border: 0;
    border-radius: var(--fl-r-md);
    color: var(--fl-texto-suave);
    cursor: pointer;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida),
                color var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-datepicker-nav:hover {
    background: var(--fl-superficie-hover);
    color: var(--fl-texto-fuerte);
}

.fl-datepicker-nav .fl-icono {
    width: 16px;
    height: 16px;
}

.fl-datepicker-titulo {
    flex: 1;
    text-align: center;
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-fuerte);
    cursor: pointer;
    padding: var(--fl-sp-1) var(--fl-sp-2);
    border-radius: var(--fl-r-md);
    background: transparent;
    border: 0;
    transition: background var(--fl-t-rapido);
    text-transform: capitalize;
}

.fl-datepicker-titulo:hover {
    background: var(--fl-superficie-hover);
}

/* Filas de días de la semana */
.fl-datepicker-semana {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 2px;
    margin-bottom: var(--fl-sp-1);
    padding: 0 2px;
}

.fl-datepicker-dia-semana {
    text-align: center;
    font-size: 10px;
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-tenue);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    padding: 4px 0;
}

/* Grilla de días */
.fl-datepicker-grilla {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 2px;
    padding: 0 2px;
}

.fl-datepicker-dia {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 32px;
    padding: 0;
    font-size: var(--fl-texto-sm);
    font-variant-numeric: tabular-nums;
    color: var(--fl-texto);
    background: transparent;
    border: 0;
    border-radius: var(--fl-r-md);
    cursor: pointer;
    position: relative;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida),
                color var(--fl-t-rapido) var(--fl-ease-salida),
                transform 120ms var(--fl-ease-resorte);
}

.fl-datepicker-dia:hover:not(:disabled) {
    background: var(--fl-superficie-hover);
    color: var(--fl-texto-fuerte);
}

.fl-datepicker-dia:active:not(:disabled) {
    transform: scale(0.92);
}

.fl-datepicker-dia--otro-mes {
    color: var(--fl-texto-tenue);
}

.fl-datepicker-dia--hoy {
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-acento-texto);
}

.fl-datepicker-dia--hoy::after {
    content: "";
    position: absolute;
    bottom: 4px;
    left: 50%;
    transform: translateX(-50%);
    width: 3px;
    height: 3px;
    background: var(--fl-acento);
    border-radius: var(--fl-r-full);
}

.fl-datepicker-dia--seleccionado {
    background: var(--fl-destaque-fondo);
    color: var(--fl-destaque-texto);
    font-weight: var(--fl-peso-semibold);
}

.fl-datepicker-dia--seleccionado::after {
    background: var(--fl-destaque-texto);
}

.fl-datepicker-dia--seleccionado:hover {
    background: var(--fl-destaque-fondo-hover);
    color: var(--fl-destaque-texto);
}

.fl-datepicker-dia:disabled {
    opacity: 0.3;
    cursor: not-allowed;
    pointer-events: none;
}

/* Vista de meses (al clickear el título) */
.fl-datepicker-meses,
.fl-datepicker-anios {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--fl-sp-1);
    padding: var(--fl-sp-1) 0;
}

.fl-datepicker-mes,
.fl-datepicker-anio {
    padding: var(--fl-sp-2);
    background: transparent;
    border: 0;
    border-radius: var(--fl-r-md);
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-medio);
    color: var(--fl-texto);
    cursor: pointer;
    text-transform: capitalize;
    transition: background var(--fl-t-rapido);
}

.fl-datepicker-mes:hover,
.fl-datepicker-anio:hover {
    background: var(--fl-superficie-hover);
    color: var(--fl-texto-fuerte);
}

.fl-datepicker-mes--actual,
.fl-datepicker-anio--actual {
    background: var(--fl-destaque-fondo);
    color: var(--fl-destaque-texto);
}

.fl-datepicker-mes--actual:hover,
.fl-datepicker-anio--actual:hover {
    background: var(--fl-destaque-fondo-hover);
    color: var(--fl-destaque-texto);
}

/* Pie con botones "Hoy" y "Limpiar" */
.fl-datepicker-pie {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--fl-sp-2);
    margin-top: var(--fl-sp-2);
    padding-top: var(--fl-sp-2);
    border-top: 1px solid var(--fl-borde-sutil);
}

.fl-datepicker-pie-accion {
    padding: 4px var(--fl-sp-2);
    font-size: var(--fl-texto-xs);
    font-weight: var(--fl-peso-medio);
    color: var(--fl-acento-enlace);
    background: transparent;
    border: 0;
    border-radius: var(--fl-r-sm);
    cursor: pointer;
    transition: background var(--fl-t-rapido);
}

.fl-datepicker-pie-accion:hover {
    background: var(--fl-superficie-hover);
    color: var(--fl-acento-hover);
}


/* ===== resources/css/componentes/dropdown.css ===== */
/* ==========================================================================
   Flora · Dropdown
   Menú flotante con gradient dark del acento + texto blanco. Hover:
   overlay blanco translúcido. Selected: bloque blanco con texto acento
   (inversión clara). Posicionamiento automático por JS.
   ========================================================================== */

.fl-dropdown {
    position: relative;
    display: inline-block;
}

/* Menú flotante — al abrir, JS lo portala al <body> y le pone position: fixed
   con posición calculada desde el trigger. */
.fl-dropdown-menu {
    position: absolute;
    z-index: var(--fl-z-popover);
    min-width: 200px;
    padding: var(--fl-sp-1);
    background: linear-gradient(
        135deg,
        var(--fl-acento-600) 0%,
        var(--fl-acento-900) 100%
    );
    color: white;
    border: 1px solid transparent;
    border-radius: var(--fl-r-lg);
    box-shadow:
        0 12px 28px -8px color-mix(in srgb, var(--fl-acento) 55%, transparent),
        inset 0 1px 0 color-mix(in srgb, white 18%, transparent);
    opacity: 0;
    transform: translateY(-4px) scale(0.98);
    visibility: hidden;
    pointer-events: none;
    transition: opacity 160ms var(--fl-ease-salida),
                transform 220ms var(--fl-ease-resorte),
                visibility 200ms;
    max-height: 70vh;
    overflow-y: auto;
}

.fl-dropdown-menu--portal {
    position: fixed !important;
    top: 0;
    left: 0;
    right: auto;
    bottom: auto;
    width: auto;
    max-width: min(360px, calc(100vw - 16px));
    z-index: var(--fl-z-popover);
}

.fl-dropdown-menu[data-fl-abierto="true"],
.fl-dropdown-menu--portal[data-fl-abierto="true"] {
    opacity: 1;
    transform: translateY(0) scale(1);
    visibility: visible;
    pointer-events: auto;
}

/* Items del menú — texto blanco por default */
.fl-dropdown-item {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
    width: 100%;
    padding: var(--fl-sp-1-5) var(--fl-sp-2-5);
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-regular);
    color: white;
    background: transparent;
    border: 0;
    border-radius: var(--fl-r-md);
    text-align: left;
    cursor: pointer;
    text-decoration: none;
    white-space: nowrap;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida),
                color var(--fl-t-rapido) var(--fl-ease-salida);
}

/* Hover/focus — overlay blanco translúcido */
.fl-dropdown-item:hover,
.fl-dropdown-item:focus-visible {
    background: color-mix(in srgb, white 15%, transparent);
    color: white;
    outline: none;
}

.fl-dropdown-item:active {
    background: color-mix(in srgb, white 22%, transparent);
}

/* Seleccionado — inversión: bloque blanco con texto acento */
.fl-dropdown-item[aria-selected="true"] {
    background: white;
    color: var(--fl-acento-700);
    outline: none;
    font-weight: var(--fl-peso-semibold);
    box-shadow: 0 2px 6px -1px color-mix(in srgb, black 25%, transparent);
}

.fl-dropdown-item[aria-selected="true"]:hover,
.fl-dropdown-item[aria-selected="true"]:focus-visible {
    background: color-mix(in srgb, white 92%, var(--fl-acento));
    color: var(--fl-acento-800);
}

.fl-dropdown-item[aria-selected="true"] .fl-icono {
    color: var(--fl-acento-700);
}

.fl-dropdown-item[aria-disabled="true"] {
    opacity: 0.4;
    pointer-events: none;
}

/* Íconos — blanco traslúcido, más blanco al hover */
.fl-dropdown-item .fl-icono {
    width: 16px;
    height: 16px;
    color: color-mix(in srgb, white 75%, transparent);
    flex: none;
    transition: color var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-dropdown-item:hover .fl-icono,
.fl-dropdown-item:focus-visible .fl-icono {
    color: white;
}

/* Atajo de teclado (kbd al final) — chip glass sobre dark */
.fl-dropdown-item-atajo {
    margin-left: auto;
    font-size: var(--fl-texto-2xs);
    color: color-mix(in srgb, white 85%, transparent);
    font-family: var(--fl-fuente-mono);
    padding: 1px 6px;
    background: color-mix(in srgb, white 15%, transparent);
    border-radius: var(--fl-r-sm);
    border: 1px solid color-mix(in srgb, white 20%, transparent);
}

.fl-dropdown-item[aria-selected="true"] .fl-dropdown-item-atajo {
    color: var(--fl-acento-700);
    background: color-mix(in srgb, var(--fl-acento) 10%, transparent);
    border-color: color-mix(in srgb, var(--fl-acento) 25%, transparent);
}

/* Variante peligro — diferenciada por tinte palette claro + italic + hover
   inverso (light→dark palette). Nada de rojo; la señal es el contraste
   visual, no semántico por color. */
.fl-dropdown-item--peligro {
    color: var(--fl-acento-200);
    font-style: italic;
}

.fl-dropdown-item--peligro .fl-icono {
    color: var(--fl-acento-300);
}

.fl-dropdown-item--peligro:hover,
.fl-dropdown-item--peligro:focus-visible {
    background: var(--fl-acento-200);
    color: var(--fl-acento-950);
    font-style: normal;
    font-weight: var(--fl-peso-semibold);
}

.fl-dropdown-item--peligro:hover .fl-icono,
.fl-dropdown-item--peligro:focus-visible .fl-icono {
    color: var(--fl-acento-950);
}

/* Atajo: en hover de peligro el bg se vuelve claro, así que forzamos
   colores oscuros al kbd para que no se pierda contra el fondo. */
.fl-dropdown-item--peligro:hover .fl-dropdown-item-atajo,
.fl-dropdown-item--peligro:focus-visible .fl-dropdown-item-atajo {
    color: var(--fl-acento-950);
    background: color-mix(in srgb, var(--fl-acento-950) 12%, transparent);
    border-color: color-mix(in srgb, var(--fl-acento-950) 22%, transparent);
}

/* Separador dentro del menú — línea blanca translúcida */
.fl-dropdown-separador {
    height: 1px;
    background: color-mix(in srgb, white 18%, transparent);
    margin: var(--fl-sp-1) calc(-1 * var(--fl-sp-1));
    border: 0;
}

/* Label de grupo — uppercase blanco translúcido */
.fl-dropdown-grupo-titulo {
    padding: var(--fl-sp-1-5) var(--fl-sp-2-5) var(--fl-sp-1);
    font-size: var(--fl-texto-2xs);
    font-weight: var(--fl-peso-semibold);
    text-transform: uppercase;
    letter-spacing: var(--fl-ls-mayus);
    color: color-mix(in srgb, white 65%, transparent);
}

/* Posiciones */
.fl-dropdown-menu[data-fl-posicion="bottom-start"] { top: calc(100% + 4px); left: 0; }
.fl-dropdown-menu[data-fl-posicion="bottom-end"]   { top: calc(100% + 4px); right: 0; }
.fl-dropdown-menu[data-fl-posicion="top-start"]    { bottom: calc(100% + 4px); left: 0; }
.fl-dropdown-menu[data-fl-posicion="top-end"]      { bottom: calc(100% + 4px); right: 0; }

@media (prefers-reduced-motion: reduce) {
    .fl-dropdown-menu {
        transition: opacity 80ms linear, visibility 80ms;
        transform: none;
    }
    .fl-dropdown-menu[data-fl-abierto="true"] {
        transform: none;
    }
}


/* ===== resources/css/componentes/empty-state.css ===== */
/* ==========================================================================
   Flora · Empty State
   Pantalla/sección vacía con ícono, título, descripción y acciones opcionales.
   Usar cuando no hay datos para mostrar.
   ========================================================================== */

.fl-vacio {
    display: flex;
    width: 100%;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: var(--fl-sp-12) var(--fl-sp-6);
    gap: var(--fl-sp-3);
    color: var(--fl-texto-suave);
    min-height: 240px;
}

.fl-vacio-icono {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 64px;
    height: 64px;
    margin-bottom: var(--fl-sp-2);
    background: var(--fl-superficie-muda);
    color: var(--fl-texto-tenue);
    border-radius: var(--fl-r-full);
}

.fl-vacio-icono .fl-icono {
    width: 28px;
    height: 28px;
}

.fl-vacio-titulo {
    font-size: var(--fl-texto-lg);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-fuerte);
    line-height: var(--fl-lh-compacta);
    margin: 0;
}

.fl-vacio-descripcion {
    font-size: var(--fl-texto-sm);
    line-height: var(--fl-lh-ajustada);
    max-width: 420px;
    margin: 0;
}

.fl-vacio-acciones {
    display: flex;
    gap: var(--fl-sp-2);
    margin-top: var(--fl-sp-3);
    flex-wrap: wrap;
    justify-content: center;
}

/* --------------------------------------------------------------------------
   Variantes
   -------------------------------------------------------------------------- */

/* Compacto — menos padding, para dentro de tarjetas */
.fl-vacio--compacto {
    padding: var(--fl-sp-6) var(--fl-sp-4);
    min-height: auto;
}

.fl-vacio--compacto .fl-vacio-icono {
    width: 44px;
    height: 44px;
}

.fl-vacio--compacto .fl-vacio-icono .fl-icono {
    width: 20px;
    height: 20px;
}

.fl-vacio--compacto .fl-vacio-titulo {
    font-size: var(--fl-texto-base);
}

/* Con borde — tipo drop zone desactivada */
.fl-vacio--borde {
    border: 2px dashed var(--fl-borde-fuerte);
    border-radius: var(--fl-r-lg);
    background: var(--fl-fondo-sutil);
}

/* Error / no disponible */
.fl-vacio--error .fl-vacio-icono {
    background: var(--fl-error-suave);
    color: var(--fl-error);
}

.fl-vacio--exito .fl-vacio-icono {
    background: var(--fl-exito-suave);
    color: var(--fl-exito);
}


/* ===== resources/css/componentes/explorador.css ===== */
/* ==========================================================================
   Flora · Explorador de archivos
   Estilo Google Drive / OneDrive. Sidebar opcional, breadcrumbs, vista
   lista/grilla con thumbnails, selección, dropzone, acciones contextuales.
   ========================================================================== */

.fl-explorador {
    display: grid;
    grid-template-columns: 1fr;
    width: 100%;
    background: var(--fl-superficie);
    border: 1px solid var(--fl-borde);
    border-radius: var(--fl-r-lg);
    overflow: hidden;
    min-height: 540px;
    position: relative;
}

.fl-explorador--con-sidebar { grid-template-columns: 240px 1fr; }
.fl-explorador--con-panel   { grid-template-columns: 1fr 320px; }
.fl-explorador--con-sidebar.fl-explorador--con-panel { grid-template-columns: 240px 1fr 320px; }

@media (max-width: 1100px) {
    .fl-explorador--con-sidebar,
    .fl-explorador--con-sidebar.fl-explorador--con-panel { grid-template-columns: 1fr; }
    .fl-explorador--con-sidebar > .fl-explorador-sidebar,
    .fl-explorador--con-sidebar.fl-explorador--con-panel > .fl-explorador-panel { display: none; }
}

.fl-explorador-principal {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

/* --------------------------------------------------------------------------
   Sidebar opcional (Mi unidad, Compartido conmigo, Destacados, Papelera, etc.)
   -------------------------------------------------------------------------- */
.fl-explorador-sidebar {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-1);
    padding: var(--fl-sp-3);
    background: var(--fl-fondo-sutil);
    border-right: 1px solid var(--fl-borde-sutil);
    overflow-y: auto;
}

.fl-explorador-sidebar-titulo {
    font-size: var(--fl-texto-2xs);
    font-weight: var(--fl-peso-semibold);
    text-transform: uppercase;
    letter-spacing: var(--fl-ls-mayus);
    color: var(--fl-texto-tenue);
    padding: var(--fl-sp-1) var(--fl-sp-2);
    margin-top: var(--fl-sp-3);
}

.fl-explorador-sidebar-titulo:first-child { margin-top: 0; }

.fl-explorador-nav-item {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
    padding: var(--fl-sp-1-5) var(--fl-sp-2);
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto-suave);
    border-radius: var(--fl-r-md);
    cursor: pointer;
    text-decoration: none;
    transition: background var(--fl-t-rapido), color var(--fl-t-rapido);
}

.fl-explorador-nav-item:hover {
    background: var(--fl-superficie-hover);
    color: var(--fl-texto-fuerte);
}

.fl-explorador-nav-item .fl-icono {
    width: 16px;
    height: 16px;
    flex: none;
    color: var(--fl-texto-tenue);
}

.fl-explorador-nav-item:hover .fl-icono { color: var(--fl-texto-suave); }

.fl-explorador-nav-item-conteo {
    margin-left: auto;
    font-size: var(--fl-texto-2xs);
    color: var(--fl-texto-tenue);
    font-variant-numeric: tabular-nums;
}

.fl-explorador-nav-item--activo {
    background: var(--fl-acento-suave);
    color: var(--fl-acento-texto);
    font-weight: var(--fl-peso-semibold);
}

.fl-explorador-nav-item--activo .fl-icono,
.fl-explorador-nav-item--activo .fl-explorador-nav-item-conteo {
    color: var(--fl-acento-texto);
}

/* Sidebar footer: barra de almacenamiento */
.fl-explorador-sidebar-footer {
    margin-top: auto;
    padding-top: var(--fl-sp-3);
    border-top: 1px solid var(--fl-borde-sutil);
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-1);
}

.fl-explorador-storage {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: var(--fl-sp-1);
}

.fl-explorador-storage-titulo {
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-suave);
    display: flex;
    align-items: center;
    gap: 6px;
}

.fl-explorador-storage-titulo .fl-icono {
    width: 13px;
    height: 13px;
}

.fl-explorador-storage-barra {
    height: 6px;
    background: var(--fl-borde-sutil);
    border-radius: var(--fl-r-full);
    overflow: hidden;
}

.fl-explorador-storage-barra-fill {
    display: block;
    height: 100%;
    background: var(--fl-acento);
    border-radius: var(--fl-r-full);
}

.fl-explorador-storage-texto {
    font-size: 10px;
    color: var(--fl-texto-tenue);
    font-variant-numeric: tabular-nums;
    display: flex;
    justify-content: space-between;
}

/* Widget de cuota — aparece en el slot acciones del header-pagina de Nube */
.fl-explorador-cuota {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
    padding: 5px var(--fl-sp-2);
    background: var(--fl-superficie-muda);
    border: 1px solid var(--fl-borde-sutil);
    border-radius: var(--fl-r-md);
    min-width: 160px;
}
.fl-explorador-cuota-pct {
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-fuerte);
    font-variant-numeric: tabular-nums;
    min-width: 34px;
    text-align: right;
}
.fl-explorador-cuota-detalles {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
}
.fl-explorador-cuota-barra {
    height: 5px;
    background: var(--fl-borde-sutil);
    border-radius: var(--fl-r-full);
    overflow: hidden;
}
.fl-explorador-cuota-barra-fill {
    display: block;
    height: 100%;
    background: var(--fl-acento);
    border-radius: var(--fl-r-full);
    transition: width 300ms var(--fl-ease-salida);
}
.fl-explorador-cuota-barra-fill[data-fl-cuota-critica="true"] {
    background: var(--fl-error);
}
.fl-explorador-cuota-texto {
    font-size: 10px;
    color: var(--fl-texto-tenue);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* --------------------------------------------------------------------------
   Toolbar: buscador + acciones + vista (arriba)
   -------------------------------------------------------------------------- */
.fl-explorador-toolbar {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
    padding: var(--fl-sp-2) var(--fl-sp-4);
    border-bottom: 1px solid var(--fl-borde-sutil);
    flex-wrap: wrap;
    background: var(--fl-fondo-sutil);
    flex: none;
}

/* --------------------------------------------------------------------------
   Migas de pan (cinta contextual debajo del toolbar, ancho completo)
   -------------------------------------------------------------------------- */
.fl-explorador-migas {
    padding: var(--fl-sp-2-5) var(--fl-sp-4);
    background: color-mix(in srgb, var(--fl-acento) 8%, var(--fl-fondo-sutil));
    border-bottom: 1px solid color-mix(in srgb, var(--fl-acento) 15%, var(--fl-borde-sutil));
    flex: none;
    overflow-x: auto;
    overflow-y: hidden;
    -ms-overflow-style: none;
    scrollbar-width: none;
}

.fl-explorador-migas::-webkit-scrollbar { display: none; }

.fl-explorador-migas > * { min-width: max-content; }

.fl-explorador-buscador {
    flex: 1 1 260px;
    min-width: 200px;
    max-width: 420px;
}

/* Cruz nativa del input[type="search"] teñida con el color de la paleta.
   La X default de los browsers es gris pálido — al usar mask-image podemos
   pintarla con --fl-acento. Solo webkit (Chrome/Safari/Edge); en Firefox no
   hay equivalente nativo. */
.fl-explorador-buscador .fl-campo-entrada::-webkit-search-cancel-button {
    -webkit-appearance: none;
    appearance: none;
    width: 14px;
    height: 14px;
    background-color: var(--fl-acento);
    -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round'><path d='M6 6l12 12M18 6L6 18'/></svg>");
            mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round'><path d='M6 6l12 12M18 6L6 18'/></svg>");
    -webkit-mask-size: contain;
            mask-size: contain;
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
    -webkit-mask-position: center;
            mask-position: center;
    cursor: pointer;
    transition: background-color var(--fl-t-rapido) var(--fl-ease-salida),
                transform var(--fl-t-rapido) var(--fl-ease-salida);
}
.fl-explorador-buscador .fl-campo-entrada::-webkit-search-cancel-button:hover {
    background-color: var(--fl-acento-texto);
    transform: scale(1.15);
}

.fl-explorador-toolbar-acciones {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-1);
    flex: none;
}

.fl-explorador-toolbar-sep {
    width: 1px;
    height: 18px;
    background: var(--fl-borde-sutil);
    margin: 0 var(--fl-sp-1);
}

/* Toggle vista: grilla / lista */
.fl-explorador-vista-toggle {
    display: inline-flex;
    padding: 2px;
    background: var(--fl-fondo-sutil);
    border: 1px solid var(--fl-borde-sutil);
    border-radius: var(--fl-r-md);
}

.fl-explorador-vista-boton {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    padding: 0;
    background: transparent;
    border: 0;
    border-radius: var(--fl-r-sm);
    color: var(--fl-texto-tenue);
    cursor: pointer;
    transition: background var(--fl-t-rapido), color var(--fl-t-rapido);
}

.fl-explorador-vista-boton:hover { color: var(--fl-texto-fuerte); }

.fl-explorador-vista-boton[aria-pressed="true"] {
    background: var(--fl-superficie);
    color: var(--fl-texto-fuerte);
    box-shadow: 0 1px 2px rgb(0 0 0 / .08);
}

.fl-explorador-vista-boton .fl-icono {
    width: 14px;
    height: 14px;
}

/* --------------------------------------------------------------------------
   Marquee / rubber-band — cuadro de selección con drag tipo SO/Drive
   -------------------------------------------------------------------------- */
.fl-explorador-marquee {
    position: absolute;
    z-index: 5;
    background: color-mix(in srgb, var(--fl-acento) 18%, transparent);
    border: 1px solid var(--fl-acento);
    border-radius: 2px;
    pointer-events: none;
}

/* --------------------------------------------------------------------------
   Barra de selección (aparece cuando hay items seleccionados)
   -------------------------------------------------------------------------- */
.fl-explorador-seleccion {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
    padding: 6px var(--fl-sp-3);
    background: var(--fl-acento-suave);
    border-bottom: 1px solid var(--fl-acento-borde);
    color: var(--fl-acento-texto);
    font-size: var(--fl-texto-sm);
    flex: none;
}

.fl-explorador-seleccion-conteo { font-weight: var(--fl-peso-semibold); }

.fl-explorador-seleccion-acciones {
    display: flex;
    gap: 2px;
    margin-left: auto;
}

/* --------------------------------------------------------------------------
   Cuerpo: grilla o lista de items
   -------------------------------------------------------------------------- */
.fl-explorador-cuerpo {
    flex: 1;
    overflow-y: auto;
    padding: var(--fl-sp-3);
    min-height: 0;
    position: relative;
    background: var(--fl-fondo-sutil);
}

/* ==========================================================================
   Vista GRILLA — item = tarjeta con media (thumb o icono) arriba e info debajo
   Markup unificado para que funcione también en vista lista al togglear.
   ========================================================================== */
.fl-explorador--grilla .fl-explorador-items {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: var(--fl-sp-3);
}

.fl-explorador--grilla .fl-explorador-items-cabecera { display: none; }

.fl-explorador--grilla .fl-explorador-item {
    display: flex;
    flex-direction: column;
    background: var(--fl-superficie);
    border: 1px solid var(--fl-borde);
    border-radius: var(--fl-r-md);
    cursor: pointer;
    transition: border-color var(--fl-t-rapido), box-shadow var(--fl-t-rapido),
                transform 140ms var(--fl-ease-resorte);
    user-select: none;
    position: relative;
    overflow: hidden;
}

.fl-explorador--grilla .fl-explorador-item:hover {
    border-color: var(--fl-acento);
    box-shadow: 0 6px 20px -8px color-mix(in srgb, var(--fl-acento) 35%, transparent);
    transform: translateY(-2px);
}

.fl-explorador--grilla .fl-explorador-item[data-fl-seleccionado="true"] {
    border-color: var(--fl-acento);
    box-shadow: 0 0 0 2px var(--fl-acento),
                0 6px 20px -8px color-mix(in srgb, var(--fl-acento) 40%, transparent);
}

/* Media tile: thumb como background o icono centrado */
.fl-explorador--grilla .fl-explorador-item-media {
    position: relative;
    aspect-ratio: 16 / 10;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: var(--fl-fondo-sutil);
    background-image: var(--_thumb, none);
    background-size: cover;
    background-position: center;
    overflow: hidden;
    flex: none;
    transition: background-size 400ms var(--fl-ease-salida);
}

.fl-explorador--grilla .fl-explorador-item--con-thumb:hover .fl-explorador-item-media {
    background-size: 108%;
}

.fl-explorador--grilla .fl-explorador-item-icono {
    width: 48px;
    height: 48px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--fl-r-md);
    background: color-mix(in srgb, var(--_color, var(--fl-texto-tenue)) 14%, var(--fl-superficie));
    color: var(--_color, var(--fl-texto-suave));
}

.fl-explorador--grilla .fl-explorador-item-icono .fl-icono {
    width: 24px;
    height: 24px;
}

/* Cuando hay thumb real, ocultamos el icono (el media ya tiene background-image) */
.fl-explorador--grilla .fl-explorador-item--con-thumb .fl-explorador-item-icono { display: none; }

/* Badges overlay (destacado + compartido) en sup-izq del media.
   Usamos un wrapper flex para garantizar que ambos se vean lado a lado
   cuando ambos existen, sin depender de selectores de hermano. */
.fl-explorador--grilla .fl-explorador-item-badges {
    position: absolute;
    top: 8px;
    left: 8px;
    display: inline-flex;
    gap: 4px;
    z-index: 1;
}

.fl-explorador--grilla .fl-explorador-item-star,
.fl-explorador--grilla .fl-explorador-item-compartido-badge {
    width: 24px;
    height: 24px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: color-mix(in srgb, var(--fl-superficie) 92%, transparent);
    border-radius: var(--fl-r-full);
    box-shadow: 0 2px 8px -2px rgb(0 0 0 / .12);
    backdrop-filter: blur(8px);
}

.fl-explorador--grilla .fl-explorador-item-star { color: var(--fl-acento-900); }
.fl-explorador--grilla .fl-explorador-item-compartido-badge { color: var(--fl-acento); }

.fl-explorador--grilla .fl-explorador-item-star .fl-icono,
.fl-explorador--grilla .fl-explorador-item-compartido-badge .fl-icono {
    width: 12px;
    height: 12px;
}

.fl-explorador--grilla .fl-explorador-item-star .fl-icono {
    fill: currentColor;
}

/* Menú 3-puntos (esquina sup-der del media) */
.fl-explorador--grilla .fl-explorador-item-menu {
    position: absolute;
    top: 6px;
    right: 6px;
    opacity: 0;
    pointer-events: none;
    background: color-mix(in srgb, var(--fl-superficie) 92%, transparent);
    border-radius: var(--fl-r-sm);
    backdrop-filter: blur(6px);
    transition: opacity var(--fl-t-rapido);
    z-index: 2;
}

.fl-explorador--grilla .fl-explorador-item:hover .fl-explorador-item-menu {
    opacity: 1;
    pointer-events: auto;
}

/* Nombre */
.fl-explorador--grilla .fl-explorador-item-nombre {
    padding: var(--fl-sp-2) var(--fl-sp-2-5) 2px;
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-fuerte);
    line-height: 1.3;
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
}

.fl-explorador--grilla .fl-explorador-item-nombre-texto {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
    flex: 1;
}

.fl-explorador--grilla .fl-explorador-item-compartido-icono { display: none; }

/* Meta: fecha · peso como línea debajo del nombre */
.fl-explorador--grilla .fl-explorador-item-meta {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 0 var(--fl-sp-2-5) var(--fl-sp-2-5);
    font-size: 10px;
    color: var(--fl-texto-tenue);
    font-variant-numeric: tabular-nums;
}

.fl-explorador--grilla .fl-explorador-item-fecha + .fl-explorador-item-peso::before {
    content: "·";
    margin-right: 6px;
    opacity: 0.5;
}

.fl-explorador--grilla .fl-explorador-item-propietario { display: none; }

/* Avatars stack de compartidos (esquina inferior derecha, overlay) */
.fl-explorador--grilla .fl-explorador-item-compartido {
    position: absolute;
    right: var(--fl-sp-2-5);
    bottom: var(--fl-sp-2);
    display: inline-flex;
    flex-direction: row-reverse;
    z-index: 1;
}

.fl-explorador--grilla .fl-explorador-item-compartido-avatar {
    width: 20px;
    height: 20px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: color-mix(in srgb, var(--_color, var(--fl-acento)) 60%, var(--fl-texto-fuerte));
    color: white;
    border: 2px solid var(--fl-superficie);
    border-radius: var(--fl-r-full);
    font-size: 9px;
    font-weight: var(--fl-peso-semibold);
    margin-left: -8px;
    text-transform: uppercase;
}

.fl-explorador--grilla .fl-explorador-item-compartido-avatar--mas {
    background: var(--fl-fondo-sutil);
    color: var(--fl-texto-suave);
}

/* Carpetas: tinte en el media + icono grande con opacidad */
.fl-explorador--grilla .fl-explorador-item--carpeta .fl-explorador-item-media {
    background: color-mix(in srgb, var(--_color, var(--fl-acento)) 12%, var(--fl-fondo-sutil));
}

.fl-explorador--grilla .fl-explorador-item--carpeta .fl-explorador-item-icono {
    background: color-mix(in srgb, var(--_color, var(--fl-acento)) 22%, var(--fl-superficie));
    color: var(--_color, var(--fl-acento));
    width: 56px;
    height: 56px;
}

.fl-explorador--grilla .fl-explorador-item--carpeta .fl-explorador-item-icono .fl-icono {
    width: 28px;
    height: 28px;
    fill: currentColor;
    fill-opacity: 0.12;
}

/* Iconos coloreados por tipo — tokens semánticos Flora */
/* Íconos por tipo — profundidades de paleta (no colores semánticos externos) */
.fl-explorador--grilla .fl-explorador-item--pdf       .fl-explorador-item-icono { background: color-mix(in srgb, var(--fl-acento-900) 14%, var(--fl-superficie)); color: var(--fl-acento-900); }
.fl-explorador--grilla .fl-explorador-item--imagen    .fl-explorador-item-icono { background: color-mix(in srgb, var(--fl-acento) 14%, var(--fl-superficie));     color: var(--fl-acento-texto); }
.fl-explorador--grilla .fl-explorador-item--documento .fl-explorador-item-icono { background: color-mix(in srgb, var(--fl-acento-700) 14%, var(--fl-superficie)); color: var(--fl-acento-700); }
.fl-explorador--grilla .fl-explorador-item--planilla  .fl-explorador-item-icono { background: color-mix(in srgb, var(--fl-acento-500) 14%, var(--fl-superficie)); color: var(--fl-acento-texto); }
.fl-explorador--grilla .fl-explorador-item--video     .fl-explorador-item-icono { background: color-mix(in srgb, var(--fl-acento-800) 14%, var(--fl-superficie)); color: var(--fl-acento-800); }
.fl-explorador--grilla .fl-explorador-item--audio     .fl-explorador-item-icono { background: color-mix(in srgb, var(--fl-acento-300) 22%, var(--fl-superficie)); color: var(--fl-acento-texto); }
.fl-explorador--grilla .fl-explorador-item--archivo   .fl-explorador-item-icono {
    background: color-mix(in srgb, var(--fl-texto-tenue) 15%, var(--fl-superficie));
    color: var(--fl-texto-suave);
}

/* ==========================================================================
   Vista LISTA densa — tabla clean con headers ordenables
   Markup unificado: .item-media se vuelve un ícono chico 32x32;
   .item-meta usa display:contents así fecha+peso se vuelven grid-cells.
   ========================================================================== */
.fl-explorador--lista .fl-explorador-items {
    display: flex;
    flex-direction: column;
    background: var(--fl-superficie);
    border: 1px solid var(--fl-borde);
    border-radius: var(--fl-r-md);
    overflow: hidden;
}

.fl-explorador--lista .fl-explorador-items-cabecera {
    display: grid;
    grid-template-columns: var(--_cols, 44px minmax(200px, 1fr) 140px 110px 44px);
    gap: var(--fl-sp-3);
    padding: var(--fl-sp-2) var(--fl-sp-4);
    background: var(--fl-fondo-sutil);
    font-size: var(--fl-texto-2xs);
    font-weight: var(--fl-peso-semibold);
    text-transform: uppercase;
    letter-spacing: var(--fl-ls-mayus);
    color: var(--fl-texto-tenue);
    align-items: center;
    border-bottom: 1px solid var(--fl-borde-sutil);
}

.fl-explorador--lista .fl-explorador-sort {
    background: transparent;
    border: 0;
    padding: 0;
    color: inherit;
    font: inherit;
    text-transform: inherit;
    letter-spacing: inherit;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    text-align: left;
    transition: color var(--fl-t-rapido);
}

/* Headers Modificado / Tamaño / Propietario (todos menos "Nombre" que va en
   nth-child(2)) van centrados — alinean visualmente con sus celdas centradas. */
.fl-explorador--lista .fl-explorador-items-cabecera > .fl-explorador-sort:not(:nth-child(2)) {
    justify-self: center;
}

.fl-explorador--lista .fl-explorador-sort:hover { color: var(--fl-texto-suave); }
.fl-explorador--lista .fl-explorador-sort--activo { color: var(--fl-texto-fuerte); }

.fl-explorador--lista .fl-explorador-sort .fl-icono {
    width: 11px;
    height: 11px;
    opacity: 0;
    transition: opacity var(--fl-t-rapido);
}

.fl-explorador--lista .fl-explorador-sort--activo .fl-icono,
.fl-explorador--lista .fl-explorador-sort:hover .fl-icono { opacity: 1; }

.fl-explorador--lista .fl-explorador-item {
    display: grid;
    grid-template-columns: var(--_cols, 44px minmax(200px, 1fr) 140px 110px 44px);
    gap: var(--fl-sp-3);
    padding: var(--fl-sp-1-5) var(--fl-sp-4);
    background: var(--fl-superficie);
    align-items: center;
    cursor: pointer;
    transition: background var(--fl-t-rapido);
    font-size: var(--fl-texto-sm);
    border-top: 1px solid var(--fl-borde-sutil);
    min-height: 44px;
    position: relative;
}

.fl-explorador--lista .fl-explorador-item:first-of-type { border-top: 0; }

.fl-explorador--lista .fl-explorador-item:hover { background: var(--fl-superficie-hover); }

.fl-explorador--lista .fl-explorador-item[data-fl-seleccionado="true"] {
    background: var(--fl-acento-suave);
}

.fl-explorador--lista .fl-explorador-item[data-fl-seleccionado="true"]::before {
    content: "";
    position: absolute;
    left: 0;
    top: 4px;
    bottom: 4px;
    width: 3px;
    background: var(--fl-acento);
    border-radius: 0 var(--fl-r-full) var(--fl-r-full) 0;
}

/* .item-meta colapsa para que fecha y peso se vuelvan grid-cells directos */
.fl-explorador--lista .fl-explorador-item-meta { display: contents; }

/* .item-compartido stack (avatars) oculto en lista — usamos el iconito users inline */
.fl-explorador--lista .fl-explorador-item-compartido { display: none; }

/* Badge de compartido oculto en lista — el ícono inline junto al nombre lo cubre */
.fl-explorador--lista .fl-explorador-item-compartido-badge { display: none; }

/* Wrapper de badges: en lista colapsa para que la estrella quede posicionable libre */
.fl-explorador--lista .fl-explorador-item-badges { display: contents; }

/* Media → icono chico 32x32, aspect-ratio auto */
.fl-explorador--lista .fl-explorador-item-media {
    position: relative;
    width: 32px;
    height: 32px;
    aspect-ratio: auto;
    border-radius: var(--fl-r-sm);
    background-color: var(--fl-fondo-sutil);
    background-image: var(--_thumb, none);
    background-size: cover;
    background-position: center;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    justify-self: center;
    overflow: visible;
    flex: none;
    padding: 0;
}

/* Recortar el fondo (icono/thumb) sin que afecte al badge estrella */
.fl-explorador--lista .fl-explorador-item-media > .fl-explorador-item-icono {
    border-radius: var(--fl-r-sm);
    overflow: hidden;
}

.fl-explorador--lista .fl-explorador-item-icono {
    width: 100%;
    height: 100%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--fl-r-sm);
    background: color-mix(in srgb, var(--_color, var(--fl-texto-tenue)) 14%, var(--fl-fondo-sutil));
    color: var(--_color, var(--fl-texto-suave));
}

.fl-explorador--lista .fl-explorador-item-icono .fl-icono {
    width: 16px;
    height: 16px;
}

/* Thumb presente → ocultamos el icono (el bg-image del media ya lo muestra) */
.fl-explorador--lista .fl-explorador-item--con-thumb .fl-explorador-item-icono { display: none; }

/* Colores por tipo (vista lista) */
.fl-explorador--lista .fl-explorador-item--carpeta .fl-explorador-item-icono {
    background: color-mix(in srgb, var(--_color, var(--fl-acento)) 14%, var(--fl-fondo-sutil));
    color: var(--_color, var(--fl-acento));
}
.fl-explorador--lista .fl-explorador-item--pdf       .fl-explorador-item-icono { background: color-mix(in srgb, var(--fl-acento-900) 14%, var(--fl-fondo-sutil)); color: var(--fl-acento-900); }
.fl-explorador--lista .fl-explorador-item--imagen    .fl-explorador-item-icono { background: color-mix(in srgb, var(--fl-acento) 14%, var(--fl-fondo-sutil));     color: var(--fl-acento-texto); }
.fl-explorador--lista .fl-explorador-item--documento .fl-explorador-item-icono { background: color-mix(in srgb, var(--fl-acento-700) 14%, var(--fl-fondo-sutil)); color: var(--fl-acento-700); }
.fl-explorador--lista .fl-explorador-item--planilla  .fl-explorador-item-icono { background: color-mix(in srgb, var(--fl-acento-500) 14%, var(--fl-fondo-sutil)); color: var(--fl-acento-texto); }
.fl-explorador--lista .fl-explorador-item--video     .fl-explorador-item-icono { background: color-mix(in srgb, var(--fl-acento-800) 14%, var(--fl-fondo-sutil)); color: var(--fl-acento-800); }
.fl-explorador--lista .fl-explorador-item--audio     .fl-explorador-item-icono { background: color-mix(in srgb, var(--fl-acento-300) 22%, var(--fl-fondo-sutil)); color: var(--fl-acento-texto); }

/* Estrella como badge mini arriba-derecha del ícono 32x32 */
.fl-explorador--lista .fl-explorador-item-star {
    position: absolute;
    top: -5px;
    right: -5px;
    width: 16px;
    height: 16px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--fl-acento-900);
    color: var(--fl-acento-texto-sobre);
    border: 2px solid var(--fl-superficie);
    border-radius: var(--fl-r-full);
    box-shadow: 0 1px 3px -1px rgb(0 0 0 / .2);
    z-index: 2;
    box-sizing: content-box;
}

.fl-explorador--lista .fl-explorador-item-star .fl-icono {
    width: 10px;
    height: 10px;
    fill: currentColor;
}

.fl-explorador--lista .fl-explorador-item-nombre {
    color: var(--fl-texto-fuerte);
    font-weight: var(--fl-peso-medio);
    text-align: left;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
}

.fl-explorador--lista .fl-explorador-item-nombre-texto {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

.fl-explorador--lista .fl-explorador-item-compartido-icono {
    color: var(--fl-texto-tenue);
    flex: none;
    display: inline-flex;
}

.fl-explorador--lista .fl-explorador-item-compartido-icono .fl-icono {
    width: 12px;
    height: 12px;
}

.fl-explorador--lista .fl-explorador-item-propietario {
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-suave);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    display: block;
}

.fl-explorador--lista .fl-explorador-item-fecha,
.fl-explorador--lista .fl-explorador-item-peso {
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-tenue);
    font-variant-numeric: tabular-nums;
    text-align: center;
    align-self: center;
}

.fl-explorador--lista .fl-explorador-item-menu {
    justify-self: center;
    opacity: 0.6;
    transition: opacity var(--fl-t-rapido);
}

.fl-explorador--lista .fl-explorador-item:hover .fl-explorador-item-menu { opacity: 1; }

/* --------------------------------------------------------------------------
   Panel derecho opcional (detalle de archivo)
   Fondo base con tinte sutil de la paleta (en vez de blanco puro).
   Cada sección se tinta de un color distinto para dar jerarquía visual.
   -------------------------------------------------------------------------- */
.fl-explorador-panel {
    display: flex;
    flex-direction: column;
    border-left: 1px solid var(--fl-borde-sutil);
    background: color-mix(in srgb, var(--fl-acento) 3%, var(--fl-superficie));
    overflow-y: auto;
}

.fl-explorador-panel-media {
    aspect-ratio: 4 / 3;
    background-color: var(--fl-fondo-sutil);
    background-size: cover;
    background-position: center;
    border-bottom: 1px solid var(--fl-borde-sutil);
}

.fl-explorador-panel-cabecera {
    padding: var(--fl-sp-3);
    display: flex;
    flex-direction: column;
    gap: 4px;
    background: color-mix(in srgb, var(--fl-acento) 8%, var(--fl-superficie));
    border-bottom: 1px solid color-mix(in srgb, var(--fl-acento) 18%, var(--fl-borde-sutil));
}

.fl-explorador-panel-titulo {
    font-size: var(--fl-texto-base);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-fuerte);
    line-height: 1.3;
    word-break: break-word;
}

.fl-explorador-panel-tipo {
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-tenue);
}

.fl-explorador-panel-acciones {
    display: flex;
    gap: 2px;
    justify-content: center;
    align-items: center;
    padding: var(--fl-sp-2) var(--fl-sp-3);
    margin: 0;
    background: linear-gradient(
        135deg,
        var(--fl-acento) 0%,
        color-mix(in srgb, var(--fl-acento) 50%, var(--fl-texto-fuerte)) 45%,
        var(--fl-texto-fuerte) 100%
    );
    border-bottom: 1px solid var(--fl-borde-sutil);
    flex-wrap: wrap;
}

.fl-explorador-panel-acciones > .fl-boton {
    background: transparent;
    border: 0;
    color: var(--fl-superficie);
    box-shadow: none;
    transition: background var(--fl-t-rapido);
}

.fl-explorador-panel-acciones > .fl-boton:hover {
    background: color-mix(in srgb, white 18%, transparent);
    color: var(--fl-superficie);
}

.fl-explorador-panel-acciones > .fl-boton .fl-icono {
    color: inherit;
}

.fl-explorador-panel-seccion {
    padding: var(--fl-sp-3);
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-1-5);
    background: color-mix(in srgb, var(--fl-acento) 10%, var(--fl-superficie));
    border-bottom: 1px solid color-mix(in srgb, var(--fl-acento) 20%, var(--fl-borde-sutil));
}

/* Alternado: cada 2da sección usa una intensidad más fuerte de acento */
.fl-explorador-panel-seccion + .fl-explorador-panel-seccion {
    background: color-mix(in srgb, var(--fl-acento) 22%, var(--fl-superficie));
}

.fl-explorador-panel-seccion + .fl-explorador-panel-seccion + .fl-explorador-panel-seccion {
    background: color-mix(in srgb, var(--fl-acento) 10%, var(--fl-superficie));
}

.fl-explorador-panel-seccion + .fl-explorador-panel-seccion + .fl-explorador-panel-seccion + .fl-explorador-panel-seccion {
    background: color-mix(in srgb, var(--fl-acento) 22%, var(--fl-superficie));
}

.fl-explorador-panel-seccion:last-child { border-bottom: 0; }

.fl-explorador-panel-seccion .fl-explorador-panel-seccion-titulo {
    color: var(--fl-acento-texto);
}

.fl-explorador-panel-seccion-titulo {
    font-size: var(--fl-texto-2xs);
    font-weight: var(--fl-peso-semibold);
    text-transform: uppercase;
    letter-spacing: var(--fl-ls-mayus);
    color: var(--fl-texto-tenue);
}

.fl-explorador-panel-meta {
    display: grid;
    grid-template-columns: 90px 1fr;
    gap: 8px 12px;
    font-size: var(--fl-texto-xs);
}

.fl-explorador-panel-meta dt {
    color: var(--fl-texto-tenue);
    font-weight: var(--fl-peso-medio);
}

.fl-explorador-panel-meta dd {
    color: var(--fl-texto);
    margin: 0;
    font-variant-numeric: tabular-nums;
}

.fl-explorador-panel-avatars {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-1-5);
}

.fl-explorador-panel-avatar-fila {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
    font-size: var(--fl-texto-xs);
}

.fl-explorador-panel-avatar-fila-nombre {
    color: var(--fl-texto);
    font-weight: var(--fl-peso-medio);
}

.fl-explorador-panel-avatar-fila-rol {
    color: var(--fl-texto-tenue);
    margin-left: auto;
    font-size: 10px;
    padding: 1px 6px;
    background: var(--fl-fondo-sutil);
    border-radius: var(--fl-r-full);
}

/* --------------------------------------------------------------------------
   Estado vacío / dropzone
   -------------------------------------------------------------------------- */
.fl-explorador-cuerpo[data-fl-arrastrando="true"] {
    background: var(--fl-acento-suave);
    box-shadow: inset 0 0 0 2px var(--fl-acento);
    border-radius: var(--fl-r-md);
}

.fl-explorador-cuerpo[data-fl-arrastrando="true"]::before {
    content: "Soltá los archivos para subirlos";
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: var(--fl-texto-lg);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-acento-texto);
    pointer-events: none;
}

.fl-explorador-vacio {
    padding: var(--fl-sp-12);
    text-align: center;
    color: var(--fl-texto-tenue);
}


/* ===== resources/css/componentes/file-drop.css ===== */
/* ==========================================================================
   Flora · File-drop
   Dropzone de archivos: click para seleccionar o drag-and-drop.
   Preview de archivos agregados con barra de progreso opcional.
   ========================================================================== */

.fl-file-drop {
    position: relative;
    display: flex;
    width: 100%;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--fl-sp-2);
    padding: var(--fl-sp-8) var(--fl-sp-4);
    min-height: 180px;
    background: var(--fl-fondo-sutil);
    border: 2px dashed var(--fl-borde-fuerte);
    border-radius: var(--fl-r-lg);
    text-align: center;
    cursor: pointer;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida),
                border-color var(--fl-t-rapido) var(--fl-ease-salida),
                transform 200ms var(--fl-ease-resorte);
}

.fl-file-drop:hover {
    background: var(--fl-acento-suave);
    border-color: var(--fl-acento);
}

.fl-file-drop[data-fl-arrastrando="true"] {
    background: color-mix(in srgb, var(--fl-destaque-fondo) 12%, var(--fl-superficie));
    border-color: var(--fl-destaque-fondo);
    border-style: solid;
    transform: scale(1.01);
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--fl-destaque-fondo) 18%, transparent);
}

.fl-file-drop[data-fl-deshabilitado="true"] {
    opacity: 0.5;
    cursor: not-allowed;
    pointer-events: none;
}

/* Input file nativo oculto pero accesible — patrón "visually-hidden" para
   compatibilidad mobile (iOS Safari no dispara click en inputs con opacity:0
   cubriendo todo el label; tamaño 1px + sr-only evita ese quirk). El click
   llega al input vía el <label> que lo envuelve. Drag-and-drop se maneja
   con listeners directos sobre el dropzone (no sobre el input). */
.fl-file-drop-input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    pointer-events: none;
    margin: 0;
    padding: 0;
    border: 0;
}

.fl-file-drop-input:focus-visible + .fl-file-drop-contenido {
    outline: 3px solid var(--fl-acento-foco);
    outline-offset: -2px;
    border-radius: var(--fl-r-md);
}

.fl-file-drop-contenido {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--fl-sp-2);
    pointer-events: none;
    position: relative;
    z-index: 1;
}

.fl-file-drop-icono {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    background: var(--fl-superficie);
    color: var(--fl-acento);
    border-radius: var(--fl-r-full);
    box-shadow: var(--fl-sombra-xs);
    transition: transform 260ms var(--fl-ease-resorte);
}

.fl-file-drop:hover .fl-file-drop-icono,
.fl-file-drop[data-fl-arrastrando="true"] .fl-file-drop-icono {
    transform: translateY(-2px) scale(1.06);
}

.fl-file-drop-icono .fl-icono {
    width: 24px;
    height: 24px;
}

.fl-file-drop-titulo {
    font-size: var(--fl-texto-base);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-fuerte);
    line-height: 1.3;
}

.fl-file-drop-titulo em {
    color: var(--fl-acento-texto);
    font-style: normal;
    font-weight: inherit;
}

.fl-file-drop-pista {
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto-suave);
    line-height: 1.4;
}

/* --------------------------------------------------------------------------
   Lista de archivos agregados
   -------------------------------------------------------------------------- */
.fl-file-drop-lista {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-2);
    margin: 0;
    list-style: none;
    padding: 0;
    width: 100%;
    align-self: stretch;   /* El padre es flex column con align-items:center;
                              sin esto la lista queda con width:fit-content y
                              archivos con nombres largos se salen del dropzone. */
    min-width: 0;
    max-width: 100%;
    box-sizing: border-box;
}

/* Cuando está vacía se saca del flujo del flex — así el contenido queda
   realmente centrado vertical y no "empujado" hacia arriba por un <ul>
   invisible que igual reservaba espacio/gap. */
.fl-file-drop-lista:empty {
    display: none;
}

.fl-file-drop-archivo {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-3);
    padding: var(--fl-sp-2) var(--fl-sp-3);
    background: var(--fl-superficie);
    border: 1px solid var(--fl-borde);
    border-radius: var(--fl-r-md);
    font-size: var(--fl-texto-sm);
    position: relative;
    overflow: hidden;
    min-width: 0;
    max-width: 100%;
    box-sizing: border-box;
}

.fl-file-drop-archivo-icono {
    flex: none;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--fl-acento-suave);
    color: var(--fl-acento);
    border-radius: var(--fl-r-sm);
}

.fl-file-drop-archivo-info {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.fl-file-drop-archivo-nombre {
    color: var(--fl-texto-fuerte);
    font-weight: var(--fl-peso-medio);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.fl-file-drop-archivo-peso {
    color: var(--fl-texto-tenue);
    font-size: var(--fl-texto-xs);
    font-variant-numeric: tabular-nums;
}

.fl-file-drop-archivo-accion {
    flex: none;
    width: 28px;
    height: 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 0;
    border-radius: var(--fl-r-sm);
    color: var(--fl-texto-tenue);
    cursor: pointer;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida),
                color var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-file-drop-archivo-accion:hover {
    background: var(--fl-error-suave);
    color: var(--fl-error);
}

.fl-file-drop-archivo-accion .fl-icono {
    width: 14px;
    height: 14px;
}

/* Progreso sobre el archivo */
.fl-file-drop-archivo-progreso {
    position: absolute;
    left: 0;
    bottom: 0;
    height: 2px;
    background: var(--fl-acento);
    transition: width 200ms linear;
}

/* --------------------------------------------------------------------------
   Variantes
   -------------------------------------------------------------------------- */

/* Compacto */
.fl-file-drop--compacto {
    padding: var(--fl-sp-4);
    min-height: 80px;
    flex-direction: row;
    justify-content: center;
    gap: var(--fl-sp-3);
}

.fl-file-drop--compacto .fl-file-drop-icono {
    width: 36px;
    height: 36px;
}

.fl-file-drop--compacto .fl-file-drop-icono .fl-icono {
    width: 18px;
    height: 18px;
}

.fl-file-drop--compacto .fl-file-drop-contenido {
    flex-direction: row;
    align-items: center;
    gap: var(--fl-sp-3);
}

/* La lista en compacto fluye en línea (width:auto) para no empujar el
   contenido a un costado. El width:100% global es para el layout column. */
.fl-file-drop--compacto .fl-file-drop-lista {
    width: auto;
    align-self: auto;
    flex: 0 1 auto;
    margin-top: 0;
    max-width: 100%;
}

/* Mobile: compact se apila (archivo debajo del contenido) para que
   contenido y archivo no compitan por el ancho horizontal.
   Centrado vertical explícito + min-height que deje espacio real para
   que el justify-content:center se note. */
@media (max-width: 640px) {
    .fl-file-drop--compacto {
        flex-direction: column;
        align-items: center;
        justify-content: center;
        text-align: center;
        min-height: 140px;
        gap: var(--fl-sp-3);
    }
    .fl-file-drop--compacto .fl-file-drop-contenido {
        justify-content: center;
    }
    .fl-file-drop--compacto .fl-file-drop-lista {
        width: 100%;
        align-self: stretch;
        margin-top: 0;
    }
}

/* Error */
.fl-file-drop[data-fl-error="true"] {
    border-color: var(--fl-error);
    background: var(--fl-error-suave);
}


/* ===== resources/css/componentes/formulario.css ===== */
/* ==========================================================================
   Flora · Formulario
   Estructura y layout para forms complejos: secciones, grilla de campos,
   resumen de errores, acciones pegadas al pie.
   ========================================================================== */

.fl-formulario {
    display: flex;
    flex-direction: column;
    width: 100%;
    gap: var(--fl-sp-8);
}

/* En tarjetas y modales, fl-apilar--md hereda el gap de formulario (sp-8)
   para que todos los grupos de campos tengan el mismo aire por defecto,
   sin importar si se usa x-flora::formulario o un <div> plano. */
.fl-tarjeta-cuerpo .fl-apilar--md,
.fl-modal-cuerpo   .fl-apilar--md {
    gap: var(--fl-sp-8);
}
/* Dentro de un formulario, las filas de campos que wrappean mantienen
   el mismo row-gap que el gap general, para no generar espaciados dispares. */
.fl-formulario .fl-fila--md {
    row-gap: var(--fl-sp-8);
}

/* Sección — grupo lógico de campos con título.
   Gap vertical entre campos dentro de una sección: sp-7 (28px). Pausa
   clara entre campos para que el ojo registre cada uno como unidad
   separada antes de pasar al siguiente. Cambio global. */
.fl-formulario-seccion {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-7);
}

.fl-formulario-seccion-encabezado {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-1);
    padding-bottom: var(--fl-sp-3);
    border-bottom: 1px solid var(--fl-borde-sutil);
}

.fl-formulario-seccion-titulo {
    font-size: var(--fl-texto-base);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-fuerte);
    line-height: var(--fl-lh-compacta);
}

.fl-formulario-seccion-descripcion {
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto-suave);
    line-height: var(--fl-lh-ajustada);
}

/* Grilla de campos — responsive, colapsa a 1 col en mobile */
.fl-formulario-grilla {
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    gap: var(--fl-sp-4);
}

/* Clases para span de campos dentro de la grilla */
.fl-form-col-1  { grid-column: span 1; }
.fl-form-col-2  { grid-column: span 2; }
.fl-form-col-3  { grid-column: span 3; }
.fl-form-col-4  { grid-column: span 4; }
.fl-form-col-5  { grid-column: span 5; }
.fl-form-col-6  { grid-column: span 6; }
.fl-form-col-7  { grid-column: span 7; }
.fl-form-col-8  { grid-column: span 8; }
.fl-form-col-9  { grid-column: span 9; }
.fl-form-col-10 { grid-column: span 10; }
.fl-form-col-11 { grid-column: span 11; }
.fl-form-col-12 { grid-column: span 12; }

@media (max-width: 767px) {
    .fl-form-col-1, .fl-form-col-2, .fl-form-col-3, .fl-form-col-4,
    .fl-form-col-5, .fl-form-col-6, .fl-form-col-7, .fl-form-col-8,
    .fl-form-col-9, .fl-form-col-10, .fl-form-col-11 {
        grid-column: span 12;
    }
}

/* Resumen de errores global (arriba del formulario) */
.fl-formulario-resumen-errores {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-2);
    padding: var(--fl-sp-3) var(--fl-sp-4);
    background: var(--fl-error-suave);
    border: 1px solid var(--fl-error-borde);
    border-left: 3px solid var(--fl-error);
    border-radius: var(--fl-r-md);
    color: var(--fl-error-texto);
    font-size: var(--fl-texto-sm);
}

.fl-formulario-resumen-errores-titulo {
    font-weight: var(--fl-peso-semibold);
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
}

.fl-formulario-resumen-errores-titulo .fl-icono {
    width: 16px;
    height: 16px;
}

.fl-formulario-resumen-errores ul {
    margin: 0;
    padding-left: var(--fl-sp-5);
}

.fl-formulario-resumen-errores li {
    line-height: var(--fl-lh-ajustada);
}

/* Acciones del formulario — pegadas al pie, con separador arriba */
.fl-formulario-acciones {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--fl-sp-2);
    padding-top: var(--fl-sp-5);
    border-top: 1px solid var(--fl-borde-sutil);
    flex-wrap: wrap;
}

.fl-formulario-acciones--izquierda {
    justify-content: flex-start;
}

.fl-formulario-acciones--distribuida {
    justify-content: space-between;
}

/* Variante compacta — menos gap entre secciones */
.fl-formulario--compacto {
    gap: var(--fl-sp-5);
}

.fl-formulario--compacto .fl-formulario-seccion {
    gap: var(--fl-sp-3);
}

/* Variante inline — campos en fila (para filtros) */
.fl-formulario--inline {
    gap: var(--fl-sp-3);
    flex-direction: row;
    flex-wrap: wrap;
    align-items: flex-end;
}


/* ===== resources/css/componentes/grafico.css ===== */
/* ==========================================================================
   Flora · Gráfico (charts SVG nativos)
   Variantes: linea | area | barras | dona | sparkline | stat
   CSS + SVG, sin chart.js. Data se pasa como prop y el Blade renderiza el
   SVG directamente — sin JS para ver. El JS se usa para tooltips opcionales.
   ========================================================================== */

.fl-grafico {
    display: block;
    width: 100%;
    position: relative;
    color: var(--fl-texto);
}

.fl-grafico-svg {
    display: block;
    width: 100%;
    height: auto;
    max-height: 320px;
    overflow: visible;
}

/* Dona — centrar el SVG en su container, no estirar al 100% */
.fl-grafico--dona {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--fl-sp-3);
}

.fl-grafico--dona .fl-grafico-svg {
    width: auto;
    height: auto;
    max-width: 100%;
    max-height: none;
}

/* Wrapper interno del SVG + centro — asegurar centrado absoluto */
.fl-grafico-dona {
    flex: none;
}

/* Sparkline — tamaño chico, aspect ratio matchea el viewBox (160:48) */
.fl-grafico--sparkline {
    width: 100px;
    height: 30px;
    display: inline-block;
    vertical-align: middle;
}

.fl-grafico--sparkline .fl-grafico-svg {
    width: 100%;
    height: 100%;
    max-height: none;
}

/* Line stroke un poco más grueso para sparkline — resalta en tamaño chico */
.fl-grafico--sparkline .fl-grafico-linea {
    stroke-width: 2;
}

/* --------------------------------------------------------------------------
   Ejes y grilla — para linea / area / barras
   -------------------------------------------------------------------------- */
.fl-grafico-eje {
    stroke: var(--fl-borde-fuerte);
    stroke-width: 1;
    fill: none;
}

.fl-grafico-grilla-linea {
    stroke: var(--fl-borde);
    stroke-width: 1;
    stroke-dasharray: 2 3;
    fill: none;
}

/* En modo oscuro, las grillas necesitan más contraste porque el --fl-borde
   se vuelve muy oscuro contra el fondo negro. */
[data-fl-enfasis="oscuro"] .fl-grafico-eje {
    stroke: var(--fl-borde-intenso);
}
[data-fl-enfasis="oscuro"] .fl-grafico-grilla-linea {
    stroke: var(--fl-borde-fuerte);
}

.fl-grafico-etiqueta {
    /* font-size va como atributo SVG en el template — acá sólo fill/family
       para que la escala sea consistente con el viewBox. */
    font-family: var(--fl-fuente-sans);
    fill: var(--fl-texto-tenue);
}

.fl-grafico-etiqueta--eje-y {
    text-anchor: end;
}

.fl-grafico-etiqueta--eje-x {
    text-anchor: middle;
}

/* --------------------------------------------------------------------------
   Variante LINEA
   -------------------------------------------------------------------------- */
.fl-grafico-linea {
    stroke: var(--fl-destaque-fondo);
    stroke-width: 2;
    fill: none;
    stroke-linecap: round;
    stroke-linejoin: round;
    /* Que el stroke se mantenga en CSS pixels aunque el SVG se comprima
       (clave para sparklines embebidos en KPI cards) */
    vector-effect: non-scaling-stroke;
}

.fl-grafico-punto {
    /* r viene como atributo SVG en el template */
    fill: var(--fl-destaque-fondo);
    stroke: var(--fl-superficie);
    stroke-width: 2;
    transition: transform var(--fl-t-rapido) var(--fl-ease-salida);
    transform-origin: center;
    transform-box: fill-box;
    cursor: pointer;
}

.fl-grafico-punto:hover {
    transform: scale(1.3);
}

/* --------------------------------------------------------------------------
   Variante AREA — linea + relleno degradé hacia abajo
   -------------------------------------------------------------------------- */
.fl-grafico-area {
    fill: url(#fl-grafico-area-degrade);
}

/* --------------------------------------------------------------------------
   Variante BARRAS
   -------------------------------------------------------------------------- */
.fl-grafico-barra {
    fill: var(--fl-destaque-fondo);
    transition: fill var(--fl-t-rapido) var(--fl-ease-salida);
    cursor: pointer;
}

.fl-grafico-barra:hover {
    fill: var(--fl-destaque-fondo-hover);
}

/* Series coloreadas con profundidades de paleta — 7 niveles distinguibles */
.fl-grafico-barra[data-fl-serie="0"] { fill: var(--fl-acento-900); }
.fl-grafico-barra[data-fl-serie="1"] { fill: var(--fl-acento-500); }
.fl-grafico-barra[data-fl-serie="2"] { fill: var(--fl-acento-700); }
.fl-grafico-barra[data-fl-serie="3"] { fill: var(--fl-acento-300); }
.fl-grafico-barra[data-fl-serie="4"] { fill: var(--fl-acento-800); }
.fl-grafico-barra[data-fl-serie="5"] { fill: var(--fl-acento-400); }

/* --------------------------------------------------------------------------
   Variante DONA
   -------------------------------------------------------------------------- */
.fl-grafico-dona {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.fl-grafico-dona-segmento {
    /* stroke-width viene como atributo SVG en el template — no override acá */
    fill: none;
    transition: opacity var(--fl-t-rapido) var(--fl-ease-salida);
    cursor: pointer;
}

.fl-grafico-dona-segmento:hover {
    opacity: 0.82;
}

.fl-grafico-dona-segmento[data-fl-serie="0"] { stroke: var(--fl-acento-900); }
.fl-grafico-dona-segmento[data-fl-serie="1"] { stroke: var(--fl-acento-500); }
.fl-grafico-dona-segmento[data-fl-serie="2"] { stroke: var(--fl-acento-700); }
.fl-grafico-dona-segmento[data-fl-serie="3"] { stroke: var(--fl-acento-300); }
.fl-grafico-dona-segmento[data-fl-serie="4"] { stroke: var(--fl-acento-800); }
.fl-grafico-dona-segmento[data-fl-serie="5"] { stroke: var(--fl-acento-400); }
.fl-grafico-dona-segmento[data-fl-serie="6"] { stroke: var(--fl-acento-200); }

.fl-grafico-dona-centro {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    text-align: center;
    pointer-events: none;
}

.fl-grafico-dona-valor {
    font-size: var(--fl-texto-2xl);
    font-weight: var(--fl-peso-bold);
    color: var(--fl-texto-fuerte);
    line-height: 1;
    font-variant-numeric: tabular-nums;
}

.fl-grafico-dona-etiqueta {
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-suave);
    margin-top: 2px;
    text-transform: uppercase;
    letter-spacing: var(--fl-ls-mayus);
}

/* --------------------------------------------------------------------------
   Leyenda — lista de etiquetas con color + valor (opcional)
   -------------------------------------------------------------------------- */
.fl-grafico-leyenda {
    display: flex;
    flex-wrap: wrap;
    gap: var(--fl-sp-3);
    margin-top: var(--fl-sp-3);
    font-size: var(--fl-texto-xs);
}

.fl-grafico-leyenda-item {
    display: inline-flex;
    align-items: center;
    gap: var(--fl-sp-1-5);
    color: var(--fl-texto-suave);
}

.fl-grafico-leyenda-color {
    width: 10px;
    height: 10px;
    border-radius: 2px;
    flex: none;
}

.fl-grafico-leyenda-item[data-fl-serie="0"] .fl-grafico-leyenda-color { background: var(--fl-acento-900); }
.fl-grafico-leyenda-item[data-fl-serie="1"] .fl-grafico-leyenda-color { background: var(--fl-acento-500); }
.fl-grafico-leyenda-item[data-fl-serie="2"] .fl-grafico-leyenda-color { background: var(--fl-acento-700); }
.fl-grafico-leyenda-item[data-fl-serie="3"] .fl-grafico-leyenda-color { background: var(--fl-acento-300); }
.fl-grafico-leyenda-item[data-fl-serie="4"] .fl-grafico-leyenda-color { background: var(--fl-acento-800); }
.fl-grafico-leyenda-item[data-fl-serie="5"] .fl-grafico-leyenda-color { background: var(--fl-acento-400); }
.fl-grafico-leyenda-item[data-fl-serie="6"] .fl-grafico-leyenda-color { background: var(--fl-acento-200); }

.fl-grafico-leyenda-valor {
    color: var(--fl-texto-fuerte);
    font-weight: var(--fl-peso-medio);
    font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------------------
   SPARKLINE — estilos para el trazo, el tamaño del contenedor está arriba
   -------------------------------------------------------------------------- */
.fl-grafico--sparkline .fl-grafico-linea {
    stroke-width: 1.5;
}

.fl-grafico--sparkline .fl-grafico-punto {
    display: none;
}

/* --------------------------------------------------------------------------
   Tooltip (opcional, via JS)
   -------------------------------------------------------------------------- */
.fl-grafico-tooltip {
    position: absolute;
    padding: var(--fl-sp-1-5) var(--fl-sp-2-5);
    background: var(--fl-superficie-invertida);
    color: var(--fl-texto-invertido);
    font-size: var(--fl-texto-xs);
    border-radius: var(--fl-r-md);
    pointer-events: none;
    opacity: 0;
    transition: opacity var(--fl-t-rapido) var(--fl-ease-salida);
    white-space: nowrap;
    z-index: var(--fl-z-tooltip);
    transform: translate(-50%, -100%) translateY(-8px);
}

.fl-grafico-tooltip[data-fl-visible="true"] {
    opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
    .fl-grafico-punto,
    .fl-grafico-barra,
    .fl-grafico-dona-segmento,
    .fl-grafico-treemap-celda,
    .fl-grafico-funnel-tramo { transition: none; }
}

/* ==========================================================================
   Variantes extendidas: radar, treemap, funnel
   ========================================================================== */

/* Radar — polígono de área + puntos en vértices */
.fl-grafico--radar { display: flex; justify-content: center; align-items: center; }
.fl-grafico--radar .fl-grafico-svg { max-width: 360px; }

.fl-grafico-radar-forma {
    transition: fill-opacity 180ms;
}
.fl-grafico-radar-forma:hover { fill-opacity: 0.4; }

/* Treemap — rectángulos coloreados proporcionales al valor */
.fl-grafico--treemap .fl-grafico-svg { max-height: 480px; }

.fl-grafico-treemap-celda {
    stroke: var(--fl-superficie);
    stroke-width: 2;
    transition: opacity 160ms, transform 160ms;
    cursor: pointer;
}
.fl-grafico-treemap-celda:hover {
    opacity: 0.85;
}

.fl-grafico-treemap-celda[data-fl-serie="0"] { fill: var(--fl-destaque-fondo); }
.fl-grafico-treemap-celda[data-fl-serie="1"] { fill: var(--fl-acento-700); }
.fl-grafico-treemap-celda[data-fl-serie="2"] { fill: var(--fl-acento-500); }
.fl-grafico-treemap-celda[data-fl-serie="3"] { fill: var(--fl-acento-900); }
.fl-grafico-treemap-celda[data-fl-serie="4"] { fill: var(--fl-acento-400); }
.fl-grafico-treemap-celda[data-fl-serie="5"] { fill: var(--fl-acento-800); }
.fl-grafico-treemap-celda[data-fl-serie="6"] { fill: var(--fl-acento-300); }

.fl-grafico-treemap-label,
.fl-grafico-treemap-valor {
    pointer-events: none;
}

/* Funnel — trapezoides apilados, mismos colores que treemap */
.fl-grafico--funnel .fl-grafico-svg { max-height: 420px; }

.fl-grafico-funnel-tramo {
    stroke: var(--fl-superficie);
    stroke-width: 2;
    transition: opacity 160ms;
    cursor: pointer;
}
.fl-grafico-funnel-tramo:hover { opacity: 0.85; }

.fl-grafico-funnel-tramo[data-fl-serie="0"] { fill: var(--fl-destaque-fondo); }
.fl-grafico-funnel-tramo[data-fl-serie="1"] { fill: var(--fl-acento-900); }
.fl-grafico-funnel-tramo[data-fl-serie="2"] { fill: var(--fl-acento-800); }
.fl-grafico-funnel-tramo[data-fl-serie="3"] { fill: var(--fl-acento-700); }
.fl-grafico-funnel-tramo[data-fl-serie="4"] { fill: var(--fl-acento-600); }
.fl-grafico-funnel-tramo[data-fl-serie="5"] { fill: var(--fl-acento-500); }
.fl-grafico-funnel-tramo[data-fl-serie="6"] { fill: var(--fl-acento-400); }

.fl-grafico-funnel-label,
.fl-grafico-funnel-valor {
    pointer-events: none;
}

/* ==========================================================================
   Variantes extendidas (fase 8): gauge, stacked, combo, candlestick
   ========================================================================== */

/* Gauge */
.fl-grafico--gauge { display: flex; justify-content: center; align-items: center; }
.fl-grafico--gauge .fl-grafico-svg { max-width: 320px; }
.fl-grafico-gauge-valor { transition: stroke-dashoffset 600ms ease-out; }

/* Stacked — colores por serie */
.fl-grafico--stacked .fl-grafico-barra[data-fl-serie="0"] { fill: var(--fl-destaque-fondo); }
.fl-grafico--stacked .fl-grafico-barra[data-fl-serie="1"] { fill: color-mix(in srgb, var(--fl-destaque-fondo) 70%, white); }
.fl-grafico--stacked .fl-grafico-barra[data-fl-serie="2"] { fill: var(--fl-acento-700); }
.fl-grafico--stacked .fl-grafico-barra[data-fl-serie="3"] { fill: var(--fl-acento-500); }
.fl-grafico--stacked .fl-grafico-barra[data-fl-serie="4"] { fill: var(--fl-acento-300); }
.fl-grafico--stacked .fl-grafico-barra[data-fl-serie="5"] { fill: var(--fl-acento-800); }
.fl-grafico--stacked .fl-grafico-barra[data-fl-serie="6"] { fill: var(--fl-acento-400); }

/* Combo: barras + línea */
.fl-grafico--combo .fl-grafico-barra { fill: var(--fl-destaque-fondo); opacity: 0.8; }
.fl-grafico--combo .fl-grafico-linea { stroke: var(--fl-acento-900); stroke-width: 2.5; fill: none; }

/* Candlestick */
.fl-grafico--candlestick .fl-grafico-svg rect { transition: opacity 120ms; cursor: pointer; }
.fl-grafico--candlestick .fl-grafico-svg rect:hover { opacity: 1 !important; }


/* ===== resources/css/componentes/header.css ===== */
/* ==========================================================================
   Flora · Header de página
   Sección superior de contenido: breadcrumbs + título + subtítulo + acciones.
   ========================================================================== */

.fl-header-pagina {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-3);
    padding-bottom: var(--fl-sp-5);
    margin-bottom: var(--fl-sp-6);
    border-bottom: 1px solid var(--fl-borde-sutil);
}

.fl-header-pagina--sin-borde {
    border-bottom: 0;
    padding-bottom: 0;
}

.fl-header-pagina--compacto {
    gap: var(--fl-sp-3);       /* igualado al padding-bottom → título
                                  queda vertical entre breadcrumb y borde */
    padding-bottom: var(--fl-sp-3);
    margin-bottom: var(--fl-sp-4);
}

/* Compacto con un solo título (sin subtítulo/meta) suele ser más bajo que
   las acciones; align-items:center centra el texto contra los botones
   para que no quede pegado arriba. */
.fl-header-pagina--compacto .fl-header-pagina-principal {
    align-items: center;
}

/* Fila superior: GRILLA de 3 columnas.
     · Col 1 (1fr): botón "Volver", anclado al BORDE IZQUIERDO de la hoja.
     · Col 2 (auto): breadcrumb, CENTRADO en la hoja.
     · Col 3 (1fr): reservada (vacía por ahora — futuras acciones globales).
   Las dos columnas 1fr se balancean entre sí, lo que garantiza que la col 2
   queda en el centro real de la hoja, no pegada al botón. */
.fl-header-pagina-fila-superior {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;   /* 3 tercios EXACTOS — garantizamos separación visual */
    align-items: center;
    align-self: stretch;                  /* anti-colapso si el padre flex column no estira */
    gap: var(--fl-sp-3);
    margin: 0 0 var(--fl-sp-2) 0;
    padding: 0;
    width: 100%;
    min-height: 32px;                     /* eje vertical compartido */
    box-sizing: border-box;
}
.fl-header-pagina-fila-superior > .fl-volver {
    grid-column: 1 / 2;
    justify-self: start;
    align-self: center;             /* explícito por si algún reset del browser interfiere */
}
.fl-header-pagina-fila-superior > nav {
    grid-column: 2 / 3;
    justify-self: center;
    align-self: center;
    /* Forzamos al <nav> a comportarse como una caja flex de altura fija — así la
       altura del nav coincide con la del botón (32px) y align-items del grid
       los centra contra la misma línea media. */
    display: flex;
    align-items: center;
    height: 32px;
    margin: 0;
    padding: 0;
    min-width: 0;
}
/* Tercio derecho queda implícitamente vacío (col 3) — reservado para futuras
   acciones globales del header (notif, atajos, etc.). */
.fl-header-pagina-fila-superior .fl-breadcrumb {
    margin: 0;
    padding: 0;
}
/* Mobile: misma grilla 3 col que desktop pero col 1 = auto (volver natural),
   col 2 = 1fr centrado (migas), col 3 implícita vacía.
   El overflow-hidden va en el nav, NO en el contenedor, para no cortar el
   transform translateY del botón Volver. */
@media (max-width: 720px) {
    .fl-header-pagina-fila-superior {
        grid-template-columns: auto 1fr;
    }
    .fl-header-pagina-fila-superior > .fl-volver {
        grid-column: 1;
        flex-shrink: 0;
    }
    .fl-header-pagina-fila-superior > nav {
        grid-column: 2;
        justify-content: center;
        min-width: 0;
        overflow: hidden;
    }
    .fl-header-pagina-fila-superior > nav .fl-breadcrumb {
        justify-content: center;
        width: 100%;
        flex-wrap: nowrap;
        overflow: hidden;
    }
}

/* Botón "Volver" — copia EXACTA de la geometría de los pills del breadcrumb
   (.fl-breadcrumb--pasos .fl-breadcrumb-enlace) → centrado vertical garantizado.
   Único cambio: colores de paleta y border-radius redondeado. */
.fl-volver {
    box-sizing: border-box;
    flex-shrink: 0;
    margin: 0;
    height: 32px;
    line-height: 32px;              /* MATCH breadcrumb pill */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--fl-sp-1-5);          /* MATCH breadcrumb pill */
    padding: 0 var(--fl-sp-4);      /* MATCH breadcrumb pill */
    background: transparent;
    border: 1px solid color-mix(in srgb, var(--fl-acento) 30%, transparent);
    color: var(--fl-acento);
    font: inherit;                  /* hereda TODA la tipografía del documento (size/weight/family) */
    font-size: var(--fl-texto-sm);  /* override del size para igualar el pill */
    cursor: pointer;
    border-radius: var(--fl-r-md);
    transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease, transform 0.12s ease;
    /* Compensación visual: en el render real el botón cae más abajo que los
       pills del breadcrumb por diferencias de baseline entre <button> y <a>.
       translateY no afecta layout — sólo posición visual. */
    transform: translateY(-5px);
}
.fl-volver:hover {
    background: color-mix(in srgb, var(--fl-acento) 12%, transparent);
    border-color: var(--fl-acento);
    color: var(--fl-acento-fuerte, var(--fl-acento));
    /* mantenemos los -5px de baseline + 2px hacia la izquierda como microefecto "atrás" */
    transform: translate(-2px, -5px);
}
.fl-volver:focus-visible {
    outline: 2px solid var(--fl-acento);
    outline-offset: 2px;
}
/* El ícono se renderiza como <span class="fl-icono"><svg/></span>.
   Estilizar el span (no el svg directo) es lo que hace el breadcrumb pill,
   replicamos exactamente para que la altura/posición óptica matcheen. */
.fl-volver .fl-icono {
    width: 14px;
    height: 14px;
    flex: none;
    vertical-align: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.fl-volver .fl-icono svg {
    width: 100%;
    height: 100%;
    display: block;
}
@media (max-width: 600px) {
    .fl-volver-texto { display: none; }
    .fl-volver { padding: 0 10px; }
}

/* Fila principal: título + acciones */
.fl-header-pagina-principal {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--fl-sp-4);
    flex-wrap: wrap;
}

/* Ícono grande de sección — opcional, a la izquierda del título.
   Cuadrado con bg suave del acento, ícono grande adentro. Da identidad
   visual inmediata a cada sección sin ser invasivo. */
.fl-header-pagina-icono {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    border-radius: var(--fl-r-md);
    background: color-mix(in srgb, var(--fl-acento) 12%, transparent);
    color: var(--fl-acento-texto);
}
.fl-header-pagina-icono .fl-icono {
    width: 32px;
    height: 32px;
}
.fl-header-pagina--compacto .fl-header-pagina-icono {
    width: 44px;
    height: 44px;
}
.fl-header-pagina--compacto .fl-header-pagina-icono .fl-icono {
    width: 24px;
    height: 24px;
}
.fl-header-pagina--grande .fl-header-pagina-icono {
    width: 72px;
    height: 72px;
}
.fl-header-pagina--grande .fl-header-pagina-icono .fl-icono {
    width: 40px;
    height: 40px;
}
@media (max-width: 640px) {
    .fl-header-pagina-icono {
        width: 44px;
        height: 44px;
    }
    .fl-header-pagina-icono .fl-icono {
        width: 24px;
        height: 24px;
    }
}

.fl-header-pagina-texto {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-1);
    min-width: 0;
    flex: 1;
}

.fl-header-pagina-titulo {
    font-size: var(--fl-texto-2xl);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-fuerte);
    line-height: var(--fl-lh-compacta);
    letter-spacing: var(--fl-ls-compacto);
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
    margin: 0;
}

.fl-header-pagina-titulo .fl-badge,
.fl-header-pagina-titulo .fl-chip {
    margin-left: var(--fl-sp-1);
    flex: none;
}

.fl-header-pagina-subtitulo {
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto-suave);
    line-height: var(--fl-lh-ajustada);
    max-width: 720px;
}

.fl-header-pagina-meta {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-3);
    margin-top: var(--fl-sp-1);
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-tenue);
    flex-wrap: wrap;
}

.fl-header-pagina-meta-item {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

.fl-header-pagina-meta-item .fl-icono {
    width: 12px;
    height: 12px;
}

.fl-header-pagina-acciones {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
    flex: none;
    flex-wrap: wrap;
}

.fl-header-pagina--compacto .fl-header-pagina-titulo {
    font-size: var(--fl-texto-xl);
}

/* Tamaño grande — hero style */
.fl-header-pagina--grande .fl-header-pagina-titulo {
    font-size: var(--fl-texto-3xl);
}

.fl-header-pagina--grande .fl-header-pagina-subtitulo {
    font-size: var(--fl-texto-base);
}

/* --------------------------------------------------------------------------
   Variante destaque — hero con gradiente diagonal de la paleta.
   Texto blanco, ideal para landing de módulos o páginas CRUD premium.
   Inspirado en flora vieja (coros-header de resonum).

   IMPORTANTE: NO redefino --fl-texto-* globalmente acá porque eso rompe
   botones secundarios descendientes (que usan --fl-superficie + --fl-texto-fuerte,
   quedaban blanco sobre blanco). En su lugar, estilo elementos específicos.
   -------------------------------------------------------------------------- */
.fl-header-pagina--destaque {
    background: var(--fl-destaque-gradiente);
    color: var(--fl-destaque-texto);
    padding: var(--fl-sp-6) var(--fl-sp-6);
    border-radius: var(--fl-r-xl);
    border-bottom: 0;
    margin-bottom: var(--fl-sp-6);
    position: relative;
    overflow: hidden;
}

/* Highlight superior tipo "vidrio" que atraviesa el hero */
.fl-header-pagina--destaque::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 1px;
    background: linear-gradient(
        to right,
        transparent 10%,
        rgb(255 255 255 / 0.22),
        transparent 90%
    );
    pointer-events: none;
}

/* Textos propios del header — siempre blancos */
.fl-header-pagina--destaque .fl-header-pagina-titulo,
.fl-header-pagina--destaque .fl-header-pagina-subtitulo,
.fl-header-pagina--destaque .fl-header-pagina-meta {
    color: var(--fl-destaque-texto);
}

.fl-header-pagina--destaque .fl-header-pagina-subtitulo,
.fl-header-pagina--destaque .fl-header-pagina-meta {
    opacity: 0.85;
}

/* Botones descendientes en versión "on-dark" — legibles sobre el fondo
   oscuro del hero. Usan opacidad del texto blanco en vez de superficies
   neutras que se blanquearían con el destaque. */
.fl-header-pagina--destaque .fl-boton--secundario {
    background: color-mix(in srgb, var(--fl-destaque-texto) 12%, transparent);
    color: var(--fl-destaque-texto);
    border-color: color-mix(in srgb, var(--fl-destaque-texto) 32%, transparent);
}

.fl-header-pagina--destaque .fl-boton--secundario:hover:not(:disabled) {
    background: color-mix(in srgb, var(--fl-destaque-texto) 20%, transparent);
    border-color: color-mix(in srgb, var(--fl-destaque-texto) 48%, transparent);
    color: var(--fl-destaque-texto);
}

.fl-header-pagina--destaque .fl-boton--fantasma {
    color: var(--fl-destaque-texto);
}

.fl-header-pagina--destaque .fl-boton--fantasma:hover:not(:disabled) {
    background: color-mix(in srgb, var(--fl-destaque-texto) 14%, transparent);
    color: var(--fl-destaque-texto);
}

.fl-header-pagina--destaque .fl-boton--enlace {
    color: var(--fl-destaque-texto);
}

.fl-header-pagina--destaque .fl-boton--enlace:hover:not(:disabled) {
    color: var(--fl-destaque-texto);
    opacity: 0.85;
}

/* Responsive — en mobile, el título y acciones se apilan verticalmente.
   El título reduce su tamaño para entrar cómodamente en <= 640px. */
@media (max-width: 640px) {
    .fl-header-pagina-principal { gap: var(--fl-sp-2); }
    .fl-header-pagina-acciones { width: 100%; }
    .fl-header-pagina-titulo { font-size: var(--fl-texto-xl); }
    .fl-header-pagina--grande .fl-header-pagina-titulo { font-size: var(--fl-texto-2xl); }
    .fl-header-pagina--destaque { padding: var(--fl-sp-4); }
}


/* ===== resources/css/componentes/icono.css ===== */
/* ==========================================================================
   Flora · Ícono
   Wrapper para SVGs inline. Hereda currentColor. Tamaños semánticos.
   Los SVGs vienen de Lucide (licencia ISC, stroke 2px, viewBox 24×24).
   ========================================================================== */

.fl-icono {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1em;
    height: 1em;
    flex: none;
    color: inherit;
    vertical-align: -0.125em; /* alinea con texto */
}

.fl-icono svg {
    width: 100%;
    height: 100%;
    display: block;
    stroke: currentColor;
    fill: none;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* Tamaños específicos cuando no se quiere usar 1em */
.fl-icono--xs { width: 12px; height: 12px; }
.fl-icono--sm { width: 14px; height: 14px; }
.fl-icono--md { width: 16px; height: 16px; }
.fl-icono--lg { width: 20px; height: 20px; }
.fl-icono--xl { width: 24px; height: 24px; }
.fl-icono--2xl { width: 32px; height: 32px; }
.fl-icono--3xl { width: 48px; height: 48px; }

/* Stroke más fino para íconos grandes */
.fl-icono--fino svg { stroke-width: 1.5; }
.fl-icono--grueso svg { stroke-width: 2.5; }


/* ===== resources/css/componentes/imprimir.css ===== */
/* ==========================================================================
   Flora · Imprimir (print stylesheets + templates para factura/etiqueta/ticket)
   Uso: agregar clase fl-imprimir--factura / --etiqueta / --ticket al <body>
   o al wrapper para aplicar el formato. También hay utilidades u-print-* para
   ocultar/mostrar elementos sólo en print.
   ========================================================================== */

/* ---------- Utilidades print ---------- */
@media screen {
    .u-solo-print { display: none !important; }
}

@media print {
    .u-no-print,
    .u-no-print * { display: none !important; }

    .u-page-break-antes { page-break-before: always; break-before: page; }
    .u-page-break-despues { page-break-after: always; break-after: page; }
    .u-page-break-evitar { page-break-inside: avoid; break-inside: avoid; }

    /* Navigation siempre oculta en print */
    .fl-navbar, .fl-sidebar, .fl-toolbar, .fl-accion-flotante,
    .fl-volver-arriba, .fl-barra-carga, .fl-toast-contenedor,
    .fl-cajon, .fl-cajon-fondo, .fl-paleta-fondo, .fl-paleta,
    .fl-tour-overlay, .fl-tour-panel {
        display: none !important;
    }

    /* Reset colores y sombras para tinta */
    body {
        background: white !important;
        color: black !important;
        font-size: 11pt;
        line-height: 1.4;
    }

    a[href]::after { content: " (" attr(href) ")"; font-size: 0.85em; color: #666; }
    a[href^="#"]::after,
    a[href^="javascript:"]::after { content: ""; }

    .fl-tarjeta, .fl-alerta, .fl-callout {
        box-shadow: none !important;
        border: 1px solid #ccc !important;
        page-break-inside: avoid;
    }

    .fl-tabla-datos {
        font-size: 10pt;
    }
    .fl-tabla-datos thead { display: table-header-group; }
    .fl-tabla-datos tr { page-break-inside: avoid; }

    /* Fijar tamaño de página */
    @page {
        margin: 18mm 14mm;
    }
    @page :first { margin-top: 12mm; }
}

/* ---------- Templates específicos ---------- */

/* FACTURA — A4, cabecera + items + totales */
.fl-imprimir-factura {
    max-width: 210mm;
    margin: 0 auto;
    padding: 18mm 14mm;
    font-family: var(--fl-fuente-sans, "IBM Plex Sans", sans-serif);
    color: #1a1a1a;
    background: white;
}

.fl-imprimir-factura-cabecera {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 24mm;
    padding-bottom: 6mm;
    border-bottom: 1.5px solid #000;
    margin-bottom: 8mm;
}

.fl-imprimir-factura-emisor-nombre {
    font-size: 16pt;
    font-weight: 700;
    letter-spacing: -0.01em;
}

.fl-imprimir-factura-emisor-detalle {
    font-size: 9pt;
    color: #4a4a4a;
    line-height: 1.5;
    margin-top: 2mm;
}

.fl-imprimir-factura-meta {
    text-align: right;
    font-size: 9pt;
}

.fl-imprimir-factura-tipo {
    font-size: 22pt;
    font-weight: 900;
    border: 2px solid #000;
    padding: 2mm 6mm;
    display: inline-block;
    letter-spacing: 0.05em;
}

.fl-imprimir-factura-numero {
    font-size: 11pt;
    font-weight: 700;
    margin-top: 2mm;
    font-variant-numeric: tabular-nums;
}

.fl-imprimir-factura-fecha {
    color: #555;
    font-size: 9pt;
    margin-top: 1mm;
}

.fl-imprimir-factura-cliente {
    margin-bottom: 6mm;
    padding: 3mm 4mm;
    background: #f5f5f5;
    border-radius: 2mm;
    font-size: 9.5pt;
}

.fl-imprimir-factura-cliente-etiqueta {
    font-size: 8pt;
    color: #666;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-bottom: 1mm;
}

.fl-imprimir-factura-items {
    width: 100%;
    border-collapse: collapse;
    font-size: 9.5pt;
    margin-bottom: 4mm;
}

.fl-imprimir-factura-items th {
    background: #111;
    color: white;
    text-align: left;
    padding: 2.5mm 3mm;
    font-weight: 600;
    font-size: 9pt;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.fl-imprimir-factura-items td {
    padding: 2.5mm 3mm;
    border-bottom: 1px solid #ddd;
    vertical-align: top;
}

.fl-imprimir-factura-items .numero { text-align: right; font-variant-numeric: tabular-nums; }

.fl-imprimir-factura-totales {
    display: flex;
    justify-content: flex-end;
    margin-top: 4mm;
}

.fl-imprimir-factura-totales-tabla {
    min-width: 70mm;
    border-collapse: collapse;
    font-size: 10pt;
}

.fl-imprimir-factura-totales-tabla td {
    padding: 1.5mm 3mm;
    font-variant-numeric: tabular-nums;
}

.fl-imprimir-factura-totales-tabla .etiqueta { color: #555; }
.fl-imprimir-factura-totales-tabla .valor { text-align: right; font-weight: 600; }

.fl-imprimir-factura-total-final {
    border-top: 1.5px solid #000;
    font-size: 12pt !important;
    font-weight: 800 !important;
    padding-top: 3mm !important;
}

.fl-imprimir-factura-pie {
    margin-top: 10mm;
    padding-top: 4mm;
    border-top: 1px solid #ccc;
    font-size: 8.5pt;
    color: #666;
    text-align: center;
    line-height: 1.5;
}

/* ETIQUETA — formatos comunes */
.fl-imprimir-etiqueta {
    width: 62mm;
    height: 29mm;
    padding: 3mm;
    font-family: var(--fl-fuente-sans, sans-serif);
    font-size: 8pt;
    background: white;
    color: #000;
    border: 0.5px dashed #aaa; /* visible on screen, removes in print */
    page-break-inside: avoid;
}

.fl-imprimir-etiqueta-titulo {
    font-weight: 700;
    font-size: 10pt;
    margin-bottom: 1mm;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.fl-imprimir-etiqueta-sku {
    font-family: monospace;
    font-size: 9pt;
    letter-spacing: 0.02em;
}

.fl-imprimir-etiqueta-precio {
    font-size: 12pt;
    font-weight: 700;
    margin-top: 1mm;
}

.fl-imprimir-etiqueta-grilla {
    display: grid;
    grid-template-columns: repeat(3, 62mm);
    grid-auto-rows: 29mm;
    gap: 2mm;
    padding: 5mm;
}

@media print {
    .fl-imprimir-etiqueta { border: 0 !important; }
}

/* TICKET — formato de 80mm para impresora térmica */
.fl-imprimir-ticket {
    width: 72mm;
    padding: 3mm;
    font-family: var(--fl-fuente-mono, "IBM Plex Mono", monospace);
    font-size: 9pt;
    line-height: 1.3;
    color: #000;
    background: white;
    margin: 0 auto;
    border: 1px dashed #ccc;
}

@media print {
    .fl-imprimir-ticket { border: 0; }
    @page { margin: 0; size: 80mm auto; }
}

.fl-imprimir-ticket-cabecera {
    text-align: center;
    padding-bottom: 2mm;
    border-bottom: 1px dashed #888;
    margin-bottom: 2mm;
}
.fl-imprimir-ticket-titulo { font-size: 12pt; font-weight: 700; }
.fl-imprimir-ticket-subtitulo { font-size: 8.5pt; color: #555; margin-top: 1mm; }

.fl-imprimir-ticket-item {
    display: flex;
    justify-content: space-between;
    gap: 4mm;
    padding: 0.5mm 0;
}
.fl-imprimir-ticket-item-nombre { flex: 1; }
.fl-imprimir-ticket-item-precio { font-variant-numeric: tabular-nums; }

.fl-imprimir-ticket-total {
    border-top: 1px dashed #888;
    border-bottom: 1px dashed #888;
    padding: 2mm 0;
    margin-top: 2mm;
    display: flex;
    justify-content: space-between;
    font-size: 11pt;
    font-weight: 700;
}

.fl-imprimir-ticket-pie {
    text-align: center;
    font-size: 8pt;
    margin-top: 3mm;
    color: #555;
    line-height: 1.5;
}


/* ===== resources/css/componentes/inbox.css ===== */
/* ==========================================================================
   Flora · Inbox (multi-cuenta)
   Cliente de email con sidebar + lista + detalle. Responsive: colapsa a
   una columna en mobile, navegable por estado (lista ↔ detalle).
   ========================================================================== */

.fl-inbox {
    display: grid;
    width: 100%;
    grid-template-columns: 360px 1fr;
    min-height: 540px;
    background: var(--fl-superficie);
    border: 1px solid var(--fl-borde);
    border-radius: var(--fl-r-lg);
    overflow: hidden;
}

.fl-inbox--ancho { grid-template-columns: 420px 1fr; }
.fl-inbox--tres-paneles { grid-template-columns: 240px 360px 1fr; }

/* Zona intermedia: el sidebar colapsa antes que el layout entero en laptops
   (el docs-sidebar ya consume 260px de ancho). */
@media (max-width: 1200px) {
    .fl-inbox--tres-paneles { grid-template-columns: 300px 1fr; }
    .fl-inbox--tres-paneles .fl-inbox-sidebar { display: none; }
}

@media (max-width: 900px) {
    .fl-inbox,
    .fl-inbox--ancho,
    .fl-inbox--tres-paneles {
        grid-template-columns: 1fr;
    }
    .fl-inbox[data-fl-vista="detalle"] .fl-inbox-lista { display: none; }
    .fl-inbox:not([data-fl-vista="detalle"]) .fl-inbox-detalle { display: none; }
}

/* --------------------------------------------------------------------------
   Sidebar — navegación principal + cuentas
   -------------------------------------------------------------------------- */
.fl-inbox-sidebar {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-1);
    padding: var(--fl-sp-3);
    background: var(--fl-fondo-sutil);
    border-right: 1px solid var(--fl-borde-sutil);
    overflow-y: auto;
}

/* Botón compose prominente arriba */
.fl-inbox-compose {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--fl-sp-2);
    width: 100%;
    padding: var(--fl-sp-2-5) var(--fl-sp-3);
    margin-bottom: var(--fl-sp-3);
    background: var(--fl-acento);
    color: var(--fl-acento-texto-sobre);
    border: 0;
    border-radius: var(--fl-r-md);
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-semibold);
    cursor: pointer;
    box-shadow: 0 1px 2px rgba(0 0 0 / .05),
                0 6px 16px -6px color-mix(in srgb, var(--fl-acento) 60%, transparent);
    transition: background var(--fl-t-rapido), transform var(--fl-t-rapido), box-shadow var(--fl-t-rapido);
}

.fl-inbox-compose:hover {
    background: var(--fl-acento-hover);
    transform: translateY(-1px);
    box-shadow: 0 2px 4px rgba(0 0 0 / .06),
                0 10px 24px -8px color-mix(in srgb, var(--fl-acento) 65%, transparent);
}

.fl-inbox-compose:active { transform: translateY(0); }
.fl-inbox-compose .fl-icono { width: 16px; height: 16px; }

/* Título de grupo en sidebar */
.fl-inbox-sidebar-titulo {
    font-size: var(--fl-texto-2xs);
    font-weight: var(--fl-peso-semibold);
    text-transform: uppercase;
    letter-spacing: var(--fl-ls-mayus);
    color: var(--fl-texto-tenue);
    padding: var(--fl-sp-1) var(--fl-sp-2);
    margin-top: var(--fl-sp-3);
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.fl-inbox-sidebar-titulo:first-child { margin-top: 0; }

/* Item genérico del sidebar (Todas, Destacados, Enviados, etc.) */
.fl-inbox-sidebar-item {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
    padding: var(--fl-sp-1-5) var(--fl-sp-2);
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto-suave);
    border-radius: var(--fl-r-md);
    cursor: pointer;
    text-decoration: none;
    transition: background var(--fl-t-rapido), color var(--fl-t-rapido);
}

.fl-inbox-sidebar-item:hover {
    background: var(--fl-superficie-hover);
    color: var(--fl-texto-fuerte);
}

.fl-inbox-sidebar-item .fl-icono {
    width: 16px;
    height: 16px;
    flex: none;
    color: var(--fl-texto-tenue);
}

.fl-inbox-sidebar-item:hover .fl-icono { color: var(--fl-texto-suave); }

.fl-inbox-sidebar-item-conteo {
    margin-left: auto;
    font-size: var(--fl-texto-2xs);
    color: var(--fl-texto-tenue);
    font-variant-numeric: tabular-nums;
    font-weight: var(--fl-peso-medio);
}

.fl-inbox-sidebar-item--activo {
    background: var(--fl-acento-suave);
    color: var(--fl-acento-texto);
    font-weight: var(--fl-peso-semibold);
}

.fl-inbox-sidebar-item--activo .fl-icono,
.fl-inbox-sidebar-item--activo .fl-inbox-sidebar-item-conteo {
    color: var(--fl-acento-texto);
    opacity: 1;
}

/* --------------------------------------------------------------------------
   Cuentas conectadas — cada cuenta = fila compacta con avatar + color
   -------------------------------------------------------------------------- */
.fl-inbox-cuenta {
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.fl-inbox-cuenta-header {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
    padding: var(--fl-sp-1-5) var(--fl-sp-2);
    border-radius: var(--fl-r-md);
    cursor: pointer;
    transition: background var(--fl-t-rapido);
    position: relative;
}

.fl-inbox-cuenta-header:hover { background: var(--fl-superficie-hover); }

.fl-inbox-cuenta-header[aria-current="true"] {
    background: color-mix(in srgb, var(--_color, var(--fl-acento)) 14%, transparent);
}

.fl-inbox-cuenta-header[aria-current="true"]::before {
    content: "";
    position: absolute;
    left: 0;
    top: 6px;
    bottom: 6px;
    width: 3px;
    border-radius: 0 var(--fl-r-full) var(--fl-r-full) 0;
    background: var(--_color, var(--fl-acento));
}

.fl-inbox-cuenta-avatar {
    flex: none;
    width: 24px;
    height: 24px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--_color, var(--fl-acento));
    color: white;
    border-radius: var(--fl-r-md);
    font-size: 11px;
    font-weight: var(--fl-peso-semibold);
    text-transform: uppercase;
    letter-spacing: 0;
    box-shadow: 0 1px 3px -1px color-mix(in srgb, var(--_color, var(--fl-acento)) 55%, transparent);
}

.fl-inbox-cuenta-info {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.fl-inbox-cuenta-nombre {
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-fuerte);
    line-height: 1.2;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.fl-inbox-cuenta-email {
    font-size: 10px;
    color: var(--fl-texto-tenue);
    line-height: 1.3;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.fl-inbox-cuenta-conteo {
    flex: none;
    min-width: 18px;
    padding: 0 6px;
    height: 18px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--_color, var(--fl-acento));
    color: white;
    font-size: 10px;
    font-weight: var(--fl-peso-semibold);
    border-radius: var(--fl-r-full);
    text-align: center;
    font-variant-numeric: tabular-nums;
    line-height: 1;
}

.fl-inbox-cuenta-conteo:empty,
.fl-inbox-cuenta-conteo[data-conteo="0"] { display: none; }

/* Chevron para expandir/colapsar carpetas */
.fl-inbox-cuenta-chevron {
    flex: none;
    width: 14px;
    height: 14px;
    color: var(--fl-texto-tenue);
    transition: transform 200ms var(--fl-ease-resorte);
}

.fl-inbox-cuenta[data-fl-colapsada="true"] .fl-inbox-cuenta-chevron {
    transform: rotate(-90deg);
}

.fl-inbox-cuenta-carpetas {
    display: flex;
    flex-direction: column;
    gap: 1px;
    padding: 2px 0 4px calc(var(--fl-sp-2) + 24px + var(--fl-sp-2));
    overflow: hidden;
    transition: max-height 260ms var(--fl-ease-salida);
}

.fl-inbox-cuenta[data-fl-colapsada="true"] .fl-inbox-cuenta-carpetas {
    max-height: 0;
    padding-top: 0;
    padding-bottom: 0;
}

/* Subitem carpeta compacto */
.fl-inbox-cuenta-carpeta {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-1-5);
    padding: 4px var(--fl-sp-2);
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-suave);
    border-radius: var(--fl-r-sm);
    cursor: pointer;
    text-decoration: none;
    transition: background var(--fl-t-rapido), color var(--fl-t-rapido);
}

.fl-inbox-cuenta-carpeta:hover {
    background: var(--fl-superficie-hover);
    color: var(--fl-texto-fuerte);
}

.fl-inbox-cuenta-carpeta--activa {
    background: color-mix(in srgb, var(--_color, var(--fl-acento)) 15%, transparent);
    color: var(--fl-texto-fuerte);
    font-weight: var(--fl-peso-medio);
}

.fl-inbox-cuenta-carpeta .fl-icono {
    width: 13px;
    height: 13px;
    color: var(--fl-texto-tenue);
}

.fl-inbox-cuenta-carpeta-conteo {
    margin-left: auto;
    font-size: 10px;
    color: var(--fl-texto-tenue);
    font-variant-numeric: tabular-nums;
}

/* Botón para agregar cuenta */
.fl-inbox-agregar-cuenta {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--fl-sp-1-5);
    padding: var(--fl-sp-2);
    margin-top: var(--fl-sp-2);
    background: transparent;
    border: 1px dashed var(--fl-borde);
    border-radius: var(--fl-r-md);
    color: var(--fl-texto-suave);
    cursor: pointer;
    font-size: var(--fl-texto-xs);
    font-weight: var(--fl-peso-medio);
    transition: background var(--fl-t-rapido), border-color var(--fl-t-rapido), color var(--fl-t-rapido);
}

.fl-inbox-agregar-cuenta:hover {
    background: var(--fl-acento-suave);
    border-color: var(--fl-acento);
    border-style: solid;
    color: var(--fl-acento-texto);
}

.fl-inbox-agregar-cuenta .fl-icono { width: 14px; height: 14px; }

/* Footer del sidebar: almacenamiento / perfil */
.fl-inbox-sidebar-footer {
    margin-top: auto;
    padding-top: var(--fl-sp-3);
    border-top: 1px solid var(--fl-borde-sutil);
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-1);
}

.fl-inbox-storage-barra {
    height: 4px;
    background: var(--fl-borde-sutil);
    border-radius: var(--fl-r-full);
    overflow: hidden;
}

.fl-inbox-storage-barra-fill {
    display: block;
    height: 100%;
    background: var(--fl-acento);
    border-radius: var(--fl-r-full);
}

.fl-inbox-storage-texto {
    font-size: 10px;
    color: var(--fl-texto-tenue);
    padding: 0 var(--fl-sp-1);
    display: flex;
    justify-content: space-between;
}

/* --------------------------------------------------------------------------
   Lista de mensajes
   -------------------------------------------------------------------------- */
.fl-inbox-lista {
    display: flex;
    flex-direction: column;
    border-right: 1px solid var(--fl-borde-sutil);
    min-height: 0;
    background: var(--fl-superficie);
}

.fl-inbox-lista-cabecera {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--fl-sp-2);
    padding: var(--fl-sp-3) var(--fl-sp-3) var(--fl-sp-2);
    flex: none;
}

.fl-inbox-lista-titulo {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.fl-inbox-lista-titulo-principal {
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-fuerte);
    font-size: var(--fl-texto-base);
    letter-spacing: var(--fl-ls-compacto);
    display: inline-flex;
    align-items: center;
    gap: var(--fl-sp-1-5);
}

.fl-inbox-lista-titulo-sub {
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-tenue);
    font-variant-numeric: tabular-nums;
}

.fl-inbox-lista-acciones {
    display: inline-flex;
    gap: 2px;
    color: var(--fl-texto-suave);
}

/* Tabs de filtro dentro de la lista (Todos / No leídos / Destacados) */
.fl-inbox-lista-filtros {
    display: inline-flex;
    gap: 2px;
    padding: 0 var(--fl-sp-3) var(--fl-sp-2);
    flex: none;
}

.fl-inbox-lista-filtro {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px var(--fl-sp-2);
    background: transparent;
    border: 0;
    border-radius: var(--fl-r-full);
    font-size: var(--fl-texto-xs);
    font-weight: var(--fl-peso-medio);
    color: var(--fl-texto-suave);
    cursor: pointer;
    transition: background var(--fl-t-rapido), color var(--fl-t-rapido);
}

.fl-inbox-lista-filtro:hover {
    background: var(--fl-superficie-hover);
    color: var(--fl-texto-fuerte);
}

.fl-inbox-lista-filtro--activo {
    background: var(--fl-acento);
    color: var(--fl-superficie);
}

.fl-inbox-lista-filtro-conteo {
    font-size: 10px;
    padding: 0 5px;
    background: color-mix(in srgb, currentColor 15%, transparent);
    border-radius: var(--fl-r-full);
    font-variant-numeric: tabular-nums;
    min-width: 14px;
    text-align: center;
}

/* Cuando el filtro está activo el texto es --fl-superficie (blanco), así que
   el color-mix da casi nada de contraste. Forzamos un fondo visible. */
.fl-inbox-lista-filtro--activo .fl-inbox-lista-filtro-conteo {
    background: color-mix(in srgb, var(--fl-superficie) 25%, transparent);
}

/* Buscador */
.fl-inbox-buscador {
    padding: 0 var(--fl-sp-3) var(--fl-sp-2);
    flex: none;
}

/* Barra de acciones bulk (aparece cuando hay items seleccionados o mostramos el select-all) */
.fl-inbox-lista-bulk {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
    padding: 6px var(--fl-sp-3);
    border-top: 1px solid var(--fl-borde-sutil);
    border-bottom: 1px solid var(--fl-borde-sutil);
    background: var(--fl-fondo-sutil);
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-suave);
    flex: none;
}

.fl-inbox-lista-bulk-check {
    width: 16px;
    height: 16px;
    border-radius: var(--fl-r-xs);
    border: 1.5px solid var(--fl-borde);
    background: var(--fl-superficie);
    display: inline-block;
    cursor: pointer;
}

.fl-inbox-lista-bulk-iconos {
    display: inline-flex;
    gap: 0;
    margin-left: auto;
    color: var(--fl-texto-tenue);
}

.fl-inbox-items {
    flex: 1;
    overflow-y: auto;
    padding: var(--fl-sp-1) 0;
    display: flex;
    flex-direction: column;
}

/* --------------------------------------------------------------------------
   Item (mensaje en la lista)
   Barra lateral de color = cuenta origen. Activo = fondo acento + borde más grueso.
   -------------------------------------------------------------------------- */
.fl-inbox-item {
    display: flex;
    gap: var(--fl-sp-2-5);
    padding: var(--fl-sp-2-5) var(--fl-sp-3);
    cursor: pointer;
    position: relative;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida);
    border-bottom: 1px solid var(--fl-borde-sutil);
}

.fl-inbox-item:last-child { border-bottom: 0; }
.fl-inbox-item:hover { background: var(--fl-superficie-hover); }

/* Barra lateral izquierda del item — color = cuenta */
.fl-inbox-item::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    background: var(--_color, transparent);
    transition: width var(--fl-t-rapido);
}

.fl-inbox-item--activo {
    background: var(--fl-acento-suave);
}

.fl-inbox-item--activo::before {
    width: 4px;
    background: var(--_color, var(--fl-acento));
}

.fl-inbox-item--no-leido .fl-inbox-item-asunto,
.fl-inbox-item--no-leido .fl-inbox-item-remitente {
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-fuerte);
}

.fl-inbox-item-avatar {
    flex: none;
    position: relative;
}

/* Punto no-leído como "dot" sobre el avatar (top-right) */
.fl-inbox-item--no-leido .fl-inbox-item-avatar::after {
    content: "";
    position: absolute;
    top: -2px;
    right: -2px;
    width: 10px;
    height: 10px;
    border-radius: var(--fl-r-full);
    background: var(--_color, var(--fl-acento));
    border: 2px solid var(--fl-superficie);
}

.fl-inbox-item:hover .fl-inbox-item--no-leido .fl-inbox-item-avatar::after,
.fl-inbox-item--activo.fl-inbox-item--no-leido .fl-inbox-item-avatar::after {
    border-color: var(--fl-superficie-hover);
}

.fl-inbox-item--activo.fl-inbox-item--no-leido .fl-inbox-item-avatar::after {
    border-color: var(--fl-acento-suave);
}

.fl-inbox-item-contenido {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.fl-inbox-item-fila {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--fl-sp-2);
}

.fl-inbox-item-remitente {
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto);
    font-weight: var(--fl-peso-medio);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    flex: 1;
    min-width: 0;
}

.fl-inbox-item-fecha {
    font-size: var(--fl-texto-2xs);
    color: var(--fl-texto-tenue);
    flex: none;
    font-variant-numeric: tabular-nums;
}

.fl-inbox-item--no-leido .fl-inbox-item-fecha {
    color: var(--_color, var(--fl-acento-texto));
    font-weight: var(--fl-peso-semibold);
}

.fl-inbox-item-asunto {
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    line-height: 1.3;
    display: flex;
    align-items: center;
    gap: 6px;
}

.fl-inbox-item-asunto-tag {
    display: inline-flex;
    padding: 1px 5px;
    font-size: 9px;
    font-weight: var(--fl-peso-semibold);
    text-transform: uppercase;
    letter-spacing: var(--fl-ls-mayus);
    color: var(--_tag-color, var(--fl-texto-tenue));
    background: color-mix(in srgb, var(--_tag-color, var(--fl-texto-tenue)) 14%, transparent);
    border-radius: var(--fl-r-xs);
    line-height: 1.4;
    flex: none;
}

.fl-inbox-item-preview {
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-suave);
    line-height: 1.4;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.fl-inbox-item-meta {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-1-5);
    margin-top: 4px;
    font-size: 10px;
    color: var(--fl-texto-tenue);
}

.fl-inbox-item-meta .fl-icono {
    width: 11px;
    height: 11px;
}

.fl-inbox-item-meta-cuenta {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    color: var(--_color, var(--fl-texto-tenue));
    font-weight: var(--fl-peso-medio);
}

.fl-inbox-item-meta-cuenta::before {
    content: "";
    width: 6px;
    height: 6px;
    background: var(--_color, var(--fl-acento));
    border-radius: var(--fl-r-full);
    flex: none;
}

.fl-inbox-item-meta-separador {
    width: 2px;
    height: 2px;
    background: var(--fl-texto-tenue);
    border-radius: var(--fl-r-full);
    opacity: 0.6;
}

.fl-inbox-item-etiquetas {
    display: flex;
    gap: 4px;
    margin-top: 4px;
    flex-wrap: wrap;
}

/* Acciones rápidas on-hover (star / archive / trash) */
.fl-inbox-item-acciones {
    position: absolute;
    right: var(--fl-sp-2);
    top: 50%;
    transform: translateY(-50%) translateX(4px);
    display: flex;
    gap: 2px;
    padding: 2px;
    background: var(--fl-superficie);
    border: 1px solid var(--fl-borde-sutil);
    border-radius: var(--fl-r-md);
    box-shadow: 0 4px 12px -4px rgb(0 0 0 / .08);
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--fl-t-rapido), transform var(--fl-t-rapido);
}

.fl-inbox-item:hover .fl-inbox-item-acciones {
    opacity: 1;
    transform: translateY(-50%) translateX(0);
    pointer-events: auto;
}

.fl-inbox-item-accion {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    background: transparent;
    border: 0;
    border-radius: var(--fl-r-sm);
    color: var(--fl-texto-suave);
    cursor: pointer;
    transition: background var(--fl-t-rapido), color var(--fl-t-rapido);
}

.fl-inbox-item-accion:hover {
    background: var(--fl-superficie-hover);
    color: var(--fl-texto-fuerte);
}

.fl-inbox-item-accion .fl-icono {
    width: 13px;
    height: 13px;
}

/* --------------------------------------------------------------------------
   Panel de detalle
   -------------------------------------------------------------------------- */
.fl-inbox-detalle {
    display: flex;
    flex-direction: column;
    min-width: 0;
    background: var(--fl-superficie);
}

.fl-inbox-detalle-cabecera {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-1);
    padding: var(--fl-sp-2) var(--fl-sp-3);
    border-bottom: 1px solid var(--fl-borde-sutil);
    flex: none;
}

.fl-inbox-detalle-cabecera-izq,
.fl-inbox-detalle-cabecera-der {
    display: inline-flex;
    gap: 2px;
}

.fl-inbox-detalle-cabecera-der { margin-left: auto; }

.fl-inbox-detalle-cabecera-sep {
    width: 1px;
    height: 18px;
    background: var(--fl-borde-sutil);
    margin: 0 var(--fl-sp-1);
    align-self: center;
}

.fl-inbox-detalle-asunto {
    padding: var(--fl-sp-4) var(--fl-sp-5) var(--fl-sp-2);
    font-size: var(--fl-texto-xl);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-fuerte);
    letter-spacing: var(--fl-ls-compacto);
    line-height: 1.3;
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
    flex-wrap: wrap;
}

.fl-inbox-detalle-asunto-count {
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-medio);
    color: var(--fl-texto-tenue);
    padding: 2px 8px;
    background: var(--fl-fondo-sutil);
    border: 1px solid var(--fl-borde-sutil);
    border-radius: var(--fl-r-full);
}

.fl-inbox-detalle-etiquetas {
    padding: 0 var(--fl-sp-5) var(--fl-sp-3);
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
}

.fl-inbox-detalle-etiqueta {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    font-size: 10px;
    font-weight: var(--fl-peso-semibold);
    text-transform: uppercase;
    letter-spacing: var(--fl-ls-mayus);
    color: var(--_tag-color, var(--fl-texto-suave));
    background: color-mix(in srgb, var(--_tag-color, var(--fl-texto-tenue)) 14%, transparent);
    border-radius: var(--fl-r-full);
    line-height: 1.5;
}

.fl-inbox-detalle-meta {
    display: flex;
    align-items: flex-start;
    gap: var(--fl-sp-3);
    padding: var(--fl-sp-3) var(--fl-sp-5);
    border-bottom: 1px solid var(--fl-borde-sutil);
    flex-wrap: wrap;
}

.fl-inbox-detalle-meta-remitente {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
    min-width: 0;
    flex: 1;
}

.fl-inbox-detalle-meta-info {
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
}

.fl-inbox-detalle-meta-nombre {
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-fuerte);
    font-size: var(--fl-texto-sm);
}

.fl-inbox-detalle-meta-email {
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-tenue);
}

.fl-inbox-detalle-meta-destinatario {
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-suave);
}

.fl-inbox-detalle-meta-destinatario strong {
    color: var(--fl-texto);
    font-weight: var(--fl-peso-medio);
}

.fl-inbox-detalle-meta-derecha {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 4px;
    flex: none;
}

.fl-inbox-detalle-meta-fecha {
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-suave);
    font-variant-numeric: tabular-nums;
}

.fl-inbox-detalle-meta-cuenta {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    font-size: 10px;
    color: var(--_color, var(--fl-texto-suave));
    background: color-mix(in srgb, var(--_color, var(--fl-texto-tenue)) 14%, transparent);
    border-radius: var(--fl-r-full);
    font-weight: var(--fl-peso-medio);
}

.fl-inbox-detalle-meta-cuenta::before {
    content: "";
    width: 6px;
    height: 6px;
    background: var(--_color, var(--fl-acento));
    border-radius: var(--fl-r-full);
    flex: none;
}

.fl-inbox-detalle-cuerpo {
    flex: 1;
    padding: var(--fl-sp-5);
    overflow-y: auto;
    line-height: var(--fl-lh-relajada);
    color: var(--fl-texto);
    font-size: var(--fl-texto-sm);
}

.fl-inbox-detalle-cuerpo p {
    margin: 0 0 var(--fl-sp-3);
}

/* Adjuntos del mail */
.fl-inbox-adjuntos {
    padding: 0 var(--fl-sp-5) var(--fl-sp-4);
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-1-5);
}

.fl-inbox-adjuntos-titulo {
    font-size: var(--fl-texto-2xs);
    font-weight: var(--fl-peso-semibold);
    text-transform: uppercase;
    letter-spacing: var(--fl-ls-mayus);
    color: var(--fl-texto-tenue);
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.fl-inbox-adjuntos-lista {
    display: flex;
    gap: var(--fl-sp-2);
    flex-wrap: wrap;
}

.fl-inbox-adjunto {
    display: inline-flex;
    align-items: center;
    gap: var(--fl-sp-2);
    padding: var(--fl-sp-1-5) var(--fl-sp-2);
    background: var(--fl-fondo-sutil);
    border: 1px solid var(--fl-borde-sutil);
    border-radius: var(--fl-r-md);
    text-decoration: none;
    color: var(--fl-texto);
    transition: border-color var(--fl-t-rapido), background var(--fl-t-rapido), transform var(--fl-t-rapido);
    cursor: pointer;
}

.fl-inbox-adjunto:hover {
    border-color: var(--fl-acento);
    background: var(--fl-superficie);
    transform: translateY(-1px);
}

.fl-inbox-adjunto-icono {
    flex: none;
    width: 32px;
    height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--fl-superficie);
    border-radius: var(--fl-r-sm);
    color: var(--_color, var(--fl-acento));
}

.fl-inbox-adjunto-icono .fl-icono { width: 16px; height: 16px; }

.fl-inbox-adjunto-info {
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
}

.fl-inbox-adjunto-nombre {
    font-size: var(--fl-texto-xs);
    font-weight: var(--fl-peso-medio);
    color: var(--fl-texto-fuerte);
    line-height: 1.2;
    max-width: 200px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.fl-inbox-adjunto-tamano {
    font-size: 10px;
    color: var(--fl-texto-tenue);
    font-variant-numeric: tabular-nums;
}

/* Respuesta inline al final del detalle */
.fl-inbox-responder {
    padding: var(--fl-sp-3) var(--fl-sp-5) var(--fl-sp-4);
    border-top: 1px solid var(--fl-borde-sutil);
    background: var(--fl-fondo-sutil);
    flex: none;
}

.fl-inbox-responder-cabecera {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
    margin-bottom: var(--fl-sp-2);
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-suave);
}

.fl-inbox-responder-cabecera strong {
    color: var(--fl-texto);
    font-weight: var(--fl-peso-semibold);
}

.fl-inbox-responder-caja {
    display: flex;
    flex-direction: column;
    gap: 0;
    background: var(--fl-superficie);
    border: 1px solid var(--fl-borde);
    border-radius: var(--fl-r-md);
    overflow: hidden;
    transition: border-color var(--fl-t-rapido), box-shadow var(--fl-t-rapido);
}

.fl-inbox-responder-caja:focus-within {
    border-color: var(--fl-acento);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--fl-acento) 18%, transparent);
}

.fl-inbox-responder-textarea {
    width: 100%;
    padding: var(--fl-sp-2-5) var(--fl-sp-3);
    background: transparent;
    border: 0;
    outline: 0;
    resize: none;
    font-family: inherit;
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto);
    line-height: 1.5;
    min-height: 76px;
}

.fl-inbox-responder-textarea::placeholder { color: var(--fl-texto-tenue); }

.fl-inbox-responder-acciones {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-1);
    padding: 6px var(--fl-sp-2);
    border-top: 1px solid var(--fl-borde-sutil);
    background: var(--fl-fondo-sutil);
}

.fl-inbox-responder-acciones-iconos {
    display: inline-flex;
    gap: 0;
    color: var(--fl-texto-tenue);
}

.fl-inbox-responder-acciones-botones {
    margin-left: auto;
    display: inline-flex;
    gap: var(--fl-sp-1);
}

/* Empty state cuando no hay mensaje seleccionado */
.fl-inbox-detalle-vacio {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100%;
    padding: var(--fl-sp-12);
    color: var(--fl-texto-tenue);
    text-align: center;
    gap: var(--fl-sp-2);
}

.fl-inbox-detalle-vacio-icono {
    width: 56px;
    height: 56px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--fl-fondo-sutil);
    border-radius: var(--fl-r-full);
    color: var(--fl-texto-tenue);
    margin-bottom: var(--fl-sp-2);
}

.fl-inbox-detalle-vacio-icono .fl-icono {
    width: 24px;
    height: 24px;
}

.fl-inbox-detalle-vacio-titulo {
    font-size: var(--fl-texto-base);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto);
}


/* ===== resources/css/componentes/indicador-offline.css ===== */
/* ==========================================================================
   Flora · Indicador-Offline (banner fijo cuando no hay conexión)
   ========================================================================== */

.fl-indicador-offline {
    position: fixed;
    left: 0;
    right: 0;
    top: 0;
    z-index: 90;
    padding: 8px var(--fl-sp-3);
    background: var(--fl-error);
    color: white;
    text-align: center;
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-medium);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    transform: translateY(-100%);
    transition: transform 280ms var(--fl-ease-salida);
}
.fl-indicador-offline[data-fl-visible="true"] { transform: translateY(0); }

.fl-indicador-offline[data-fl-estado="reconectando"] { background: var(--fl-advertencia); }
.fl-indicador-offline[data-fl-estado="reconectado"] { background: var(--fl-exito); }

.fl-indicador-offline .fl-icono { width: 16px; height: 16px; }


/* ===== resources/css/componentes/kanban.css ===== */
/* ==========================================================================
   Flora · Kanban
   Columnas de estado con tarjetas arrastrables entre ellas.
   Compatible con Trello-style, GitHub Projects, Notion board.
   ========================================================================== */

.fl-kanban {
    display: flex;
    width: 100%;
    gap: var(--fl-sp-3);
    padding: var(--fl-sp-3);
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    min-height: 200px;
    background: var(--fl-fondo-sutil);
    border-radius: var(--fl-r-lg);
    /* Centrado horizontal cuando el contenido cabe en el contenedor.
       "safe center" evita el bug clásico de justify-content: center en
       containers scrollables: si el contenido DESBORDA, alinea a flex-start
       en lugar de recortarse a la izquierda e impedir el scroll a los
       primeros ítems. Con pocas columnas se ve centrado, con muchas se
       ancla al inicio y scrollea normal. */
    justify-content: safe center;
    /* Scrollbar horizontal del kanban (Windows) — se mezcla con el fondo. */
    scrollbar-width: thin;
    scrollbar-color: var(--fl-borde) var(--fl-fondo-sutil);
}

/* --------------------------------------------------------------------------
   Columna · cada variante setea --_color (token semántico) y el resto de
   los estilos derivan de ahí con color-mix, así la columna tiene
   personalidad cromática real en vez de ser un bloque blanco con un punto.
   -------------------------------------------------------------------------- */
.fl-kanban-columna {
    --_color: var(--fl-acento);

    flex: 0 0 300px;
    display: flex;
    flex-direction: column;
    background: color-mix(in srgb, var(--_color) 6%, var(--fl-superficie));
    border: 1px solid color-mix(in srgb, var(--_color) 22%, var(--fl-borde));
    border-radius: var(--fl-r-lg);
    max-height: 100%;
    transition: background var(--fl-t-rapido), border-color var(--fl-t-rapido);
}

.fl-kanban-columna[data-fl-arrastrando-sobre="true"] {
    background: color-mix(in srgb, var(--_color) 14%, var(--fl-superficie));
    border-color: var(--_color);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--_color) 28%, transparent);
}

.fl-kanban-columna-cabecera {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
    padding: var(--fl-sp-3);
    background: color-mix(in srgb, var(--_color) 12%, transparent);
    border-bottom: 1px solid color-mix(in srgb, var(--_color) 22%, var(--fl-borde-sutil));
    border-top-left-radius: var(--fl-r-lg);
    border-top-right-radius: var(--fl-r-lg);
    flex: none;
}

.fl-kanban-columna-titulo {
    flex: 1;
    font-weight: var(--fl-peso-semibold);
    letter-spacing: var(--fl-ls-amplio);
    text-transform: uppercase;
    font-size: var(--fl-texto-xs);
    color: color-mix(in srgb, var(--_color) 85%, var(--fl-texto-fuerte));
}

.fl-kanban-columna-punto {
    width: 10px;
    height: 10px;
    border-radius: var(--fl-r-full);
    background: var(--_color);
    flex: none;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--_color) 25%, transparent);
}

.fl-kanban-columna-conteo {
    font-size: var(--fl-texto-2xs);
    font-weight: var(--fl-peso-semibold);
    color: color-mix(in srgb, var(--_color) 90%, var(--fl-texto-fuerte));
    background: color-mix(in srgb, var(--_color) 18%, var(--fl-superficie));
    border: 1px solid color-mix(in srgb, var(--_color) 30%, transparent);
    border-radius: var(--fl-r-full);
    height: 22px;
    min-width: 26px;
    padding: 0 8px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
    font-variant-numeric: tabular-nums;
}

/* Variantes — profundidades de paleta crecientes según "avance" del flujo */
.fl-kanban-columna--por-hacer   { --_color: var(--fl-texto-tenue); }
.fl-kanban-columna--en-progreso { --_color: var(--fl-acento); }
.fl-kanban-columna--en-revision { --_color: var(--fl-acento-700); }
.fl-kanban-columna--completado  { --_color: var(--fl-acento-900); }

/* --------------------------------------------------------------------------
   Lista de tarjetas dentro de la columna
   -------------------------------------------------------------------------- */
.fl-kanban-lista {
    flex: 1;
    padding: var(--fl-sp-2);
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-2);
    overflow-y: auto;
    min-height: 0;
}

/* --------------------------------------------------------------------------
   Tarjeta del kanban
   -------------------------------------------------------------------------- */
.fl-kanban-tarjeta {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-2);
    padding: var(--fl-sp-3);
    background: var(--fl-superficie);
    /* Border izquierdo tintado con el color de la columna: la tarjeta
       mantiene su identidad pero se lee que pertenece a ese grupo. */
    border: 1px solid var(--fl-borde);
    border-left: 3px solid color-mix(in srgb, var(--_color) 70%, transparent);
    border-radius: var(--fl-r-md);
    cursor: grab;
    user-select: none;
    font-size: var(--fl-texto-sm);
    box-shadow: var(--fl-sombra-xs);
    transition: border-color var(--fl-t-rapido) var(--fl-ease-salida),
                box-shadow var(--fl-t-rapido) var(--fl-ease-salida),
                transform 120ms var(--fl-ease-resorte);
}

.fl-kanban-tarjeta:hover {
    border-color: color-mix(in srgb, var(--_color) 40%, var(--fl-borde));
    border-left-color: var(--_color);
    box-shadow: var(--fl-sombra-sm),
                0 0 0 3px color-mix(in srgb, var(--_color) 10%, transparent);
    transform: translateY(-1px);
}

.fl-kanban-tarjeta:active {
    cursor: grabbing;
}

.fl-kanban-tarjeta[data-fl-arrastrando="true"] {
    opacity: 0.4;
    transform: scale(0.98) rotate(-1deg);
    cursor: grabbing;
}

.fl-kanban-tarjeta-labels {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}

.fl-kanban-tarjeta-label {
    display: inline-block;
    width: 32px;
    height: 6px;
    border-radius: var(--fl-r-full);
    background: var(--_color, var(--fl-acento));
}

.fl-kanban-tarjeta-titulo {
    font-weight: var(--fl-peso-medio);
    color: var(--fl-texto-fuerte);
    line-height: 1.35;
}

.fl-kanban-tarjeta-descripcion {
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-suave);
    line-height: 1.4;
}

.fl-kanban-tarjeta-pie {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--fl-sp-2);
    margin-top: var(--fl-sp-1);
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-tenue);
}

.fl-kanban-tarjeta-meta {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

.fl-kanban-tarjeta-meta .fl-icono {
    width: 12px;
    height: 12px;
}

.fl-kanban-tarjeta-asignados {
    display: inline-flex;
    align-items: center;
}

.fl-kanban-tarjeta-asignados > * {
    margin-left: -6px;
    border: 2px solid var(--fl-superficie);
}

.fl-kanban-tarjeta-asignados > *:first-child {
    margin-left: 0;
}

.fl-kanban-tarjeta-asignados .fl-avatar { --_size: 32px; }

/* Botón de agregar tarjeta */
.fl-kanban-agregar {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--fl-sp-1-5);
    padding: var(--fl-sp-2);
    background: transparent;
    border: 1px dashed var(--fl-borde);
    border-radius: var(--fl-r-md);
    color: var(--fl-texto-suave);
    cursor: pointer;
    font-size: var(--fl-texto-xs);
    font-weight: var(--fl-peso-medio);
    margin-top: var(--fl-sp-1);
    transition: background var(--fl-t-rapido) var(--fl-ease-salida),
                border-color var(--fl-t-rapido) var(--fl-ease-salida),
                color var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-kanban-agregar:hover {
    background: color-mix(in srgb, var(--_color) 10%, transparent);
    border-color: var(--_color);
    color: color-mix(in srgb, var(--_color) 80%, var(--fl-texto-fuerte));
    border-style: solid;
}

.fl-kanban-agregar .fl-icono {
    width: 14px;
    height: 14px;
}

/* Editor inline para agregar tarjeta nueva */
.fl-kanban-editor-nueva {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-1-5);
    padding: var(--fl-sp-2);
    background: var(--fl-superficie);
    border: 1px solid var(--fl-acento);
    border-radius: var(--fl-r-md);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--fl-acento) 12%, transparent);
}

.fl-kanban-editor-input {
    width: 100%;
    min-height: 48px;
    padding: var(--fl-sp-1-5) var(--fl-sp-2);
    font: inherit;
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto);
    background: transparent;
    border: 0;
    outline: none;
    resize: vertical;
}

.fl-kanban-editor-acciones {
    display: flex;
    gap: var(--fl-sp-1-5);
    align-items: center;
}

.fl-kanban-editor-confirmar {
    padding: 6px 12px;
    font-size: var(--fl-texto-xs);
    font-weight: var(--fl-peso-medio);
    color: var(--fl-sobre-acento, #fff);
    background: var(--fl-acento);
    border: 0;
    border-radius: var(--fl-r-sm);
    cursor: pointer;
}

.fl-kanban-editor-confirmar:hover {
    background: var(--fl-acento-hover, var(--fl-acento));
    filter: brightness(1.05);
}

.fl-kanban-editor-cancelar {
    padding: 4px 8px;
    font-size: var(--fl-texto-base);
    line-height: 1;
    color: var(--fl-texto-suave);
    background: transparent;
    border: 0;
    border-radius: var(--fl-r-sm);
    cursor: pointer;
}

.fl-kanban-editor-cancelar:hover {
    background: var(--fl-superficie-hover);
    color: var(--fl-texto-fuerte);
}

/* Agregar columna entera (última columna) */
.fl-kanban-agregar-columna {
    flex: 0 0 260px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--fl-sp-2);
    padding: var(--fl-sp-6);
    background: transparent;
    border: 2px dashed var(--fl-borde);
    border-radius: var(--fl-r-lg);
    color: var(--fl-texto-suave);
    cursor: pointer;
    font-weight: var(--fl-peso-medio);
    transition: background var(--fl-t-rapido), border-color var(--fl-t-rapido),
                color var(--fl-t-rapido);
    min-height: 120px;
    align-self: flex-start;
}

.fl-kanban-agregar-columna:hover {
    background: var(--fl-acento-suave);
    border-color: var(--fl-acento);
    color: var(--fl-acento-texto);
}

/* --------------------------------------------------------------------------
   Modal de edición de tarea
   -------------------------------------------------------------------------- */
/* Gap vertical entre los .fl-campo dentro del modal — si no, el label
   del siguiente campo queda pegado al input anterior, sin respiro. El
   .fl-campo tiene gap interno entre label/input, pero NO entre campos. */
.fl-kanban-modal .fl-modal-cuerpo {
    /* Gap entre campos del form — mismo valor que usa .fl-formulario-seccion
       para mantener consistencia a lo largo de todos los forms de Flora. */
    gap: var(--fl-sp-7);
    justify-content: flex-start;
}

.fl-kanban-modal-pie {
    /* Sobrescribe el justify-content: center default de .fl-modal-pie para
       tener layout split: eliminar a la izquierda, cancelar + guardar derecha. */
    justify-content: space-between;
}

.fl-kanban-modal-acciones {
    display: inline-flex;
    gap: var(--fl-sp-2);
    align-items: center;
}

/* --------------------------------------------------------------------------
   Selector de Estado (pills) en el modal de tarea.
   Reemplaza un <select> por un radiogroup visual con una pill por columna.
   - Default: outlined con el color de la variante
   - Hover: fondo tinte del color
   - Activo: filled con el color + punto interno blanco + sombra sutil
   -------------------------------------------------------------------------- */
.fl-kanban-modal-estados {
    display: flex;
    flex-wrap: wrap;
    gap: var(--fl-sp-2);
}

.fl-kanban-modal-estado-opcion {
    --_color: var(--fl-acento);

    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 6px 14px;
    height: 32px;
    border-radius: var(--fl-r-full);
    background: transparent;
    border: 1.5px solid color-mix(in srgb, var(--_color) 35%, var(--fl-borde));
    color: color-mix(in srgb, var(--_color) 85%, var(--fl-texto-fuerte));
    font-family: inherit;
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-medio);
    line-height: 1;
    cursor: pointer;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida),
                border-color var(--fl-t-rapido) var(--fl-ease-salida),
                color var(--fl-t-rapido) var(--fl-ease-salida),
                box-shadow var(--fl-t-rapido) var(--fl-ease-salida),
                transform 120ms var(--fl-ease-resorte);
}

.fl-kanban-modal-estado-opcion:hover {
    background: color-mix(in srgb, var(--_color) 10%, transparent);
    border-color: var(--_color);
}

.fl-kanban-modal-estado-opcion:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--_color) 25%, transparent);
}

/* Activo: filled con el color semántico — destaca fuerte contra las otras
   opciones outlined. El punto interno se invierte a blanco para contrastar. */
.fl-kanban-modal-estado-opcion[aria-checked="true"] {
    background: var(--_color);
    border-color: var(--_color);
    color: #fff;
    box-shadow: 0 4px 10px -3px color-mix(in srgb, var(--_color) 45%, transparent);
}

/* Punto indicador — mismo color que el border/background para integrarse */
.fl-kanban-modal-estado-opcion-punto {
    width: 8px;
    height: 8px;
    border-radius: var(--fl-r-full);
    background: var(--_color);
    flex: none;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-kanban-modal-estado-opcion[aria-checked="true"] .fl-kanban-modal-estado-opcion-punto {
    background: #fff;
}

/* Mapa de variantes — mismos colores que .fl-kanban-columna (profundidad paleta) */
.fl-kanban-modal-estado-opcion[data-fl-variante="por-hacer"]   { --_color: var(--fl-texto-tenue); }
.fl-kanban-modal-estado-opcion[data-fl-variante="en-progreso"] { --_color: var(--fl-acento); }
.fl-kanban-modal-estado-opcion[data-fl-variante="en-revision"] { --_color: var(--fl-acento-700); }
.fl-kanban-modal-estado-opcion[data-fl-variante="completado"]  { --_color: var(--fl-acento-900); }

/* Botón "Eliminar" del modal: base sutil (texto rojo, fondo transparente),
   hover se rellena en sólido con texto blanco — leve pero claro, sin el
   look chillón del hover de --peligro default. */
.fl-kanban-modal-eliminar {
    color: var(--fl-error);
    background: transparent;
    border-color: transparent;
}

.fl-kanban-modal-eliminar:hover:not(:disabled),
.fl-kanban-modal-eliminar:focus-visible:not(:disabled) {
    background: var(--fl-error);
    border-color: var(--fl-error);
    color: #fff;
}

.fl-kanban-modal-eliminar:active:not(:disabled) {
    background: var(--fl-error-hover, var(--fl-error));
    color: #fff;
    filter: brightness(0.95);
}

/* Responsive — en mobile achicamos columnas para que se vea 1+ columna completa
   a la vez. El scroll horizontal ya está habilitado en .fl-kanban. */
@media (max-width: 640px) {
    .fl-kanban { padding: var(--fl-sp-2); gap: var(--fl-sp-2); min-height: 480px; }
    .fl-kanban-columna { flex: 0 0 260px; }
    .fl-kanban-agregar-columna { flex: 0 0 220px; padding: var(--fl-sp-4); min-height: 80px; }
}


/* ===== resources/css/componentes/linea-tiempo.css ===== */
/* ==========================================================================
   Flora · Línea de tiempo (timeline / activity feed)
   Lista vertical de eventos con marca temporal, ícono y descripción.
   Conectados por una línea continua. Variantes: compacta, con-iconos.
   ========================================================================== */

.fl-linea-tiempo {
    display: flex;
    flex-direction: column;
    gap: 0;
    padding: 0;
    margin: 0;
    list-style: none;
    position: relative;
}

.fl-linea-tiempo-item {
    position: relative;
    display: grid;
    grid-template-columns: 32px 1fr;
    column-gap: var(--fl-sp-4);
    padding-bottom: var(--fl-sp-5);
}

.fl-linea-tiempo-item:last-child {
    padding-bottom: 0;
}

/* Línea conectora — dibujada detrás del ícono, con tint de acento */
.fl-linea-tiempo-item:not(:last-child)::before {
    content: "";
    position: absolute;
    left: 15px;
    top: 32px;
    bottom: 0;
    width: 2px;
    background: color-mix(in srgb, var(--fl-acento) 22%, transparent);
}

/* Marcador — círculo con ícono. Usa paleta activa por default. */
.fl-linea-tiempo-marcador {
    grid-column: 1;
    grid-row: 1 / span 2;
    width: 32px;
    height: 32px;
    border-radius: var(--fl-r-full);
    background: var(--fl-acento-suave);
    border: 2px solid color-mix(in srgb, var(--fl-acento) 40%, transparent);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--fl-acento-texto);
    flex: none;
    z-index: 1;
    box-shadow: 0 1px 3px color-mix(in srgb, var(--fl-acento) 18%, transparent);
}

.fl-linea-tiempo-marcador .fl-icono {
    width: 16px;
    height: 16px;
}

/* Sin ícono — punto relleno del acento */
.fl-linea-tiempo-marcador--punto {
    width: 14px;
    height: 14px;
    margin: 9px;
    background: var(--fl-acento);
    border: 0;
    box-shadow: 0 0 0 3px var(--fl-acento-suave);
}

/* Contenido — título + descripción + pie */
.fl-linea-tiempo-contenido {
    grid-column: 2;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-1);
    padding-top: 2px;
}

.fl-linea-tiempo-cabecera {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--fl-sp-2);
    flex-wrap: wrap;
}

.fl-linea-tiempo-titulo {
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-medio);
    color: var(--fl-texto-fuerte);
    line-height: 1.3;
    margin: 0;
}

.fl-linea-tiempo-tiempo {
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-tenue);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.fl-linea-tiempo-descripcion {
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto-suave);
    line-height: var(--fl-lh-ajustada);
}

/* --------------------------------------------------------------------------
   Variante destaque — marcador con relleno fuerte (paleta activa).
   Para el evento "protagonista" sin introducir colores semánticos. */
.fl-linea-tiempo-item--destaque .fl-linea-tiempo-marcador {
    background: var(--fl-destaque-fondo);
    border-color: var(--fl-destaque-fondo);
    color: var(--fl-destaque-texto);
    box-shadow: 0 2px 6px color-mix(in srgb, var(--fl-destaque-fondo) 45%, transparent);
}

/* --------------------------------------------------------------------------
   Estados del evento — todos dentro de la paleta activa, sin mezclar con
   verdes/rojos semánticos. Se modulan intensidades del acento.
   -------------------------------------------------------------------------- */

/* Completado — evento ya sucedido / chequeado OK. Relleno sólido fuerte. */
.fl-linea-tiempo-item--completado .fl-linea-tiempo-marcador {
    background: var(--fl-acento);
    border-color: var(--fl-acento);
    color: var(--fl-acento-texto-sobre);
    box-shadow: 0 2px 5px color-mix(in srgb, var(--fl-acento) 40%, transparent);
}

/* Línea conectora bajo un completado también va fuerte */
.fl-linea-tiempo-item--completado:not(:last-child)::before {
    background: color-mix(in srgb, var(--fl-acento) 55%, transparent);
}

/* Actual — en curso. Borde fuerte del acento + pulso de halo. */
.fl-linea-tiempo-item--actual .fl-linea-tiempo-marcador {
    background: var(--fl-superficie);
    border: 3px solid var(--fl-acento);
    color: var(--fl-acento-texto);
    animation: fl-linea-tiempo-pulso 2s ease-in-out infinite;
}

@keyframes fl-linea-tiempo-pulso {
    0%, 100% {
        box-shadow: 0 0 0 0 color-mix(in srgb, var(--fl-acento) 45%, transparent);
    }
    50% {
        box-shadow: 0 0 0 8px color-mix(in srgb, var(--fl-acento) 0%, transparent);
    }
}

/* Pendiente — aún no sucedió. Ghost style: toda la fila se atenúa mucho,
   el marcador queda outlined dashed, el texto en italic para enfatizar
   "algo que todavía no es real". */
.fl-linea-tiempo-item--pendiente {
    opacity: 0.55;
}

.fl-linea-tiempo-item--pendiente .fl-linea-tiempo-marcador {
    background: transparent;
    border: 2px dashed color-mix(in srgb, var(--fl-acento) 50%, transparent);
    color: color-mix(in srgb, var(--fl-acento-texto) 70%, transparent);
    box-shadow: none;
}

.fl-linea-tiempo-item--pendiente .fl-linea-tiempo-titulo,
.fl-linea-tiempo-item--pendiente .fl-linea-tiempo-descripcion {
    font-style: italic;
}

.fl-linea-tiempo-item--pendiente:not(:last-child)::before {
    /* Línea conectora también dashed — refuerza el "esto no pasó aún" */
    background: none;
    border-left: 2px dashed color-mix(in srgb, var(--fl-acento) 35%, transparent);
    width: 0;
    left: 15px;
}

.fl-linea-tiempo--compacta .fl-linea-tiempo-item--pendiente:not(:last-child)::before {
    left: 13px;
}

/* Rechazado / fallido — dentro de la paleta: marcador tachado con línea
   diagonal. Usa el mismo tint suave del acento pero con un "cross-out". */
.fl-linea-tiempo-item--rechazado .fl-linea-tiempo-marcador {
    background: var(--fl-acento-suave);
    border-color: color-mix(in srgb, var(--fl-acento) 60%, transparent);
    color: color-mix(in srgb, var(--fl-acento-texto) 50%, transparent);
    position: relative;
}

.fl-linea-tiempo-item--rechazado .fl-linea-tiempo-marcador::after {
    content: "";
    position: absolute;
    inset: 4px;
    background: linear-gradient(
        135deg,
        transparent 45%,
        color-mix(in srgb, var(--fl-acento) 70%, transparent) 45%,
        color-mix(in srgb, var(--fl-acento) 70%, transparent) 55%,
        transparent 55%
    );
    border-radius: inherit;
    pointer-events: none;
}

.fl-linea-tiempo-item--rechazado .fl-linea-tiempo-titulo {
    color: var(--fl-texto-suave);
    text-decoration: line-through;
    text-decoration-color: color-mix(in srgb, var(--fl-acento) 40%, transparent);
}

@media (prefers-reduced-motion: reduce) {
    .fl-linea-tiempo-item--actual .fl-linea-tiempo-marcador {
        animation: none;
    }
}

/* --------------------------------------------------------------------------
   Variante compacta — menos padding, sin descripción separada
   -------------------------------------------------------------------------- */
.fl-linea-tiempo--compacta .fl-linea-tiempo-item {
    grid-template-columns: 28px 1fr;
    column-gap: var(--fl-sp-3);
    padding-bottom: var(--fl-sp-4);
}

.fl-linea-tiempo--compacta .fl-linea-tiempo-marcador {
    width: 28px;
    height: 28px;
    border-width: 2px;
}

.fl-linea-tiempo--compacta .fl-linea-tiempo-marcador .fl-icono {
    width: 14px;
    height: 14px;
}

.fl-linea-tiempo--compacta .fl-linea-tiempo-item::before {
    left: 13px;
    top: 28px;
}


/* ===== resources/css/componentes/lista-virtual.css ===== */
/* ==========================================================================
   Flora · Lista-Virtual (windowed rendering)
   Para listas enormes. Sólo renderiza los items visibles + buffer.
   Usa altura fija por item para cálculo simple.
   ========================================================================== */

.fl-lista-virtual {
    position: relative;
    overflow: auto;
    width: 100%;
    border: 1px solid var(--fl-borde);
    border-radius: var(--fl-r-md);
    background: var(--fl-superficie);
}

.fl-lista-virtual-espaciador {
    position: relative;
    width: 100%;
}

.fl-lista-virtual-items {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    will-change: transform;
}

.fl-lista-virtual-item {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-3);
    padding: 0 var(--fl-sp-4);
    border-bottom: 1px solid var(--fl-borde-sutil);
    background: var(--fl-superficie);
}

.fl-lista-virtual-item:hover {
    background: var(--fl-superficie-hover);
}


/* ===== resources/css/componentes/marca.css ===== */
/* ==========================================================================
   Flora · Marca
   Combo logo + nombre, reutilizado por navbar, sidebar, plantilla-auth,
   y cualquier lugar donde aparezca la identidad del proyecto.
   ========================================================================== */

.fl-marca {
    display: inline-flex;
    align-items: center;
    gap: var(--fl-sp-2);
    color: var(--fl-texto-fuerte);
    text-decoration: none;
    font-weight: var(--fl-peso-semibold);
    letter-spacing: var(--fl-ls-compacto);
    line-height: 1.1;
    transition: opacity var(--fl-t-rapido) var(--fl-ease-salida);
}

a.fl-marca:hover {
    opacity: 0.8;
}

.fl-marca-logo {
    display: block;
    object-fit: contain;
    border-radius: var(--fl-r-sm);
    flex: none;
}

.fl-marca-icono {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--fl-acento);
    flex: none;
}

.fl-marca-nombre {
    /* Mismo texto visible en los 3 tamaños (sm/md/lg) — no truncamos por
       defecto; el que necesite recorte debe envolver en un contenedor con
       ancho fijo. Sin ellipsis el nombre aparece completo en todas las
       variantes. */
    white-space: nowrap;
    min-width: 0;
    display: inline-block;
}

/* Variante explícita para cuando sí se quiere truncar (sidebar colapsado) */
.fl-marca--truncar .fl-marca-nombre {
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}

/* Tamaños */
.fl-marca--sm { font-size: var(--fl-texto-sm); gap: var(--fl-sp-1-5); }
.fl-marca--sm .fl-marca-logo { width: 18px; height: 18px; }
.fl-marca--sm .fl-marca-icono .fl-icono { width: 16px; height: 16px; }

.fl-marca--md { font-size: var(--fl-texto-base); }
.fl-marca--md .fl-marca-logo { width: 24px; height: 24px; }
.fl-marca--md .fl-marca-icono .fl-icono { width: 20px; height: 20px; }

.fl-marca--lg { font-size: var(--fl-texto-lg); gap: var(--fl-sp-2-5); }
.fl-marca--lg .fl-marca-logo { width: 32px; height: 32px; }
.fl-marca--lg .fl-marca-icono .fl-icono { width: 26px; height: 26px; }

/* Variantes sin logo o sin texto */
.fl-marca--solo-logo { gap: 0; }
.fl-marca--solo-texto .fl-marca-logo,
.fl-marca--solo-texto .fl-marca-icono { display: none; }


/* ===== resources/css/componentes/menu-contextual.css ===== */
/* ==========================================================================
   Flora · Menú contextual (right-click)
   Reutiliza .fl-dropdown-menu para la apariencia. Sólo cambia la forma de
   activación: data-fl-menu-contextual="id-del-menu" en el elemento target,
   y click-derecho dispara el menú.
   ========================================================================== */

.fl-menu-contextual {
    /* Hereda casi todo de .fl-dropdown-menu. Esta clase se aplica junto. */
    min-width: 180px;
}

/* Indicador visual sutil de que un elemento soporta menú contextual */
[data-fl-menu-contextual] {
    /* Nada por default — mantener comportamiento nativo del cursor */
}

/* Cuando está activo, se puede marcar el target */
[data-fl-menu-contextual-activo="true"] {
    background: color-mix(in srgb, var(--fl-acento) 6%, transparent);
    outline: 1px dashed var(--fl-acento-borde);
    outline-offset: -1px;
}


/* ===== resources/css/componentes/modal.css ===== */
/* ==========================================================================
   Flora · Modal
   Overlay + caja centrada con entrada en capas:
   1. backdrop fade + blur (200ms)
   2. modal slide-up + scale + fade (360ms, spring)
   3. ícono semántico pop (220ms, delay 180ms)
   4. contenido interior fade-in cascada (opcional via :has + selectores)
   ========================================================================== */

.fl-modal-fondo {
    position: fixed;
    inset: 0;
    z-index: var(--fl-z-overlay);
    display: none;
    align-items: center;
    justify-content: center;
    padding: var(--fl-sp-4);
    background:
        radial-gradient(ellipse at top, rgb(0 0 0 / 0.08), transparent 60%),
        var(--fl-overlay);
    backdrop-filter: blur(12px) saturate(150%);
    -webkit-backdrop-filter: blur(12px) saturate(150%);
    opacity: 0;
    transition: opacity 220ms var(--fl-ease-salida);
    /* NO overflow en el fondo — el modal tiene su propio scroll interno en
       .fl-modal-cuerpo. Con overflow-y:auto acá, en mobile flex-centering
       se rompe cuando queda espacio vertical → el modal queda pegado arriba. */
    overflow: hidden;
    overscroll-behavior: contain;
}

/* En mobile chico el padding del backdrop se reduce así el modal entra mejor.
   Usamos dvh (dynamic viewport height) en lugar de vh porque vh en mobile
   no descuenta la address bar que aparece/desaparece, y el modal quedaba
   cortado o descentrado al hacer scroll. */
@media (max-width: 480px) {
    .fl-modal-fondo { padding: var(--fl-sp-2); }
    .fl-modal { max-width: 100%; max-height: calc(100dvh - var(--fl-sp-4)); }
}

[data-fl-enfasis="oscuro"] .fl-modal-fondo,
.fl-modal-fondo {
    background:
        radial-gradient(ellipse at top, color-mix(in srgb, var(--fl-acento) 6%, transparent), transparent 70%),
        var(--fl-overlay);
}

.fl-modal-fondo[data-fl-abierto="true"] {
    display: flex;
    opacity: 1;
}

.fl-modal {
    z-index: var(--fl-z-modal);
    width: 100%;
    max-width: 520px;
    /* dvh en lugar de vh: respeta el alto visible real en mobile (sin
       contar la address bar). Esto mantiene el modal centrado vertical-
       mente incluso cuando aparece/desaparece el chrome del browser. */
    max-height: calc(100dvh - var(--fl-sp-8));
    display: flex;
    flex-direction: column;
    background: var(--fl-superficie-elevada);
    border: 1px solid var(--fl-borde-sutil);
    border-radius: var(--fl-r-2xl);
    box-shadow:
        0 32px 64px -12px rgb(0 0 0 / 0.25),
        0 0 0 1px rgb(0 0 0 / 0.04),
        inset 0 1px 0 0 rgb(255 255 255 / 0.06);
    overflow: hidden;
    transform: translateY(24px) scale(0.94);
    opacity: 0;
    transition: transform 360ms var(--fl-ease-resorte),
                opacity 260ms var(--fl-ease-salida);
    position: relative;
}

/* Highlight superior muy sutil — refleja luz desde arriba (capa de glass) */
.fl-modal::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 1px;
    background: linear-gradient(
        to right,
        transparent 10%,
        color-mix(in srgb, var(--fl-texto-fuerte) 8%, transparent),
        transparent 90%
    );
    pointer-events: none;
    z-index: 1;
}

.fl-modal-fondo[data-fl-abierto="true"] .fl-modal {
    transform: translateY(0) scale(1);
    opacity: 1;
}

/* --------------------------------------------------------------------------
   Tamaños — fluidos con viewport.
   Cada tamaño es min(Xvw, Ypx) así el modal se adapta continuamente al
   ancho de pantalla: toma el valor en px en viewports amplios, y se
   achica a X% del viewport en pantallas angostas. Sin breakpoint jumps.
   El backdrop también tiene padding sp-4, que suma margen adicional.
   -------------------------------------------------------------------------- */
.fl-modal--xs   { max-width: min(94vw, 380px); }
.fl-modal--sm   { max-width: min(94vw, 500px); }
.fl-modal--md   { max-width: min(94vw, 620px); }  /* default */
.fl-modal--lg   { max-width: min(92vw, 800px); }
.fl-modal--xl   { max-width: min(94vw, 1040px); }
.fl-modal--2xl  { max-width: min(96vw, 1280px); }
.fl-modal--full {
    max-width: calc(100vw - var(--fl-sp-8));
    max-height: calc(100dvh - var(--fl-sp-8));
    width: calc(100vw - var(--fl-sp-8));
    height: calc(100dvh - var(--fl-sp-8));
}

/* --------------------------------------------------------------------------
   Cabecera
   -------------------------------------------------------------------------- */
.fl-modal-cabecera {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--fl-sp-3);
    padding: var(--fl-sp-5) var(--fl-sp-6) var(--fl-sp-4);
    flex: none;
    position: relative;
    /* Tint muy suave del color activo — por default el acento de la paleta.
       Las variantes semánticas sobreescriben con su propio tinte suave. */
    background: var(--fl-acento-suave);
    border-bottom: 1px solid color-mix(in srgb, var(--fl-acento) 12%, transparent);
}

.fl-modal--peligro .fl-modal-cabecera {
    background: var(--fl-error-suave);
    border-bottom-color: color-mix(in srgb, var(--fl-error) 18%, transparent);
}

.fl-modal--exito .fl-modal-cabecera {
    background: var(--fl-exito-suave);
    border-bottom-color: color-mix(in srgb, var(--fl-exito) 18%, transparent);
}

.fl-modal--advertencia .fl-modal-cabecera {
    background: var(--fl-advertencia-suave);
    border-bottom-color: color-mix(in srgb, var(--fl-advertencia) 18%, transparent);
}

.fl-modal--info .fl-modal-cabecera {
    background: var(--fl-info-suave);
    border-bottom-color: color-mix(in srgb, var(--fl-info) 18%, transparent);
}

/* Si hay ícono semántico a la izquierda, la cabecera usa grid de 3 columnas
   iguales (ícono · texto · cerrar). Las columnas laterales tienen el ancho
   del ícono (52px) así ambos "bordes" son simétricos y el texto queda
   verdaderamente centrado en el medio. La X (36px) se centra dentro de
   su columna de 52px vía justify-self:center. */
.fl-modal-cabecera:has(> .fl-modal-icono-semantico) {
    display: grid;
    grid-template-columns: 52px 1fr 52px;
    align-items: center;
}

.fl-modal-cabecera:has(> .fl-modal-icono-semantico) .fl-modal-cabecera-texto {
    text-align: center;
}

.fl-modal-cabecera:has(> .fl-modal-icono-semantico) .fl-modal-cerrar {
    justify-self: center;
    /* Anular el margen negativo original (pensado para flex-start, que
       empujaba la X al borde superior derecho). En grid centrado ya no hace falta. */
    margin: 0;
}

.fl-modal-cabecera-texto {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-1-5);
    min-width: 0;
    flex: 1;
}

.fl-modal-titulo {
    font-size: var(--fl-texto-xl);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-fuerte);
    line-height: var(--fl-lh-compacta);
    letter-spacing: var(--fl-ls-compacto);
    margin: 0;
}

.fl-modal-subtitulo {
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto-suave);
    line-height: var(--fl-lh-ajustada);
}

/* Botón cerrar — detalle premium: rota 90° al hover */
.fl-modal-cerrar {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    padding: 0;
    margin: -4px -6px 0 0;
    background: transparent;
    border: 0;
    border-radius: var(--fl-r-md);
    color: var(--fl-texto-tenue);
    cursor: pointer;
    transition: background 160ms var(--fl-ease-salida),
                color 160ms var(--fl-ease-salida),
                transform 220ms var(--fl-ease-resorte);
}

.fl-modal-cerrar:hover {
    background: var(--fl-superficie-hover);
    color: var(--fl-texto-fuerte);
    transform: rotate(90deg);
}

.fl-modal-cerrar:focus-visible {
    outline: none;
    background: var(--fl-superficie-hover);
    box-shadow: 0 0 0 var(--fl-foco-ancho) var(--fl-acento-foco);
}

.fl-modal-cerrar:active {
    transform: rotate(90deg) scale(0.92);
}

.fl-modal-cerrar .fl-icono {
    width: 18px;
    height: 18px;
}

/* --------------------------------------------------------------------------
   Cuerpo
   -------------------------------------------------------------------------- */
.fl-modal-cuerpo {
    /* Padding top = padding bottom para que el contenido respire igual
       arriba y abajo. display:flex + justify-content:center centra
       vertical-mente el contenido si queda espacio libre (modal con
       min-height o contenido corto). */
    padding: var(--fl-sp-5) var(--fl-sp-6);
    overflow-y: auto;
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto);
    line-height: var(--fl-lh-normal);
}

.fl-modal-cuerpo--compacto {
    padding: var(--fl-sp-4) var(--fl-sp-5);
}

/* --------------------------------------------------------------------------
   Pie
   -------------------------------------------------------------------------- */
.fl-modal-pie {
    display: flex;
    align-items: center;
    /* Centrado por default — los modales del sistema (confirmaciones,
       avisos de éxito/error) quedan mejor con acciones centradas en vez
       de pegadas a la derecha. Los modificadores abajo cambian el
       alineamiento para casos específicos (wizards, paneles largos). */
    justify-content: center;
    gap: var(--fl-sp-2);
    padding: var(--fl-sp-4) var(--fl-sp-6);
    background: var(--fl-fondo-sutil);
    border-top: 1px solid var(--fl-borde-sutil);
    flex: none;
}

.fl-modal-pie--derecha {
    justify-content: flex-end;
}

.fl-modal-pie--izquierda {
    justify-content: flex-start;
}

.fl-modal-pie--distribuido {
    justify-content: space-between;
}

/* Tinte semántico del pie — mantiene sintonía con el header por variante.
   Neutro (sin variante) queda con el --fl-fondo-sutil + borde sutil. */
.fl-modal--peligro .fl-modal-pie {
    background: var(--fl-error-suave);
    border-top-color: color-mix(in srgb, var(--fl-error) 18%, transparent);
}

.fl-modal--exito .fl-modal-pie {
    background: var(--fl-exito-suave);
    border-top-color: color-mix(in srgb, var(--fl-exito) 18%, transparent);
}

.fl-modal--advertencia .fl-modal-pie {
    background: var(--fl-advertencia-suave);
    border-top-color: color-mix(in srgb, var(--fl-advertencia) 18%, transparent);
}

.fl-modal--info .fl-modal-pie {
    background: var(--fl-info-suave);
    border-top-color: color-mix(in srgb, var(--fl-info) 18%, transparent);
}

/* Botones fantasma dentro del pie heredan el color semántico de la variante
   del modal (base + hover) — "Cancelar" se tiñe con el color del contexto
   (rojo en peligro, verde en éxito, etc.) para que el gesto se sienta
   coherente con el intent. El SECUNDARIO mantiene su color de paleta. */

/* Base: color del texto según variante del modal */
.fl-modal--peligro .fl-modal-pie .fl-boton--fantasma {
    color: var(--fl-error);
}
.fl-modal--exito .fl-modal-pie .fl-boton--fantasma {
    color: var(--fl-exito);
}
.fl-modal--advertencia .fl-modal-pie .fl-boton--fantasma {
    color: var(--fl-advertencia);
}
.fl-modal--info .fl-modal-pie .fl-boton--fantasma {
    color: var(--fl-info);
}

/* Hover: agrega tint de fondo + borde del color semántico */
.fl-modal--peligro .fl-modal-pie .fl-boton--fantasma:hover:not(:disabled) {
    background: color-mix(in srgb, var(--fl-error) 7%, transparent);
    border-color: var(--fl-error);
    color: var(--fl-error);
}

.fl-modal--exito .fl-modal-pie .fl-boton--fantasma:hover:not(:disabled) {
    background: color-mix(in srgb, var(--fl-exito) 7%, transparent);
    border-color: var(--fl-exito);
    color: var(--fl-exito);
}

.fl-modal--advertencia .fl-modal-pie .fl-boton--fantasma:hover:not(:disabled) {
    background: color-mix(in srgb, var(--fl-advertencia) 7%, transparent);
    border-color: var(--fl-advertencia);
    color: var(--fl-advertencia);
}

.fl-modal--info .fl-modal-pie .fl-boton--fantasma:hover:not(:disabled) {
    background: color-mix(in srgb, var(--fl-info) 7%, transparent);
    border-color: var(--fl-info);
    color: var(--fl-info);
}

/* La X de cerrar también hereda el color semántico en hover según la
   variante del modal — gesto consistente con el pie y el header. */
.fl-modal--peligro .fl-modal-cerrar:hover {
    background: color-mix(in srgb, var(--fl-error) 12%, transparent);
    color: var(--fl-error);
}

.fl-modal--exito .fl-modal-cerrar:hover {
    background: color-mix(in srgb, var(--fl-exito) 12%, transparent);
    color: var(--fl-exito);
}

.fl-modal--advertencia .fl-modal-cerrar:hover {
    background: color-mix(in srgb, var(--fl-advertencia) 12%, transparent);
    color: var(--fl-advertencia);
}

.fl-modal--info .fl-modal-cerrar:hover {
    background: color-mix(in srgb, var(--fl-info) 12%, transparent);
    color: var(--fl-info);
}

/* --------------------------------------------------------------------------
   Variantes semánticas — tintan sutilmente el borde y el ícono
   -------------------------------------------------------------------------- */
.fl-modal--peligro {
    border-color: color-mix(in srgb, var(--fl-error) 30%, var(--fl-borde));
}

.fl-modal--peligro .fl-modal-icono-semantico {
    background: color-mix(in srgb, var(--fl-error) 14%, transparent);
    color: var(--fl-error);
}

.fl-modal--exito {
    border-color: color-mix(in srgb, var(--fl-exito) 30%, var(--fl-borde));
}

.fl-modal--exito .fl-modal-icono-semantico {
    background: color-mix(in srgb, var(--fl-exito) 14%, transparent);
    color: var(--fl-exito);
}

.fl-modal--advertencia {
    border-color: color-mix(in srgb, var(--fl-advertencia) 30%, var(--fl-borde));
}

.fl-modal--advertencia .fl-modal-icono-semantico {
    background: color-mix(in srgb, var(--fl-advertencia) 14%, transparent);
    color: var(--fl-advertencia);
}

.fl-modal--info {
    border-color: color-mix(in srgb, var(--fl-info) 30%, var(--fl-borde));
}

.fl-modal--info .fl-modal-icono-semantico {
    background: color-mix(in srgb, var(--fl-info) 14%, transparent);
    color: var(--fl-info);
}

/* --------------------------------------------------------------------------
   Ícono semántico — animación pop con rotación al abrir
   -------------------------------------------------------------------------- */
.fl-modal-icono-semantico {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 52px;
    height: 52px;
    border-radius: var(--fl-r-full);
    background: var(--fl-acento-suave);
    color: var(--fl-acento);
    position: relative;
    transform: scale(0) rotate(-8deg);
    opacity: 0;
}

.fl-modal-fondo[data-fl-abierto="true"] .fl-modal-icono-semantico {
    animation: fl-modal-icono-entrada 420ms var(--fl-ease-resorte) 160ms forwards;
}

.fl-modal-icono-semantico::after {
    content: "";
    position: absolute;
    inset: -6px;
    border-radius: inherit;
    background: inherit;
    opacity: 0;
    z-index: -1;
    animation: fl-modal-icono-halo 1800ms var(--fl-ease-salida) 400ms infinite;
}

.fl-modal-icono-semantico .fl-icono {
    width: 26px;
    height: 26px;
}

@keyframes fl-modal-icono-entrada {
    0% {
        transform: scale(0) rotate(-8deg);
        opacity: 0;
    }
    60% {
        transform: scale(1.12) rotate(2deg);
        opacity: 1;
    }
    100% {
        transform: scale(1) rotate(0);
        opacity: 1;
    }
}

@keyframes fl-modal-icono-halo {
    0% {
        opacity: 0.25;
        transform: scale(1);
    }
    100% {
        opacity: 0;
        transform: scale(1.35);
    }
}

/* --------------------------------------------------------------------------
   Stagger del contenido interior — cada sección aparece con un pequeño delay
   para que el modal se "arme" elegantemente en vez de todo junto.
   -------------------------------------------------------------------------- */
.fl-modal-fondo[data-fl-abierto="true"] .fl-modal-cabecera,
.fl-modal-fondo[data-fl-abierto="true"] .fl-modal-cuerpo,
.fl-modal-fondo[data-fl-abierto="true"] .fl-modal-pie {
    animation: fl-modal-contenido-aparece 380ms var(--fl-ease-salida) backwards;
}

.fl-modal-fondo[data-fl-abierto="true"] .fl-modal-cabecera { animation-delay: 120ms; }
.fl-modal-fondo[data-fl-abierto="true"] .fl-modal-cuerpo   { animation-delay: 180ms; }
.fl-modal-fondo[data-fl-abierto="true"] .fl-modal-pie      { animation-delay: 240ms; }

@keyframes fl-modal-contenido-aparece {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* --------------------------------------------------------------------------
   Reduced motion — todo queda en fade simple, sin transforms
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .fl-modal-fondo,
    .fl-modal,
    .fl-modal-cerrar,
    .fl-modal-icono-semantico {
        transition: opacity 120ms linear;
        animation: none !important;
    }
    .fl-modal {
        transform: none;
    }
    .fl-modal-fondo[data-fl-abierto="true"] .fl-modal {
        transform: none;
    }
    .fl-modal-icono-semantico {
        transform: none;
        opacity: 1;
    }
    .fl-modal-icono-semantico::after {
        display: none;
    }
    .fl-modal-fondo[data-fl-abierto="true"] .fl-modal-cabecera,
    .fl-modal-fondo[data-fl-abierto="true"] .fl-modal-cuerpo,
    .fl-modal-fondo[data-fl-abierto="true"] .fl-modal-pie {
        animation: none;
    }
    .fl-modal-cerrar:hover {
        transform: none;
    }
}


/* ===== resources/css/componentes/navbar.css ===== */
/* ==========================================================================
   Flora · Navbar (top bar de aplicación)
   Barra superior fija con marca, navegación principal y área de usuario.
   ========================================================================== */

.fl-navbar {
    /* Separador translúcido derivado del texto — funciona en claro y oscuro */
    --_separador: color-mix(in srgb, var(--fl-destaque-texto) 12%, transparent);

    /* Redefino los tokens de texto localmente para que cualquier descendiente
       (botones fantasma, marca, íconos) se lea claro sobre el fondo destaque.
       Sin esto los .fl-boton--fantasma dentro del navbar quedaban en texto
       neutro-900 casi negro sobre el navbar oscuro. */
    --fl-texto:          var(--fl-destaque-texto);
    --fl-texto-fuerte:   var(--fl-destaque-texto);
    --fl-texto-suave:    color-mix(in srgb, var(--fl-destaque-texto) 75%, transparent);
    --fl-texto-tenue:    color-mix(in srgb, var(--fl-destaque-texto) 55%, transparent);
    --fl-superficie-hover: color-mix(in srgb, var(--fl-destaque-texto) 12%, transparent);
    --fl-superficie-activa: color-mix(in srgb, var(--fl-destaque-texto) 18%, transparent);

    display: flex;
    align-items: center;
    gap: var(--fl-sp-4);
    padding: 0 var(--fl-sp-5);
    height: 56px;
    min-height: 56px;
    background: var(--fl-destaque-fondo);
    color: var(--fl-destaque-texto);
    border-bottom: 1px solid var(--_separador);
    position: sticky;
    top: 0;
    z-index: var(--fl-z-pegajoso);
}

/* Variante sobria — opt-out */
.fl-navbar--sobrio {
    background: var(--fl-superficie);
    color: var(--fl-texto);
    --_separador: var(--fl-borde);
    border-bottom: 1px solid var(--fl-borde);
}

/* Fuerza centrado vertical de todos los descendientes directos */
.fl-navbar > * {
    align-self: center;
}

/* fl-dropdown dentro del navbar debe ser inline-flex alineado */
.fl-navbar .fl-dropdown {
    display: inline-flex;
    align-items: center;
}

.fl-navbar--elevada {
    box-shadow: var(--fl-sombra-xs);
    border-bottom-color: transparent;
}

/* Marca / logo — el componente <x-flora::marca> provee el combo; navbar
   sólo agrega padding y hover propio de la barra. */
.fl-navbar-marca {
    padding: var(--fl-sp-1) var(--fl-sp-2);
    margin-left: calc(-1 * var(--fl-sp-2));
    border-radius: var(--fl-r-md);
    transition: background var(--fl-t-rapido);
}

.fl-navbar-marca:hover {
    background: color-mix(in srgb, var(--fl-destaque-texto) 12%, transparent);
    opacity: 1; /* override del default .fl-marca hover */
}

.fl-navbar .fl-marca-nombre { color: var(--fl-destaque-texto); }

/* Navegación principal — links horizontales */
.fl-navbar-nav {
    display: flex;
    align-items: center;
    gap: 2px;
    height: 100%;
}

.fl-navbar-nav-item {
    display: inline-flex;
    align-items: center;
    gap: var(--fl-sp-1-5);
    padding: 0 var(--fl-sp-3);
    height: 36px;
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-medio);
    color: color-mix(in srgb, var(--fl-destaque-texto) 75%, transparent);
    text-decoration: none;
    border-radius: var(--fl-r-md);
    white-space: nowrap;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida),
                color var(--fl-t-rapido) var(--fl-ease-salida);
    position: relative;
}

.fl-navbar-nav-item:hover {
    background: color-mix(in srgb, var(--fl-destaque-texto) 12%, transparent);
    color: var(--fl-destaque-texto);
}

.fl-navbar-nav-item:focus-visible {
    outline: none;
    background: color-mix(in srgb, var(--fl-destaque-texto) 12%, transparent);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--fl-destaque-texto) 35%, transparent);
}

/* Activo — underline del color del texto sobre destaque (alto contraste).
   Aplicamos tanto por clase como por aria-current para que el JS pueda
   usar cualquiera de los dos. */
.fl-navbar-nav-item.fl-navbar-nav-item--activo,
.fl-navbar-nav-item[aria-current="page"] {
    color: var(--fl-destaque-texto);
    background: transparent;
    font-weight: var(--fl-peso-semibold);
}

.fl-navbar-nav-item.fl-navbar-nav-item--activo::after,
.fl-navbar-nav-item[aria-current="page"]::after {
    content: "";
    position: absolute;
    left: var(--fl-sp-3);
    right: var(--fl-sp-3);
    bottom: -2px;
    height: 2px;
    background: var(--fl-destaque-texto);
    border-radius: 2px 2px 0 0;
    animation: fl-underline-dibuja 240ms var(--fl-ease-salida) both;
}

.fl-navbar-nav-item.fl-navbar-nav-item--activo:hover,
.fl-navbar-nav-item[aria-current="page"]:hover {
    background: color-mix(in srgb, var(--fl-destaque-texto) 12%, transparent);
    color: var(--fl-destaque-texto);
}

@keyframes fl-underline-dibuja {
    from { transform: scaleX(0); transform-origin: left center; }
    to   { transform: scaleX(1); transform-origin: left center; }
}

.fl-navbar-nav-item .fl-icono {
    width: 16px;
    height: 16px;
}

/* Área de acciones a la derecha */
.fl-navbar-espaciador {
    flex: 1;
    min-height: 1px;
}

.fl-navbar-acciones {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-1);
}

/* Buscador global opcional */
.fl-navbar-buscador {
    flex: 1;
    max-width: 400px;
    min-width: 180px;
}

/* Input del buscador en navbar destaque (oscuro) — theme glass/translúcido
   para que se integre con la barra y el texto sea legible. Sin esto, el
   override de --fl-texto-fuerte (blanco) del navbar pintaba el texto sobre
   el fondo blanco del .fl-campo-entrada → invisible. Mismo con el ícono.
   Scopeado a la variante default (no sobrio, que tiene fondo claro). */
.fl-navbar:not(.fl-navbar--sobrio) .fl-navbar-buscador .fl-campo-entrada {
    background: color-mix(in srgb, var(--fl-destaque-texto) 12%, transparent);
    border-color: color-mix(in srgb, var(--fl-destaque-texto) 25%, transparent);
    color: var(--fl-destaque-texto);
}

.fl-navbar:not(.fl-navbar--sobrio) .fl-navbar-buscador .fl-campo-entrada::placeholder {
    color: color-mix(in srgb, var(--fl-destaque-texto) 55%, transparent);
    opacity: 1;
}

.fl-navbar:not(.fl-navbar--sobrio) .fl-navbar-buscador .fl-campo-entrada:hover:not(:focus) {
    background: color-mix(in srgb, var(--fl-destaque-texto) 16%, transparent);
    border-color: color-mix(in srgb, var(--fl-destaque-texto) 35%, transparent);
}

.fl-navbar:not(.fl-navbar--sobrio) .fl-navbar-buscador .fl-campo-entrada:focus {
    background: color-mix(in srgb, var(--fl-destaque-texto) 20%, transparent);
    border-color: color-mix(in srgb, var(--fl-destaque-texto) 50%, transparent);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--fl-destaque-texto) 25%, transparent);
}

.fl-navbar:not(.fl-navbar--sobrio) .fl-navbar-buscador .fl-campo-grupo-icono {
    color: color-mix(in srgb, var(--fl-destaque-texto) 70%, transparent);
}

/* Crucecita nativa de input[type="search"] — por default es un X gris
   oscuro que se pierde contra el navbar destaque. Reemplazamos con una
   X claro via mask-image, con hover que la intensifica. */
.fl-navbar:not(.fl-navbar--sobrio) .fl-navbar-buscador .fl-campo-entrada::-webkit-search-cancel-button {
    -webkit-appearance: none;
    appearance: none;
    width: 14px;
    height: 14px;
    background-color: color-mix(in srgb, var(--fl-destaque-texto) 70%, transparent);
    -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round'><path d='M6 6l12 12M18 6L6 18'/></svg>");
    mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round'><path d='M6 6l12 12M18 6L6 18'/></svg>");
    -webkit-mask-size: contain;
    mask-size: contain;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
    cursor: pointer;
    transition: background-color var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-navbar:not(.fl-navbar--sobrio) .fl-navbar-buscador .fl-campo-entrada::-webkit-search-cancel-button:hover {
    background-color: var(--fl-destaque-texto);
}

/* Botones fantasma dentro del navbar destaque (campanita, menú usuario) —
   por default usan --fl-acento-texto, que es un tono oscuro del acento y
   se pierde contra el fondo destaque. Forzamos blanco/destaque-texto. */
.fl-navbar:not(.fl-navbar--sobrio) .fl-boton--fantasma {
    color: var(--fl-destaque-texto);
}

.fl-navbar:not(.fl-navbar--sobrio) .fl-boton--fantasma:hover:not(:disabled),
.fl-navbar:not(.fl-navbar--sobrio) .fl-boton--fantasma:active:not(:disabled) {
    color: var(--fl-destaque-texto);
    background: color-mix(in srgb, var(--fl-destaque-texto) 14%, transparent);
}

/* Responsive: ocultar nav principal en mobile (requiere drawer) */
@media (max-width: 767px) {
    .fl-navbar-nav {
        display: none;
    }
    .fl-navbar-buscador {
        display: none;
    }
}


/* ===== resources/css/componentes/onda.css ===== */
/* ==========================================================================
   Flora · Onda (waveform visualizer)
   Barras verticales simulando el perfil de un audio. Puede ser:
    - Estática: recibe array de amplitudes, las renderiza como bars
    - Con progreso: las barras antes de `--_progreso` van pintadas (played),
      las de después quedan atenuadas (unplayed)

   Ideal al lado de un fl-player o embebido en una fila de lista de canciones.
   ========================================================================== */

.fl-onda {
    --_progreso: 0%;
    display: flex;
    align-items: center;
    gap: 2px;
    height: 40px;
    width: 100%;
    padding: var(--fl-sp-1) 0;
    overflow: hidden;
}

.fl-onda-barra {
    flex: 1 1 0;
    min-width: 2px;
    max-width: 4px;
    /* Tint del acento (no gris neutro) — integra visualmente con la paleta. */
    background: color-mix(in srgb, var(--fl-acento) 28%, transparent);
    border-radius: var(--fl-r-full);
    height: var(--_altura, 40%);
    transition: background var(--fl-t-rapido) var(--fl-ease-salida);
}

/* Barras "reproducidas" — hasta donde llega el progreso */
.fl-onda[data-fl-progreso]:hover,
.fl-onda--interactiva {
    cursor: pointer;
}

.fl-onda-barra[data-fl-reproducida="true"] {
    background: var(--fl-acento);
}

/* Interactiva — las barras reaccionan al hover del container para dar
   feedback visual antes del click (estilo SoundCloud). */
.fl-onda--interactiva:hover .fl-onda-barra {
    background: color-mix(in srgb, var(--fl-acento) 45%, transparent);
}

.fl-onda--interactiva:hover .fl-onda-barra[data-fl-reproducida="true"] {
    background: var(--fl-acento-600);
}

.fl-onda--interactiva:active .fl-onda-barra {
    transition: none;
}

/* --------------------------------------------------------------------------
   Tamaños
   -------------------------------------------------------------------------- */
.fl-onda--sm { height: 24px; }
.fl-onda--sm .fl-onda-barra { max-width: 3px; }

.fl-onda--lg { height: 64px; }
.fl-onda--lg .fl-onda-barra { max-width: 5px; }

.fl-onda--xl { height: 96px; }

/* --------------------------------------------------------------------------
   Variante reproduciendo — barra cercana al progreso se anima
   -------------------------------------------------------------------------- */
.fl-onda--reproduciendo .fl-onda-barra[data-fl-reproducida="true"]:last-of-type {
    animation: fl-onda-pulsa 900ms var(--fl-ease-inout) infinite alternate;
}

@keyframes fl-onda-pulsa {
    from { transform: scaleY(0.8); }
    to   { transform: scaleY(1.08); }
}

@media (prefers-reduced-motion: reduce) {
    .fl-onda-barra { animation: none !important; }
}


/* ===== resources/css/componentes/paginacion.css ===== */
/* ==========================================================================
   Flora · Paginación
   Navegación de páginas. Botones prev/next + números o sólo prev/next.
   ========================================================================== */

.fl-paginacion {
    display: inline-flex;
    align-items: center;
    gap: var(--fl-sp-1);
    list-style: none;
    padding: 0;
    margin: 0;
    font-size: var(--fl-texto-sm);
}

.fl-paginacion-item {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 36px;
    height: 36px;
    padding: 0 var(--fl-sp-2);
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--fl-r-md);
    color: var(--fl-texto-suave);
    cursor: pointer;
    text-decoration: none;
    font-weight: var(--fl-peso-medio);
    font-variant-numeric: tabular-nums;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida),
                color var(--fl-t-rapido) var(--fl-ease-salida),
                border-color var(--fl-t-rapido) var(--fl-ease-salida),
                transform 80ms var(--fl-ease-salida);
}

.fl-paginacion-item:hover:not(:disabled):not(.fl-paginacion-item--actual):not(.fl-paginacion-item--elipsis) {
    background: var(--fl-superficie-hover);
    color: var(--fl-texto-fuerte);
    border-color: var(--fl-borde);
}

.fl-paginacion-item:active:not(:disabled) {
    transform: scale(0.96);
}

.fl-paginacion-item:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px var(--fl-acento-foco);
}

/* Página actual — alto contraste con el color de acento del tema.
   Aplicamos tanto por clase como por aria-current para robustez. */
.fl-paginacion-item.fl-paginacion-item--actual,
.fl-paginacion-item[aria-current="page"] {
    background: var(--fl-acento);
    color: var(--fl-acento-texto-sobre, #fff);
    cursor: default;
    border-color: var(--fl-acento);
    font-weight: var(--fl-peso-semibold);
    box-shadow: 0 2px 8px -2px color-mix(in srgb, var(--fl-acento) 50%, transparent);
}

.fl-paginacion-item.fl-paginacion-item--actual:hover,
.fl-paginacion-item[aria-current="page"]:hover {
    background: var(--fl-acento);
    color: var(--fl-acento-texto-sobre, #fff);
    border-color: var(--fl-acento);
}

.fl-paginacion-item--elipsis {
    cursor: default;
    color: var(--fl-texto-tenue);
}

.fl-paginacion-item:disabled,
.fl-paginacion-item[aria-disabled="true"] {
    opacity: 0.4;
    cursor: not-allowed;
    pointer-events: none;
}

.fl-paginacion-item .fl-icono {
    width: 16px;
    height: 16px;
}

/* --------------------------------------------------------------------------
   Variantes
   -------------------------------------------------------------------------- */

/* Compacta — sólo prev/next + info de página */
.fl-paginacion--compacta {
    padding: var(--fl-sp-1) var(--fl-sp-2);
    background: var(--fl-fondo-sutil);
    border: 1px solid var(--fl-borde);
    border-radius: var(--fl-r-md);
}

.fl-paginacion-info {
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto-suave);
    padding: 0 var(--fl-sp-3);
    font-variant-numeric: tabular-nums;
}

/* Tamaños */
.fl-paginacion--sm .fl-paginacion-item {
    min-width: 28px;
    height: 28px;
    font-size: var(--fl-texto-xs);
}

.fl-paginacion--lg .fl-paginacion-item {
    min-width: 44px;
    height: 44px;
    font-size: var(--fl-texto-base);
}


/* ===== resources/css/componentes/pasos.css ===== */
/* ==========================================================================
   Flora · Pasos (stepper standalone)
   Indicador visual de progreso por pasos. Distinto del wizard (wizard maneja
   contenido por paso). Este sólo muestra dónde estoy.
   ========================================================================== */

.fl-pasos {
    display: flex;
    align-items: flex-start;
    gap: 0;
    padding: 0;
}

.fl-pasos--vertical {
    flex-direction: column;
    gap: var(--fl-sp-1);
}

/* Cada paso */
.fl-pasos-item {
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2-5);
    flex: 1 1 0;
    min-width: 0;
}

.fl-pasos--vertical .fl-pasos-item {
    flex: none;
    width: 100%;
}

/* Línea conectora */
.fl-pasos-item:not(:last-child)::after {
    content: "";
    flex: 1 1 auto;
    height: 2px;
    background: var(--fl-borde-intenso);
    margin: 0 var(--fl-sp-2);
    align-self: center;
    border-radius: var(--fl-r-full);
    transition: background var(--fl-t-medio);
}

.fl-pasos--vertical .fl-pasos-item:not(:last-child)::after {
    position: absolute;
    width: 2px;
    height: auto;
    top: 32px;
    bottom: -12px;
    left: 14px;
    flex: none;
    margin: 0;
}

.fl-pasos-item[data-fl-estado="completado"]:not(:last-child)::after { background: var(--fl-acento); }
.fl-pasos-item[data-fl-estado="actual"]:not(:last-child)::after {
    background: linear-gradient(to right, var(--fl-acento) 0%, var(--fl-borde-intenso) 100%);
}
.fl-pasos-item[data-fl-estado="pendiente"]:not(:last-child)::after { background: var(--fl-borde); }

/* Círculo indicador */
.fl-pasos-indicador {
    width: 30px;
    height: 30px;
    border-radius: var(--fl-r-full);
    background: var(--fl-superficie);
    border: 2px solid var(--fl-borde-intenso);
    color: var(--fl-texto-tenue);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-semibold);
    flex: none;
    transition: all var(--fl-t-medio);
    z-index: 1;
}

.fl-pasos-indicador .fl-icono { width: 16px; height: 16px; }

.fl-pasos-item[data-fl-estado="actual"] .fl-pasos-indicador {
    background: var(--fl-destaque-fondo);
    border-color: var(--fl-destaque-fondo);
    color: var(--fl-destaque-texto);
    box-shadow: 0 0 0 4px var(--fl-acento-foco);
}

.fl-pasos-item[data-fl-estado="completado"] .fl-pasos-indicador {
    background: var(--fl-acento);
    border-color: var(--fl-acento);
    color: var(--fl-acento-texto-sobre);
}

.fl-pasos-item[data-fl-estado="error"] .fl-pasos-indicador {
    background: var(--fl-error);
    border-color: var(--fl-error);
    color: var(--fl-neutro-0);
}

.fl-pasos-texto {
    min-width: 0;
    flex: 0 1 auto;
}

.fl-pasos-etiqueta {
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-suave);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.fl-pasos-descripcion {
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-tenue);
    margin-top: 1px;
}

.fl-pasos-item[data-fl-estado="actual"] .fl-pasos-etiqueta {
    color: var(--fl-texto-fuerte);
    font-weight: var(--fl-peso-bold);
}

.fl-pasos-item[data-fl-estado="completado"] .fl-pasos-etiqueta {
    color: var(--fl-texto-fuerte);
    font-weight: var(--fl-peso-semibold);
}

.fl-pasos-item[data-fl-estado="pendiente"] .fl-pasos-etiqueta {
    color: var(--fl-texto-tenue);
    font-weight: var(--fl-peso-medio);
}

/* Tamaños */
.fl-pasos--sm .fl-pasos-indicador { width: 24px; height: 24px; font-size: var(--fl-texto-xs); }
.fl-pasos--sm .fl-pasos-indicador .fl-icono { width: 12px; height: 12px; }
.fl-pasos--lg .fl-pasos-indicador { width: 36px; height: 36px; font-size: var(--fl-texto-base); }
.fl-pasos--lg .fl-pasos-indicador .fl-icono { width: 20px; height: 20px; }

/* Variante puntos (dot only) */
.fl-pasos--puntos .fl-pasos-indicador { width: 10px; height: 10px; }
.fl-pasos--puntos .fl-pasos-indicador > * { display: none; }


/* ===== resources/css/componentes/plantillas.css ===== */
/* ==========================================================================
   Flora · Plantillas · base
   Wrappers para las pantallas estándar de un admin CRUD. Cada plantilla
   (lista/form/detalle/panel/auth) tiene su archivo propio y comparte esta
   base. No definen markup nuevo — componen organismos existentes.
   ========================================================================== */

.fl-plantilla {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-5);
    width: 100%;
}
/* ==========================================================================
   Flora · Plantilla LISTA
   header + [metricas] + (filtros lateral) + (tabs + toolbar + tabla + paginación)
   ========================================================================== */

/* Métricas strip debajo del header */
.fl-plantilla-lista-metricas {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: var(--fl-sp-3);
}

.fl-plantilla-lista-cuerpo {
    display: flex;
    gap: var(--fl-sp-5);
    align-items: flex-start;
}

.fl-plantilla-lista-filtros {
    flex: 0 0 260px;
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-3);
    padding: var(--fl-sp-4);
    background: color-mix(in srgb, var(--fl-acento) 5%, var(--fl-superficie));
    border: 1px solid color-mix(in srgb, var(--fl-acento) 15%, var(--fl-borde));
    border-radius: var(--fl-r-lg);
    position: sticky;
    top: var(--fl-sp-4);
}

.fl-plantilla-lista-filtros-titulo {
    font-size: var(--fl-texto-2xs);
    font-weight: var(--fl-peso-semibold);
    text-transform: uppercase;
    letter-spacing: var(--fl-ls-mayus);
    color: var(--fl-acento-texto);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-bottom: var(--fl-sp-2);
    border-bottom: 1px solid color-mix(in srgb, var(--fl-acento) 18%, var(--fl-borde-sutil));
}

.fl-plantilla-lista-filtros-grupo {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-1-5);
}

.fl-plantilla-lista-filtros-grupo-titulo {
    font-size: var(--fl-texto-xs);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-fuerte);
    letter-spacing: var(--fl-ls-compacto);
}

.fl-plantilla-lista-principal {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-3);
}

/* Tabs/segmentos arriba de la toolbar — vista filter-by-section */
.fl-plantilla-lista-tabs {
    display: flex;
    align-items: center;
    gap: 2px;
    padding: 4px;
    background: color-mix(in srgb, var(--fl-acento) 6%, var(--fl-fondo-sutil));
    border: 1px solid color-mix(in srgb, var(--fl-acento) 14%, var(--fl-borde));
    border-radius: var(--fl-r-lg);
    overflow-x: auto;
    scrollbar-width: none;
}

.fl-plantilla-lista-tabs::-webkit-scrollbar { display: none; }

.fl-plantilla-lista-tab {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    background: transparent;
    border: 0;
    border-radius: var(--fl-r-md);
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-medio);
    color: var(--fl-texto-suave);
    cursor: pointer;
    text-decoration: none;
    white-space: nowrap;
    transition: background var(--fl-t-rapido), color var(--fl-t-rapido);
}

.fl-plantilla-lista-tab:hover {
    color: var(--fl-texto-fuerte);
    background: color-mix(in srgb, var(--fl-superficie) 60%, transparent);
}

.fl-plantilla-lista-tab--activo {
    background: var(--fl-superficie);
    color: var(--fl-acento-texto);
    box-shadow: 0 1px 2px rgb(0 0 0 / .06),
                0 0 0 1px color-mix(in srgb, var(--fl-acento) 20%, transparent);
}

.fl-plantilla-lista-tab-conteo {
    font-size: 10px;
    padding: 1px 6px;
    background: color-mix(in srgb, currentColor 14%, transparent);
    border-radius: var(--fl-r-full);
    font-variant-numeric: tabular-nums;
    min-width: 18px;
    text-align: center;
}

/* Toolbar: búsqueda + filtros rápidos + acciones */
.fl-plantilla-lista-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--fl-sp-3);
    flex-wrap: wrap;
    padding: var(--fl-sp-2-5) var(--fl-sp-3);
    background: color-mix(in srgb, var(--fl-acento) 4%, var(--fl-superficie));
    border: 1px solid color-mix(in srgb, var(--fl-acento) 12%, var(--fl-borde));
    border-radius: var(--fl-r-lg);
}

.fl-plantilla-lista-toolbar-izq,
.fl-plantilla-lista-toolbar-der {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
    flex-wrap: wrap;
}

.fl-plantilla-lista-toolbar-izq {
    flex: 1;
    min-width: 200px;
}

.fl-plantilla-lista-toolbar-der {
    flex: none;
}

.fl-plantilla-lista-contenido {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-3);
}

/* Paginación con resumen de totales a la izquierda */
.fl-plantilla-lista-paginacion {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--fl-sp-3);
    padding: var(--fl-sp-2) var(--fl-sp-1);
    flex-wrap: wrap;
}

.fl-plantilla-lista-paginacion-resumen {
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-tenue);
    font-variant-numeric: tabular-nums;
}

.fl-plantilla-lista-paginacion-resumen strong {
    color: var(--fl-texto-fuerte);
    font-weight: var(--fl-peso-semibold);
}

@media (max-width: 900px) {
    .fl-plantilla-lista-cuerpo {
        flex-direction: column;
    }
    .fl-plantilla-lista-filtros {
        flex: 0 0 auto;
        width: 100%;
        position: static;
    }
    .fl-plantilla-lista-paginacion {
        justify-content: center;
    }
}
/* ==========================================================================
   Flora · Plantilla FORMULARIO
   header + (principal + [lateral]) + [pie sticky]
   ========================================================================== */
.fl-plantilla-form-cuerpo {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-4);
}

.fl-plantilla-form-cuerpo--con-lateral {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 320px;
    gap: var(--fl-sp-5);
    align-items: start;
}

.fl-plantilla-form-principal {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-4);
    min-width: 0;
}

.fl-plantilla-form-lateral {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-3);
    position: sticky;
    top: var(--fl-sp-4);
}

.fl-plantilla-form-pie {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    gap: var(--fl-sp-2);
    padding: var(--fl-sp-3) var(--fl-sp-4);
    background: var(--fl-superficie);
    border: 1px solid var(--fl-borde);
    border-radius: var(--fl-r-lg);
}

.fl-plantilla-form-pie--sticky {
    position: sticky;
    bottom: var(--fl-sp-3);
    z-index: 10;
    box-shadow: 0 -4px 16px -8px color-mix(in srgb, var(--fl-sombra-color) 30%, transparent);
    backdrop-filter: blur(6px);
    background: color-mix(in srgb, var(--fl-superficie) 92%, transparent);
}

@media (max-width: 900px) {
    .fl-plantilla-form-cuerpo--con-lateral {
        grid-template-columns: minmax(0, 1fr);
    }
    .fl-plantilla-form-lateral {
        position: static;
    }
}
/* ==========================================================================
   Flora · Plantilla DETALLE
   hero/header + [kpis] + (principal + [lateral metadata])
   Lenguaje visual: gradient dark palette en el hero, tarjetas con tintes
   alternados en el principal, lateral con secciones jerárquicas.
   ========================================================================== */

/* HERO — reemplazo premium del header-pagina para pantallas de detalle */
.fl-plantilla-detalle-hero {
    position: relative;
    padding: var(--fl-sp-5) var(--fl-sp-6);
    background: linear-gradient(
        135deg,
        var(--fl-acento-800) 0%,
        var(--fl-acento-900) 50%,
        color-mix(in srgb, var(--fl-acento-950) 80%, #000) 100%
    );
    border: 1px solid var(--fl-acento-900);
    border-radius: var(--fl-r-lg);
    color: var(--fl-acento-texto-sobre);
    overflow: hidden;
    box-shadow: 0 14px 36px -14px color-mix(in srgb, var(--fl-acento-900) 70%, transparent),
                inset 0 1px 0 0 color-mix(in srgb, #fff 10%, transparent);
    isolation: isolate;
}

/* Brillo radial sup-der para dar profundidad */
.fl-plantilla-detalle-hero::before {
    content: "";
    position: absolute;
    top: -120px;
    right: -120px;
    width: 380px;
    height: 380px;
    background: radial-gradient(circle, color-mix(in srgb, #fff 10%, transparent) 0%, transparent 65%);
    pointer-events: none;
    z-index: 0;
}

/* Sombra inferior interna */
.fl-plantilla-detalle-hero::after {
    content: "";
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 40%;
    background: linear-gradient(to top, color-mix(in srgb, #000 20%, transparent) 0%, transparent 100%);
    pointer-events: none;
    z-index: 0;
}

.fl-plantilla-detalle-hero > * {
    position: relative;
    z-index: 1;
}

.fl-plantilla-detalle-hero-breadcrumb {
    margin-bottom: var(--fl-sp-3);
    opacity: 0.85;
}

.fl-plantilla-detalle-hero-breadcrumb .fl-breadcrumb,
.fl-plantilla-detalle-hero-breadcrumb .fl-breadcrumb * {
    color: color-mix(in srgb, var(--fl-acento-texto-sobre) 82%, transparent) !important;
}

.fl-plantilla-detalle-hero-breadcrumb .fl-breadcrumb-actual {
    color: var(--fl-acento-texto-sobre) !important;
}

.fl-plantilla-detalle-hero-contenido {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-5);
    flex-wrap: wrap;
}

.fl-plantilla-detalle-hero-avatar {
    flex: none;
    width: 96px;
    height: 96px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--fl-r-lg);
    background: color-mix(in srgb, #fff 14%, transparent);
    border: 2px solid color-mix(in srgb, #fff 28%, transparent);
    box-shadow: 0 8px 20px -8px rgb(0 0 0 / 0.4),
                inset 0 1px 0 0 color-mix(in srgb, #fff 20%, transparent);
    backdrop-filter: blur(8px);
    color: var(--fl-acento-texto-sobre);
    font-size: var(--fl-texto-3xl);
    font-weight: var(--fl-peso-bold);
    text-transform: uppercase;
    letter-spacing: var(--fl-ls-compacto);
    overflow: hidden;
}

.fl-plantilla-detalle-hero-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.fl-plantilla-detalle-hero-info {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-1);
}

.fl-plantilla-detalle-hero-eyebrow {
    font-size: var(--fl-texto-xs);
    font-weight: var(--fl-peso-semibold);
    text-transform: uppercase;
    letter-spacing: var(--fl-ls-mayus);
    color: color-mix(in srgb, var(--fl-acento-texto-sobre) 75%, transparent);
}

.fl-plantilla-detalle-hero-titulo {
    font-size: var(--fl-texto-3xl);
    font-weight: var(--fl-peso-bold);
    color: var(--fl-acento-texto-sobre);
    letter-spacing: var(--fl-ls-compacto);
    line-height: 1.15;
    margin: 0;
    text-shadow: 0 2px 4px rgb(0 0 0 / 0.25);
}

.fl-plantilla-detalle-hero-subtitulo {
    font-size: var(--fl-texto-base);
    color: color-mix(in srgb, var(--fl-acento-texto-sobre) 82%, transparent);
    margin: 0;
}

.fl-plantilla-detalle-hero-meta {
    display: inline-flex;
    flex-wrap: wrap;
    gap: var(--fl-sp-1-5);
    margin-top: var(--fl-sp-2);
}

/* Chips/badges dentro del hero — glass style sobre fondo oscuro */
.fl-plantilla-detalle-hero-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 10px;
    background: color-mix(in srgb, #fff 15%, transparent);
    border: 1px solid color-mix(in srgb, #fff 25%, transparent);
    border-radius: var(--fl-r-full);
    color: var(--fl-acento-texto-sobre);
    font-size: var(--fl-texto-xs);
    font-weight: var(--fl-peso-medio);
    backdrop-filter: blur(6px);
}

.fl-plantilla-detalle-hero-chip .fl-icono {
    width: 12px;
    height: 12px;
}

/* Acciones del hero — botones glass */
.fl-plantilla-detalle-hero-acciones {
    position: absolute;
    top: var(--fl-sp-4);
    right: var(--fl-sp-4);
    display: inline-flex;
    gap: 6px;
    z-index: 2;
}

.fl-plantilla-detalle-hero-boton {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 14px;
    background: color-mix(in srgb, #fff 18%, transparent);
    border: 1px solid color-mix(in srgb, #fff 28%, transparent);
    border-radius: var(--fl-r-md);
    color: var(--fl-acento-texto-sobre);
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-semibold);
    text-decoration: none;
    cursor: pointer;
    backdrop-filter: blur(8px);
    transition: background 160ms, transform 180ms var(--fl-ease-resorte);
}

.fl-plantilla-detalle-hero-boton:hover {
    background: color-mix(in srgb, #fff 28%, transparent);
    transform: translateY(-1px);
}

.fl-plantilla-detalle-hero-boton--primario {
    background: var(--fl-acento-texto-sobre);
    color: var(--fl-acento-900);
    border-color: var(--fl-acento-texto-sobre);
}

.fl-plantilla-detalle-hero-boton--primario:hover {
    background: color-mix(in srgb, var(--fl-acento-texto-sobre) 90%, var(--fl-acento-900));
}

.fl-plantilla-detalle-hero-boton--fantasma {
    background: transparent;
    border-color: color-mix(in srgb, #fff 22%, transparent);
}

.fl-plantilla-detalle-hero-boton--peligro {
    background: color-mix(in srgb, var(--fl-error) 80%, transparent);
    border-color: color-mix(in srgb, var(--fl-error) 90%, transparent);
}

.fl-plantilla-detalle-hero-boton--peligro:hover {
    background: var(--fl-error);
}

.fl-plantilla-detalle-hero-boton .fl-icono {
    width: 14px;
    height: 14px;
}

/* KPIs strip debajo del hero */
.fl-plantilla-detalle-kpis {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: var(--fl-sp-3);
}

/* CUERPO / principal / lateral */
.fl-plantilla-detalle-cuerpo {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-4);
}

.fl-plantilla-detalle-cuerpo--con-lateral {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 320px;
    gap: var(--fl-sp-5);
    align-items: start;
}

.fl-plantilla-detalle-principal {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-4);
    min-width: 0;
}

/* Tarjetas dentro del principal alternan tinte sutil para dar ritmo visual */
.fl-plantilla-detalle-principal > .fl-tarjeta:nth-child(even) {
    background: color-mix(in srgb, var(--fl-acento) 5%, var(--fl-superficie));
    border-color: color-mix(in srgb, var(--fl-acento) 15%, var(--fl-borde));
}

/* LATERAL — sticky con secciones coloreadas */
.fl-plantilla-detalle-lateral {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-3);
    position: sticky;
    top: var(--fl-sp-4);
}

.fl-plantilla-detalle-lateral .fl-tarjeta {
    overflow: hidden;
}

/* Header dark dentro de una tarjeta del lateral — pega a los bordes de la card.
   Compensa el padding del .fl-tarjeta-cuerpo (--fl-sp-5) con margins negativos
   en los 3 lados (top, left, right). El bottom queda como separación con el contenido. */
.fl-plantilla-detalle-lateral-header {
    padding: var(--fl-sp-3) var(--fl-sp-4);
    margin: calc(-1 * var(--fl-sp-5)) calc(-1 * var(--fl-sp-5)) var(--fl-sp-4);
    background: linear-gradient(
        135deg,
        var(--fl-acento-800) 0%,
        var(--fl-acento-950) 100%
    );
    color: var(--fl-acento-texto-sobre);
    font-size: var(--fl-texto-xs);
    font-weight: var(--fl-peso-semibold);
    text-transform: uppercase;
    letter-spacing: var(--fl-ls-mayus);
    display: flex;
    align-items: center;
    gap: 6px;
    box-shadow: inset 0 -1px 0 0 color-mix(in srgb, #000 20%, transparent);
}

.fl-plantilla-detalle-lateral-header .fl-icono {
    width: 14px;
    height: 14px;
}

/* Metadatos tipo dl inside lateral */
.fl-plantilla-detalle-lateral-meta {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 10px 12px;
    font-size: var(--fl-texto-xs);
}

.fl-plantilla-detalle-lateral-meta dt {
    color: var(--fl-texto-tenue);
    font-weight: var(--fl-peso-medio);
}

.fl-plantilla-detalle-lateral-meta dd {
    margin: 0;
    color: var(--fl-texto-fuerte);
    font-weight: var(--fl-peso-medio);
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* Timeline de actividad */
.fl-plantilla-detalle-timeline {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-2-5);
    position: relative;
}

.fl-plantilla-detalle-timeline-item {
    display: grid;
    grid-template-columns: 28px 1fr;
    gap: var(--fl-sp-2);
    align-items: flex-start;
    position: relative;
}

.fl-plantilla-detalle-timeline-item:not(:last-child)::before {
    content: "";
    position: absolute;
    left: 13px;
    top: 26px;
    bottom: calc(-1 * var(--fl-sp-2-5));
    width: 2px;
    background: color-mix(in srgb, var(--fl-acento) 20%, var(--fl-borde-sutil));
}

.fl-plantilla-detalle-timeline-punto {
    width: 26px;
    height: 26px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--fl-r-full);
    background: color-mix(in srgb, var(--fl-acento) 20%, var(--fl-superficie));
    border: 2px solid var(--fl-acento);
    color: var(--fl-acento-texto);
    z-index: 1;
    font-size: 10px;
    flex: none;
}

.fl-plantilla-detalle-timeline-punto .fl-icono {
    width: 12px;
    height: 12px;
}

.fl-plantilla-detalle-timeline-cuerpo {
    font-size: var(--fl-texto-xs);
    line-height: 1.5;
}

.fl-plantilla-detalle-timeline-cuerpo strong {
    color: var(--fl-texto-fuerte);
    font-weight: var(--fl-peso-semibold);
}

.fl-plantilla-detalle-timeline-fecha {
    display: block;
    color: var(--fl-texto-tenue);
    font-size: 10px;
    margin-top: 2px;
}

/* Tags dentro del lateral */
.fl-plantilla-detalle-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.fl-plantilla-detalle-tag {
    display: inline-flex;
    align-items: center;
    padding: 3px 9px;
    background: color-mix(in srgb, var(--fl-acento) 12%, var(--fl-superficie));
    border: 1px solid color-mix(in srgb, var(--fl-acento) 22%, var(--fl-borde-sutil));
    border-radius: var(--fl-r-full);
    color: var(--fl-acento-texto);
    font-size: var(--fl-texto-xs);
    font-weight: var(--fl-peso-medio);
    cursor: pointer;
    transition: background 140ms;
}

.fl-plantilla-detalle-tag:hover {
    background: color-mix(in srgb, var(--fl-acento) 18%, var(--fl-superficie));
}

@media (max-width: 900px) {
    .fl-plantilla-detalle-cuerpo--con-lateral {
        grid-template-columns: minmax(0, 1fr);
    }
    .fl-plantilla-detalle-lateral {
        position: static;
    }
    .fl-plantilla-detalle-hero-acciones {
        position: static;
        margin-top: var(--fl-sp-3);
    }
    .fl-plantilla-detalle-hero {
        padding: var(--fl-sp-4);
    }
    .fl-plantilla-detalle-hero-avatar {
        width: 72px;
        height: 72px;
        font-size: var(--fl-texto-xl);
    }
    .fl-plantilla-detalle-hero-titulo {
        font-size: var(--fl-texto-2xl);
    }
}
/* ==========================================================================
   Flora · Plantilla PANEL (dashboard)
   hero + métricas + contenido libre. Lenguaje visual: gradient dark paleta
   en el hero con greeting + period selector + acciones glass. KPIs strip.
   Grid de widgets con tarjetas "premium" (header dark).
   ========================================================================== */
.fl-plantilla-panel-cuerpo {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-5);
}

.fl-plantilla-panel-contenido {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--fl-sp-4);
}

/* HERO premium para dashboard */
.fl-plantilla-panel-hero {
    position: relative;
    padding: var(--fl-sp-5) var(--fl-sp-6);
    background: linear-gradient(
        135deg,
        var(--fl-acento-800) 0%,
        var(--fl-acento-900) 50%,
        color-mix(in srgb, var(--fl-acento-950) 80%, #000) 100%
    );
    border: 1px solid var(--fl-acento-900);
    border-radius: var(--fl-r-lg);
    color: var(--fl-acento-texto-sobre);
    overflow: hidden;
    box-shadow: 0 14px 36px -14px color-mix(in srgb, var(--fl-acento-900) 70%, transparent),
                inset 0 1px 0 0 color-mix(in srgb, #fff 10%, transparent);
    isolation: isolate;
}

.fl-plantilla-panel-hero::before {
    content: "";
    position: absolute;
    top: -140px;
    right: -80px;
    width: 420px;
    height: 420px;
    background: radial-gradient(circle, color-mix(in srgb, #fff 12%, transparent) 0%, transparent 65%);
    pointer-events: none;
    z-index: 0;
}

.fl-plantilla-panel-hero::after {
    content: "";
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 35%;
    background: linear-gradient(to top, color-mix(in srgb, #000 22%, transparent) 0%, transparent 100%);
    pointer-events: none;
    z-index: 0;
}

.fl-plantilla-panel-hero > * {
    position: relative;
    z-index: 1;
}

.fl-plantilla-panel-hero-breadcrumb {
    margin-bottom: var(--fl-sp-3);
}

.fl-plantilla-panel-hero-breadcrumb .fl-breadcrumb,
.fl-plantilla-panel-hero-breadcrumb .fl-breadcrumb * {
    color: color-mix(in srgb, var(--fl-acento-texto-sobre) 82%, transparent) !important;
}

.fl-plantilla-panel-hero-breadcrumb .fl-breadcrumb-actual {
    color: var(--fl-acento-texto-sobre) !important;
}

.fl-plantilla-panel-hero-contenido {
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    gap: var(--fl-sp-4);
    flex-wrap: wrap;
}

.fl-plantilla-panel-hero-greeting {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-1);
    min-width: 0;
}

.fl-plantilla-panel-hero-eyebrow {
    font-size: var(--fl-texto-xs);
    font-weight: var(--fl-peso-semibold);
    text-transform: uppercase;
    letter-spacing: var(--fl-ls-mayus);
    color: color-mix(in srgb, var(--fl-acento-texto-sobre) 75%, transparent);
}

.fl-plantilla-panel-hero-titulo {
    font-size: var(--fl-texto-3xl);
    font-weight: var(--fl-peso-bold);
    color: var(--fl-acento-texto-sobre);
    letter-spacing: var(--fl-ls-compacto);
    line-height: 1.15;
    margin: 0;
    text-shadow: 0 2px 4px rgb(0 0 0 / 0.25);
}

.fl-plantilla-panel-hero-subtitulo {
    font-size: var(--fl-texto-sm);
    color: color-mix(in srgb, var(--fl-acento-texto-sobre) 80%, transparent);
    margin: 0;
}

/* Period selector glass style */
.fl-plantilla-panel-hero-periodos {
    display: inline-flex;
    padding: 4px;
    background: color-mix(in srgb, #fff 10%, transparent);
    border: 1px solid color-mix(in srgb, #fff 22%, transparent);
    border-radius: var(--fl-r-lg);
    backdrop-filter: blur(10px);
    gap: 2px;
}

.fl-plantilla-panel-hero-periodo {
    display: inline-flex;
    align-items: center;
    padding: 6px 14px;
    background: transparent;
    border: 0;
    border-radius: var(--fl-r-md);
    color: color-mix(in srgb, var(--fl-acento-texto-sobre) 78%, transparent);
    font-size: var(--fl-texto-xs);
    font-weight: var(--fl-peso-semibold);
    cursor: pointer;
    text-decoration: none;
    transition: background 160ms, color 160ms;
    white-space: nowrap;
}

.fl-plantilla-panel-hero-periodo:hover {
    color: var(--fl-acento-texto-sobre);
    background: color-mix(in srgb, #fff 10%, transparent);
}

.fl-plantilla-panel-hero-periodo--activo {
    background: var(--fl-acento-texto-sobre);
    color: var(--fl-acento-900);
    box-shadow: 0 2px 6px -2px rgb(0 0 0 / 0.3);
}

/* Acciones del hero panel — floating top-right */
.fl-plantilla-panel-hero-acciones {
    position: absolute;
    top: var(--fl-sp-4);
    right: var(--fl-sp-5);
    display: inline-flex;
    gap: 6px;
    z-index: 2;
}

.fl-plantilla-panel-hero-boton {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 14px;
    background: color-mix(in srgb, #fff 16%, transparent);
    border: 1px solid color-mix(in srgb, #fff 26%, transparent);
    border-radius: var(--fl-r-md);
    color: var(--fl-acento-texto-sobre);
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-semibold);
    text-decoration: none;
    cursor: pointer;
    backdrop-filter: blur(8px);
    transition: background 160ms, transform 180ms var(--fl-ease-resorte);
}

.fl-plantilla-panel-hero-boton:hover {
    background: color-mix(in srgb, #fff 26%, transparent);
    transform: translateY(-1px);
}

.fl-plantilla-panel-hero-boton--primario {
    background: var(--fl-acento-texto-sobre);
    color: var(--fl-acento-900);
    border-color: var(--fl-acento-texto-sobre);
}

.fl-plantilla-panel-hero-boton--primario:hover {
    background: color-mix(in srgb, var(--fl-acento-texto-sobre) 90%, var(--fl-acento-900));
}

.fl-plantilla-panel-hero-boton .fl-icono {
    width: 14px;
    height: 14px;
}

/* Widgets premium: header dark pegado a los bordes (como en plantilla-detalle) */
.fl-panel-widget-header {
    padding: var(--fl-sp-3) var(--fl-sp-4);
    margin: calc(-1 * var(--fl-sp-5)) calc(-1 * var(--fl-sp-5)) var(--fl-sp-4);
    background: linear-gradient(
        135deg,
        var(--fl-acento-800) 0%,
        var(--fl-acento-950) 100%
    );
    color: var(--fl-acento-texto-sobre);
    font-size: var(--fl-texto-xs);
    font-weight: var(--fl-peso-semibold);
    text-transform: uppercase;
    letter-spacing: var(--fl-ls-mayus);
    display: flex;
    align-items: center;
    gap: 6px;
    justify-content: space-between;
    box-shadow: inset 0 -1px 0 0 color-mix(in srgb, #000 20%, transparent);
}

.fl-panel-widget-header-titulo {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.fl-panel-widget-header .fl-icono {
    width: 14px;
    height: 14px;
}

.fl-panel-widget-header-acciones {
    display: inline-flex;
    gap: 4px;
    color: color-mix(in srgb, var(--fl-acento-texto-sobre) 85%, transparent);
}

.fl-panel-widget-header-acciones a,
.fl-panel-widget-header-acciones button {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    background: color-mix(in srgb, #fff 14%, transparent);
    border: 1px solid color-mix(in srgb, #fff 22%, transparent);
    border-radius: var(--fl-r-sm);
    color: inherit;
    font-size: 10px;
    font-weight: var(--fl-peso-semibold);
    text-transform: none;
    letter-spacing: 0;
    cursor: pointer;
    text-decoration: none;
    transition: background 140ms;
}

.fl-panel-widget-header-acciones a:hover,
.fl-panel-widget-header-acciones button:hover {
    background: color-mix(in srgb, #fff 22%, transparent);
}

/* Top list ranking — para widgets tipo "Top clientes / productos" */
.fl-panel-ranking {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-2-5);
}

.fl-panel-ranking-item {
    display: grid;
    grid-template-columns: 28px 1fr auto;
    gap: var(--fl-sp-2);
    align-items: center;
}

.fl-panel-ranking-pos {
    width: 24px;
    height: 24px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: color-mix(in srgb, var(--fl-acento) 14%, var(--fl-fondo-sutil));
    color: var(--fl-acento-texto);
    border-radius: var(--fl-r-full);
    font-size: 11px;
    font-weight: var(--fl-peso-bold);
    font-variant-numeric: tabular-nums;
}

.fl-panel-ranking-item:nth-child(1) .fl-panel-ranking-pos {
    background: var(--fl-acento-900);
    color: var(--fl-acento-texto-sobre);
}

.fl-panel-ranking-item:nth-child(2) .fl-panel-ranking-pos {
    background: var(--fl-acento-700);
    color: var(--fl-acento-texto-sobre);
}

.fl-panel-ranking-item:nth-child(3) .fl-panel-ranking-pos {
    background: var(--fl-acento-500);
    color: var(--fl-acento-texto-sobre);
}

.fl-panel-ranking-info {
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.fl-panel-ranking-nombre {
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-fuerte);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.fl-panel-ranking-sub {
    font-size: 10px;
    color: var(--fl-texto-tenue);
}

.fl-panel-ranking-valor {
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-fuerte);
    font-variant-numeric: tabular-nums;
}

.fl-panel-ranking-barra {
    height: 4px;
    background: color-mix(in srgb, var(--fl-acento) 14%, var(--fl-fondo-sutil));
    border-radius: var(--fl-r-full);
    overflow: hidden;
    grid-column: 2 / -1;
    margin-top: 4px;
}

.fl-panel-ranking-barra-fill {
    display: block;
    height: 100%;
    background: var(--fl-acento);
    border-radius: var(--fl-r-full);
}

/* Mini sparkline chart mock (placeholder visual para widgets) */
.fl-panel-chart-mock {
    position: relative;
    width: 100%;
    height: 220px;
    background: linear-gradient(
        to top,
        color-mix(in srgb, var(--fl-acento) 14%, var(--fl-fondo-sutil)) 0%,
        transparent 100%
    );
    border-radius: var(--fl-r-md);
    overflow: hidden;
}

.fl-panel-chart-mock::before {
    content: "";
    position: absolute;
    inset: 0;
    background-image:
        linear-gradient(to right, color-mix(in srgb, var(--fl-borde) 50%, transparent) 1px, transparent 1px),
        linear-gradient(to bottom, color-mix(in srgb, var(--fl-borde) 50%, transparent) 1px, transparent 1px);
    background-size: 14.28% 25%;
    opacity: 0.5;
}

.fl-panel-chart-mock svg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
}

/* Quick actions grid */
.fl-panel-quick-actions {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--fl-sp-2);
}

.fl-panel-quick-action {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
    padding: var(--fl-sp-3);
    background: color-mix(in srgb, var(--fl-acento) 6%, var(--fl-superficie));
    border: 1px solid color-mix(in srgb, var(--fl-acento) 16%, var(--fl-borde));
    border-radius: var(--fl-r-md);
    text-decoration: none;
    cursor: pointer;
    transition: background 160ms, transform 160ms var(--fl-ease-resorte), border-color 160ms;
}

.fl-panel-quick-action:hover {
    background: color-mix(in srgb, var(--fl-acento) 14%, var(--fl-superficie));
    border-color: var(--fl-acento);
    transform: translateY(-2px);
}

.fl-panel-quick-action-icono {
    width: 36px;
    height: 36px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--fl-acento-800);
    color: var(--fl-acento-texto-sobre);
    border-radius: var(--fl-r-md);
}

.fl-panel-quick-action-icono .fl-icono {
    width: 18px;
    height: 18px;
}

.fl-panel-quick-action-titulo {
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-fuerte);
    line-height: 1.2;
}

.fl-panel-quick-action-sub {
    font-size: 10px;
    color: var(--fl-texto-tenue);
    line-height: 1.3;
}

@media (max-width: 768px) {
    .fl-plantilla-panel-hero {
        padding: var(--fl-sp-4);
    }
    .fl-plantilla-panel-hero-contenido {
        align-items: flex-start;
        flex-direction: column;
    }
    .fl-plantilla-panel-hero-titulo {
        font-size: var(--fl-texto-2xl);
    }
    .fl-plantilla-panel-hero-acciones {
        position: static;
        margin-top: var(--fl-sp-3);
    }
    .fl-panel-quick-actions {
        grid-template-columns: 1fr;
    }
}

/* ==========================================================================
   Flora · Plantilla AUTH (login/registro) — premium
   Card centrada con logo grande arriba + app name abajo, background con
   8 círculos autónomos animados + radial gradient tintado de paleta.
   Links sin underline (solo hover).
   ========================================================================== */
.fl-plantilla--auth {
    position: fixed;
    inset: 0;
    display: grid;
    grid-template-columns: 1fr;
    gap: 0;
    overflow: hidden;
    /* Background abstracto "mesh gradient" + FORMAS GEOMÉTRICAS —
       capas de blobs (oscuros 800/900/950 + claros 400/500/600) + SVG con
       círculos, triángulos, diamantes. Todo paleta. */
    background:
        radial-gradient(ellipse 55% 50% at 12% 18%,
            color-mix(in srgb, var(--fl-acento-500) 85%, transparent) 0%,
            transparent 55%),
        radial-gradient(ellipse 70% 60% at 88% 82%,
            color-mix(in srgb, var(--fl-acento-900) 92%, transparent) 0%,
            transparent 55%),
        radial-gradient(ellipse 45% 40% at 82% 15%,
            color-mix(in srgb, var(--fl-acento-400) 72%, transparent) 0%,
            transparent 50%),
        radial-gradient(ellipse 50% 60% at 18% 75%,
            color-mix(in srgb, var(--fl-acento-800) 85%, transparent) 0%,
            transparent 55%),
        radial-gradient(circle at 50% 50%,
            color-mix(in srgb, var(--fl-acento-700) 45%, transparent) 0%,
            transparent 45%),
        var(--fl-acento-950);
}

/* Overlay con FORMAS GEOMÉTRICAS ABSTRACTAS GRANDES Y DOBLES —
   anillos concéntricos (3 capas), triángulos anidados, diamantes anidados,
   líneas largas que atraviesan la pantalla. Centros fuera del viewBox para
   que se vean como arcos dominantes. */
/* SVG con formas abstractas inline — cada grupo se anima independiente.
   Position absolute + inset -5% para que el drift/rotate no muestre bordes. */
.fl-plantilla-auth-formas {
    position: absolute;
    top: -5%;
    left: -5%;
    width: 110%;
    height: 110%;
    pointer-events: none;
    z-index: 0;
    overflow: visible;
    display: block;
    grid-column: 1 / -1;
    grid-row: 1;
}

/* CONTRASTE BRUTAL contra el bg dark — 100% tonos de paleta (ninguno blanco) */
.fl-plantilla-auth-trazo-a { stroke: var(--fl-acento-100);  opacity: 0.9;  } /* super claro */
.fl-plantilla-auth-trazo-b { stroke: var(--fl-acento-200);  opacity: 0.9;  } /* claro */
.fl-plantilla-auth-trazo-c { stroke: var(--fl-acento-300);  opacity: 0.92; } /* claro saturado */
.fl-plantilla-auth-trazo-d { stroke: var(--fl-acento-400);  opacity: 0.85; } /* medio claro */
.fl-plantilla-auth-trazo-e { stroke: var(--fl-acento-500);  opacity: 0.8;  } /* medio saturado */
.fl-plantilla-auth-trazo-f { stroke: var(--fl-acento-200);  opacity: 0.7;  } /* claro secundario */

/* transform-box: fill-box hace que transform-origin use el centro del círculo
   (su cx/cy) en vez del origen del SVG. Así rotan sobre su propio eje. */
.fl-plantilla-auth-circulo {
    transform-box: fill-box;
    transform-origin: center;
}

/* 5 círculos grandes giran fijos sobre su eje */
.fl-plantilla-auth-circulo--gira-1 { animation: fl-auth-gira 95s  linear infinite; }
.fl-plantilla-auth-circulo--gira-2 { animation: fl-auth-gira 120s linear infinite reverse; }
.fl-plantilla-auth-circulo--gira-3 { animation: fl-auth-gira 180s linear infinite; }
.fl-plantilla-auth-circulo--gira-4 { animation: fl-auth-gira 140s linear infinite reverse; }
.fl-plantilla-auth-circulo--gira-5 { animation: fl-auth-gira 75s  linear infinite; }

/* 9 círculos en movimiento de desplazamiento */
.fl-plantilla-auth-circulo--atraviesa-hor       { animation: fl-auth-horizontal 55s ease-in-out infinite; }
.fl-plantilla-auth-circulo--atraviesa-hor-rev   { animation: fl-auth-horizontal 48s ease-in-out infinite reverse; }
.fl-plantilla-auth-circulo--atraviesa-ver       { animation: fl-auth-vertical 60s ease-in-out infinite; }
.fl-plantilla-auth-circulo--orbita              { animation: fl-auth-orbita 42s linear infinite; }
.fl-plantilla-auth-circulo--orbita-chica        { animation: fl-auth-orbita-chica 35s linear infinite; }
.fl-plantilla-auth-circulo--diagonal            { animation: fl-auth-diagonal 72s ease-in-out infinite; }
.fl-plantilla-auth-circulo--diagonal-rev        { animation: fl-auth-diagonal 58s ease-in-out infinite reverse; }
.fl-plantilla-auth-circulo--pulsa               { animation: fl-auth-pulsa 14s ease-in-out infinite; }
.fl-plantilla-auth-circulo--pulsa-rapida        { animation: fl-auth-pulsa 8s ease-in-out infinite; }

@keyframes fl-auth-gira {
    0%   { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}

@keyframes fl-auth-horizontal {
    0%, 100% { transform: translateX(-240px); }
    50%      { transform: translateX(240px); }
}

@keyframes fl-auth-vertical {
    0%, 100% { transform: translateY(-180px); }
    50%      { transform: translateY(180px); }
}

@keyframes fl-auth-orbita {
    0%   { transform: rotate(0deg) translateX(80px) rotate(0deg); }
    100% { transform: rotate(360deg) translateX(80px) rotate(-360deg); }
}

@keyframes fl-auth-orbita-chica {
    0%   { transform: rotate(0deg) translateX(50px) rotate(0deg); }
    100% { transform: rotate(360deg) translateX(50px) rotate(-360deg); }
}

@keyframes fl-auth-diagonal {
    0%, 100% { transform: translate(-180px, 100px); }
    50%      { transform: translate(180px, -100px); }
}

@keyframes fl-auth-pulsa {
    0%, 100% { transform: scale(1); }
    50%      { transform: scale(1.35); }
}

/* Blob volumétrico flotante con heavy blur + pulso */
.fl-plantilla--auth::after {
    content: "";
    position: absolute;
    top: 30%;
    right: 15%;
    width: 360px;
    height: 360px;
    background: radial-gradient(
        circle,
        color-mix(in srgb, var(--fl-acento-600) 70%, transparent) 0%,
        transparent 70%
    );
    filter: blur(40px);
    pointer-events: none;
    z-index: 0;
    opacity: 0.55;
    animation: fl-auth-blob 18s ease-in-out infinite;
}

/* Blob pulsante — escala + drift + opacidad */
@keyframes fl-auth-blob {
    0%, 100% {
        transform: translate(0, 0) scale(1);
        opacity: 0.55;
    }
    50% {
        transform: translate(-50px, 40px) scale(1.25);
        opacity: 0.75;
    }
}

/* Respetar usuarios que prefieren menos movimiento */
@media (prefers-reduced-motion: reduce) {
    .fl-plantilla-auth-forma,
    .fl-plantilla--auth::after {
        animation: none;
    }
}

.fl-plantilla--auth > * {
    position: relative;
    z-index: 1;
}

.fl-plantilla--auth-con-lateral {
    grid-template-columns: 1fr 1fr;
}

/* Sin lateral: la tarjeta queda centrada vertical y horizontalmente en el
   grid (que mide 100vh por el `position: fixed; inset: 0` del container).
   Para el caso con lateral se mantiene el default stretch para que ambas
   columnas ocupen toda la altura. */
.fl-plantilla--auth:not(.fl-plantilla--auth-con-lateral) {
    place-content: center;
}

.fl-plantilla-auth-panel {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--fl-sp-6) var(--fl-sp-5);
    position: relative;
    z-index: 2;
    min-width: 0;
    grid-column: 1;
    grid-row: 1;
}

.fl-plantilla-auth-tarjeta {
    width: 100%;
    max-width: 440px;
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-5);
    padding: var(--fl-sp-8) var(--fl-sp-7) var(--fl-sp-6);
    /* Fondo MUY tintado de paleta — acento 35% arriba → 22% abajo */
    background: linear-gradient(
        180deg,
        color-mix(in srgb, var(--fl-acento) 35%, var(--fl-superficie)) 0%,
        color-mix(in srgb, var(--fl-acento) 22%, var(--fl-superficie)) 100%
    );
    border: 1px solid color-mix(in srgb, var(--fl-acento) 55%, var(--fl-borde));
    border-top: 4px solid var(--fl-acento-800);
    border-radius: var(--fl-r-xl);
    /* SOMBRA MUY OSCURA Y PRESENTE — mezcla acento-950 con negro puro.
       Tres capas apiladas con offset y y blurs distintos para presencia total. */
    box-shadow:
        0 0 0 1px color-mix(in srgb, var(--fl-acento) 40%, transparent),
        0 80px 180px 20px color-mix(in srgb, var(--fl-acento-950) 70%, #000),
        0 40px 90px 10px color-mix(in srgb, var(--fl-acento-950) 50%, #000),
        0 20px 50px 0 color-mix(in srgb, var(--fl-acento-950) 30%, #000),
        0 8px 20px 0 rgb(0 0 0 / 0.6),
        inset 0 2px 0 0 color-mix(in srgb, var(--fl-acento) 45%, transparent),
        inset 0 -40px 80px -40px color-mix(in srgb, var(--fl-acento) 18%, transparent);
    position: relative;
    isolation: isolate;
    text-align: center;
    overflow: hidden;
}

/* Gradient horizontal decorativo sobre el border-top — le da profundidad al borde
   mostrando el recorrido de la paleta. */
.fl-plantilla-auth-tarjeta::before {
    content: "";
    position: absolute;
    top: -4px;
    left: 0;
    right: 0;
    height: 4px;
    background: linear-gradient(
        90deg,
        var(--fl-acento-700) 0%,
        var(--fl-acento-950) 50%,
        var(--fl-acento-700) 100%
    );
    z-index: 2;
}

/* Glow radial sutil en el fondo del logo */
.fl-plantilla-auth-tarjeta::after {
    content: "";
    position: absolute;
    top: 40px;
    left: 50%;
    transform: translateX(-50%);
    width: 200px;
    height: 200px;
    background: radial-gradient(
        circle,
        color-mix(in srgb, var(--fl-acento) 20%, transparent) 0%,
        transparent 65%
    );
    pointer-events: none;
    z-index: 0;
    opacity: 0.7;
}

.fl-plantilla-auth-tarjeta > * {
    position: relative;
    z-index: 1;
}

.fl-plantilla--auth--sm .fl-plantilla-auth-tarjeta { max-width: 380px; }
.fl-plantilla--auth--lg .fl-plantilla-auth-tarjeta { max-width: 540px; }

/* MARCA: logo grande arriba centrado + nombre app abajo grande */
.fl-plantilla-auth-marca {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--fl-sp-2);
    margin-bottom: 0;
}

.fl-plantilla-auth-marca-logo {
    width: 96px;
    height: 96px;
    object-fit: cover;
    background: transparent;
    border: 4px solid var(--fl-acento-900);
    padding: 0;
    border-radius: var(--fl-r-full);
    margin-bottom: var(--fl-sp-2);
    box-shadow:
        0 0 0 2px color-mix(in srgb, var(--fl-acento-900) 30%, transparent),
        0 16px 40px -8px color-mix(in srgb, var(--fl-acento-950) 55%, transparent),
        0 6px 16px -4px color-mix(in srgb, var(--fl-acento-950) 35%, transparent);
}

.fl-plantilla-auth-marca-icono {
    width: 96px;
    height: 96px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--fl-r-lg);
    background: linear-gradient(135deg, var(--fl-acento-800) 0%, var(--fl-acento-950) 100%);
    color: var(--fl-acento-texto-sobre);
    box-shadow:
        0 8px 24px -8px color-mix(in srgb, var(--fl-acento) 50%, transparent),
        inset 0 1px 0 0 color-mix(in srgb, #fff 14%, transparent);
}

.fl-plantilla-auth-marca-icono .fl-icono {
    width: 48px;
    height: 48px;
}

/* Nombre de la app — el PROTAGONISTA. Gradient de paleta adaptativo.
   Usa --fl-texto-fuerte (negro/blanco según modo) mezclado con acento.
   Así funciona en las 7 paletas claras Y en la oscura. */
.fl-plantilla-auth-marca-nombre {
    font-size: var(--fl-texto-3xl);
    font-weight: var(--fl-peso-bold);
    letter-spacing: var(--fl-ls-compacto);
    line-height: 1.05;
    background: linear-gradient(
        135deg,
        var(--fl-texto-fuerte) 0%,
        var(--fl-acento-hover) 100%
    );
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: var(--fl-texto-fuerte); /* fallback */
}

/* Pill separador debajo del nombre de marca — también adaptativo */
.fl-plantilla-auth-marca-nombre::after {
    content: "";
    display: block;
    width: 42px;
    height: 3px;
    margin: var(--fl-sp-2) auto 0;
    background: linear-gradient(90deg, var(--fl-acento), var(--fl-acento-hover));
    border-radius: var(--fl-r-full);
    opacity: 0.8;
}

/* Título: SECUNDARIO al brand — más chico, en acento-texto para acompañar paleta */
.fl-plantilla-auth-titulo {
    font-size: var(--fl-texto-lg);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-acento-texto);
    line-height: 1.3;
    margin: 0;
    letter-spacing: var(--fl-ls-compacto);
}

.fl-plantilla-auth-subtitulo {
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto-suave);
    line-height: 1.5;
    margin: 0;
}

.fl-plantilla-auth-cuerpo {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-3);
    text-align: left;
    margin-top: 0;
}

/* Fila "Recuérdame + olvidé clave": mismo tamaño, alineación consistente */
.fl-plantilla-auth-cuerpo .fl-fila--separar {
    align-items: center;
    font-size: var(--fl-texto-sm);
}

/* Links dentro de la card: SIN subrayado por default, subrayado on hover.
   Aplica a cualquier <a> (incluyendo .fl-enlace) dentro del auth. */
.fl-plantilla-auth-tarjeta a,
.fl-plantilla-auth-tarjeta .fl-enlace {
    text-decoration: none;
    color: var(--fl-acento-enlace);
    font-weight: var(--fl-peso-medio);
    font-size: var(--fl-texto-sm);
    transition: color var(--fl-t-rapido), text-decoration-color var(--fl-t-rapido);
}

.fl-plantilla-auth-tarjeta a:hover,
.fl-plantilla-auth-tarjeta .fl-enlace:hover {
    color: var(--fl-acento-hover);
    text-decoration: underline;
    text-decoration-thickness: 1.5px;
    text-underline-offset: 0.22em;
}

/* Normalizar tamaño de los labels dentro del auth (incluyendo switch-etiqueta) */
.fl-plantilla-auth-tarjeta .fl-switch-etiqueta,
.fl-plantilla-auth-tarjeta .fl-check-etiqueta {
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto);
}

/* Pie: links centrados, mismo tamaño */
.fl-plantilla-auth-pie {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--fl-sp-1);
    flex-wrap: wrap;
    padding-top: var(--fl-sp-4);
    margin-top: var(--fl-sp-1);
    border-top: 1px solid color-mix(in srgb, var(--fl-acento) 20%, var(--fl-borde-sutil));
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto-suave);
}

/* Panel lateral con dark palette gradient */
.fl-plantilla-auth-lateral {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--fl-sp-7);
    background: linear-gradient(
        135deg,
        var(--fl-acento-800) 0%,
        var(--fl-acento-900) 50%,
        color-mix(in srgb, var(--fl-acento-950) 80%, #000) 100%
    );
    color: var(--fl-acento-texto-sobre);
    position: relative;
    overflow: hidden;
    z-index: 2;
    grid-column: 2;
    grid-row: 1;
}

.fl-plantilla-auth-lateral::before {
    content: "";
    position: absolute;
    top: -150px;
    right: -150px;
    width: 500px;
    height: 500px;
    background: radial-gradient(circle, color-mix(in srgb, #fff 10%, transparent) 0%, transparent 65%);
    pointer-events: none;
}

.fl-plantilla-auth-lateral > * {
    position: relative;
    z-index: 1;
}

.fl-plantilla-auth-lateral-titulo {
    font-size: var(--fl-texto-4xl);
    font-weight: var(--fl-peso-bold);
    color: var(--fl-acento-texto-sobre);
    letter-spacing: var(--fl-ls-compacto);
    line-height: 1.1;
    margin: 0 0 var(--fl-sp-3);
    text-shadow: 0 2px 4px rgb(0 0 0 / 0.2);
}

.fl-plantilla-auth-lateral-texto {
    font-size: var(--fl-texto-base);
    color: color-mix(in srgb, var(--fl-acento-texto-sobre) 85%, transparent);
    line-height: 1.6;
    max-width: 420px;
}

@media (max-width: 900px) {
    .fl-plantilla--auth-con-lateral {
        grid-template-columns: 1fr;
    }
    .fl-plantilla-auth-lateral {
        display: none;
    }
    .fl-plantilla-auth-marca-logo,
    .fl-plantilla-auth-marca-icono {
        width: 80px;
        height: 80px;
    }
}


/* ===== resources/css/componentes/player.css ===== */
/* ==========================================================================
   Flora · Player (audio / MIDI)
   Default dark: gradient sólido del acento en las paradas 600→900. El viejo
   look "tintado light" daba gris en palettes apagadas — adoptamos ahora el
   hero look (antes llamado `--destaque`) como única identidad visual.
   ========================================================================== */

.fl-player {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-2);
    padding: var(--fl-sp-3) var(--fl-sp-4);
    background: linear-gradient(
        135deg,
        var(--fl-acento-600) 0%,
        var(--fl-acento-900) 100%
    );
    color: var(--fl-destaque-texto);
    border: 1px solid transparent;
    border-radius: var(--fl-r-lg);
    box-shadow:
        0 8px 24px -6px color-mix(in srgb, var(--fl-acento) 55%, transparent),
        inset 0 1px 0 color-mix(in srgb, white 18%, transparent);
    font-size: var(--fl-texto-sm);
    min-width: 0;
    overflow: hidden;
    /* Habilita container queries — el control se compacta según el ancho
       real del player (no del viewport), así funciona bien embebido en
       cards chicos sin depender de media queries del parent. */
    container-type: inline-size;
    container-name: fl-player;
}

/* Highlight superior tipo "glass" */
.fl-player::before {
    content: "";
    position: absolute;
    top: 0;
    left: 10%;
    right: 10%;
    height: 1px;
    background: linear-gradient(
        to right,
        transparent 0%,
        color-mix(in srgb, white 28%, transparent) 50%,
        transparent 100%
    );
    pointer-events: none;
}

.fl-player-barra-control {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-3);
    min-width: 0;
}

/* Container queries — SIEMPRE una sola fila.
   `play | 0:00 | onda | 3:42 | 🔊` es el layout único; lo único que cambia
   con el ancho es el tamaño de los elementos (gap, fuente, play button, etc).
   Como un reproductor físico: la tira no se rompe, se achica. */
@container fl-player (max-width: 460px) {
    .fl-player-barra-control {
        gap: var(--fl-sp-2);
    }
    .fl-player-tiempo,
    .fl-player-total {
        min-width: 32px;
        font-size: var(--fl-texto-2xs);
    }
}

@container fl-player (max-width: 360px) {
    .fl-player {
        padding: var(--fl-sp-2) var(--fl-sp-3);
    }
    .fl-player-barra-control {
        gap: 6px;
    }
    .fl-player-play {
        width: 34px;
        height: 34px;
    }
    .fl-player-play .fl-icono {
        width: 14px;
        height: 14px;
    }
    .fl-player-volumen {
        width: 28px;
        height: 28px;
    }
    .fl-player-volumen .fl-icono {
        width: 16px;
        height: 16px;
    }
    .fl-player-tiempo,
    .fl-player-total {
        min-width: 28px;
    }
    .fl-player--onda .fl-player-onda {
        height: 36px;
        padding: 0 var(--fl-sp-1);
    }
}

@container fl-player (max-width: 260px) {
    .fl-player-barra-control {
        gap: 4px;
    }
    .fl-player-play {
        width: 30px;
        height: 30px;
    }
    .fl-player-tiempo,
    .fl-player-total {
        min-width: 0;
    }
    /* Barras más finas para que entren en onda muy chica */
    .fl-player--onda .fl-player-onda-barra {
        min-width: 1px;
    }
    .fl-player--onda .fl-player-onda {
        gap: 1px;
        padding: 0 2px;
    }
}

/* Play — círculo blanco con ícono tinted del acento */
.fl-player-play {
    flex: none;
    position: relative;
    width: 40px;
    height: 40px;
    border-radius: var(--fl-r-full);
    border: 0;
    background: white;
    color: var(--fl-acento-700);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-shadow:
        0 4px 14px -2px color-mix(in srgb, black 35%, transparent),
        inset 0 1px 0 color-mix(in srgb, white 60%, transparent);
    transition: transform 180ms var(--fl-ease-resorte),
                background 180ms var(--fl-ease-salida),
                box-shadow 200ms var(--fl-ease-salida);
}

.fl-player-play:hover {
    transform: scale(1.08);
    /* Tint sutil del acento sobre el blanco */
    background: color-mix(in srgb, white 82%, var(--fl-acento));
    box-shadow:
        0 8px 22px -2px color-mix(in srgb, black 50%, transparent),
        inset 0 1px 0 color-mix(in srgb, white 80%, transparent);
}

.fl-player-play:active {
    transform: scale(0.94);
}

.fl-player-play .fl-icono {
    width: 18px;
    height: 18px;
    fill: currentColor;
    /* Offset óptico del triángulo de play */
    margin-left: 2px;
}

.fl-player[data-fl-reproduciendo="true"] .fl-player-play .fl-icono {
    margin-left: 0;
}

/* Halo pulsante del play mientras reproduce */
.fl-player[data-fl-reproduciendo="true"] .fl-player-play::after {
    content: "";
    position: absolute;
    inset: -4px;
    border-radius: 50%;
    border: 2px solid color-mix(in srgb, white 55%, transparent);
    animation: fl-player-pulso 1.6s ease-out infinite;
    pointer-events: none;
}

@keyframes fl-player-pulso {
    0%   { transform: scale(1);   opacity: 1; }
    100% { transform: scale(1.4); opacity: 0; }
}

/* Tiempos en blanco */
.fl-player-tiempo,
.fl-player-total {
    flex: none;
    font-variant-numeric: tabular-nums;
    font-size: var(--fl-texto-xs);
    font-weight: var(--fl-peso-medio);
    min-width: 40px;
    text-align: center;
    letter-spacing: 0.02em;
}

.fl-player-tiempo {
    color: white;
}

.fl-player-total {
    color: color-mix(in srgb, white 65%, transparent);
}

/* Barra de progreso thin (fallback cuando :onda="false") */
.fl-player-barra {
    flex: 1 1 auto;
    position: relative;
    height: 6px;
    background: color-mix(in srgb, white 18%, transparent);
    border-radius: var(--fl-r-full);
    cursor: pointer;
    min-width: 60px;
    transition: height 180ms var(--fl-ease-salida);
    box-shadow: inset 0 1px 2px color-mix(in srgb, black 20%, transparent);
}

.fl-player-progreso {
    position: absolute;
    inset: 0 auto 0 0;
    width: 0%;
    background: linear-gradient(
        to right,
        color-mix(in srgb, white 90%, transparent) 0%,
        white 100%
    );
    border-radius: var(--fl-r-full);
    transition: width 80ms linear;
    pointer-events: none;
    box-shadow: 0 0 10px color-mix(in srgb, white 60%, transparent);
}

.fl-player-handle {
    position: absolute;
    top: 50%;
    left: 0%;
    width: 14px;
    height: 14px;
    background: white;
    border: 2px solid white;
    border-radius: 50%;
    transform: translate(-50%, -50%) scale(0);
    transition: transform 200ms var(--fl-ease-resorte);
    pointer-events: none;
    box-shadow:
        0 0 0 4px color-mix(in srgb, white 25%, transparent),
        0 2px 8px color-mix(in srgb, black 30%, transparent);
}

.fl-player-barra:hover .fl-player-handle,
.fl-player[data-fl-seeking="true"] .fl-player-handle {
    transform: translate(-50%, -50%) scale(1);
}

.fl-player-barra:hover {
    height: 8px;
}

/* Volumen — botón fantasma blanco */
.fl-player-volumen {
    flex: none;
    width: 34px;
    height: 34px;
    border: 0;
    background: transparent;
    color: color-mix(in srgb, white 75%, transparent);
    border-radius: var(--fl-r-md);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida),
                color var(--fl-t-rapido) var(--fl-ease-salida),
                transform 180ms var(--fl-ease-resorte);
}

.fl-player-volumen:hover {
    background: color-mix(in srgb, white 15%, transparent);
    color: white;
    transform: scale(1.08);
}

.fl-player-volumen .fl-icono {
    width: 18px;
    height: 18px;
}

/* --------------------------------------------------------------------------
   Metadata (título + subtítulo)
   -------------------------------------------------------------------------- */
.fl-player-metadata {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding-bottom: var(--fl-sp-1);
    min-width: 0;
}

.fl-player-titulo {
    font-weight: var(--fl-peso-semibold);
    color: white;
    line-height: 1.2;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    letter-spacing: -0.01em;
}

.fl-player-subtitulo {
    font-size: var(--fl-texto-xs);
    color: color-mix(in srgb, white 75%, transparent);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: var(--fl-peso-medio);
}

/* --------------------------------------------------------------------------
   Variantes
   -------------------------------------------------------------------------- */

/* Compacto — una sola línea, ideal en listas */
.fl-player--compacto {
    padding: var(--fl-sp-2) var(--fl-sp-3);
}

.fl-player--compacto .fl-player-play {
    width: 32px;
    height: 32px;
}

.fl-player--compacto .fl-player-play .fl-icono {
    width: 14px;
    height: 14px;
}

.fl-player--compacto .fl-player-barra {
    height: 5px;
}

/* `--destaque` — alias legacy del look por defecto (no-op).
   Antes era la variante dark; ahora el default ya es dark.
   Mantiene compat con blades existentes que pasan variante="destaque". */
.fl-player--destaque {
    /* hereda todo del base */
}

/* --------------------------------------------------------------------------
   Layout amalgamado — waveform como única superficie de seek (SoundCloud)
   El JS renderiza una .fl-player-onda en lugar de la barra thin.
   -------------------------------------------------------------------------- */
.fl-player--onda .fl-player-barra {
    display: none;
}

.fl-player--onda .fl-player-onda {
    flex: 1 1 auto;
    min-width: 0;
    height: 48px;
    display: flex;
    align-items: center;
    gap: 2px;
    padding: var(--fl-sp-1) var(--fl-sp-2);
    cursor: pointer;
    border-radius: var(--fl-r-md);
    transition: background var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-player--onda .fl-player-onda:hover {
    background: color-mix(in srgb, white 10%, transparent);
}

.fl-player--onda .fl-player-onda-barra {
    flex: 1 1 0;
    min-width: 2px;
    background: color-mix(in srgb, white 35%, transparent);
    border-radius: var(--fl-r-full);
    height: var(--_altura, 40%);
    transition: background 120ms var(--fl-ease-salida),
                transform 180ms var(--fl-ease-resorte);
    pointer-events: none;
}

.fl-player--onda .fl-player-onda-barra[data-fl-reproducida="true"] {
    background: white;
    box-shadow: 0 0 8px color-mix(in srgb, white 55%, transparent);
}

.fl-player--onda .fl-player-onda:hover .fl-player-onda-barra {
    background: color-mix(in srgb, white 55%, transparent);
}

.fl-player--onda .fl-player-onda:hover .fl-player-onda-barra[data-fl-reproducida="true"] {
    background: white;
}

/* Pulso en la última barra reproducida */
.fl-player--onda[data-fl-reproduciendo="true"] .fl-player-onda-barra[data-fl-reproducida="true"]:last-of-type {
    animation: fl-player-onda-pulsa 900ms var(--fl-ease-inout) infinite alternate;
}

@keyframes fl-player-onda-pulsa {
    from { transform: scaleY(0.85); }
    to   { transform: scaleY(1.1); }
}

/* Compacto + onda — más bajo */
.fl-player--compacto.fl-player--onda .fl-player-onda {
    height: 32px;
}

@media (prefers-reduced-motion: reduce) {
    .fl-player[data-fl-reproduciendo="true"] .fl-player-play::after,
    .fl-player--onda[data-fl-reproduciendo="true"] .fl-player-onda-barra[data-fl-reproducida="true"]:last-of-type {
        animation: none;
    }
    .fl-player-play,
    .fl-player-volumen,
    .fl-player-handle,
    .fl-player-barra,
    .fl-player-onda-barra { transition: none; }
}


/* ===== resources/css/componentes/popover.css ===== */
/* ==========================================================================
   Flora · Popover (popup anclado con contenido rico)
   Distinto de tooltip: el popover puede contener HTML, títulos, botones,
   formularios. Se abre al click (o hover con data-fl-popover-hover).
   Posicionado con Flora.flotante.
   ========================================================================== */

.fl-popover {
    position: fixed;
    z-index: var(--fl-z-popover);
    min-width: 180px;
    /* Fluid: cap 94vw en viewports angostos, 380px en amplios. */
    max-width: min(94vw, 380px);
    background: var(--fl-superficie-elevada);
    color: var(--fl-texto);
    border: 1px solid var(--fl-borde);
    border-radius: var(--fl-r-lg);
    box-shadow: var(--fl-sombra-lg), 0 0 0 1px rgb(0 0 0 / 0.03);
    padding: var(--fl-sp-3) var(--fl-sp-3);
    font-size: var(--fl-texto-sm);
    line-height: var(--fl-lh-comoda);
    opacity: 0;
    transform: translate3d(0,0,0) scale(0.96);
    visibility: hidden;
    pointer-events: none;
    transition: opacity 140ms var(--fl-ease-salida),
                transform 200ms var(--fl-ease-resorte),
                visibility 180ms;
    transform-origin: top left;
}

.fl-popover[data-fl-abierto="true"] {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
}

.fl-popover-flecha {
    position: absolute;
    width: 10px;
    height: 10px;
    background: var(--fl-superficie-elevada);
    border: 1px solid var(--fl-borde);
    transform: rotate(45deg);
    z-index: -1;
}

.fl-popover[data-fl-lado="bottom"] .fl-popover-flecha { top: -6px; left: 50%; margin-left: -5px; border-right: 0; border-bottom: 0; }
.fl-popover[data-fl-lado="top"]    .fl-popover-flecha { bottom: -6px; left: 50%; margin-left: -5px; border-left: 0; border-top: 0; }
.fl-popover[data-fl-lado="left"]   .fl-popover-flecha { right: -6px; top: 50%; margin-top: -5px; border-left: 0; border-bottom: 0; }
.fl-popover[data-fl-lado="right"]  .fl-popover-flecha { left: -6px; top: 50%; margin-top: -5px; border-right: 0; border-top: 0; }

.fl-popover-titulo {
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-fuerte);
    margin-bottom: var(--fl-sp-1);
}

.fl-popover-cerrar {
    position: absolute;
    top: 4px;
    right: 4px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px; height: 24px;
    border: 0; background: transparent;
    border-radius: var(--fl-r-sm);
    color: var(--fl-texto-tenue);
    cursor: pointer;
    transition: color 120ms, background 120ms;
}
.fl-popover-cerrar:hover { color: var(--fl-texto); background: var(--fl-superficie-hover); }
.fl-popover-cerrar .fl-icono { width: 12px; height: 12px; }

.fl-popover-acciones {
    display: flex;
    gap: var(--fl-sp-2);
    justify-content: flex-end;
    margin-top: var(--fl-sp-3);
    padding-top: var(--fl-sp-2);
    border-top: 1px solid var(--fl-borde-sutil);
}

/* Variante sin padding (para menús) */
.fl-popover--menu { padding: var(--fl-sp-1); }

/* HoverCard — estilo más etéreo, sin click */
.fl-popover--hover {
    max-width: min(92vw, 320px);
    padding: var(--fl-sp-3) var(--fl-sp-4);
}


/* ===== resources/css/componentes/progreso.css ===== */
/* ==========================================================================
   Flora · Progreso + Progreso-circular + Spinner (archivo unificado)
   Consolida los 3 indicadores de progreso — antes 3 archivos separados.
   Clases separadas por prefix, animaciones compartidas, mismos tokens.
   ========================================================================== */

/* ==========================================================================
   1) BARRA DE PROGRESO (lineal)
   Determinada o indeterminada. Variantes semánticas.
   ========================================================================== */

.fl-progreso {
    display: block;
    width: 100%;
}

.fl-progreso-cabecera {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--fl-sp-2);
    margin-bottom: var(--fl-sp-1-5);
    font-size: var(--fl-texto-sm);
}

.fl-progreso-etiqueta {
    color: var(--fl-texto);
    font-weight: var(--fl-peso-medio);
}

.fl-progreso-valor {
    color: var(--fl-texto-suave);
    font-variant-numeric: tabular-nums;
    font-size: var(--fl-texto-xs);
}

.fl-progreso-pista {
    position: relative;
    width: 100%;
    height: 8px;
    background: var(--fl-superficie-muda);
    border-radius: var(--fl-r-full);
    overflow: hidden;
    transition: filter var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-progreso[title]:hover .fl-progreso-pista,
.fl-progreso-pista[title]:hover {
    filter: brightness(1.08);
    cursor: help;
}

.fl-progreso-relleno {
    position: absolute;
    inset: 0 auto 0 0;
    width: var(--_valor, 0%);
    background: var(--fl-destaque-fondo);
    border-radius: var(--fl-r-full);
    transition: width 320ms var(--fl-ease-salida);
}

.fl-progreso--xs .fl-progreso-pista { height: 4px; }
.fl-progreso--sm .fl-progreso-pista { height: 6px; }
.fl-progreso--lg .fl-progreso-pista { height: 12px; }

.fl-progreso--exito .fl-progreso-relleno       { background: var(--fl-exito); }
.fl-progreso--error .fl-progreso-relleno       { background: var(--fl-error); }
.fl-progreso--advertencia .fl-progreso-relleno { background: var(--fl-advertencia); }
.fl-progreso--info .fl-progreso-relleno        { background: var(--fl-info); }

.fl-progreso--gradiente .fl-progreso-relleno {
    background: var(--fl-destaque-gradiente);
}

.fl-progreso--indeterminado .fl-progreso-relleno {
    width: 40%;
    animation: fl-progreso-indeterminado 1400ms var(--fl-ease-inout) infinite;
    transition: none;
}

@keyframes fl-progreso-indeterminado {
    0%   { left: -40%; }
    100% { left: 100%; }
}

.fl-progreso--shimmer .fl-progreso-relleno::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(
        90deg,
        transparent 0%,
        rgb(255 255 255 / 0.35) 50%,
        transparent 100%
    );
    transform: translateX(-100%);
    animation: fl-progreso-shimmer 1600ms var(--fl-ease-inout) infinite;
}

@keyframes fl-progreso-shimmer {
    to { transform: translateX(300%); }
}

/* ==========================================================================
   2) PROGRESO CIRCULAR (ring)
   SVG circle con stroke-dashoffset animado. Muestra porcentaje central.
   ========================================================================== */

.fl-progreso-circular {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--fl-pc-tamano, 64px);
    height: var(--fl-pc-tamano, 64px);
}

.fl-progreso-circular-svg {
    width: 100%;
    height: 100%;
    transform: rotate(-90deg);
}

.fl-progreso-circular-fondo {
    fill: none;
    stroke: var(--fl-borde-intenso);
    stroke-width: var(--fl-pc-ancho, 6);
}

.fl-progreso-circular-valor {
    fill: none;
    stroke: var(--fl-destaque-fondo);
    stroke-width: var(--fl-pc-ancho, 6);
    stroke-linecap: round;
    transition: stroke-dashoffset 600ms var(--fl-ease-salida);
}

.fl-progreso-circular-texto {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: calc(var(--fl-pc-tamano, 64px) * 0.24);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-fuerte);
    font-variant-numeric: tabular-nums;
}

.fl-progreso-circular--exito .fl-progreso-circular-valor { stroke: var(--fl-exito); }
.fl-progreso-circular--error .fl-progreso-circular-valor { stroke: var(--fl-error); }
.fl-progreso-circular--adv .fl-progreso-circular-valor   { stroke: var(--fl-advertencia); }

.fl-progreso-circular[data-fl-indeterminado="true"] .fl-progreso-circular-svg {
    animation: fl-pc-girar 1.4s linear infinite;
}
.fl-progreso-circular[data-fl-indeterminado="true"] .fl-progreso-circular-valor {
    animation: fl-pc-dash 1.4s ease-in-out infinite;
}

@keyframes fl-pc-girar { to { transform: rotate(270deg); } }
@keyframes fl-pc-dash {
    0%   { stroke-dasharray: 1, 200; stroke-dashoffset: 0; }
    50%  { stroke-dasharray: 90, 200; stroke-dashoffset: -35; }
    100% { stroke-dasharray: 90, 200; stroke-dashoffset: -125; }
}

/* ==========================================================================
   3) SPINNER (circular/puntos/barra) — indicador simple
   ========================================================================== */

.fl-spinner {
    display: inline-block;
    width: 1em;
    height: 1em;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: var(--fl-r-full);
    animation: fl-spinner-giro 700ms linear infinite;
    flex: none;
    vertical-align: -0.125em;
}

.fl-spinner--xs   { width: 12px; height: 12px; border-width: 1.5px; }
.fl-spinner--sm   { width: 18px; height: 18px; border-width: 2px; }
.fl-spinner--md   { width: 30px; height: 30px; border-width: 2.5px; }
.fl-spinner--lg   { width: 46px; height: 46px; border-width: 3px; }
.fl-spinner--xl   { width: 64px; height: 64px; border-width: 3.5px; }
.fl-spinner--2xl  { width: 84px; height: 84px; border-width: 4px; }

.fl-spinner--acento { color: var(--fl-acento); }
.fl-spinner--exito  { color: var(--fl-exito); }
.fl-spinner--error  { color: var(--fl-error); }
.fl-spinner--tenue  { color: var(--fl-texto-tenue); }

@keyframes fl-spinner-giro {
    to { transform: rotate(360deg); }
}

/* Variante puntos — 3 puntos saltando (chat writing indicator) */
.fl-spinner-puntos {
    display: inline-flex;
    gap: 3px;
    align-items: center;
}

.fl-spinner-puntos > span {
    width: 6px;
    height: 6px;
    border-radius: var(--fl-r-full);
    background: currentColor;
    animation: fl-spinner-punto-salto 1200ms var(--fl-ease-inout) infinite;
}

.fl-spinner-puntos > span:nth-child(2) { animation-delay: 200ms; }
.fl-spinner-puntos > span:nth-child(3) { animation-delay: 400ms; }

@keyframes fl-spinner-punto-salto {
    0%, 80%, 100% { opacity: 0.3; transform: translateY(0); }
    40%            { opacity: 1;   transform: translateY(-4px); }
}

/* Variante barra — reutiliza la animación indeterminada de progreso */
.fl-spinner-barra {
    position: relative;
    width: 100%;
    height: 3px;
    overflow: hidden;
    background: var(--fl-superficie-muda);
    border-radius: var(--fl-r-full);
}

.fl-spinner-barra::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    width: 40%;
    background: var(--fl-acento);
    border-radius: inherit;
    animation: fl-progreso-indeterminado 1600ms var(--fl-ease-inout) infinite;
}

/* ==========================================================================
   prefers-reduced-motion: detener animaciones
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
    .fl-progreso-relleno,
    .fl-progreso--indeterminado .fl-progreso-relleno,
    .fl-progreso--shimmer .fl-progreso-relleno::after,
    .fl-progreso-circular-valor,
    .fl-progreso-circular[data-fl-indeterminado="true"] .fl-progreso-circular-svg,
    .fl-progreso-circular[data-fl-indeterminado="true"] .fl-progreso-circular-valor,
    .fl-spinner,
    .fl-spinner-puntos > span,
    .fl-spinner-barra::before {
        animation: none;
        transition: none;
    }
}


/* ===== resources/css/componentes/radio.css ===== */
/* ==========================================================================
   Flora · Radio / Radio Group
   Input de elección exclusiva. Siempre en grupo (aunque sea de 2 opciones).
   ========================================================================== */

.fl-radio {
    display: inline-flex;
    align-items: flex-start;
    gap: var(--fl-sp-2-5);
    cursor: pointer;
    user-select: none;
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto);
    line-height: var(--fl-lh-ajustada);
}

.fl-radio:has(input:disabled) {
    cursor: not-allowed;
    opacity: 0.6;
}

.fl-radio-control {
    /* Visualmente oculto pero focuseable — patrón "sr-only" estable.
       Width:1/height:1 (no 0) para que los browsers lo traten como radio
       navegable con flechas; clip para que no ocupe espacio visible. */
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    margin: 0;
    padding: 0;
    border: 0;
    opacity: 0;
    pointer-events: none;
}

.fl-radio-caja {
    position: relative;
    width: 18px;
    height: 18px;
    flex: none;
    background: var(--fl-superficie);
    border: 1.5px solid var(--fl-borde-intenso);
    border-radius: var(--fl-r-full);
    transition: background var(--fl-t-rapido) var(--fl-ease-salida),
                border-color var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-radio:hover .fl-radio-control:not(:disabled) + .fl-radio-caja {
    border-color: var(--fl-acento);
}

.fl-radio-caja::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 8px;
    height: 8px;
    background: var(--fl-neutro-0);
    border-radius: var(--fl-r-full);
    transform: translate(-50%,-50%) scale(0);
    transition: transform 200ms var(--fl-ease-resorte);
}

.fl-radio-control:checked + .fl-radio-caja {
    background: var(--fl-destaque-fondo);
    border-color: var(--fl-destaque-fondo);
}

.fl-radio-control:checked + .fl-radio-caja::after {
    transform: translate(-50%,-50%) scale(1);
}

.fl-radio-control:focus-visible + .fl-radio-caja {
    outline: none;
    box-shadow: 0 0 0 var(--fl-foco-ancho) var(--fl-acento-foco);
}

.fl-radio-texto { flex: 1 1 auto; padding-top: 1px; }
.fl-radio-texto-secundario {
    display: block;
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-suave);
    margin-top: 2px;
}

.fl-radio--sm .fl-radio-caja { width: 15px; height: 15px; }
.fl-radio--sm .fl-radio-caja::after { width: 6px; height: 6px; }
.fl-radio--lg .fl-radio-caja { width: 22px; height: 22px; }
.fl-radio--lg .fl-radio-caja::after { width: 10px; height: 10px; }

/* Grupo */
.fl-radio-grupo {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-2);
}
.fl-radio-grupo--horizontal { flex-direction: row; flex-wrap: wrap; gap: var(--fl-sp-4); }

/* Variante tarjeta — cada radio es una tarjeta clickeable */
.fl-radio-tarjeta {
    display: flex;
    align-items: flex-start;
    gap: var(--fl-sp-3);
    padding: var(--fl-sp-3) var(--fl-sp-4);
    background: var(--fl-superficie);
    border: 1px solid var(--fl-borde);
    border-radius: var(--fl-r-lg);
    cursor: pointer;
    transition: border-color var(--fl-t-rapido), background var(--fl-t-rapido);
}
.fl-radio-tarjeta:hover { border-color: var(--fl-acento-suave); background: var(--fl-superficie-hover); }
.fl-radio-tarjeta:has(.fl-radio-control:checked) {
    border-color: var(--fl-acento);
    background: var(--fl-acento-suave);
}
.fl-radio-tarjeta:has(.fl-radio-control:focus-visible) {
    box-shadow: 0 0 0 var(--fl-foco-ancho) var(--fl-acento-foco);
}

@media (prefers-reduced-motion: reduce) {
    .fl-radio-caja, .fl-radio-caja::after { transition: none; }
}


/* ===== resources/css/componentes/rating.css ===== */
/* ==========================================================================
   Flora · Rating (puntuación por estrellas)
   Fill fraccional real (cualquier 0-100% por estrella) usando CSS mask + gradient.
   Único sistema de color: paleta activa. Contenedor con pill elevada + sombra
   interior para que las estrellas se "asienten" en un campo visual propio.
   Tamaños: xs / sm / md (default) / lg / xl.
   ========================================================================== */

.fl-rating {
    /* Jerarquía de colores de la paleta activa:
       - vacío: tint firme del acento (visible, no washed-out).
       - lleno: gradient acento-300 → acento-500 → acento-700 + shine radial
         que simula joya pulida (ver .fl-rating-estrella::after).
       - marco de estrellas: superficie elevada + borde tint-acento. */
    --fl-rating-vacio: color-mix(in srgb, var(--fl-acento) 28%, transparent);
    --fl-rating-tamano: 22px;
    --fl-rating-gap: 3px;
    --fl-rating-sombra: 0 2px 4px color-mix(in srgb, var(--fl-acento) 45%, transparent);

    display: inline-flex;
    align-items: center;
    gap: var(--fl-sp-2);
    line-height: 1;
    vertical-align: middle;
}

/* Marco de estrellas — pill elevada con borde sutil de acento. Aísla el
   rating visualmente y mejora percepción sobre distintos fondos. */
.fl-rating-estrellas {
    display: inline-flex;
    align-items: center;
    gap: var(--fl-rating-gap);
    padding: 6px 10px;
    background: var(--fl-superficie);
    border: 1px solid color-mix(in srgb, var(--fl-acento) 22%, transparent);
    border-radius: 999px;
    box-shadow:
        inset 0 1px 0 color-mix(in srgb, var(--fl-acento) 8%, transparent),
        0 1px 2px color-mix(in srgb, var(--fl-acento) 10%, transparent);
}

.fl-rating-estrella {
    --_fill: 0%;
    position: relative;
    display: inline-block;
    width: var(--fl-rating-tamano);
    height: var(--fl-rating-tamano);
    background: transparent;
    border: 0;
    padding: 0;
    cursor: default;
    outline: none;
    transition: transform 180ms var(--fl-ease-salida),
                filter   180ms var(--fl-ease-salida);
    /* Máscara de estrella embebida (independiente de fl-icono) */
    --fl-rating-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M12 2.3l2.94 6.35 6.96.64-5.26 4.77 1.55 6.86L12 17.2l-6.19 3.72 1.55-6.86L2.1 9.29l6.96-.64L12 2.3z'/></svg>");
}

/* Capa vacía (fondo) */
.fl-rating-estrella::before {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--fl-rating-vacio);
    -webkit-mask: var(--fl-rating-mask) center / contain no-repeat;
            mask: var(--fl-rating-mask) center / contain no-repeat;
}

/* Capa llena — gradient de paleta + SHIMMER automático:
   · Gradient base: acento-200 → acento-800 (rango amplio, visible).
   · Shimmer: una banda blanca diagonal que barre periódicamente la
     estrella, como el "shine" de un botón premium.
   · background-size del gradient base = 100%, y del shimmer = 200%
     para tener espacio de desplazamiento.
   · drop-shadow del acento para separar del fondo. */
.fl-rating-estrella::after {
    content: "";
    position: absolute;
    inset: 0;
    background:
        linear-gradient(
            110deg,
            transparent 35%,
            color-mix(in srgb, white 70%, transparent) 48%,
            color-mix(in srgb, white 70%, transparent) 52%,
            transparent 65%
        ),
        linear-gradient(
            135deg,
            var(--fl-acento-200) 0%,
            var(--fl-acento-400) 35%,
            var(--fl-acento-600) 65%,
            var(--fl-acento-800) 100%
        );
    background-size: 220% 100%, 100% 100%;
    background-position: -110% 0, 0 0;
    -webkit-mask: var(--fl-rating-mask) center / contain no-repeat;
            mask: var(--fl-rating-mask) center / contain no-repeat;
    clip-path: inset(0 calc(100% - var(--_fill)) 0 0);
    filter: drop-shadow(var(--fl-rating-sombra));
    transition: clip-path 220ms var(--fl-ease-salida);
    animation: fl-rating-brillo 3.2s ease-in-out infinite;
}

/* Delay escalonado para que el brillo recorra las estrellas como una onda */
.fl-rating-estrella:nth-child(1)::after { animation-delay: 0s; }
.fl-rating-estrella:nth-child(2)::after { animation-delay: 0.25s; }
.fl-rating-estrella:nth-child(3)::after { animation-delay: 0.5s; }
.fl-rating-estrella:nth-child(4)::after { animation-delay: 0.75s; }
.fl-rating-estrella:nth-child(5)::after { animation-delay: 1s; }
.fl-rating-estrella:nth-child(6)::after { animation-delay: 1.25s; }
.fl-rating-estrella:nth-child(7)::after { animation-delay: 1.5s; }
.fl-rating-estrella:nth-child(8)::after { animation-delay: 1.75s; }

@keyframes fl-rating-brillo {
    0% {
        background-position: -110% 0, 0 0;
    }
    50% {
        background-position: 210% 0, 0 0;
    }
    100% {
        background-position: 210% 0, 0 0;
    }
}

/* --------------------------------------------------------------------------
   Modo editable — cursor, hover lift con micro-rotación
   -------------------------------------------------------------------------- */
.fl-rating--editable .fl-rating-estrella {
    cursor: pointer;
}

.fl-rating--editable .fl-rating-estrella:hover {
    transform: scale(1.18) rotate(-6deg);
}

.fl-rating--editable .fl-rating-estrella:active {
    transform: scale(1.05) rotate(-2deg);
}

/* Focus del contenedor (teclado) */
.fl-rating[tabindex]:focus-visible {
    outline: 2px solid var(--fl-acento);
    outline-offset: 4px;
    border-radius: 999px;
}

/* --------------------------------------------------------------------------
   Animación pop al recibir valor (escalonada desde JS)
   -------------------------------------------------------------------------- */
@keyframes fl-rating-pop {
    0%   { transform: scale(1)    rotate(0); }
    35%  { transform: scale(1.35) rotate(-10deg); }
    70%  { transform: scale(0.94) rotate(2deg); }
    100% { transform: scale(1)    rotate(0); }
}

.fl-rating-estrella[data-fl-pop="true"] {
    animation: fl-rating-pop 440ms var(--fl-ease-salida);
}

/* --------------------------------------------------------------------------
   Tamaños — ajusta también el padding del marco para que quede proporcional
   -------------------------------------------------------------------------- */
.fl-rating--xs .fl-rating-estrellas { padding: 3px 6px; }
.fl-rating--xs { --fl-rating-tamano: 14px; --fl-rating-gap: 1px; }

.fl-rating--sm .fl-rating-estrellas { padding: 4px 8px; }
.fl-rating--sm { --fl-rating-tamano: 18px; --fl-rating-gap: 2px; }

.fl-rating--lg .fl-rating-estrellas { padding: 8px 12px; }
.fl-rating--lg { --fl-rating-tamano: 30px; --fl-rating-gap: 4px; }

.fl-rating--xl .fl-rating-estrellas { padding: 10px 16px; }
.fl-rating--xl {
    --fl-rating-tamano: 44px;
    --fl-rating-gap: 6px;
    --fl-rating-sombra: 0 3px 6px color-mix(in srgb, var(--fl-acento) 50%, transparent);
}

/* --------------------------------------------------------------------------
   Chip de valor numérico — espejo del marco de estrellas
   -------------------------------------------------------------------------- */
.fl-rating-valor {
    display: inline-flex;
    align-items: baseline;
    gap: 3px;
    font-size: var(--fl-texto-sm);
    font-weight: 600;
    color: var(--fl-acento-texto);
    font-variant-numeric: tabular-nums;
    padding: 4px 12px;
    background: var(--fl-acento-suave);
    border: 1px solid color-mix(in srgb, var(--fl-acento) 30%, transparent);
    border-radius: 999px;
}

.fl-rating-valor-total {
    color: color-mix(in srgb, var(--fl-acento-texto) 70%, transparent);
    font-weight: 400;
    font-size: 0.85em;
}

@media (prefers-reduced-motion: reduce) {
    .fl-rating-estrella,
    .fl-rating-estrella::after {
        transition: none;
        animation: none;
    }
    .fl-rating--editable .fl-rating-estrella:hover,
    .fl-rating--editable .fl-rating-estrella:active {
        transform: none;
    }
    .fl-rating-estrella[data-fl-pop="true"] {
        animation: none;
    }
}


/* ===== resources/css/componentes/resaltador-codigo.css ===== */
/* ==========================================================================
   Flora · Resaltador-Codigo (syntax highlighter tipo Prism.js)
   Soporta js/ts, php, html/xml, css, sql, bash/shell, json, plaintext.
   Variantes: con números de línea, tema claro/oscuro auto según paleta.
   ========================================================================== */

.fl-codigo {
    display: block;
    position: relative;
    background: var(--fl-fondo-sutil);
    color: var(--fl-texto-fuerte);
    border: 1px solid var(--fl-borde);
    border-radius: var(--fl-r-md);
    padding: var(--fl-sp-3) var(--fl-sp-4);
    font-family: var(--fl-fuente-mono, "IBM Plex Mono", ui-monospace, monospace);
    font-size: var(--fl-texto-sm);
    line-height: var(--fl-lh-comoda);
    overflow-x: auto;
    tab-size: 2;
    white-space: pre;
    word-wrap: normal;
    position: relative;
}

.fl-codigo code {
    display: block;
    font-family: inherit;
    font-size: inherit;
    background: transparent;
    padding: 0;
}

.fl-codigo--lineas { padding-left: 0; }

.fl-codigo-lineas {
    display: inline-flex;
    flex-direction: column;
    padding: 0 var(--fl-sp-3);
    margin-right: var(--fl-sp-3);
    border-right: 1px solid var(--fl-borde-sutil);
    color: var(--fl-texto-tenue);
    font-variant-numeric: tabular-nums;
    user-select: none;
    float: left;
}

.fl-codigo-linea { display: block; line-height: var(--fl-lh-comoda); }

.fl-codigo-etiqueta {
    position: absolute;
    top: 8px;
    right: 8px;
    font-size: var(--fl-texto-xs);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--fl-texto-tenue);
    background: var(--fl-superficie);
    padding: 2px 8px;
    border-radius: var(--fl-r-sm);
    font-family: var(--fl-fuente-sans, sans-serif);
    font-weight: var(--fl-peso-semibold);
}

.fl-codigo-copiar {
    position: absolute;
    top: 6px;
    right: 6px;
    opacity: 0;
    transition: opacity 160ms;
}
.fl-codigo:hover .fl-codigo-copiar { opacity: 1; }
.fl-codigo-copiar + .fl-codigo-etiqueta { right: 72px; }

/* Tokens — estilo balanced tanto en paleta clara como oscuro */
.fl-codigo .tk-comentario { color: var(--fl-texto-tenue); font-style: italic; }
.fl-codigo .tk-keyword { color: color-mix(in srgb, var(--fl-destaque-fondo) 90%, var(--fl-texto-fuerte)); font-weight: var(--fl-peso-semibold); }
.fl-codigo .tk-string { color: #16a34a; }
.fl-codigo .tk-numero { color: #d97706; }
.fl-codigo .tk-boolean { color: #7c3aed; font-weight: var(--fl-peso-semibold); }
.fl-codigo .tk-funcion { color: #2563eb; }
.fl-codigo .tk-operador { color: var(--fl-texto-suave); }
.fl-codigo .tk-tag { color: #e11d48; }
.fl-codigo .tk-atributo { color: #ea580c; }
.fl-codigo .tk-regex { color: #0891b2; }
.fl-codigo .tk-variable { color: #be185d; }
.fl-codigo .tk-punteo { color: var(--fl-texto-suave); }
.fl-codigo .tk-selector { color: #e11d48; }
.fl-codigo .tk-propiedad { color: #2563eb; }
.fl-codigo .tk-valor { color: #16a34a; }

/* En paleta oscuro — colores más saturados */
[data-fl-enfasis="oscuro"] .fl-codigo .tk-keyword { color: #c084fc; }
[data-fl-enfasis="oscuro"] .fl-codigo .tk-string { color: #86efac; }
[data-fl-enfasis="oscuro"] .fl-codigo .tk-numero { color: #fdba74; }
[data-fl-enfasis="oscuro"] .fl-codigo .tk-funcion { color: #93c5fd; }
[data-fl-enfasis="oscuro"] .fl-codigo .tk-tag { color: #fda4af; }
[data-fl-enfasis="oscuro"] .fl-codigo .tk-atributo { color: #fdba74; }
[data-fl-enfasis="oscuro"] .fl-codigo .tk-variable { color: #f9a8d4; }
[data-fl-enfasis="oscuro"] .fl-codigo .tk-selector { color: #fda4af; }
[data-fl-enfasis="oscuro"] .fl-codigo .tk-propiedad { color: #93c5fd; }

/* Inline code */
.fl-codigo-inline {
    display: inline;
    font-family: var(--fl-fuente-mono, monospace);
    font-size: 0.9em;
    background: var(--fl-fondo-sutil);
    color: var(--fl-texto-fuerte);
    padding: 0 6px;
    border-radius: var(--fl-r-sm);
    border: 1px solid var(--fl-borde-sutil);
    white-space: nowrap;
}


/* ===== resources/css/componentes/select.css ===== */
/* ==========================================================================
   Flora · Select (propio, reemplazo de Select2)
   Combobox con búsqueda, posicionamiento dinámico, teclado completo.
   ========================================================================== */

.fl-select {
    position: relative;
    display: block;
    width: 100%;
}

/* Trigger — se ve igual que un .fl-campo-entrada pero es un button */
.fl-select-trigger {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
    width: 100%;
    min-height: var(--fl-alto-control-md);
    padding: 0 var(--fl-sp-8) 0 var(--fl-sp-3);
    font-family: inherit;
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-regular);
    color: var(--fl-texto-fuerte);
    text-align: left;
    background: var(--fl-superficie);
    border: 1px solid var(--fl-borde-fuerte);
    border-radius: var(--fl-r-md);
    box-shadow: var(--fl-sombra-xs);
    cursor: pointer;
    transition: border-color var(--fl-t-rapido) var(--fl-ease-salida),
                box-shadow var(--fl-t-rapido) var(--fl-ease-salida);
    position: relative;
}

.fl-select-trigger::after {
    content: "";
    position: absolute;
    right: var(--fl-sp-3);
    top: 50%;
    width: 16px;
    height: 16px;
    margin-top: -8px;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='m6 9 6 6 6-6'/></svg>");
    background-size: 16px;
    background-repeat: no-repeat;
    color: var(--fl-texto-tenue);
    transition: transform 220ms var(--fl-ease-resorte);
}

.fl-select[data-fl-abierto="true"] .fl-select-trigger::after {
    transform: rotate(180deg);
}

.fl-select-trigger:hover:not(:disabled) {
    border-color: var(--fl-borde-intenso);
}

.fl-select-trigger:focus-visible,
.fl-select[data-fl-abierto="true"] .fl-select-trigger {
    outline: none;
    border-color: var(--fl-acento);
    box-shadow: 0 0 0 var(--fl-foco-ancho) var(--fl-acento-foco);
}

.fl-select-trigger:disabled {
    background: var(--fl-fondo-sutil);
    color: var(--fl-texto-deshabilitado);
    cursor: not-allowed;
    opacity: 0.8;
}

/* Placeholder */
.fl-select-trigger[data-fl-sin-valor="true"] .fl-select-valor {
    color: var(--fl-texto-tenue);
}

.fl-select-valor {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Ícono prefijo del trigger */
.fl-select-trigger .fl-icono--prefijo {
    width: 16px;
    height: 16px;
    color: var(--fl-texto-tenue);
    flex: none;
}

/* Botón de limpiar (x) */
.fl-select-limpiar {
    position: absolute;
    right: 32px;
    top: 50%;
    transform: translateY(-50%);
    width: 18px;
    height: 18px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 0;
    border-radius: var(--fl-r-full);
    color: var(--fl-texto-tenue);
    cursor: pointer;
    opacity: 0;
    transition: opacity 120ms, background 120ms;
}

.fl-select:hover .fl-select-limpiar[data-fl-visible="true"] {
    opacity: 1;
}

.fl-select-limpiar:hover {
    background: var(--fl-superficie-muda);
    color: var(--fl-texto);
}

.fl-select-limpiar .fl-icono {
    width: 12px;
    height: 12px;
}

/* Dropdown panel
   Cuando se abre, se portala al <body> y pasa a position: fixed (via JS).
   Esto evita cualquier problema de clipping/z-index con contenedores padres. */
.fl-select-panel {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    z-index: var(--fl-z-popover);
    background: var(--fl-superficie-elevada);
    border: 1px solid var(--fl-borde);
    border-radius: var(--fl-r-lg);
    box-shadow: var(--fl-sombra-lg),
                0 0 0 1px rgb(0 0 0 / 0.03);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    max-height: 320px;
    opacity: 0;
    transform: translateY(-4px);
    visibility: hidden;
    transition: opacity 140ms var(--fl-ease-salida),
                transform 200ms var(--fl-ease-resorte),
                visibility 180ms;
    pointer-events: none;
}

/* Cuando el panel está portalado al body, JS le asigna position: fixed y
   lo posiciona contra el trigger. */
.fl-select-panel--portal {
    position: fixed !important;
    top: 0;
    left: 0;
    bottom: auto;
    right: auto;
    z-index: var(--fl-z-popover);
}

.fl-select[data-fl-abierto="true"] .fl-select-panel,
.fl-select-panel--portal[data-fl-abierto="true"] {
    opacity: 1;
    transform: translateY(0);
    visibility: visible;
    pointer-events: auto;
}

.fl-select-panel[data-fl-arriba="true"] {
    transform: translateY(4px);
}

.fl-select[data-fl-abierto="true"] .fl-select-panel[data-fl-arriba="true"],
.fl-select-panel--portal[data-fl-abierto="true"][data-fl-arriba="true"] {
    transform: translateY(0);
}

/* Búsqueda */
.fl-select-busqueda {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
    padding: var(--fl-sp-2) var(--fl-sp-3);
    border-bottom: 1px solid var(--fl-borde-sutil);
    flex: none;
}

.fl-select-busqueda .fl-icono {
    width: 14px;
    height: 14px;
    color: var(--fl-texto-tenue);
    flex: none;
}

.fl-select-busqueda-input {
    flex: 1;
    background: transparent;
    border: 0;
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto);
    outline: none;
    padding: 2px 0;
}

.fl-select-busqueda-input::placeholder {
    color: var(--fl-texto-tenue);
}

/* Lista de opciones */
.fl-select-opciones {
    list-style: none;
    padding: var(--fl-sp-1);
    margin: 0;
    overflow-y: auto;
    flex: 1 1 auto;
    min-height: 0;
}

.fl-select-opcion {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
    padding: var(--fl-sp-1-5) var(--fl-sp-2-5);
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto);
    border-radius: var(--fl-r-md);
    cursor: pointer;
    border: 0;
    background: transparent;
    width: 100%;
    text-align: left;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida),
                color var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-select-opcion:hover,
.fl-select-opcion[aria-selected="true"] {
    background: var(--fl-superficie-hover);
    color: var(--fl-texto-fuerte);
}

.fl-select-opcion[data-fl-seleccionada="true"] {
    background: var(--fl-destaque-fondo);
    color: var(--fl-destaque-texto);
    font-weight: var(--fl-peso-semibold);
}

.fl-select-opcion[data-fl-seleccionada="true"]:hover {
    background: var(--fl-destaque-fondo-hover);
    color: var(--fl-destaque-texto);
}

.fl-select-opcion[data-fl-seleccionada="true"] .fl-icono {
    color: var(--fl-destaque-texto);
}

.fl-select-opcion[data-fl-seleccionada="true"]::after {
    content: "";
    width: 14px;
    height: 14px;
    margin-left: auto;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='20 6 9 17 4 12'/></svg>");
    background-repeat: no-repeat;
    background-size: 14px;
    flex: none;
}

.fl-select-opcion .fl-icono {
    width: 16px;
    height: 16px;
    color: var(--fl-texto-suave);
    flex: none;
}

/* Empty state dentro del select */
.fl-select-vacio {
    padding: var(--fl-sp-4) var(--fl-sp-3);
    text-align: center;
    color: var(--fl-texto-tenue);
    font-size: var(--fl-texto-sm);
}

/* Tamaños */
.fl-select--sm .fl-select-trigger {
    min-height: var(--fl-alto-control-sm);
    padding-left: var(--fl-sp-2-5);
    font-size: var(--fl-texto-sm);
}

.fl-select--lg .fl-select-trigger {
    min-height: var(--fl-alto-control-lg);
    padding-left: var(--fl-sp-4);
    font-size: var(--fl-texto-base);
}


/* ===== resources/css/componentes/selector-enfasis.css ===== */
/* ==========================================================================
   Flora · Selector de énfasis
   Pastilla rectangular con 4 stripes de la paleta (acento-200/400/600/800).
   Sin nombre visible — el tooltip/aria-label lleva el título. Cada pastilla
   lleva también data-fl-enfasis="<slug>" para que las variables de
   04-tokens-enfasis.css se resuelvan localmente sobre ese botón.
   ========================================================================== */

.fl-selector-enfasis {
    position: relative;
    padding: 0;
    margin: 0;
    list-style: none;
}

/* Panel: por default es solo un wrapper flex horizontal en desktop. */
.fl-selector-enfasis-panel {
    display: flex;
    flex-wrap: wrap;
    gap: var(--fl-sp-2);
    align-items: center;
}

/* Trigger — oculto en desktop, visible solo en mobile como "select" */
.fl-selector-enfasis-trigger {
    display: none;
}

.fl-selector-enfasis-opcion {
    --_ancho: 44px;
    --_alto: 26px;
    position: relative;
    width: var(--_ancho);
    height: var(--_alto);
    padding: 0;
    overflow: hidden;
    border-radius: var(--fl-r-md);
    border: 1.5px solid color-mix(in srgb, var(--fl-acento-700) 35%, transparent);
    background:
        linear-gradient(
            to right,
            var(--fl-acento-200) 0% 25%,
            var(--fl-acento-400) 25% 50%,
            var(--fl-acento-600) 50% 75%,
            var(--fl-acento-800) 75% 100%
        );
    cursor: pointer;
    /* Sombra base transparente — tenerla en ambos estados evita que el
       browser cambie el modo de composición a mitad de animación (causa
       del "pop" al final) y fuerza repaint por frame = sin raster cache. */
    box-shadow: 0 0 0 0 transparent;
    /* Mismo timing + easing para las 3 props — evita "dos tiempos". */
    transition: transform 420ms var(--fl-ease-salida),
                box-shadow 420ms var(--fl-ease-salida),
                border-color 420ms var(--fl-ease-salida);
}

.fl-selector-enfasis-opcion:hover {
    /* Sin scale para evitar el raster-cache blur+pop del gradient.
       Combinamos un lift mayor + triple sombra con halo sutil para dar
       la sensación de "crece/se eleva" con movimiento único crisp. */
    transform: translateY(-3px);
    border-color: var(--fl-acento-700);
    box-shadow:
        0 0 0 4px color-mix(in srgb, var(--fl-acento-600) 14%, transparent),
        0 14px 28px -8px color-mix(in srgb, var(--fl-acento-600) 65%, transparent),
        0 4px 10px -2px color-mix(in srgb, var(--fl-acento-600) 40%, transparent);
}

.fl-selector-enfasis-opcion:active {
    transform: translateY(0);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--fl-acento-600) 20%, transparent);
    transition-duration: 80ms;
}

.fl-selector-enfasis-opcion:focus-visible {
    outline: none;
    box-shadow: 0 0 0 1px var(--fl-acento-700),
                0 0 0 calc(var(--fl-foco-ancho) + 1px) var(--fl-acento-foco);
}

/* Estado seleccionado — anillo compuesto + tick central */
.fl-selector-enfasis-opcion[aria-pressed="true"] {
    box-shadow: 0 0 0 2px var(--fl-superficie),
                0 0 0 4px var(--fl-acento-700);
}

.fl-selector-enfasis-opcion[aria-pressed="true"]::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 8px;
    height: 8px;
    background: var(--fl-neutro-0);
    /* Borde del color fuerte de la paleta local — cada botón resuelve
       --fl-acento-700 según su data-fl-enfasis, así el dot se tiñe con
       el color de su propia paleta. */
    border: 1.5px solid var(--fl-acento-700);
    border-radius: 50%;
    transform: translate(-50%, -50%);
    box-shadow: 0 1px 2px rgb(0 0 0 / 0.25);
}

/* La paleta "oscuro" necesita un tratamiento especial — sus stripes son
   indigo sobre una "ventana" casi negra, así transmite que es dark mode. */
.fl-selector-enfasis-opcion[data-fl-enfasis="oscuro"] {
    background:
        linear-gradient(
            to right,
            #0a0a0a 0% 20%,
            var(--fl-acento-400) 20% 45%,
            var(--fl-acento-600) 45% 70%,
            #0a0a0a 70% 100%
        );
    border-color: color-mix(in srgb, var(--fl-acento-400) 45%, transparent);
}

/* Cuando la página está en paleta oscura, los swatches de otras paletas
   muestran acento-200 (muy claro, casi blanco) en el primer 25% — se ve
   como una "franja blanca al costado" sobre el fondo oscuro. Desplazamos
   los stops a tonos más oscuros (400/600/800/950) para eliminar ese brillo.
   La paleta oscuro propia tiene su propia regla (arriba). */
[data-fl-enfasis="oscuro"] .fl-selector-enfasis-opcion:not([data-fl-enfasis="oscuro"]) {
    background:
        linear-gradient(
            to right,
            var(--fl-acento-400) 0% 25%,
            var(--fl-acento-600) 25% 50%,
            var(--fl-acento-800) 50% 75%,
            var(--fl-acento-950) 75% 100%
        );
    border-color: color-mix(in srgb, var(--fl-acento-500) 45%, transparent);
}

/* Tamaños */
.fl-selector-enfasis--sm .fl-selector-enfasis-opcion {
    --_ancho: 34px;
    --_alto: 20px;
}
.fl-selector-enfasis--lg .fl-selector-enfasis-opcion {
    --_ancho: 56px;
    --_alto: 32px;
}

/* Variante con etiqueta debajo */
.fl-selector-enfasis--con-etiquetas {
    gap: var(--fl-sp-3);
}

.fl-selector-enfasis-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--fl-sp-1);
}

.fl-selector-enfasis-etiqueta {
    font-size: var(--fl-texto-2xs);
    color: var(--fl-texto-suave);
    text-transform: capitalize;
    letter-spacing: var(--fl-ls-amplio);
}

.fl-selector-enfasis-item:has(.fl-selector-enfasis-opcion[aria-pressed="true"])
    .fl-selector-enfasis-etiqueta {
    color: var(--fl-texto-fuerte);
    font-weight: var(--fl-peso-medio);
}

@media (prefers-reduced-motion: reduce) {
    .fl-selector-enfasis-opcion { transition: none; }
    .fl-selector-enfasis-opcion:hover,
    .fl-selector-enfasis-opcion:active { transform: none; }
}

/* --------------------------------------------------------------------------
   Mobile: el selector colapsa en un dropdown tipo "select lindo".
   · Trigger muestra un swatch preview de la paleta activa + chevron.
   · Al tap abre el panel flotante con las 8 opciones en grilla.
   · El JS maneja open/close agregando [data-fl-abierto="true"].
   En desktop el trigger queda oculto y el panel es la fila horizontal.
   -------------------------------------------------------------------------- */
@media (max-width: 767px) {
    .fl-selector-enfasis-trigger {
        display: inline-flex;
        align-items: center;
        gap: var(--fl-sp-2);
        height: 36px;
        padding: 0 10px;
        background: var(--fl-superficie);
        border: 1px solid var(--fl-borde-fuerte);
        border-radius: var(--fl-r-md);
        cursor: pointer;
        font-family: inherit;
        color: var(--fl-texto-fuerte);
        transition: border-color 160ms var(--fl-ease-salida),
                    background 160ms var(--fl-ease-salida);
    }

    .fl-selector-enfasis-trigger:hover,
    .fl-selector-enfasis[data-fl-abierto="true"] .fl-selector-enfasis-trigger {
        border-color: var(--fl-acento);
        background: var(--fl-superficie-hover);
    }

    .fl-selector-enfasis-trigger .fl-icono {
        width: 14px;
        height: 14px;
        color: var(--fl-texto-suave);
        transition: transform 180ms var(--fl-ease-resorte);
    }

    .fl-selector-enfasis[data-fl-abierto="true"] .fl-selector-enfasis-trigger .fl-icono {
        transform: rotate(180deg);
    }

    /* Preview del swatch de la paleta activa en el trigger. Hereda las
       variables --fl-acento-* del [data-fl-enfasis] global → muestra la
       paleta actual. */
    .fl-selector-enfasis-trigger-preview {
        width: 26px;
        height: 16px;
        border-radius: var(--fl-r-sm);
        border: 1.5px solid color-mix(in srgb, var(--fl-acento-700) 35%, transparent);
        background:
            linear-gradient(
                to right,
                var(--fl-acento-200) 0% 25%,
                var(--fl-acento-400) 25% 50%,
                var(--fl-acento-600) 50% 75%,
                var(--fl-acento-800) 75% 100%
            );
    }

    /* Panel oculto por default en mobile — se abre vía [data-fl-abierto]. */
    .fl-selector-enfasis-panel {
        position: absolute;
        top: calc(100% + 6px);
        right: 0;
        z-index: var(--fl-z-popover, 30);
        display: grid;
        grid-template-columns: repeat(2, auto);
        gap: var(--fl-sp-2);
        padding: var(--fl-sp-3);
        background: var(--fl-superficie-elevada);
        border: 1px solid var(--fl-borde);
        border-radius: var(--fl-r-lg);
        box-shadow: var(--fl-sombra-lg);
        opacity: 0;
        visibility: hidden;
        transform: translateY(-4px) scale(0.98);
        transform-origin: top right;
        transition: opacity 160ms var(--fl-ease-salida),
                    transform 200ms var(--fl-ease-resorte),
                    visibility 180ms;
        pointer-events: none;
    }

    .fl-selector-enfasis[data-fl-abierto="true"] .fl-selector-enfasis-panel {
        opacity: 1;
        visibility: visible;
        transform: translateY(0) scale(1);
        pointer-events: auto;
    }

    /* Variante con etiquetas: en mobile el panel se vuelve 1 columna con
       label al lado del swatch para mejor legibilidad. */
    .fl-selector-enfasis--con-etiquetas .fl-selector-enfasis-panel {
        grid-template-columns: 1fr;
        gap: var(--fl-sp-1-5);
    }

    .fl-selector-enfasis--con-etiquetas .fl-selector-enfasis-item {
        flex-direction: row;
        gap: var(--fl-sp-2);
        justify-content: flex-start;
    }
}


/* ===== resources/css/componentes/selector-intensidad.css ===== */
/* ==========================================================================
   Flora · Selector de intensidad
   4 opciones (vívida / media / suave / neutro) representadas como mini-bloques
   que muestran visualmente cuánto "invade" la paleta. Usa data-fl-intensidad-set
   (manejado por 02-tema.js).
   ========================================================================== */

.fl-selector-intensidad {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 2px;
    background: var(--fl-superficie-muda);
    border: 1px solid var(--fl-borde-sutil);
    border-radius: var(--fl-r-md);
}

.fl-selector-intensidad-opcion {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 4px 10px;
    font-size: var(--fl-texto-xs);
    font-weight: var(--fl-peso-medio);
    color: var(--fl-texto-suave);
    background: transparent;
    border: 0;
    border-radius: var(--fl-r-sm);
    cursor: pointer;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida),
                color var(--fl-t-rapido) var(--fl-ease-salida);
    text-transform: capitalize;
}

.fl-selector-intensidad-opcion:hover {
    color: var(--fl-texto-fuerte);
    background: color-mix(in srgb, var(--fl-acento) 8%, transparent);
}

.fl-selector-intensidad-opcion[aria-pressed="true"] {
    background: var(--fl-destaque-fondo);
    color: var(--fl-destaque-texto);
    font-weight: var(--fl-peso-semibold);
}

/* Puntito de tinte — visualiza la intensidad */
.fl-selector-intensidad-opcion::before {
    content: "";
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--fl-acento);
    flex: none;
    opacity: var(--_intensidad, 1);
}

.fl-selector-intensidad-opcion[data-fl-intensidad-set="vivida"]::before { --_intensidad: 1; }
.fl-selector-intensidad-opcion[data-fl-intensidad-set="media"]::before  { --_intensidad: 0.65; }
.fl-selector-intensidad-opcion[data-fl-intensidad-set="suave"]::before  { --_intensidad: 0.35; }
.fl-selector-intensidad-opcion[data-fl-intensidad-set="neutro"]::before {
    --_intensidad: 1;
    background: var(--fl-neutro-400);
}

.fl-selector-intensidad-opcion[aria-pressed="true"]::before {
    background: var(--fl-destaque-texto);
    opacity: 1;
}

/* Mobile: reducir padding, font-size y el puntito para que la barra
   (vívida / media / suave) ocupe menos ancho. */
@media (max-width: 767px) {
    .fl-selector-intensidad-opcion {
        padding: 3px 7px;
        font-size: var(--fl-texto-2xs);
        gap: 3px;
    }
    .fl-selector-intensidad-opcion::before {
        width: 6px;
        height: 6px;
    }
}


/* ===== resources/css/componentes/separador.css ===== */
/* ==========================================================================
   Flora · Separador (extendido)
   La base está en layout.css. Acá agregamos variantes con etiqueta central,
   verticales, discretos y con ícono.
   ========================================================================== */

/* Separador con etiqueta central — "o" / "Sección 2" / etc. */
.fl-separador-etiquetado {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-3);
    margin: var(--fl-sp-4) 0;
    color: var(--fl-texto-tenue);
}

.fl-separador-etiquetado::before,
.fl-separador-etiquetado::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--fl-borde-fuerte);
}

.fl-separador-etiquetado-texto {
    font-size: var(--fl-texto-xs);
    font-weight: var(--fl-peso-medio);
    text-transform: uppercase;
    letter-spacing: var(--fl-ls-mayus);
    white-space: nowrap;
}

/* Variante: alineación izquierda (la línea se queda a la derecha) */
.fl-separador-etiquetado--izq::before { display: none; }

/* Separador vertical más robusto — para dividir secciones en una fila */
.fl-separador-vertical {
    display: inline-block;
    width: 1px;
    height: 1em;
    background: var(--fl-borde-fuerte);
    margin: 0 var(--fl-sp-2);
    vertical-align: middle;
}

.fl-separador-vertical--alto {
    height: 1.5em;
}

/* Punto separador — tipo breadcrumb inline */
.fl-separador-punto {
    display: inline-block;
    width: 3px;
    height: 3px;
    border-radius: var(--fl-r-full);
    background: var(--fl-texto-tenue);
    margin: 0 var(--fl-sp-2);
    vertical-align: middle;
}

/* Separador punteado (dashed) — más suave, menos formal */
.fl-separador--punteado {
    background: transparent;
    border-top: 1px dashed var(--fl-borde-fuerte);
    height: 0;
}

/* Separador acentuado — con el color acento */
.fl-separador--acentuado {
    background: var(--fl-acento);
    height: 2px;
    border-radius: var(--fl-r-full);
}

/* Separador corto — para headers de sección (ej: decoración debajo de un título) */
.fl-separador--corto {
    width: 32px;
    height: 2px;
    background: var(--fl-acento);
    border-radius: var(--fl-r-full);
    margin: var(--fl-sp-2) 0;
}


/* ===== resources/css/componentes/sidebar.css ===== */
/* ==========================================================================
   Flora · Sidebar (navegación lateral)
   Vertical, con secciones, ítem activo destacado, opción colapsable a íconos.
   ========================================================================== */

.fl-sidebar {
    --_ancho-expandido: 240px;
    --_ancho-colapsado: 60px;
    /* Token local: color de hover/línea sobre el sidebar destacado. */
    --_separador: color-mix(in srgb, var(--fl-destaque-texto) 12%, transparent);

    /* Redefino los tokens de texto localmente: todo descendiente que use
       --fl-texto, --fl-texto-fuerte, etc. se lee claro sobre el fondo
       destaque sin tener que tocar cada selector interno. */
    --fl-texto:          var(--fl-destaque-texto);
    --fl-texto-fuerte:   var(--fl-destaque-texto);
    --fl-texto-suave:    color-mix(in srgb, var(--fl-destaque-texto) 75%, transparent);
    --fl-texto-tenue:    color-mix(in srgb, var(--fl-destaque-texto) 55%, transparent);
    --fl-superficie-hover: color-mix(in srgb, var(--fl-destaque-texto) 12%, transparent);
    --fl-superficie-activa: color-mix(in srgb, var(--fl-destaque-texto) 18%, transparent);

    display: flex;
    flex-direction: column;
    width: var(--_ancho-expandido);
    min-width: var(--_ancho-expandido);
    height: 100vh;
    background: var(--fl-destaque-fondo);
    color: var(--fl-destaque-texto);
    border-right: 1px solid var(--_separador);
    transition: width 280ms var(--fl-ease-salida),
                min-width 280ms var(--fl-ease-salida);
    position: sticky;
    top: 0;
    overflow: hidden;
}

/* Variante sobria — opt-out al patrón destaque. Para apps que quieren
   sidebar neutro en vez de la firma flora. */
.fl-sidebar--sobrio {
    background: var(--fl-superficie);
    color: var(--fl-texto);
    --_separador: var(--fl-borde-sutil);
    border-right: 1px solid var(--fl-borde);
}

.fl-sidebar[data-fl-colapsado="true"] {
    width: var(--_ancho-colapsado);
    min-width: var(--_ancho-colapsado);
}

/* Cabecera: marca + toggle */
.fl-sidebar-cabecera {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--fl-sp-2);
    padding: var(--fl-sp-3) var(--fl-sp-4);
    border-bottom: 1px solid var(--_separador);
    flex: none;
    min-height: 56px;
}

.fl-sidebar-marca .fl-marca-nombre {
    color: var(--fl-destaque-texto);
}

.fl-sidebar[data-fl-colapsado="true"] .fl-sidebar-cabecera {
    padding: var(--fl-sp-3);
    justify-content: center;
}

/* En colapsado ocultamos la marca — sólo queda el toggle centrado */
.fl-sidebar[data-fl-colapsado="true"] .fl-sidebar-marca {
    display: none;
}

.fl-sidebar-marca {
    overflow: hidden;
}

.fl-sidebar-marca .fl-marca-nombre {
    transition: opacity 160ms var(--fl-ease-salida);
}

.fl-sidebar[data-fl-colapsado="true"] .fl-sidebar-marca .fl-marca-nombre {
    opacity: 0;
    width: 0;
    overflow: hidden;
}

.fl-sidebar-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    background: transparent;
    border: 0;
    border-radius: var(--fl-r-md);
    color: color-mix(in srgb, var(--fl-destaque-texto) 70%, transparent);
    cursor: pointer;
    flex: none;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida),
                color var(--fl-t-rapido) var(--fl-ease-salida),
                transform 260ms var(--fl-ease-resorte);
}

.fl-sidebar-toggle:hover {
    background: color-mix(in srgb, var(--fl-destaque-texto) 12%, transparent);
    color: var(--fl-destaque-texto);
}

.fl-sidebar[data-fl-colapsado="true"] .fl-sidebar-toggle {
    transform: rotate(180deg);
}

.fl-sidebar-toggle .fl-icono {
    width: 16px;
    height: 16px;
}

/* Contenido: secciones scrollable */
.fl-sidebar-contenido {
    flex: 1;
    overflow-y: auto;
    overflow-x: hidden;
    padding: var(--fl-sp-3) var(--fl-sp-2);
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-4);
}

.fl-sidebar-seccion {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.fl-sidebar-seccion-titulo {
    padding: var(--fl-sp-1) var(--fl-sp-3);
    font-size: var(--fl-texto-2xs);
    font-weight: var(--fl-peso-semibold);
    text-transform: uppercase;
    letter-spacing: var(--fl-ls-mayus);
    color: color-mix(in srgb, var(--fl-destaque-texto) 55%, transparent);
    white-space: nowrap;
    transition: opacity 160ms var(--fl-ease-salida);
}

.fl-sidebar[data-fl-colapsado="true"] .fl-sidebar-seccion-titulo {
    opacity: 0;
    height: 0;
    padding: 0;
    overflow: hidden;
}

/* Ítems de navegación */
.fl-sidebar-item {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2-5);
    padding: var(--fl-sp-2) var(--fl-sp-3);
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-medio);
    color: color-mix(in srgb, var(--fl-destaque-texto) 78%, transparent);
    text-decoration: none;
    border-radius: var(--fl-r-md);
    transition: background var(--fl-t-rapido) var(--fl-ease-salida),
                color var(--fl-t-rapido) var(--fl-ease-salida);
    position: relative;
    white-space: nowrap;
    overflow: hidden;
}

.fl-sidebar-item:hover {
    background: color-mix(in srgb, var(--fl-destaque-texto) 12%, transparent);
    color: var(--fl-destaque-texto);
}

.fl-sidebar-item:focus-visible {
    outline: none;
    background: color-mix(in srgb, var(--fl-destaque-texto) 12%, transparent);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--fl-destaque-texto) 35%, transparent);
}

.fl-sidebar-item-icono {
    flex: none;
    width: 18px;
    height: 18px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.fl-sidebar-item-icono .fl-icono {
    width: 18px;
    height: 18px;
}

.fl-sidebar-item-texto {
    flex: 1;
    min-width: 0;
    transition: opacity 160ms var(--fl-ease-salida);
}

.fl-sidebar-item-badge {
    margin-left: auto;
    flex: none;
}

/* Colapsado: cada item = cuadrado 40x40 centrado, sólo ícono visible.
   Los textos y badges se ocultan con display:none para no romper el gap. */
.fl-sidebar[data-fl-colapsado="true"] .fl-sidebar-item {
    padding: 0;
    width: 40px;
    height: 40px;
    margin-left: auto;
    margin-right: auto;
    justify-content: center;
    gap: 0;
}

.fl-sidebar[data-fl-colapsado="true"] .fl-sidebar-item-icono {
    margin: 0;
}

.fl-sidebar[data-fl-colapsado="true"] .fl-sidebar-item-texto,
.fl-sidebar[data-fl-colapsado="true"] .fl-sidebar-item-badge {
    display: none;
}

/* Secciones colapsadas: centrar contenido para que iconos queden alineados */
.fl-sidebar[data-fl-colapsado="true"] .fl-sidebar-seccion {
    align-items: center;
}

/* Padding horizontal reducido en contenido colapsado */
.fl-sidebar[data-fl-colapsado="true"] .fl-sidebar-contenido {
    padding-left: 0;
    padding-right: 0;
}

/* Pie/usuario en colapsado: círculo centrado con sólo avatar */
.fl-sidebar[data-fl-colapsado="true"] .fl-sidebar-pie {
    padding: var(--fl-sp-2);
    display: flex;
    justify-content: center;
}

/* --------------------------------------------------------------------------
   Inputs y botones fantasma dentro del sidebar destaque
   El sidebar redefine --fl-texto-fuerte a destaque-texto (blanco) para que
   los items naveguen bien. Pero eso también pinta los inputs (que tienen
   background: var(--fl-superficie) blanco) con texto blanco → invisible.
   Mismo con .fl-boton--fantasma que usa --fl-acento-texto (oscuro).
   Mismo fix que en navbar: glass theme para inputs, blanco para fantasma.
   Scopeado a :not(.fl-sidebar--sobrio) porque la variante sobria tiene
   fondo claro y no sufre el problema.
   -------------------------------------------------------------------------- */
.fl-sidebar:not(.fl-sidebar--sobrio) .fl-campo-entrada {
    background: color-mix(in srgb, var(--fl-destaque-texto) 12%, transparent);
    border-color: color-mix(in srgb, var(--fl-destaque-texto) 25%, transparent);
    color: var(--fl-destaque-texto);
}

.fl-sidebar:not(.fl-sidebar--sobrio) .fl-campo-entrada::placeholder {
    color: color-mix(in srgb, var(--fl-destaque-texto) 55%, transparent);
    opacity: 1;
}

.fl-sidebar:not(.fl-sidebar--sobrio) .fl-campo-entrada:hover:not(:focus) {
    background: color-mix(in srgb, var(--fl-destaque-texto) 16%, transparent);
    border-color: color-mix(in srgb, var(--fl-destaque-texto) 35%, transparent);
}

.fl-sidebar:not(.fl-sidebar--sobrio) .fl-campo-entrada:focus {
    background: color-mix(in srgb, var(--fl-destaque-texto) 20%, transparent);
    border-color: color-mix(in srgb, var(--fl-destaque-texto) 50%, transparent);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--fl-destaque-texto) 25%, transparent);
}

.fl-sidebar:not(.fl-sidebar--sobrio) .fl-campo-grupo-icono {
    color: color-mix(in srgb, var(--fl-destaque-texto) 70%, transparent);
}

.fl-sidebar:not(.fl-sidebar--sobrio) .fl-campo-entrada::-webkit-search-cancel-button {
    -webkit-appearance: none;
    appearance: none;
    width: 14px;
    height: 14px;
    background-color: color-mix(in srgb, var(--fl-destaque-texto) 70%, transparent);
    -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round'><path d='M6 6l12 12M18 6L6 18'/></svg>");
    mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round'><path d='M6 6l12 12M18 6L6 18'/></svg>");
    -webkit-mask-size: contain;
    mask-size: contain;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
    cursor: pointer;
    transition: background-color var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-sidebar:not(.fl-sidebar--sobrio) .fl-campo-entrada::-webkit-search-cancel-button:hover {
    background-color: var(--fl-destaque-texto);
}

.fl-sidebar:not(.fl-sidebar--sobrio) .fl-boton--fantasma {
    color: var(--fl-destaque-texto);
}

.fl-sidebar:not(.fl-sidebar--sobrio) .fl-boton--fantasma:hover:not(:disabled),
.fl-sidebar:not(.fl-sidebar--sobrio) .fl-boton--fantasma:active:not(:disabled) {
    color: var(--fl-destaque-texto);
    background: color-mix(in srgb, var(--fl-destaque-texto) 14%, transparent);
}

.fl-sidebar[data-fl-colapsado="true"] .fl-sidebar-usuario {
    padding: var(--fl-sp-1);
    justify-content: center;
}

.fl-sidebar[data-fl-colapsado="true"] .fl-sidebar-usuario-info {
    display: none;
}

/* Activo — pastilla invertida: fondo del color texto (blanco en claro,
   oscuro en oscuro) y texto del color destaque. Máximo contraste dentro
   del sidebar ya oscuro. Aplicamos tanto por clase como por aria-current
   para que el JS pueda usar cualquiera de los dos, y con especificidad
   suficiente para ganar al :hover. */
.fl-sidebar-item.fl-sidebar-item--activo,
.fl-sidebar-item[aria-current="page"] {
    background: var(--fl-destaque-texto);
    color: var(--fl-destaque-fondo);
    font-weight: var(--fl-peso-semibold);
    box-shadow: 0 4px 14px -6px color-mix(in srgb, var(--fl-destaque-texto) 40%, transparent);
}

.fl-sidebar-item.fl-sidebar-item--activo:hover,
.fl-sidebar-item[aria-current="page"]:hover {
    background: var(--fl-destaque-texto);
    color: var(--fl-destaque-fondo);
}

.fl-sidebar-item.fl-sidebar-item--activo .fl-icono,
.fl-sidebar-item[aria-current="page"] .fl-icono {
    color: var(--fl-destaque-fondo);
}

/* Pie del sidebar */
.fl-sidebar-pie {
    padding: var(--fl-sp-3);
    border-top: 1px solid var(--_separador);
    flex: none;
}

.fl-sidebar-usuario {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
    padding: var(--fl-sp-2);
    border-radius: var(--fl-r-md);
    cursor: pointer;
    text-decoration: none;
    color: inherit;
    transition: background var(--fl-t-rapido);
}

.fl-sidebar-usuario:hover {
    background: color-mix(in srgb, var(--fl-destaque-texto) 12%, transparent);
}

.fl-sidebar-usuario-info {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    transition: opacity 160ms var(--fl-ease-salida);
}

.fl-sidebar-usuario-nombre {
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-medio);
    color: var(--fl-destaque-texto);
    line-height: 1.2;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.fl-sidebar-usuario-rol {
    font-size: var(--fl-texto-xs);
    color: color-mix(in srgb, var(--fl-destaque-texto) 60%, transparent);
    line-height: 1.2;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.fl-sidebar[data-fl-colapsado="true"] .fl-sidebar-usuario-info {
    opacity: 0;
    width: 0;
}

/* Responsive: oculta en mobile (sería drawer en Fase 4) */
@media (max-width: 767px) {
    .fl-sidebar {
        display: none;
    }
}

/* ==========================================================================
   Shell wrapper — contenedor interno con cabecera/contenido/pie.
   En modo normal es un simple flex column; en hover-peek se saca del
   flujo y flota sobre el contenido.
   ========================================================================== */
.fl-sidebar-shell {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    min-width: 0;
    overflow: hidden;
}

/* ==========================================================================
   Hover-peek — variante tipo Linear/Vercel/Notion.
   El aside reserva un slot de 60px en el layout (como colapsado normal),
   pero al hacer hover/focus, el shell se expande a 240px flotando por
   encima del contenido, con sombra fuerte y backdrop visual. No empuja
   layout → no reflow visible cada vez que el mouse pasa cerca.
   ========================================================================== */

/* En peek-collapsed, el aside actúa sólo como slot. Le sacamos fondo y
   borde porque ahora los pinta el shell (que es el que se ve). */
.fl-sidebar--hover-peek[data-fl-colapsado="true"] {
    overflow: visible;
    background: transparent;
    border-right: 0;
}

/* Shell flotante: arranca en 60px (matchea el slot) y transiciona a 240px
   cuando data-fl-peek se activa. z-index alto para quedar sobre headers
   de la app, botones flotantes, etc. */
.fl-sidebar--hover-peek[data-fl-colapsado="true"] .fl-sidebar-shell {
    position: absolute;
    inset: 0 auto 0 0;
    width: var(--_ancho-colapsado);
    height: 100%;
    background: var(--fl-destaque-fondo);
    color: var(--fl-destaque-texto);
    border-right: 1px solid var(--_separador);
    transition: width 280ms var(--fl-ease-salida),
                box-shadow 280ms var(--fl-ease-salida);
    z-index: 20;
}

/* Variante sobria: shell con tokens neutros */
.fl-sidebar--hover-peek.fl-sidebar--sobrio[data-fl-colapsado="true"] .fl-sidebar-shell {
    background: var(--fl-superficie);
    color: var(--fl-texto);
    border-right: 1px solid var(--fl-borde);
}

/* Peek activo: shell a ancho expandido, sombra grande, z-index sobre todo */
.fl-sidebar--hover-peek[data-fl-colapsado="true"][data-fl-peek="true"] .fl-sidebar-shell {
    width: var(--_ancho-expandido);
    box-shadow: var(--fl-sombra-xl),
                0 12px 32px -8px rgb(0 0 0 / 0.25);
    z-index: 50;
}

/* Pisa los visuals de data-fl-colapsado mientras peek está activo, para
   que ítems, labels y badges se vean como en modo expandido. La cadena
   [data-fl-colapsado][data-fl-peek] suma especificidad suficiente (0,4,0
   vs 0,3,0 de las reglas de colapso). */
.fl-sidebar--hover-peek[data-fl-colapsado="true"][data-fl-peek="true"] .fl-sidebar-cabecera {
    padding: var(--fl-sp-3) var(--fl-sp-4);
    justify-content: space-between;
}
.fl-sidebar--hover-peek[data-fl-colapsado="true"][data-fl-peek="true"] .fl-sidebar-marca {
    display: flex;
}
.fl-sidebar--hover-peek[data-fl-colapsado="true"][data-fl-peek="true"] .fl-sidebar-marca .fl-marca-nombre {
    opacity: 1;
    width: auto;
    overflow: visible;
}
/* En hover-peek el toggle muestra pin (para fijar) o chevron-left (para
   desfijar). Anulamos la rotación del chevron colapsado normal para que
   el pin no quede al revés, y la volvemos a aplicar sólo sobre el chevron
   de "desfijar" si se quisiera; por ahora chevron-left ya apunta hacia
   el borde izquierdo del sidebar, que es la dirección de "colapsar". */
.fl-sidebar--hover-peek .fl-sidebar-toggle {
    transform: none;
}

/* Colapsado flotante (sin peek): mostramos la marca (sólo el ícono, el
   nombre sigue oculto por la regla general de colapso) y ocultamos el
   toggle. Así los 60px del slot se ven como un brand-strip limpio, y el
   pin aparece sólo cuando peek activa (es decir, cuando la acción "fijar"
   tiene sentido porque el sidebar ya se está mostrando). */
.fl-sidebar--hover-peek[data-fl-colapsado="true"]:not([data-fl-peek="true"]) .fl-sidebar-cabecera {
    justify-content: center;
    padding: var(--fl-sp-3);
}
.fl-sidebar--hover-peek[data-fl-colapsado="true"]:not([data-fl-peek="true"]) .fl-sidebar-marca {
    display: flex;
    /* gap a 0 para que el logo quede ópticamente centrado: el nombre está
       oculto con width:0 pero el gap entre ítems flex todavía reserva 8px
       y correría el logo a la izquierda. */
    gap: 0;
}
.fl-sidebar--hover-peek[data-fl-colapsado="true"]:not([data-fl-peek="true"]) .fl-sidebar-toggle {
    display: none;
}

/* Toggle pin/unpin: mostramos sólo uno según el estado.
   - Flotante (colapsado):  pin           → "click para fijar"
   - Fijado  (expandido):   chevron-left  → "click para colapsar/desfijar" */
.fl-sidebar-toggle-pin,
.fl-sidebar-toggle-unpin {
    display: none;
}
.fl-sidebar--hover-peek[data-fl-colapsado="true"] .fl-sidebar-toggle-pin {
    display: inline-flex;
}
.fl-sidebar--hover-peek:not([data-fl-colapsado="true"]) .fl-sidebar-toggle-unpin {
    display: inline-flex;
}
.fl-sidebar--hover-peek[data-fl-colapsado="true"][data-fl-peek="true"] .fl-sidebar-seccion {
    align-items: stretch;
}
.fl-sidebar--hover-peek[data-fl-colapsado="true"][data-fl-peek="true"] .fl-sidebar-seccion-titulo {
    opacity: 1;
    height: auto;
    padding: var(--fl-sp-1) var(--fl-sp-3);
    overflow: visible;
}
.fl-sidebar--hover-peek[data-fl-colapsado="true"][data-fl-peek="true"] .fl-sidebar-contenido {
    padding: var(--fl-sp-3) var(--fl-sp-2);
}
.fl-sidebar--hover-peek[data-fl-colapsado="true"][data-fl-peek="true"] .fl-sidebar-item {
    padding: var(--fl-sp-2) var(--fl-sp-3);
    width: auto;
    height: auto;
    margin-left: 0;
    margin-right: 0;
    justify-content: flex-start;
    gap: var(--fl-sp-2-5);
}
.fl-sidebar--hover-peek[data-fl-colapsado="true"][data-fl-peek="true"] .fl-sidebar-item-texto {
    display: block;
}
.fl-sidebar--hover-peek[data-fl-colapsado="true"][data-fl-peek="true"] .fl-sidebar-item-badge {
    display: inline-flex;
}
.fl-sidebar--hover-peek[data-fl-colapsado="true"][data-fl-peek="true"] .fl-sidebar-pie {
    padding: var(--fl-sp-3);
    display: block;
    justify-content: flex-start;
}
.fl-sidebar--hover-peek[data-fl-colapsado="true"][data-fl-peek="true"] .fl-sidebar-usuario {
    padding: var(--fl-sp-2);
    justify-content: flex-start;
}
.fl-sidebar--hover-peek[data-fl-colapsado="true"][data-fl-peek="true"] .fl-sidebar-usuario-info {
    display: flex;
    opacity: 1;
    width: auto;
}

@media (prefers-reduced-motion: reduce) {
    .fl-sidebar--hover-peek .fl-sidebar-shell {
        transition: none;
    }
}


/* ===== resources/css/componentes/skeleton.css ===== */
/* ==========================================================================
   Flora · Skeleton
   Placeholder visual mientras se carga contenido. Shimmer animado.
   ========================================================================== */

.fl-skeleton {
    display: block;
    position: relative;
    /* Base tintada con el acento — el skeleton respira la paleta activa */
    background: color-mix(in srgb, var(--fl-acento) 14%, var(--fl-superficie-muda));
    border-radius: var(--fl-r-sm);
    overflow: hidden;
    min-height: 1em;
}

.fl-skeleton::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(
        90deg,
        transparent 0%,
        color-mix(in srgb, var(--fl-acento) 22%, transparent) 50%,
        transparent 100%
    );
    transform: translateX(-100%);
    animation: fl-skeleton-shimmer 1600ms var(--fl-ease-inout) infinite;
}

@keyframes fl-skeleton-shimmer {
    to { transform: translateX(100%); }
}

/* --------------------------------------------------------------------------
   Formas predefinidas
   -------------------------------------------------------------------------- */

.fl-skeleton--texto {
    height: 1em;
    border-radius: var(--fl-r-sm);
}

.fl-skeleton--titulo {
    height: 1.6em;
    border-radius: var(--fl-r-sm);
    width: 60%;
}

.fl-skeleton--parrafo {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-2);
    background: transparent;
    min-height: auto;
}

.fl-skeleton--parrafo::after {
    display: none;
}

.fl-skeleton--parrafo > .fl-skeleton {
    height: 0.9em;
}

.fl-skeleton--parrafo > .fl-skeleton:last-child {
    width: 70%;
}

/* Círculo (avatares) */
.fl-skeleton--circulo {
    border-radius: var(--fl-r-full);
    aspect-ratio: 1;
    width: 40px;
}

.fl-skeleton--circulo-sm  { width: 24px; }
.fl-skeleton--circulo-lg  { width: 56px; }

/* Botón */
.fl-skeleton--boton {
    height: var(--fl-alto-control-md);
    width: 120px;
    border-radius: var(--fl-r-md);
}

/* Tarjeta completa */
.fl-skeleton--tarjeta {
    height: 160px;
    width: 100%;
    border-radius: var(--fl-r-lg);
}

/* Imagen */
.fl-skeleton--imagen {
    aspect-ratio: 16 / 9;
    width: 100%;
    border-radius: var(--fl-r-md);
}

/* --------------------------------------------------------------------------
   Grupo — combina skeletons para simular una fila o fila completa
   -------------------------------------------------------------------------- */
.fl-skeleton-fila {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-3);
    padding: var(--fl-sp-2) 0;
}

.fl-skeleton-fila > .fl-skeleton--texto:first-of-type {
    flex: 1;
}

@media (prefers-reduced-motion: reduce) {
    .fl-skeleton::after {
        animation: none;
    }
}


/* ===== resources/css/componentes/switch.css ===== */
/* ==========================================================================
   Flora · Switch (toggle)
   Pill con pulgar deslizante. Reemplaza checkbox cuando semanticamente es
   "encender/apagar" en vez de "elegir".
   ========================================================================== */

.fl-switch {
    display: inline-flex;
    align-items: center;
    gap: var(--fl-sp-2-5);
    cursor: pointer;
    user-select: none;
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto);
    line-height: var(--fl-lh-ajustada);
}

.fl-switch:has(input:disabled) {
    cursor: not-allowed;
    opacity: 0.6;
}

/* El input nativo se oculta visualmente pero sigue funcional */
.fl-switch-control {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
    pointer-events: none;
}

/* Pista (track)
   Off: gris MUY claro neutro fijo (no varía con paleta) — claramente "apagado".
   On:  color de acento sólido — claramente "encendido" con la marca de la app.
   Antes el off era `--fl-borde-intenso` (gris medio) y el on `--fl-destaque-fondo`
   (que en algunas intensidades es pastel) — los dos parecían "medio prendido"
   y no se distinguían bien. */
.fl-switch-pista {
    position: relative;
    display: inline-block;
    width: 36px;
    height: 20px;
    background: var(--fl-neutro-200);
    border-radius: var(--fl-r-full);
    transition: background 200ms var(--fl-ease-salida);
    flex: none;
}

/* Pulgar (thumb)
   En estado off, un ring 1px gris separa el thumb (blanco) del track (gris
   claro) para que no se camufle. En estado on, el ring desaparece porque el
   contraste con el acento sólido ya es máximo. */
.fl-switch-pulgar {
    position: absolute;
    top: 2px;
    left: 2px;
    width: 16px;
    height: 16px;
    background: var(--fl-neutro-0);
    border-radius: var(--fl-r-full);
    box-shadow: 0 0 0 1px var(--fl-neutro-300),
                0 1px 2px rgb(0 0 0 / 0.15),
                0 1px 3px rgb(0 0 0 / 0.08);
    transition: transform 260ms var(--fl-ease-resorte),
                width 120ms var(--fl-ease-salida),
                box-shadow 200ms var(--fl-ease-salida);
}

/* Estado encendido — acento sólido, máximo contraste */
.fl-switch-control:checked + .fl-switch-pista {
    background: var(--fl-acento);
}

.fl-switch-control:checked + .fl-switch-pista .fl-switch-pulgar {
    transform: translateX(16px);
    box-shadow: 0 0 0 1px transparent,
                0 1px 2px rgb(0 0 0 / 0.25),
                0 1px 3px rgb(0 0 0 / 0.12);
}

/* Squish del pulgar al hacer click (press) */
.fl-switch:active .fl-switch-pulgar {
    width: 20px;
}

.fl-switch:active .fl-switch-control:checked + .fl-switch-pista .fl-switch-pulgar {
    transform: translateX(12px);
}

/* Foco */
.fl-switch-control:focus-visible + .fl-switch-pista {
    box-shadow: 0 0 0 3px var(--fl-acento-foco);
}

/* Tamaños */
.fl-switch--sm .fl-switch-pista {
    width: 28px;
    height: 16px;
}

.fl-switch--sm .fl-switch-pulgar {
    width: 12px;
    height: 12px;
    top: 2px;
    left: 2px;
}

.fl-switch--sm .fl-switch-control:checked + .fl-switch-pista .fl-switch-pulgar {
    transform: translateX(12px);
}

.fl-switch--lg .fl-switch-pista {
    width: 48px;
    height: 26px;
}

.fl-switch--lg .fl-switch-pulgar {
    width: 22px;
    height: 22px;
    top: 2px;
    left: 2px;
}

.fl-switch--lg .fl-switch-control:checked + .fl-switch-pista .fl-switch-pulgar {
    transform: translateX(22px);
}

/* Variantes semánticas */
.fl-switch--exito .fl-switch-control:checked + .fl-switch-pista { background: var(--fl-exito); }
.fl-switch--error .fl-switch-control:checked + .fl-switch-pista { background: var(--fl-error); }
.fl-switch--adv   .fl-switch-control:checked + .fl-switch-pista { background: var(--fl-advertencia); }

/* Variante con ícono dentro de la pista (check + x) */
.fl-switch--con-iconos .fl-switch-pista::before,
.fl-switch--con-iconos .fl-switch-pista::after {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    font-size: 10px;
    font-weight: var(--fl-peso-bold);
    line-height: 1;
    color: var(--fl-neutro-0);
    opacity: 0.7;
    transition: opacity 160ms var(--fl-ease-salida);
}

.fl-switch--con-iconos .fl-switch-pista::before {
    content: "✓";
    left: 5px;
    opacity: 0;
}

.fl-switch--con-iconos .fl-switch-pista::after {
    content: "×";
    right: 6px;
    opacity: 0.6;
}

.fl-switch--con-iconos .fl-switch-control:checked + .fl-switch-pista::before {
    opacity: 1;
}

.fl-switch--con-iconos .fl-switch-control:checked + .fl-switch-pista::after {
    opacity: 0;
}

@media (prefers-reduced-motion: reduce) {
    .fl-switch-pista,
    .fl-switch-pulgar {
        transition: background 60ms linear, transform 60ms linear;
    }
}


/* ===== resources/css/componentes/tabla-datos-extensiones.css ===== */
/* ==========================================================================
   Flora · Tabla-Datos · Extensiones (fila expandible, resize, columna congelada)
   ========================================================================== */

/* Fila expandible */
tr[data-fl-tabla-expandible] { cursor: pointer; }

[data-fl-tabla-toggle-detalle] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px; height: 22px;
    background: transparent;
    border: 0;
    border-radius: var(--fl-r-sm);
    color: var(--fl-texto-suave);
    cursor: pointer;
    vertical-align: middle;
    transition: color 140ms;
}
[data-fl-tabla-toggle-detalle]:hover {
    background: transparent;
    color: var(--fl-acento);
}
[data-fl-tabla-toggle-detalle] svg {
    width: 14px; height: 14px;
    transition: transform 200ms var(--fl-ease-resorte);
}
[data-fl-tabla-toggle-detalle]:hover svg {
    transform: scale(1.2);
}

tr[data-fl-tabla-detalle-de] > td {
    background: var(--fl-fondo-sutil) !important;
    padding: var(--fl-sp-3) var(--fl-sp-4) !important;
    border-top: 1px dashed var(--fl-borde);
}

/* Handle de resize */
.fl-tabla-th-handle-resize:hover {
    background: var(--fl-acento);
    opacity: 0.3;
}

/* Columna congelada (sticky) */
.fl-tabla-datos table td.fl-col-fija,
.fl-tabla-datos table th.fl-col-fija {
    position: sticky;
    left: 0;
    background: var(--fl-superficie);
    z-index: 3;
    border-right: 2px solid var(--fl-borde);
}
.fl-tabla-datos table tr:hover td.fl-col-fija { background: var(--fl-superficie-hover); }
.fl-tabla-datos table tr[data-fl-seleccionada] td.fl-col-fija { background: var(--fl-acento-suave); }

/* Indicador de prioridad multi-sort */
.fl-tabla-th-ordenable[data-fl-sort-prioridad]::before {
    content: attr(data-fl-sort-prioridad);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 14px;
    height: 14px;
    padding: 0 3px;
    margin-right: 4px;
    background: var(--fl-destaque-fondo);
    color: var(--fl-destaque-texto);
    border-radius: var(--fl-r-full);
    font-size: 10px;
    font-weight: var(--fl-peso-semibold);
    font-variant-numeric: tabular-nums;
}

/* Celda con progreso inline */
.fl-tabla-celda-progreso {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 80px;
}
.fl-tabla-celda-progreso-barra {
    flex: 1;
    height: 6px;
    background: var(--fl-borde-sutil);
    border-radius: var(--fl-r-full);
    overflow: hidden;
}
.fl-tabla-celda-progreso-valor {
    height: 100%;
    background: var(--fl-destaque-fondo);
    border-radius: var(--fl-r-full);
    transition: width 240ms ease-out;
}
.fl-tabla-celda-progreso-texto { font-size: var(--fl-texto-xs); font-variant-numeric: tabular-nums; color: var(--fl-texto-suave); min-width: 32px; text-align: right; }

/* Celda editable (doble click) */
.fl-tabla-celda-editable { cursor: cell; }
.fl-tabla-celda-editable[contenteditable="true"] {
    outline: 2px solid var(--fl-acento);
    outline-offset: -2px;
    background: var(--fl-superficie-elevada);
}


/* ===== resources/css/componentes/tabla-datos.css ===== */
/* ==========================================================================
   Flora · Tabla de datos
   Reemplazo de DataTables. Estilo base + sort + filtro + selección + acciones.
   ========================================================================== */

.fl-tabla-datos-panel {
    display: flex;
    flex-direction: column;
    width: 100%;
    max-width: 100%;
    background: var(--fl-superficie);
    border: 1px solid var(--fl-borde);
    border-radius: var(--fl-r-lg);
    overflow: hidden;
}

/* Cuando la tabla vive dentro de una tarjeta sin padding, el panel
   interno pierde su propio borde/radio/fondo para fusionarse con la card —
   así el encabezado (thead) no muestra esquinas redondeadas internas. */
.fl-tarjeta--sin-padding .fl-tabla-datos-panel {
    border: 0;
    border-radius: 0;
    background: transparent;
}

/* Toolbar superior: búsqueda + filtros + acción crear */
.fl-tabla-toolbar {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
    padding: var(--fl-sp-3) var(--fl-sp-4);
    border-bottom: 1px solid var(--fl-borde-sutil);
    flex-wrap: wrap;
}

/* En mobile la búsqueda se va a 100% y las acciones se reacomodan */
@media (max-width: 640px) {
    .fl-tabla-toolbar { padding: var(--fl-sp-2) var(--fl-sp-3); }
    .fl-tabla-toolbar-busqueda { width: 100%; max-width: 100%; min-width: 0; flex: 1 1 100%; }
    .fl-tabla-toolbar-acciones { margin-left: 0; width: 100%; justify-content: flex-start; }
    .fl-tabla-pie { padding: var(--fl-sp-2) var(--fl-sp-3); gap: var(--fl-sp-2); justify-content: flex-start; }
    .fl-tabla tbody td, .fl-tabla thead th { padding: var(--fl-sp-2); }
}

.fl-tabla-toolbar-busqueda {
    flex: 0 1 440px;
    min-width: 180px;
    margin-left: auto;
}

.fl-tabla-toolbar-acciones {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
    flex-wrap: wrap;
    margin-left: auto;
}

.fl-tabla-toolbar-seleccion {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-3);
    padding: 0 var(--fl-sp-2);
    font-size: var(--fl-texto-sm);
    color: var(--fl-acento-texto);
    font-weight: var(--fl-peso-medio);
}

.fl-tabla-toolbar-seleccion-acciones {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
    flex-wrap: wrap;
}

/* Scroll wrapper horizontal */
.fl-tabla-scroll {
    overflow-x: auto;
    overflow-y: visible;
    -webkit-overflow-scrolling: touch;
}

/* Tabla base */
.fl-tabla {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--fl-texto-sm);
    line-height: var(--fl-lh-ajustada);
}

.fl-tabla thead {
    background: color-mix(in srgb, var(--fl-acento) 12%, var(--fl-fondo-sutil));
}

.fl-tabla thead th {
    position: sticky;
    top: 0;
    z-index: 1;
    background: color-mix(in srgb, var(--fl-acento) 12%, var(--fl-fondo-sutil));
    text-align: center;
    padding: var(--fl-sp-2-5) var(--fl-sp-3);
    font-size: var(--fl-texto-xs);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-acento-texto);
    text-transform: uppercase;
    letter-spacing: var(--fl-ls-amplio);
    border-bottom: 2px solid var(--fl-acento);
    white-space: nowrap;
    user-select: none;
    vertical-align: middle;
}

.fl-tabla thead th[aria-sort]:not([aria-sort="none"]) {
    background: color-mix(in srgb, var(--fl-acento) 22%, var(--fl-fondo-sutil));
    color: var(--fl-acento-texto);
}

/* Columnas ordenables */
.fl-tabla-th-ordenable {
    cursor: pointer;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-tabla-th-ordenable:hover {
    background: color-mix(in srgb, var(--fl-acento) 18%, var(--fl-fondo-sutil));
}

.fl-tabla-th-contenido {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    width: 100%;
}

.fl-tabla-th-orden-icono {
    display: inline-flex;
    width: 12px;
    height: 12px;
    opacity: 0.35;
    transition: opacity var(--fl-t-rapido), transform 220ms var(--fl-ease-resorte);
}

.fl-tabla thead th[aria-sort="asc"] .fl-tabla-th-orden-icono,
.fl-tabla thead th[aria-sort="desc"] .fl-tabla-th-orden-icono {
    opacity: 1;
    color: var(--fl-acento);
}

.fl-tabla thead th[aria-sort="desc"] .fl-tabla-th-orden-icono {
    transform: rotate(180deg);
}

/* Filas de cuerpo */
.fl-tabla tbody tr {
    border-bottom: 1px solid var(--fl-borde-sutil);
    transition: background var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-tabla tbody tr:hover {
    background: color-mix(in srgb, var(--fl-acento) 6%, transparent);
}

.fl-tabla tbody tr:last-child {
    border-bottom: 0;
}

.fl-tabla tbody tr[data-fl-seleccionada="true"] {
    background: color-mix(in srgb, var(--fl-destaque-fondo) 12%, var(--fl-superficie));
    box-shadow: inset 4px 0 0 0 var(--fl-destaque-fondo);
}

.fl-tabla tbody tr[data-fl-seleccionada="true"]:hover {
    background: color-mix(in srgb, var(--fl-destaque-fondo) 20%, var(--fl-superficie));
}

.fl-tabla tbody td {
    padding: var(--fl-sp-3);
    color: var(--fl-texto);
    vertical-align: middle;
    text-align: center;
    min-height: var(--fl-densidad-fila);
    height: var(--fl-densidad-fila);
}

/* Cualquier .fl-fila (flex row) dentro de una celda queda centrado
   horizontalmente por default — consistente con el text-align:center
   global de la tabla. Esto cubre los casos avatar+nombre, pills con
   ícono, etc. sin tener que ponerle --centrada a mano en cada fila. */
.fl-tabla tbody td > .fl-fila {
    justify-content: center;
}

/* Checkbox de selección — primera columna */
.fl-tabla-col-check {
    width: 40px;
    text-align: center !important;
}

/* Columna de acciones — última */
.fl-tabla-col-acciones {
    width: 1%;
    white-space: nowrap;
    text-align: center !important;
    padding-right: var(--fl-sp-4) !important;
}

.fl-tabla-acciones-fila {
    display: inline-flex;
    align-items: center;
    gap: var(--fl-sp-1);
    justify-content: center;
}

/* Hover de botones de acción en filas de tabla:
   sin background, sólo el ícono se desplaza + acento.
   Override del estilo por default de .fl-boton--fantasma que sí tiene bg. */
.fl-tabla-acciones-fila .fl-boton,
.fl-tabla tbody .fl-boton--fantasma.fl-boton--solo-icono {
    background: transparent !important;
    transition: transform 140ms var(--fl-ease-resorte), color 140ms;
}

.fl-tabla-acciones-fila .fl-boton:hover,
.fl-tabla tbody .fl-boton--fantasma.fl-boton--solo-icono:hover {
    background: transparent !important;
    color: var(--fl-acento);
}

.fl-tabla-acciones-fila .fl-boton:hover .fl-icono,
.fl-tabla tbody .fl-boton--fantasma.fl-boton--solo-icono:hover .fl-icono {
    transform: scale(1.2);
}

/* Override de alineación explícita */
.fl-tabla-col-izquierda { text-align: left !important; }
.fl-tabla-col-derecha   { text-align: right !important; }
.fl-tabla-col-centro    { text-align: center !important; }

/* Celdas numéricas tabulares — centradas pero tabular (en tablas contables
   usar col-derecha explícito para alinear decimales) */
.fl-tabla-col-num {
    font-variant-numeric: tabular-nums;
}

/* Truncar contenido largo */
.fl-tabla td .truncar {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 240px;
}

/* --------------------------------------------------------------------------
   Densidad
   -------------------------------------------------------------------------- */
.fl-tabla--compacta tbody td {
    padding: var(--fl-sp-1-5) var(--fl-sp-2-5);
    min-height: var(--fl-densidad-fila-compacta);
    height: var(--fl-densidad-fila-compacta);
    font-size: var(--fl-texto-xs);
}

.fl-tabla--compacta thead th {
    padding: var(--fl-sp-2) var(--fl-sp-2-5);
}

.fl-tabla--comoda tbody td {
    padding: var(--fl-sp-4);
    min-height: 56px;
}

/* --------------------------------------------------------------------------
   Bordes por columna (variante)
   -------------------------------------------------------------------------- */
.fl-tabla--con-lineas tbody td,
.fl-tabla--con-lineas thead th {
    border-right: 1px solid var(--fl-borde-sutil);
}

.fl-tabla--con-lineas tbody td:last-child,
.fl-tabla--con-lineas thead th:last-child {
    border-right: 0;
}

/* --------------------------------------------------------------------------
   Footer / pie: info + paginación
   -------------------------------------------------------------------------- */
.fl-tabla-pie {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--fl-sp-3);
    padding: var(--fl-sp-2) var(--fl-sp-4);
    border-top: 1px solid var(--fl-borde-sutil);
    background: color-mix(in srgb, var(--fl-acento) 4%, var(--fl-superficie));
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto-suave);
    flex-wrap: wrap;
}

/* Cuando el pie va arriba de la tabla (variante por default ahora), el borde
   va abajo en vez de arriba, para que el separador quede entre pie y tabla. */
.fl-tabla-pie--arriba {
    border-top: 0;
    border-bottom: 1px solid var(--fl-borde-sutil);
    border-top-left-radius: var(--fl-r-md);
    border-top-right-radius: var(--fl-r-md);
}

.fl-tabla-pie-info {
    font-variant-numeric: tabular-nums;
}

.fl-tabla-pie-info strong {
    color: var(--fl-texto-fuerte);
    font-weight: var(--fl-peso-semibold);
}

.fl-tabla-pie-tamano {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-suave);
    margin-left: auto;
}

.fl-tabla-pie-tamano-select {
    height: 30px;
    padding: 0 28px 0 10px;
    background: var(--fl-superficie);
    border: 1px solid var(--fl-borde);
    border-radius: var(--fl-r-md);
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-medio);
    color: var(--fl-texto-fuerte);
    cursor: pointer;
    appearance: none;
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23666' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 8px center;
    background-size: 12px;
    transition: border-color var(--fl-t-rapido), box-shadow var(--fl-t-rapido);
}

.fl-tabla-pie-tamano-select:hover {
    border-color: var(--fl-acento);
}

.fl-tabla-pie-tamano-select:focus-visible {
    outline: 0;
    border-color: var(--fl-acento);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--fl-acento) 20%, transparent);
}

/* --------------------------------------------------------------------------
   Estados: vacío y cargando
   -------------------------------------------------------------------------- */
.fl-tabla-vacio {
    padding: var(--fl-sp-12) var(--fl-sp-4);
}

.fl-tabla-cargando {
    position: relative;
    opacity: 0.6;
    pointer-events: none;
}

.fl-tabla-cargando::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(
        90deg,
        transparent,
        color-mix(in srgb, var(--fl-superficie) 60%, transparent),
        transparent
    );
    animation: fl-tabla-shimmer 1600ms var(--fl-ease-inout) infinite;
    pointer-events: none;
}

@keyframes fl-tabla-shimmer {
    from { transform: translateX(-100%); }
    to   { transform: translateX(100%); }
}

/* ==========================================================================
   Filtros por columna — dentro del mismo TH que el título (no una fila aparte).
   El TH se hace un stack vertical: [Título + orden] arriba, [Filtro] abajo.
   ========================================================================== */

/* TH con filtro: hace un stack vertical título/filtro. Padding de abajo extra
   para que respire el trigger del filtro. */
.fl-tabla thead th.fl-tabla-th-con-filtro {
    padding-top: var(--fl-sp-2);
    padding-bottom: var(--fl-sp-2);
    vertical-align: top;
}

.fl-tabla thead th.fl-tabla-th-con-filtro .fl-tabla-th-contenido {
    margin-bottom: 6px;
}

/* Trigger estilo mini-select, ocupa el ancho de la columna.
   El contenido (texto + chevron) se centra horizontalmente. */
.fl-tabla-filtro-select {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--fl-sp-1-5);
    width: 100%;
    /* Min-width reservado para que el trigger nunca cambie de ancho al
       alternar entre "Todos" (corto) y "N seleccionados" (largo). 130px
       acomoda hasta "99 seleccionados" sin overflow; si el label se
       pasa, el ellipsis ya está configurado en fl-tabla-filtro-select-texto. */
    min-width: 130px;
    height: 28px;
    padding: 0 var(--fl-sp-2);
    font-family: inherit;
    font-size: var(--fl-texto-xs);
    font-weight: var(--fl-peso-medio);
    color: var(--fl-texto-suave);
    background: var(--fl-superficie);
    border: 1px solid var(--fl-borde);
    border-radius: var(--fl-r-md);
    cursor: pointer;
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    text-transform: none;
    letter-spacing: 0;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida),
                border-color var(--fl-t-rapido) var(--fl-ease-salida),
                color var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-tabla-filtro-select:hover {
    background: var(--fl-fondo);
    border-color: var(--fl-borde-fuerte);
    color: var(--fl-texto);
}

.fl-tabla-filtro-select:focus-visible {
    outline: none;
    border-color: var(--fl-acento);
    box-shadow: 0 0 0 2px var(--fl-acento-foco);
}

.fl-tabla-filtro-select::after {
    content: "";
    width: 12px;
    height: 12px;
    margin-left: auto;
    flex: none;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='m6 9 6 6 6-6'/></svg>");
    background-size: 12px;
    background-repeat: no-repeat;
    opacity: 0.5;
    transition: transform 200ms var(--fl-ease-resorte), opacity 120ms;
}

.fl-tabla-filtro-select[aria-expanded="true"]::after {
    transform: rotate(180deg);
    opacity: 1;
}

.fl-tabla-filtro-select-texto {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Activo: con filtro aplicado, trigger tintado con acento */
.fl-tabla-filtro-select[data-fl-filtro-activo="true"] {
    background: var(--fl-acento-suave);
    border-color: var(--fl-acento-borde);
    color: var(--fl-acento-texto);
    font-weight: var(--fl-peso-semibold);
}

.fl-tabla-filtro-select[data-fl-filtro-activo="true"]::after {
    opacity: 1;
    color: var(--fl-acento);
}

/* Botón limpiar dentro del trigger (x) cuando hay filtro activo */
.fl-tabla-filtro-select-limpiar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
    padding: 0;
    margin-left: -2px;
    background: transparent;
    border: 0;
    border-radius: var(--fl-r-full);
    color: inherit;
    cursor: pointer;
    opacity: 0.7;
    flex: none;
    transition: opacity var(--fl-t-rapido), background var(--fl-t-rapido),
                transform 200ms var(--fl-ease-resorte);
}

.fl-tabla-filtro-select-limpiar:hover {
    opacity: 1;
    background: color-mix(in srgb, currentColor 15%, transparent);
    transform: rotate(90deg);
}

.fl-tabla-filtro-select-limpiar .fl-icono {
    width: 10px;
    height: 10px;
}

/* Panel del filtro — reutiliza estilo del dropdown menu (se portala) */
.fl-tabla-filtro-panel {
    position: absolute;
    z-index: var(--fl-z-popover);
    min-width: 220px;
    max-width: 320px;
    background: var(--fl-superficie-elevada);
    border: 1px solid var(--fl-borde);
    border-radius: var(--fl-r-lg);
    box-shadow: var(--fl-sombra-lg),
                0 0 0 1px rgb(0 0 0 / 0.03);
    opacity: 0;
    transform: translateY(-4px) scale(0.98);
    visibility: hidden;
    pointer-events: none;
    transition: opacity 140ms var(--fl-ease-salida),
                transform 220ms var(--fl-ease-resorte),
                visibility 180ms;
    display: flex;
    flex-direction: column;
    max-height: 380px;
    overflow: hidden;
    text-transform: none;
    letter-spacing: 0;
}

.fl-tabla-filtro-panel--portal {
    position: fixed !important;
    top: 0;
    left: 0;
    right: auto;
    bottom: auto;
}

.fl-tabla-filtro-panel[data-fl-abierto="true"] {
    opacity: 1;
    transform: translateY(0) scale(1);
    visibility: visible;
    pointer-events: auto;
}

.fl-tabla-filtro-busqueda {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
    padding: var(--fl-sp-2) var(--fl-sp-3);
    border-bottom: 1px solid var(--fl-borde-sutil);
}

.fl-tabla-filtro-busqueda .fl-icono {
    width: 14px;
    height: 14px;
    color: var(--fl-texto-tenue);
    flex: none;
}

.fl-tabla-filtro-busqueda-input {
    flex: 1;
    background: transparent;
    border: 0;
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto);
    outline: none;
    font-family: inherit;
    padding: 2px 0;
}

.fl-tabla-filtro-lista {
    list-style: none;
    padding: var(--fl-sp-1);
    margin: 0;
    overflow-y: auto;
    flex: 1;
    min-height: 0;
}

.fl-tabla-filtro-opcion {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
    width: 100%;
    padding: var(--fl-sp-1-5) var(--fl-sp-2-5);
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-regular);
    color: var(--fl-texto);
    background: transparent;
    border: 0;
    border-radius: var(--fl-r-md);
    text-align: left;
    cursor: pointer;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida);
    text-transform: none;
    letter-spacing: 0;
}

.fl-tabla-filtro-opcion:hover {
    background: var(--fl-superficie-hover);
    color: var(--fl-texto-fuerte);
}

.fl-tabla-filtro-opcion[data-fl-seleccionada="true"] {
    background: var(--fl-destaque-fondo);
    color: var(--fl-destaque-texto);
    font-weight: var(--fl-peso-semibold);
    /* Borde sutil para reforzar el estado "activo" — no solo el bg,
       también el outline hace que se lea con más presencia. */
    box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--fl-destaque-texto) 35%, transparent);
}

.fl-tabla-filtro-opcion-conteo {
    margin-left: auto;
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-tenue);
    font-variant-numeric: tabular-nums;
    transition: color var(--fl-t-rapido) var(--fl-ease-salida);
}

/* Conteo hereda el color del parent cuando la opción está seleccionada —
   así el número también queda blanco (o destaque-texto) como el label. */
.fl-tabla-filtro-opcion[data-fl-seleccionada="true"] .fl-tabla-filtro-opcion-conteo {
    color: color-mix(in srgb, var(--fl-destaque-texto) 80%, transparent);
}

.fl-tabla-filtro-pie {
    display: flex;
    gap: var(--fl-sp-2);
    padding: var(--fl-sp-2) var(--fl-sp-3);
    border-top: 1px solid var(--fl-borde-sutil);
}

.fl-tabla-filtro-pie-accion {
    flex: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--fl-sp-1-5);
    padding: 6px var(--fl-sp-2);
    font-size: var(--fl-texto-xs);
    font-weight: var(--fl-peso-medio);
    color: var(--fl-texto-suave);
    background: transparent;
    border: 0;
    border-radius: var(--fl-r-sm);
    cursor: pointer;
    text-transform: none;
    letter-spacing: 0;
    transition: background var(--fl-t-rapido), color var(--fl-t-rapido);
}

.fl-tabla-filtro-pie-accion .fl-icono {
    width: 12px;
    height: 12px;
}

.fl-tabla-filtro-pie-accion:hover {
    background: var(--fl-superficie-hover);
    color: var(--fl-texto-fuerte);
}

.fl-tabla-filtro-pie-accion--peligro:hover {
    background: var(--fl-error-suave);
    color: var(--fl-error-texto);
}

.fl-tabla-filtro-vacio {
    padding: var(--fl-sp-4) var(--fl-sp-3);
    text-align: center;
    color: var(--fl-texto-tenue);
    font-size: var(--fl-texto-sm);
}

/* Botón X del input de búsqueda — igual que explorador/navbar/sidebar */
.fl-tabla-toolbar-busqueda .fl-campo-entrada::-webkit-search-cancel-button {
    -webkit-appearance: none;
    appearance: none;
    width: 14px;
    height: 14px;
    background-color: var(--fl-acento);
    -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round'><path d='M6 6l12 12M18 6L6 18'/></svg>");
            mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round'><path d='M6 6l12 12M18 6L6 18'/></svg>");
    -webkit-mask-size: contain;
            mask-size: contain;
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
    -webkit-mask-position: center;
            mask-position: center;
    cursor: pointer;
    transition: background-color var(--fl-t-rapido) var(--fl-ease-salida),
                transform var(--fl-t-rapido) var(--fl-ease-salida);
}
.fl-tabla-toolbar-busqueda .fl-campo-entrada::-webkit-search-cancel-button:hover {
    background-color: var(--fl-acento-texto);
    transform: scale(1.15);
}

/* ===== resources/css/componentes/tabs.css ===== */
/* ==========================================================================
   Flora · Tabs
   Navegación por pestañas. Panel visible según la tab activa.
   Incluye indicador animado (underline sliding).
   ========================================================================== */

.fl-tabs {
    display: flex;
    width: 100%;
    flex-direction: column;
    gap: var(--fl-sp-4);
}

/* Lista de pestañas — fila horizontal */
.fl-tabs-lista {
    position: relative;
    display: flex;
    gap: var(--fl-sp-1);
    padding: 0;
    margin: 0;
    list-style: none;
    border-bottom: 1px solid var(--fl-borde);
    overflow-x: auto;
    scrollbar-width: none;
}

.fl-tabs-lista::-webkit-scrollbar {
    display: none;
}

.fl-tabs-tab {
    display: inline-flex;
    align-items: center;
    gap: var(--fl-sp-2);
    height: 42px;
    padding: 0 var(--fl-sp-3);
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-medio);
    color: var(--fl-texto-suave);
    background: transparent;
    border: 0;
    cursor: pointer;
    white-space: nowrap;
    position: relative;
    transition: color var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-tabs-tab:hover {
    color: var(--fl-texto);
}

.fl-tabs-tab:focus-visible {
    outline: none;
    box-shadow: inset 0 0 0 2px var(--fl-acento-foco);
    border-radius: var(--fl-r-sm);
}

.fl-tabs-tab[aria-selected="true"],
.fl-tabs-tab.fl-tab--activo {
    color: var(--fl-acento-texto);
    font-weight: var(--fl-peso-semibold);
}

.fl-tabs-tab[aria-selected="true"] .fl-icono,
.fl-tabs-tab.fl-tab--activo .fl-icono {
    color: var(--fl-acento-texto);
}

.fl-tabs-tab .fl-icono {
    width: 16px;
    height: 16px;
}

/* Badge embebido en una tab (ej: conteo) */
.fl-tabs-tab .fl-badge {
    margin-left: 4px;
}

/* Indicador animado — underline deslizante con el color más fuerte */
.fl-tabs-indicador {
    position: absolute;
    bottom: -1px;
    left: 0;
    width: 0;
    height: 3px;
    background: var(--fl-destaque-fondo);
    border-radius: var(--fl-r-full) var(--fl-r-full) 0 0;
    box-shadow: 0 -2px 8px -2px color-mix(in srgb, var(--fl-destaque-fondo) 50%, transparent);
    transition: left 280ms var(--fl-ease-resorte),
                width 280ms var(--fl-ease-resorte);
    pointer-events: none;
}

/* Paneles */
.fl-tabs-paneles {
    display: block;
}

.fl-tabs-panel {
    display: none;
    animation: fl-tabs-entrada 280ms var(--fl-ease-salida);
}

.fl-tabs-panel[data-fl-activo="true"] {
    display: block;
}

@keyframes fl-tabs-entrada {
    from { opacity: 0; transform: translateY(4px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* --------------------------------------------------------------------------
   Variantes
   -------------------------------------------------------------------------- */

/* Pills — tabs estilo segmented control */
.fl-tabs--pills .fl-tabs-lista {
    border-bottom: 0;
    padding: 4px;
    background: var(--fl-fondo-sutil);
    border: 1px solid var(--fl-borde);
    border-radius: var(--fl-r-lg);
    display: inline-flex;
}

.fl-tabs--pills .fl-tabs-tab {
    height: 32px;
    border-radius: var(--fl-r-md);
    padding: 0 var(--fl-sp-3);
}

.fl-tabs--pills .fl-tabs-tab[aria-selected="true"],
.fl-tabs--pills .fl-tabs-tab.fl-tab--activo {
    background: var(--fl-superficie);
    color: var(--fl-texto-fuerte);
    box-shadow: var(--fl-sombra-xs);
}

.fl-tabs--pills .fl-tabs-indicador {
    display: none;
}

/* Vertical — tabs a la izquierda */
.fl-tabs--vertical {
    flex-direction: row;
    gap: var(--fl-sp-6);
}

.fl-tabs--vertical .fl-tabs-lista {
    flex-direction: column;
    gap: 0;
    border-bottom: 0;
    border-right: 1px solid var(--fl-borde);
    min-width: 200px;
    overflow-x: visible;
    overflow-y: auto;
}

.fl-tabs--vertical .fl-tabs-tab {
    height: auto;
    padding: var(--fl-sp-2) var(--fl-sp-3);
    justify-content: flex-start;
    border-radius: var(--fl-r-md) 0 0 var(--fl-r-md);
}

.fl-tabs--vertical .fl-tabs-tab[aria-selected="true"],
.fl-tabs--vertical .fl-tabs-tab.fl-tab--activo {
    background: var(--fl-acento-suave);
}

.fl-tabs--vertical .fl-tabs-indicador {
    bottom: auto;
    left: auto;
    right: -1px;
    width: 2px;
    height: 0;
    transition: top 280ms var(--fl-ease-resorte),
                height 280ms var(--fl-ease-resorte);
}

.fl-tabs--vertical .fl-tabs-paneles {
    flex: 1;
    min-width: 0;
}

/* Tamaños */
.fl-tabs--sm .fl-tabs-tab { height: 34px; font-size: var(--fl-texto-xs); }
.fl-tabs--lg .fl-tabs-tab { height: 48px; font-size: var(--fl-texto-base); }

@media (prefers-reduced-motion: reduce) {
    .fl-tabs-indicador,
    .fl-tabs-panel {
        transition: none;
        animation: none;
    }
}


/* ===== resources/css/componentes/tareas.css ===== */
/* ==========================================================================
   Flora · Tareas
   Wrapper multi-vista (kanban / lista / calendario / timeline) sobre un
   array único de tareas. Cada vista es un componente Flora existente;
   este wrapper sólo hace el switcher y el mapeo de datos.
   ========================================================================== */

.fl-tareas {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-4);
    width: 100%;
}

/* Barra superior con switcher de vistas */
.fl-tareas-barra {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-4);
    justify-content: space-between;
    flex-wrap: wrap;
}

/* Barra de filtros (kanban / galería / calendario).
   Fondo destaque = mismo que el navbar. flex-basis:100% la pone en
   una segunda fila dentro de fl-tareas-barra (que ya tiene flex-wrap:wrap). */
.fl-tareas-filtros {
    flex-basis: 100%;
    order: 10;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--fl-sp-5);
    padding: var(--fl-sp-3) var(--fl-sp-5);
    background: linear-gradient(to bottom, var(--fl-acento-600), var(--fl-acento-950, var(--fl-acento-900)));
    border-radius: var(--fl-r-md);
    flex-wrap: wrap;
    margin-top: var(--fl-sp-2);
}

/* Inputs nativos: ancho auto y misma altura que los triggers de fl-select (28px) */
.fl-tareas-filtros .fl-campo-entrada {
    width: auto;
    min-height: 31px;
    height: 31px;
    font-size: var(--fl-texto-xs);
}

/* fl-campo y fl-select dentro de la barra también ancho auto */
.fl-tareas-filtros .fl-campo,
.fl-tareas-filtros .fl-select {
    width: auto;
}

/* Búsqueda: ancho fijo, no se estira */
.fl-tareas-filtro-busqueda {
    width: 300px;
}

/* Wrappers de fl-select con ancho mínimo razonable */
.fl-tareas-filtro-sel-wrap {
    min-width: 130px;
}

/* Área más ancha */
.fl-tareas-filtro-sel-wrap[data-fl-tareas-filtro="area"] {
    min-width: 210px;
}

/* Asignado más ancho — los nombres pueden ser largos */
.fl-tareas-filtro-sel-wrap[data-fl-tareas-filtro="asignado"] {
    min-width: 250px;
}

/* Date input */
.fl-tareas-filtro-fecha {
    min-width: 140px;
    cursor: pointer;
}

/* Triggers de fl-select dentro de la barra: mismo estilo compacto que
   fl-tabla-filtro-select (altura 28px, texto xs, mismo border/bg). */
.fl-tareas-filtros .fl-select-trigger {
    min-height: 31px;
    height: 31px;
    font-size: var(--fl-texto-xs);
    font-weight: var(--fl-peso-medio);
    color: var(--fl-texto-suave);
    padding: 0 var(--fl-sp-2);
}
.fl-tareas-filtros .fl-select-trigger:hover {
    background: var(--fl-fondo);
    border-color: var(--fl-borde-fuerte);
    color: var(--fl-texto);
}
/* Select activo (con valor seleccionado): tintado con acento */
.fl-tareas-filtros .fl-select-trigger:not([data-fl-sin-valor="true"]) {
    background: var(--fl-acento-suave);
    border-color: var(--fl-acento-borde);
    color: var(--fl-acento-texto);
    font-weight: var(--fl-peso-semibold);
}
/* Botón limpiar del select más compacto */
.fl-tareas-filtros .fl-select-limpiar {
    width: 20px;
    height: 20px;
}

/* Botón Limpiar: blanco sobre fondo destaque oscuro */
.fl-tareas-filtros .fl-boton--fantasma {
    color: var(--fl-destaque-texto);
    border-color: color-mix(in srgb, var(--fl-destaque-texto) 25%, transparent);
}
.fl-tareas-filtros .fl-boton--fantasma:hover {
    background: color-mix(in srgb, var(--fl-destaque-texto) 12%, transparent);
    color: var(--fl-destaque-texto);
    border-color: color-mix(in srgb, var(--fl-destaque-texto) 40%, transparent);
}

.fl-tareas-switcher {
    display: inline-flex;
    gap: 2px;
    padding: 4px;
    background: var(--fl-fondo-sutil);
    border: 1px solid var(--fl-borde);
    border-radius: var(--fl-r-md);
}

.fl-tareas-vista-btn {
    display: inline-flex;
    align-items: center;
    gap: var(--fl-sp-1-5);
    padding: 6px 12px;
    background: transparent;
    border: 0;
    border-radius: var(--fl-r-sm);
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-medio);
    color: var(--fl-texto-suave);
    cursor: pointer;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida),
                color var(--fl-t-rapido) var(--fl-ease-salida);
}

/* Simetría óptica con ícono al inicio — mismo patrón que .fl-boton. */
.fl-tareas-vista-btn:has(> .fl-icono:first-child:not(:last-child)) {
    padding-left: var(--fl-sp-1-5);
}

.fl-tareas-vista-btn:hover {
    background: color-mix(in srgb, var(--fl-acento) 8%, transparent);
    color: var(--fl-texto-fuerte);
}

.fl-tareas-vista-btn[aria-selected="true"] {
    background: var(--fl-superficie);
    color: var(--fl-acento-texto);
    box-shadow: var(--fl-sombra-xs);
}

.fl-tareas-vista-btn .fl-icono {
    /* Ícono relativo + zoom lento en hover. Mismo patrón que .fl-boton y
       los demás componentes tipo pill con ícono. */
    width: 1.25em;
    height: 1.25em;
    flex: none;
    transform-origin: center;
    transition: transform 520ms var(--fl-ease-salida);
}

.fl-tareas-vista-btn:hover:not(:disabled) > .fl-icono {
    transform: scale(1.2);
}

@media (prefers-reduced-motion: reduce) {
    .fl-tareas-vista-btn .fl-icono { transition: none; }
    .fl-tareas-vista-btn:hover > .fl-icono { transform: none; }
}

/* Paneles: sólo el activo se muestra. El switcher + JS togglean
   data-fl-activo; el fallback inicial es esconder todos menos el que
   el atributo data-fl-tareas-vista del contenedor dice. */
.fl-tareas-vista {
    display: none;
}

.fl-tareas-vista[data-fl-activo="true"] {
    display: block;
}

/* Fallback server-side para la vista inicial: mostrar el panel que
   matchea el data-fl-tareas-vista del wrapper (así no hay flash vacío
   antes de que JS corra). */
.fl-tareas[data-fl-tareas-vista="kanban"]     .fl-tareas-vista--kanban,
.fl-tareas[data-fl-tareas-vista="lista"]      .fl-tareas-vista--lista,
.fl-tareas[data-fl-tareas-vista="calendario"] .fl-tareas-vista--calendario,
.fl-tareas[data-fl-tareas-vista="galeria"]    .fl-tareas-vista--galeria {
    display: block;
}

/* --------------------------------------------------------------------------
   Vista LISTA — tabla densa
   -------------------------------------------------------------------------- */
.fl-tareas-tabla {
    width: 100%;
    border-collapse: collapse;
    background: var(--fl-superficie);
    border: 1px solid var(--fl-borde);
    border-radius: var(--fl-r-md);
    overflow: hidden;
    font-size: var(--fl-texto-sm);
}

.fl-tareas-tabla thead th {
    background: var(--fl-fondo-sutil);
    padding: var(--fl-sp-2-5) var(--fl-sp-3);
    font-size: var(--fl-texto-2xs);
    font-weight: var(--fl-peso-semibold);
    text-transform: uppercase;
    letter-spacing: var(--fl-ls-amplio);
    color: var(--fl-texto-suave);
    text-align: left;
    border-bottom: 1px solid var(--fl-borde);
}

.fl-tareas-tabla td {
    padding: var(--fl-sp-2-5) var(--fl-sp-3);
    vertical-align: middle;
    border-bottom: 1px solid var(--fl-borde-sutil);
}

.fl-tareas-tabla tbody tr:last-child td {
    border-bottom: 0;
}

.fl-tareas-tabla-fila {
    cursor: pointer;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-tareas-tabla-fila:hover,
.fl-tareas-tabla-fila:focus-visible {
    background: color-mix(in srgb, var(--fl-acento) 4%, transparent);
    outline: none;
}

.fl-tareas-tabla-titulo {
    font-weight: var(--fl-peso-medio);
    color: var(--fl-texto-fuerte);
    line-height: 1.35;
}

.fl-tareas-tabla-descripcion {
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-tenue);
    margin-top: 2px;
    line-height: 1.4;
}

.fl-tareas-tabla-fecha {
    font-variant-numeric: tabular-nums;
    color: var(--fl-texto-suave);
    white-space: nowrap;
}

.fl-tareas-tabla-asignados {
    display: inline-flex;
    align-items: center;
}

.fl-tareas-tabla-asignados > * {
    margin-left: -6px;
    border: 2px solid var(--fl-superficie);
    transition: border-color var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-tareas-tabla-asignados > *:first-child {
    margin-left: 0;
}

.fl-tareas-tabla-asignados .fl-avatar { --_size: 32px; }

/* Cuando la fila está hovered el bg cambia a un tint tenue de acento. Si
   el border de los avatares queda en blanco puro, aparece como un anillo
   visible contra ese tint — queda "feo". Matcheamos el border al mismo
   color-mix del fondo de hover para que se funda ópticamente. */
.fl-tareas-tabla-fila:hover .fl-tareas-tabla-asignados > *,
.fl-tareas-tabla-fila:focus-visible .fl-tareas-tabla-asignados > * {
    border-color: color-mix(in srgb, var(--fl-acento) 4%, var(--fl-superficie));
}

.fl-tareas-tabla-vacio {
    color: var(--fl-texto-tenue);
}

.fl-tareas-tabla-empty {
    text-align: center;
    padding: var(--fl-sp-6);
    color: var(--fl-texto-tenue);
    font-style: italic;
}

/* Pill de estado reutilizable — mismo lenguaje cromático que el kanban */
.fl-tareas-estado {
    --_color: var(--fl-acento);

    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 22px;
    padding: 0 10px;
    border-radius: var(--fl-r-full);
    font-size: var(--fl-texto-xs);
    font-weight: var(--fl-peso-medio);
    line-height: 1;
    background: color-mix(in srgb, var(--_color) 12%, transparent);
    color: color-mix(in srgb, var(--_color) 90%, var(--fl-texto-fuerte));
    border: 1px solid color-mix(in srgb, var(--_color) 25%, transparent);
    white-space: nowrap;
}

.fl-tareas-estado-punto {
    width: 6px;
    height: 6px;
    background: var(--_color);
    border-radius: var(--fl-r-full);
    flex: none;
}

.fl-tareas-estado--por-hacer   { --_color: var(--fl-texto-tenue); }
.fl-tareas-estado--en-progreso { --_color: var(--fl-info); }
.fl-tareas-estado--en-revision { --_color: var(--fl-advertencia); }
.fl-tareas-estado--completado  { --_color: var(--fl-exito); }

/* --------------------------------------------------------------------------
   Vista GALERÍA — cards grandes con banner de color, labels, avatares.
   Inspirada en la vista "Gallery" de Notion; ideal para tareas con
   contenido o moodboard visual.
   -------------------------------------------------------------------------- */
.fl-tareas-galeria {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: var(--fl-sp-3);
    padding-bottom: var(--fl-sp-3);
}

.fl-tareas-galeria-card {
    --_color: var(--fl-acento);

    display: flex;
    flex-direction: column;
    background: var(--fl-superficie);
    border: 1px solid var(--fl-borde);
    border-radius: var(--fl-r-lg);
    overflow: hidden;
    cursor: pointer;
    box-shadow: var(--fl-sombra-xs);
    transition: border-color var(--fl-t-rapido) var(--fl-ease-salida),
                box-shadow var(--fl-t-rapido) var(--fl-ease-salida),
                transform 140ms var(--fl-ease-resorte);
}

.fl-tareas-galeria-card:hover,
.fl-tareas-galeria-card:focus-visible {
    border-color: color-mix(in srgb, var(--_color) 45%, var(--fl-borde));
    box-shadow: var(--fl-sombra-lg),
                0 0 0 3px color-mix(in srgb, var(--_color) 10%, transparent);
    transform: translateY(-2px);
    outline: none;
}

/* Banner superior con el color del estado — cue visual fuerte */
.fl-tareas-galeria-card-banner {
    height: 6px;
    background: var(--_color);
    flex: none;
}

.fl-tareas-galeria-card-body {
    padding: var(--fl-sp-3);
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-2);
    flex: 1;
    min-height: 0;
}

.fl-tareas-galeria-card-labels {
    display: flex;
    gap: 4px;
    flex-wrap: wrap;
}

.fl-tareas-galeria-card-label {
    width: 32px;
    height: 6px;
    border-radius: var(--fl-r-full);
    background: var(--_c, var(--fl-acento));
}

.fl-tareas-galeria-card-titulo {
    font-size: var(--fl-texto-base);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-fuerte);
    line-height: 1.3;
    margin: 0;
    word-break: break-word;
}

.fl-tareas-galeria-card-descripcion {
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto-suave);
    line-height: 1.5;
    margin: 0;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.fl-tareas-galeria-card-pie {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--fl-sp-2);
    margin-top: auto;
    padding-top: var(--fl-sp-2);
    flex-wrap: wrap;
}

.fl-tareas-galeria-card-pie-derecha {
    display: inline-flex;
    align-items: center;
    gap: var(--fl-sp-2-5);
}

.fl-tareas-galeria-card-fecha {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-tenue);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.fl-tareas-galeria-card-fecha .fl-icono {
    width: 12px;
    height: 12px;
}

.fl-tareas-galeria-card-asignados {
    display: inline-flex;
    align-items: center;
}

.fl-tareas-galeria-card-asignados > * {
    margin-left: -6px;
    border: 2px solid var(--fl-superficie);
}

.fl-tareas-galeria-card-asignados > *:first-child {
    margin-left: 0;
}

.fl-tareas-galeria-card-asignados .fl-avatar { --_size: 32px; }

/* --------------------------------------------------------------------------
   Estado vacío (vistas sin data)
   -------------------------------------------------------------------------- */
.fl-tareas-empty {
    padding: var(--fl-sp-8) var(--fl-sp-6);
    text-align: center;
    color: var(--fl-texto-tenue);
    background: var(--fl-fondo-sutil);
    border: 1px dashed var(--fl-borde);
    border-radius: var(--fl-r-md);
    line-height: 1.6;
}

.fl-tareas-empty code {
    padding: 2px 6px;
    background: var(--fl-superficie);
    border: 1px solid var(--fl-borde-sutil);
    border-radius: var(--fl-r-sm);
    font-family: var(--fl-fuente-mono);
    font-size: var(--fl-texto-xs);
    color: var(--fl-texto-fuerte);
}


/* ===== resources/css/componentes/tarjeta-metrica.css ===== */
/* ==========================================================================
   Flora · Tarjeta-métrica (KPI card)
   Cards SÓLIDAS con fondos oscuros y profundos de la paleta (no colores
   semánticos). Cada variante ajusta la "profundidad" — de acento-700 a -950 —
   para distintos niveles de intensidad dentro del mismo lenguaje cromático.
   ========================================================================== */

.fl-tarjeta-metrica {
    /* Default: acento profundo. Las variantes bajan en la escala para
       hacerse más oscuras y sólidas.
       Texto SIEMPRE blanco (acento-texto-sobre) — no uses superficie porque
       en paleta oscura esa variable se vuelve negra. */
    --_color:        var(--fl-acento-700);
    --_color-fondo:  var(--fl-acento-800);
    --_color-borde:  var(--fl-acento-900);
    --_color-hover:  var(--fl-acento-600);
    --_color-texto:  var(--fl-acento-texto-sobre);

    position: relative;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-3);
    padding: var(--fl-sp-5);
    background: linear-gradient(
        135deg,
        var(--_color) 0%,
        var(--_color-fondo) 55%,
        color-mix(in srgb, var(--_color-fondo) 70%, #000) 100%
    );
    border: 1px solid var(--_color-borde);
    border-radius: var(--fl-r-lg);
    color: var(--_color-texto);
    text-decoration: none;
    min-height: 148px;
    transition: transform 220ms var(--fl-ease-resorte),
                box-shadow 260ms var(--fl-ease-salida),
                border-color 260ms var(--fl-ease-salida);
    isolation: isolate;
    /* Sombra profunda tintada con el fondo — "presencia" cromática */
    box-shadow: 0 12px 32px -12px color-mix(in srgb, var(--_color-fondo) 70%, transparent),
                0 4px 10px -4px color-mix(in srgb, var(--_color-fondo) 50%, transparent),
                inset 0 1px 0 0 color-mix(in srgb, #fff 10%, transparent),
                inset 0 -1px 0 0 color-mix(in srgb, #000 20%, transparent);
}

/* Brillo radial sutil en la esquina top-right — profundidad sin verse plano */
.fl-tarjeta-metrica::before {
    content: "";
    position: absolute;
    top: -100px;
    right: -100px;
    width: 280px;
    height: 280px;
    background: radial-gradient(
        circle,
        color-mix(in srgb, #fff 10%, transparent) 0%,
        transparent 65%
    );
    pointer-events: none;
    z-index: 0;
    transition: transform 420ms var(--fl-ease-salida);
}

/* Bottom shine sutil — línea de "vidrio" abajo */
.fl-tarjeta-metrica::after {
    content: "";
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 50%;
    background: linear-gradient(
        to top,
        color-mix(in srgb, #000 18%, transparent) 0%,
        transparent 100%
    );
    pointer-events: none;
    z-index: 0;
}

.fl-tarjeta-metrica > * {
    position: relative;
    z-index: 1;
}

/* Hover — lift + sombra más intensa + borde más claro */
a.fl-tarjeta-metrica:hover {
    border-color: var(--_color-hover);
    box-shadow: 0 20px 48px -14px color-mix(in srgb, var(--_color-fondo) 80%, transparent),
                0 6px 16px -4px color-mix(in srgb, var(--_color-fondo) 60%, transparent),
                inset 0 1px 0 0 color-mix(in srgb, #fff 14%, transparent),
                inset 0 -1px 0 0 color-mix(in srgb, #000 24%, transparent);
    transform: translateY(-3px);
}

a.fl-tarjeta-metrica:hover::before {
    transform: scale(1.15);
}

/* --------------------------------------------------------------------------
   Header: etiqueta + ícono
   -------------------------------------------------------------------------- */
.fl-tarjeta-metrica-cabecera {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--fl-sp-2);
}

.fl-tarjeta-metrica-etiqueta {
    font-size: var(--fl-texto-xs);
    font-weight: var(--fl-peso-semibold);
    color: color-mix(in srgb, var(--_color-texto) 82%, transparent);
    text-transform: uppercase;
    letter-spacing: var(--fl-ls-mayus);
    line-height: 1.3;
}

/* Chip del ícono — glass sobre el fondo profundo */
.fl-tarjeta-metrica-icono {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    border-radius: var(--fl-r-md);
    background: color-mix(in srgb, #fff 14%, transparent);
    border: 1px solid color-mix(in srgb, #fff 22%, transparent);
    color: var(--_color-texto);
    flex: none;
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    transition: transform 320ms var(--fl-ease-resorte),
                background 260ms var(--fl-ease-salida);
    box-shadow: inset 0 1px 0 0 color-mix(in srgb, #fff 14%, transparent);
}

a.fl-tarjeta-metrica:hover .fl-tarjeta-metrica-icono {
    transform: scale(1.08) rotate(-4deg);
    background: color-mix(in srgb, #fff 22%, transparent);
}

.fl-tarjeta-metrica-icono .fl-icono {
    width: 20px;
    height: 20px;
}

/* --------------------------------------------------------------------------
   Cuerpo: valor grande + delta
   -------------------------------------------------------------------------- */
.fl-tarjeta-metrica-cuerpo {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2-5);
    flex-wrap: wrap;
    flex: 1;
}

.fl-tarjeta-metrica-valor {
    font-size: var(--fl-texto-4xl);
    font-weight: var(--fl-peso-bold);
    color: var(--_color-texto);
    line-height: 1;
    letter-spacing: var(--fl-ls-compacto);
    font-variant-numeric: tabular-nums;
    text-shadow: 0 1px 2px color-mix(in srgb, #000 30%, transparent);
}

/* Delta pill uniforme — glass sobre cualquier variante de paleta */
.fl-tarjeta-metrica-delta {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    height: 22px;
    padding: 0 8px 0 6px;
    font-size: var(--fl-texto-2xs);
    font-weight: var(--fl-peso-semibold);
    border-radius: var(--fl-r-full);
    font-variant-numeric: tabular-nums;
    line-height: 1;
    white-space: nowrap;
    background: color-mix(in srgb, #fff 18%, transparent);
    color: var(--_color-texto);
    border: 1px solid color-mix(in srgb, #fff 26%, transparent);
}

.fl-tarjeta-metrica-delta .fl-icono {
    width: 12px;
    height: 12px;
}

/* Todas las variantes del delta unificadas (glass sobre fondo oscuro) */
.fl-tarjeta-metrica-delta--exito,
.fl-tarjeta-metrica-delta--error,
.fl-tarjeta-metrica-delta--neutro {
    background: color-mix(in srgb, #fff 18%, transparent);
    color: var(--_color-texto);
    border-color: color-mix(in srgb, #fff 26%, transparent);
}

/* --------------------------------------------------------------------------
   Pie — ayuda/contexto
   -------------------------------------------------------------------------- */
.fl-tarjeta-metrica-pie {
    font-size: var(--fl-texto-2xs);
    color: color-mix(in srgb, var(--_color-texto) 72%, transparent);
    line-height: 1.4;
}

/* --------------------------------------------------------------------------
   Variantes de PROFUNDIDAD — todo paleta (no semántico)
   Cada variante desciende en la escala de acento, quedando más oscura.
   -------------------------------------------------------------------------- */

/* Default ya es acentuada (acento-700/800) — alias explícito por claridad */
.fl-tarjeta-metrica--acentuada {
    --_color:        var(--fl-acento-700);
    --_color-fondo:  var(--fl-acento-800);
    --_color-borde:  var(--fl-acento-900);
    --_color-hover:  var(--fl-acento-600);
}

.fl-tarjeta-metrica--profunda {
    --_color:        var(--fl-acento-800);
    --_color-fondo:  var(--fl-acento-900);
    --_color-borde:  var(--fl-acento-950);
    --_color-hover:  var(--fl-acento-700);
}

.fl-tarjeta-metrica--oscura {
    --_color:        var(--fl-acento-900);
    --_color-fondo:  var(--fl-acento-950);
    --_color-borde:  color-mix(in srgb, var(--fl-acento-950) 50%, #000);
    --_color-hover:  var(--fl-acento-800);
}

.fl-tarjeta-metrica--noche {
    --_color:        var(--fl-acento-950);
    --_color-fondo:  color-mix(in srgb, var(--fl-acento-950) 60%, #000);
    --_color-borde:  #000;
    --_color-hover:  var(--fl-acento-900);
}

/* DESTAQUE — acento 900, matchea con destaque-fondo (firma Flora) */
.fl-tarjeta-metrica--destaque {
    --_color:        var(--fl-acento-800);
    --_color-fondo:  var(--fl-acento-900);
    --_color-borde:  var(--fl-acento-950);
    --_color-hover:  var(--fl-acento-700);
}

/* Compatibilidad hacia atrás: las variantes semánticas anteriores también
   mapean a profundidades de paleta. Las dejo acá para no romper código viejo. */
.fl-tarjeta-metrica--exito,
.fl-tarjeta-metrica--info {
    --_color:        var(--fl-acento-700);
    --_color-fondo:  var(--fl-acento-800);
    --_color-borde:  var(--fl-acento-900);
    --_color-hover:  var(--fl-acento-600);
}

.fl-tarjeta-metrica--error,
.fl-tarjeta-metrica--adv {
    --_color:        var(--fl-acento-800);
    --_color-fondo:  var(--fl-acento-900);
    --_color-borde:  var(--fl-acento-950);
    --_color-hover:  var(--fl-acento-700);
}

/* Gráficos sobre cards sólidas — todo en color-texto (blanco) */
.fl-tarjeta-metrica .fl-grafico-linea,
.fl-tarjeta-metrica .fl-grafico-sparkline-linea {
    stroke: var(--_color-texto);
}

.fl-tarjeta-metrica .fl-grafico-area {
    fill: color-mix(in srgb, var(--_color-texto) 22%, transparent);
}

.fl-tarjeta-metrica .fl-grafico-punto {
    fill: var(--_color-texto);
    stroke: var(--_color-fondo);
}

.fl-tarjeta-metrica .fl-grafico-barra[data-fl-serie="0"] {
    fill: var(--_color-texto);
}

/* --------------------------------------------------------------------------
   Grilla de métricas — responsive
   -------------------------------------------------------------------------- */
.fl-tarjetas-metricas {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: var(--fl-sp-4);
}

@media (prefers-reduced-motion: reduce) {
    .fl-tarjeta-metrica,
    .fl-tarjeta-metrica::before,
    .fl-tarjeta-metrica-icono,
    a.fl-tarjeta-metrica:hover,
    a.fl-tarjeta-metrica:hover::before,
    a.fl-tarjeta-metrica:hover .fl-tarjeta-metrica-icono {
        transition: none;
        transform: none;
    }
}


/* ===== resources/css/componentes/tarjeta.css ===== */
/* ==========================================================================
   Flora · Tarjeta
   Contenedor semántico con cabecera, cuerpo y pie opcionales.
   Variantes: --interactiva, --elevada, --sin-borde, --con-acento.
   ========================================================================== */

.fl-tarjeta {
    display: flex;
    flex-direction: column;
    width: 100%;
    background: var(--fl-superficie);
    border: 1px solid var(--fl-borde);
    border-radius: var(--fl-r-lg);
    transition: border-color var(--fl-t-rapido) var(--fl-ease-salida),
                box-shadow var(--fl-t-rapido) var(--fl-ease-salida),
                transform var(--fl-t-rapido) var(--fl-ease-salida);
}

/* Opt-in de clipping para cuando la tarjeta tiene cabecera/pie con bg que debe
   respetar el radio exterior. Sin este modificador, dropdowns dentro pueden escapar. */
.fl-tarjeta--recortada {
    overflow: clip;
}

/* --------------------------------------------------------------------------
   Partes
   -------------------------------------------------------------------------- */
.fl-tarjeta-cabecera {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--fl-sp-3);
    padding: var(--fl-sp-4) var(--fl-sp-5);
    border-bottom: 1px solid var(--fl-borde-sutil);
    background: var(--fl-superficie);
    border-radius: calc(var(--fl-r-lg) - 1px) calc(var(--fl-r-lg) - 1px) 0 0;
}

.fl-tarjeta-cabecera-texto {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-0-5);
    min-width: 0;
}

.fl-tarjeta-titulo {
    font-size: var(--fl-texto-base);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-fuerte);
    line-height: var(--fl-lh-ajustada);
    margin: 0;
}

.fl-tarjeta-subtitulo {
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto-suave);
    line-height: var(--fl-lh-ajustada);
}

.fl-tarjeta-cabecera-acciones {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-2);
    flex: none;
}

.fl-tarjeta-cuerpo {
    padding: var(--fl-sp-5);
    flex: 1 1 auto;
}

.fl-tarjeta-cuerpo--compacto {
    padding: var(--fl-sp-3) var(--fl-sp-4);
}

.fl-tarjeta-cuerpo--denso {
    padding: var(--fl-sp-2) var(--fl-sp-3);
}

.fl-tarjeta-pie {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--fl-sp-2);
    padding: var(--fl-sp-3) var(--fl-sp-5);
    border-top: 1px solid var(--fl-borde-sutil);
    background: var(--fl-fondo-sutil);
    border-radius: 0 0 calc(var(--fl-r-lg) - 1px) calc(var(--fl-r-lg) - 1px);
}

.fl-tarjeta-pie--izquierda {
    justify-content: flex-start;
}

.fl-tarjeta-pie--distribuido {
    justify-content: space-between;
}

/* --------------------------------------------------------------------------
   Variantes
   -------------------------------------------------------------------------- */

/* Elevada — con sombra suave, sin borde visible en superficie clara */
.fl-tarjeta--elevada {
    border-color: var(--fl-borde-sutil);
    box-shadow: var(--fl-sombra-sm);
}

.fl-tarjeta--elevada:hover {
    box-shadow: var(--fl-sombra-md);
}

/* Sin borde — sólo fondo */
.fl-tarjeta--sin-borde {
    border-color: transparent;
}

/* Tenue — fondo ligeramente distinto, sin borde */
.fl-tarjeta--tenue {
    background: var(--fl-fondo-sutil);
    border-color: var(--fl-borde-sutil);
}

/* Interactiva — clickable, feedback visual */
.fl-tarjeta--interactiva {
    cursor: pointer;
    text-align: left;
}

.fl-tarjeta--interactiva:hover {
    border-color: var(--fl-acento);
    box-shadow: var(--fl-sombra-md),
                0 0 0 3px color-mix(in srgb, var(--fl-acento) 15%, transparent),
                0 8px 24px -8px color-mix(in srgb, var(--fl-acento) 35%, transparent);
    transform: translateY(-2px);
}

.fl-tarjeta--interactiva:hover .fl-tarjeta-titulo {
    color: var(--fl-acento-texto);
}

.fl-tarjeta--interactiva:active {
    transform: translateY(0) scale(0.995);
    box-shadow: var(--fl-sombra-xs);
    transition-duration: 80ms;
}

.fl-tarjeta--interactiva:focus-visible {
    outline: none;
    border-color: var(--fl-acento);
    box-shadow: 0 0 0 var(--fl-foco-ancho) var(--fl-acento-foco);
}

/* Con acento — franja lateral de color */
.fl-tarjeta--acentuada {
    border-left: 3px solid var(--fl-acento);
}

.fl-tarjeta--exito    { border-left: 3px solid var(--fl-exito); }
.fl-tarjeta--error    { border-left: 3px solid var(--fl-error); }
.fl-tarjeta--adv      { border-left: 3px solid var(--fl-advertencia); }
.fl-tarjeta--info     { border-left: 3px solid var(--fl-info); }

/* Resaltada — diferenciación clara respecto a tarjeta simple:
   borde más grueso con color acento, sombra mediana y anillo de color. */
.fl-tarjeta--resaltada {
    border: 2px solid var(--fl-acento);
    box-shadow: var(--fl-sombra-md),
                0 0 0 3px color-mix(in srgb, var(--fl-acento) 18%, transparent);
    background: color-mix(in srgb, var(--fl-acento) 4%, var(--fl-superficie));
}

.fl-tarjeta--resaltada .fl-tarjeta-titulo {
    color: var(--fl-acento-texto);
}

.fl-tarjeta--resaltada .fl-tarjeta-cabecera {
    border-bottom-color: color-mix(in srgb, var(--fl-acento) 22%, transparent);
}

/* Padding interno ajustable por la tarjeta entera (reemplaza a partes) */
.fl-tarjeta--sin-padding > .fl-tarjeta-cuerpo { padding: 0; }

/* --------------------------------------------------------------------------
   Destaque — tarjeta con fondo sólido del color más fuerte de la paleta
   + texto blanco. Para tarjetas "featured", CTAs, planes premium.
   Inversión automática en paleta "oscuro".
   -------------------------------------------------------------------------- */
.fl-tarjeta--destaque {
    background: var(--fl-destaque-fondo);
    border-color: var(--fl-destaque-fondo);
    color: var(--fl-destaque-texto);

    /* Tokens de texto locales para que cabecera/cuerpo/pie hereden claro */
    --fl-texto:          var(--fl-destaque-texto);
    --fl-texto-fuerte:   var(--fl-destaque-texto);
    --fl-texto-suave:    color-mix(in srgb, var(--fl-destaque-texto) 80%, transparent);
    --fl-texto-tenue:    color-mix(in srgb, var(--fl-destaque-texto) 60%, transparent);
}

.fl-tarjeta--destaque .fl-tarjeta-cabecera,
.fl-tarjeta--destaque .fl-tarjeta-pie {
    background: transparent;
    border-color: color-mix(in srgb, var(--fl-destaque-texto) 18%, transparent);
}

.fl-tarjeta--destaque .fl-tarjeta-titulo,
.fl-tarjeta--destaque .fl-tarjeta-subtitulo {
    color: var(--fl-destaque-texto);
}

.fl-tarjeta--destaque.fl-tarjeta--interactiva:hover {
    background: var(--fl-destaque-fondo-hover);
    border-color: var(--fl-destaque-fondo-hover);
    box-shadow: 0 10px 28px -10px color-mix(in srgb, var(--fl-destaque-fondo) 55%, transparent);
}

/* Gradiente — variante con el degradé diagonal de la paleta */
.fl-tarjeta--destaque.fl-tarjeta--gradiente {
    background: var(--fl-destaque-gradiente);
    border-color: transparent;
    position: relative;
    overflow: hidden;
}

.fl-tarjeta--destaque.fl-tarjeta--gradiente::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 1px;
    background: linear-gradient(
        to right,
        transparent 10%,
        rgb(255 255 255 / 0.22),
        transparent 90%
    );
    pointer-events: none;
}


/* ===== resources/css/componentes/tecla.css ===== */
/* ==========================================================================
   Flora · Tecla (kbd)
   Renderiza una tecla de teclado con estilo de tecla física. Para mostrar
   atajos: <x-flora::tecla>Ctrl</x-flora::tecla>+<x-flora::tecla>K</x-flora::tecla>
   ========================================================================== */

.fl-tecla {
    display: inline-block;
    padding: 1px 6px;
    font-family: var(--fl-fuente-mono, monospace);
    font-size: 0.85em;
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-fuerte);
    background: var(--fl-superficie);
    border: 1px solid var(--fl-borde-fuerte);
    border-bottom-width: 2px;
    border-radius: var(--fl-r-sm);
    box-shadow: 0 1px 0 rgb(0 0 0 / 0.05);
    line-height: 1.4;
    vertical-align: middle;
    white-space: nowrap;
}

.fl-tecla--sm { padding: 0 4px; font-size: 0.75em; }
.fl-tecla--lg { padding: 2px 8px; font-size: 0.95em; }

.fl-tecla-combo {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto-suave);
}
.fl-tecla-combo-sep { color: var(--fl-texto-tenue); font-size: 0.8em; }


/* ===== resources/css/componentes/time-picker.css ===== */
/* ==========================================================================
   Flora · Time-picker
   Input de hora con 2 campos numéricos (HH y MM) + steppers opcionales.
   Formato 24h por default. Valor se envía como HH:MM.
   ========================================================================== */

.fl-timepicker {
    display: inline-flex;
    align-items: center;
    gap: 0;
    height: var(--fl-alto-control-md);
    padding: 0 var(--fl-sp-3);
    font-family: inherit;
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto-fuerte);
    background: var(--fl-superficie);
    border: 1px solid var(--fl-borde-fuerte);
    border-radius: var(--fl-r-md);
    box-shadow: var(--fl-sombra-xs);
    transition: border-color var(--fl-t-rapido) var(--fl-ease-salida),
                box-shadow var(--fl-t-rapido) var(--fl-ease-salida);
    width: 120px;
}

.fl-timepicker:hover:not(:has(:disabled)) {
    border-color: var(--fl-borde-intenso);
}

.fl-timepicker:focus-within {
    outline: none;
    border-color: var(--fl-acento);
    box-shadow: 0 0 0 var(--fl-foco-ancho) var(--fl-acento-foco);
}

.fl-timepicker:has(:disabled) {
    background: var(--fl-fondo-sutil);
    opacity: 0.8;
}

/* Ícono de reloj al inicio (opcional) */
.fl-timepicker-icono {
    color: var(--fl-texto-tenue);
    margin-right: var(--fl-sp-2);
    flex: none;
}

.fl-timepicker-icono .fl-icono {
    width: 14px;
    height: 14px;
}

/* Inputs numéricos de hora y minuto */
.fl-timepicker-parte {
    flex: 1;
    width: 2ch;
    padding: 0;
    border: 0;
    background: transparent;
    font-family: inherit;
    font-size: inherit;
    color: inherit;
    text-align: center;
    font-variant-numeric: tabular-nums;
    -moz-appearance: textfield;
    outline: none;
}

.fl-timepicker-parte::-webkit-outer-spin-button,
.fl-timepicker-parte::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

.fl-timepicker-parte:focus {
    background: var(--fl-acento-suave);
    color: var(--fl-acento-texto);
    border-radius: var(--fl-r-sm);
}

.fl-timepicker-parte:disabled {
    cursor: not-allowed;
    color: var(--fl-texto-deshabilitado);
}

/* Separador ":" entre HH y MM */
.fl-timepicker-sep {
    color: var(--fl-texto-tenue);
    font-weight: var(--fl-peso-semibold);
    padding: 0 2px;
    user-select: none;
}

/* Steppers (botones up/down a la derecha).
   margin-right negativo DEBE igualar el padding-right del contenedor
   (var(--fl-sp-3)) para que los botones queden pegados al borde derecho
   del control, sin aire sobrante. */
.fl-timepicker-steppers {
    display: flex;
    flex-direction: column;
    gap: 0;
    margin-left: var(--fl-sp-2);
    margin-right: calc(-1 * var(--fl-sp-3));
    height: 100%;
    flex: none;
    border-left: 1px solid var(--fl-borde-sutil);
}

.fl-timepicker-stepper {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    flex: 1;
    padding: 0;
    background: transparent;
    border: 0;
    color: var(--fl-texto-suave);
    cursor: pointer;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida),
                color var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-timepicker-stepper:hover:not(:disabled) {
    background: var(--fl-superficie-hover);
    color: var(--fl-acento);
}

.fl-timepicker-stepper:first-child {
    border-radius: 0 var(--fl-r-md) 0 0;
    border-bottom: 1px solid var(--fl-borde-sutil);
}

.fl-timepicker-stepper:last-child {
    border-radius: 0 0 var(--fl-r-md) 0;
}

.fl-timepicker-stepper .fl-icono {
    width: 12px;
    height: 12px;
}

.fl-timepicker-stepper:active {
    background: var(--fl-superficie-activa);
}

/* Tamaños */
.fl-timepicker--sm {
    height: var(--fl-alto-control-sm);
    font-size: var(--fl-texto-sm);
    width: 118px;
    padding: 0 var(--fl-sp-2);
}

.fl-timepicker--sm .fl-timepicker-icono {
    margin-right: var(--fl-sp-1);
}

.fl-timepicker--sm .fl-timepicker-icono .fl-icono {
    width: 12px;
    height: 12px;
}

.fl-timepicker--sm .fl-timepicker-steppers {
    margin-left: var(--fl-sp-1);
    margin-right: calc(-1 * var(--fl-sp-2)); /* iguala padding-right sm */
}

.fl-timepicker--sm .fl-timepicker-stepper {
    width: 20px;
}

.fl-timepicker--sm .fl-timepicker-stepper .fl-icono {
    width: 10px;
    height: 10px;
}

.fl-timepicker--lg {
    height: var(--fl-alto-control-lg);
    font-size: var(--fl-texto-base);
    width: 160px;
    padding: 0 var(--fl-sp-4);
}

.fl-timepicker--lg .fl-timepicker-steppers {
    margin-right: calc(-1 * var(--fl-sp-4)); /* iguala padding-right lg */
}

.fl-timepicker--lg .fl-timepicker-stepper {
    width: 26px;
}

.fl-timepicker--lg .fl-timepicker-stepper .fl-icono {
    width: 14px;
    height: 14px;
}


/* ===== resources/css/componentes/toast.css ===== */
/* ==========================================================================
   Flora · Toast
   Notificaciones transitorias que aparecen en una esquina, con auto-dismiss
   y barra de progreso. Soporta stack múltiple.
   ========================================================================== */

.fl-toasts-contenedor {
    position: fixed;
    z-index: var(--fl-z-aviso);
    pointer-events: none;
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-2);
    padding: var(--fl-sp-4);
    max-width: min(420px, calc(100vw - var(--fl-sp-8)));
    width: 100%;
}

.fl-toasts-contenedor[data-fl-pos="arriba-derecha"]   { top: 0; right: 0; }
.fl-toasts-contenedor[data-fl-pos="arriba-izquierda"] { top: 0; left: 0; }
.fl-toasts-contenedor[data-fl-pos="arriba-centro"]    { top: 0; left: 50%; transform: translateX(-50%); }
.fl-toasts-contenedor[data-fl-pos="abajo-derecha"]    { bottom: 0; right: 0; flex-direction: column-reverse; }
.fl-toasts-contenedor[data-fl-pos="abajo-izquierda"]  { bottom: 0; left: 0; flex-direction: column-reverse; }
.fl-toasts-contenedor[data-fl-pos="abajo-centro"]     { bottom: 0; left: 50%; transform: translateX(-50%); flex-direction: column-reverse; }

/* --------------------------------------------------------------------------
   Toast individual
   -------------------------------------------------------------------------- */
.fl-toast {
    pointer-events: auto;
    display: flex;
    align-items: flex-start;
    gap: var(--fl-sp-3);
    padding: var(--fl-sp-3) var(--fl-sp-4);
    background: var(--fl-superficie-elevada);
    border: 1px solid var(--fl-borde);
    border-radius: var(--fl-r-lg);
    box-shadow: var(--fl-sombra-lg),
                0 0 0 1px rgb(0 0 0 / 0.03);
    min-width: 280px;
    position: relative;
    overflow: hidden;
    animation: fl-toast-entrada 380ms var(--fl-ease-resorte);
}

.fl-toast[data-fl-saliendo="true"] {
    animation: fl-toast-salida 220ms var(--fl-ease-entrada) forwards;
}

@keyframes fl-toast-entrada {
    from { transform: translateX(110%); opacity: 0; }
    50%  { opacity: 1; }
    to   { transform: translateX(0); opacity: 1; }
}

@keyframes fl-toast-salida {
    from { transform: translateX(0); opacity: 1; max-height: 100px; margin-bottom: var(--fl-sp-2); }
    to   { transform: translateX(110%); opacity: 0; max-height: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; }
}

/* Ícono */
.fl-toast-icono {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    color: var(--fl-texto-suave);
    margin-top: 1px;
}

.fl-toast-icono .fl-icono {
    width: 18px;
    height: 18px;
}

/* Contenido */
.fl-toast-contenido {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
    font-size: var(--fl-texto-sm);
    line-height: var(--fl-lh-ajustada);
}

.fl-toast-titulo {
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-fuerte);
    line-height: var(--fl-lh-compacta);
}

.fl-toast-mensaje {
    color: var(--fl-texto);
}

.fl-toast-acciones {
    display: flex;
    gap: var(--fl-sp-1);
    margin-top: var(--fl-sp-1);
}

/* Cerrar */
.fl-toast-cerrar {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    margin: -2px -4px 0 0;
    padding: 0;
    background: transparent;
    border: 0;
    border-radius: var(--fl-r-sm);
    color: var(--fl-texto-tenue);
    cursor: pointer;
    transition: background var(--fl-t-rapido) var(--fl-ease-salida),
                color var(--fl-t-rapido) var(--fl-ease-salida);
}

.fl-toast-cerrar:hover {
    background: var(--fl-superficie-hover);
    color: var(--fl-texto-fuerte);
}

.fl-toast-cerrar .fl-icono {
    width: 14px;
    height: 14px;
}

/* Barra de progreso inferior (auto-dismiss) */
.fl-toast-progreso {
    position: absolute;
    left: 0;
    bottom: 0;
    height: 2px;
    background: currentColor;
    opacity: 0.3;
    width: 100%;
    transform-origin: left center;
    animation: fl-toast-progreso var(--_duracion, 4000ms) linear forwards;
}

@keyframes fl-toast-progreso {
    from { transform: scaleX(1); }
    to   { transform: scaleX(0); }
}

/* --------------------------------------------------------------------------
   Variantes semánticas
   -------------------------------------------------------------------------- */
.fl-toast--exito {
    border-left: 3px solid var(--fl-exito);
}

.fl-toast--exito .fl-toast-icono {
    color: var(--fl-exito);
}

.fl-toast--error {
    border-left: 3px solid var(--fl-error);
}

.fl-toast--error .fl-toast-icono {
    color: var(--fl-error);
}

.fl-toast--advertencia {
    border-left: 3px solid var(--fl-advertencia);
}

.fl-toast--advertencia .fl-toast-icono {
    color: var(--fl-advertencia);
}

.fl-toast--info {
    border-left: 3px solid var(--fl-info);
}

.fl-toast--info .fl-toast-icono {
    color: var(--fl-info);
}

/* Destaque — toast sólido del color más fuerte de la paleta + texto blanco.
   Para mensajes de alto valor: confirmación premium, logro, suscripción. */
.fl-toast--destaque {
    background: var(--fl-destaque-fondo);
    border-left: 3px solid var(--fl-destaque-borde);
    color: var(--fl-destaque-texto);
    --fl-texto:          var(--fl-destaque-texto);
    --fl-texto-fuerte:   var(--fl-destaque-texto);
    --fl-texto-suave:    color-mix(in srgb, var(--fl-destaque-texto) 80%, transparent);
}

.fl-toast--destaque .fl-toast-icono,
.fl-toast--destaque .fl-toast-titulo,
.fl-toast--destaque .fl-toast-mensaje,
.fl-toast--destaque .fl-toast-cerrar {
    color: var(--fl-destaque-texto);
}

@media (prefers-reduced-motion: reduce) {
    .fl-toast { animation: none; }
    .fl-toast[data-fl-saliendo="true"] { animation: none; opacity: 0; }
    .fl-toast-progreso { animation: none; display: none; }
}


/* ===== resources/css/componentes/tooltip.css ===== */
/* ==========================================================================
   Flora · Tooltip
   Se activa via data-fl-tooltip="texto" en cualquier elemento. El runtime JS
   crea un popover posicionado. No requiere Blade component — es pure-attr.
   ========================================================================== */

.fl-tooltip {
    position: fixed;
    z-index: var(--fl-z-tooltip);
    pointer-events: none;
    background: var(--fl-neutro-900);
    color: var(--fl-neutro-0);
    padding: var(--fl-sp-1-5) var(--fl-sp-2-5);
    border-radius: var(--fl-r-sm);
    font-size: var(--fl-texto-xs);
    font-weight: var(--fl-peso-medio);
    line-height: 1.4;
    max-width: 280px;
    white-space: normal;
    box-shadow: 0 4px 12px rgb(0 0 0 / 0.15);
    opacity: 0;
    transform: translateY(4px) scale(0.95);
    transition: opacity 140ms var(--fl-ease-salida),
                transform 180ms var(--fl-ease-resorte);
}

[data-fl-enfasis="oscuro"] .fl-tooltip {
    background: var(--fl-neutro-100);
    color: var(--fl-neutro-950);
    box-shadow: 0 4px 12px rgb(0 0 0 / 0.5);
}

.fl-tooltip[data-fl-visible="true"] {
    opacity: 1;
    transform: translateY(0) scale(1);
}

/* Flecha apuntando al target */
.fl-tooltip::before {
    content: "";
    position: absolute;
    width: 8px;
    height: 8px;
    background: inherit;
    transform: rotate(45deg);
}

.fl-tooltip[data-fl-posicion="arriba"]::before {
    bottom: -4px;
    left: 50%;
    margin-left: -4px;
}

.fl-tooltip[data-fl-posicion="abajo"]::before {
    top: -4px;
    left: 50%;
    margin-left: -4px;
}

.fl-tooltip[data-fl-posicion="izquierda"]::before {
    right: -4px;
    top: 50%;
    margin-top: -4px;
}

.fl-tooltip[data-fl-posicion="derecha"]::before {
    left: -4px;
    top: 50%;
    margin-top: -4px;
}

/* Variante: tooltip más ancho (descripción) */
.fl-tooltip--ancho {
    max-width: 360px;
    padding: var(--fl-sp-2) var(--fl-sp-3);
    font-size: var(--fl-texto-sm);
    line-height: var(--fl-lh-ajustada);
}

@media (prefers-reduced-motion: reduce) {
    .fl-tooltip {
        transition: opacity 60ms linear;
        transform: none;
    }
    .fl-tooltip[data-fl-visible="true"] {
        transform: none;
    }
}


/* ===== resources/css/componentes/tour.css ===== */
/* ==========================================================================
   Flora · Tour (onboarding guiado)
   Overlay con hueco sobre el elemento destacado + popover de explicación.
   ========================================================================== */

.fl-tour-overlay {
    position: fixed;
    inset: 0;
    z-index: var(--fl-z-modal);
    pointer-events: none;
    background: transparent;
    opacity: 0;
    transition: opacity 220ms;
}
.fl-tour-overlay[data-fl-activo="true"] { opacity: 1; pointer-events: auto; }

/* Usamos un SVG con mask para el "hueco" */
.fl-tour-svg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: all;
}

.fl-tour-svg rect.fondo { fill: rgb(0 0 0 / 0.55); }
.fl-tour-svg rect.hueco { fill: black; }

.fl-tour-contorno {
    position: absolute;
    border: 2px solid var(--fl-destaque-fondo);
    border-radius: var(--fl-r-md);
    pointer-events: none;
    box-shadow: 0 0 0 2px var(--fl-acento-foco);
    transition: all 240ms var(--fl-ease-resorte);
    animation: fl-tour-pulso 2.2s infinite;
}

@keyframes fl-tour-pulso {
    0%, 100% { box-shadow: 0 0 0 0 rgb(59 130 246 / 0.4); }
    50% { box-shadow: 0 0 0 10px rgb(59 130 246 / 0); }
}

.fl-tour-panel {
    position: fixed;
    z-index: calc(var(--fl-z-modal) + 1);
    width: min(340px, 90vw);
    background: var(--fl-superficie-elevada);
    border-radius: var(--fl-r-lg);
    box-shadow: var(--fl-sombra-xl);
    padding: var(--fl-sp-4);
    transition: transform 240ms var(--fl-ease-resorte), opacity 160ms;
    opacity: 0;
    pointer-events: none;
}
.fl-tour-panel[data-fl-visible="true"] { opacity: 1; pointer-events: auto; }

.fl-tour-panel-titulo {
    font-size: var(--fl-texto-base);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-fuerte);
    margin-bottom: var(--fl-sp-1);
}

.fl-tour-panel-cuerpo {
    font-size: var(--fl-texto-sm);
    line-height: var(--fl-lh-comoda);
    color: var(--fl-texto);
}

.fl-tour-panel-pie {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-top: var(--fl-sp-3);
    padding-top: var(--fl-sp-2);
    border-top: 1px solid var(--fl-borde-sutil);
}

.fl-tour-puntos {
    display: inline-flex;
    gap: 4px;
}
.fl-tour-punto {
    width: 6px;
    height: 6px;
    border-radius: var(--fl-r-full);
    background: var(--fl-borde-intenso);
}
.fl-tour-punto[data-fl-activo="true"] { background: var(--fl-destaque-fondo); }


/* ===== resources/css/componentes/visor.css ===== */
/* ==========================================================================
   Flora · Visor multi-formato
   Overlay fullscreen para previsualizar PDFs, imágenes, videos, audio, MIDI, texto.
   Usa tokens de paleta (acento + texto-fuerte) para que el fondo y las
   superficies heredan el tono de la paleta activa.
   ========================================================================== */

.fl-visor-fondo {
    position: fixed;
    inset: 0;
    z-index: var(--fl-z-modal);
    display: none;
    flex-direction: column;
    /* Backdrop dark tintado con la paleta */
    background: radial-gradient(
        ellipse at top,
        color-mix(in srgb, var(--fl-acento) 18%, var(--fl-texto-fuerte)) 0%,
        color-mix(in srgb, var(--fl-acento) 8%, var(--fl-texto-fuerte)) 45%,
        var(--fl-texto-fuerte) 100%
    );
    opacity: 0;
    transition: opacity 220ms var(--fl-ease-salida);
}

.fl-visor-fondo[data-fl-abierto="true"] {
    display: flex;
    opacity: 1;
}

/* --------------------------------------------------------------------------
   Cabecera: título + acciones. Gradient acento → dark, mismo estilo que
   la botonera del panel del explorador para coherencia visual.
   -------------------------------------------------------------------------- */
.fl-visor-cabecera {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-3);
    padding: var(--fl-sp-3) var(--fl-sp-4);
    color: var(--fl-superficie);
    background: linear-gradient(
        135deg,
        var(--fl-acento) 0%,
        color-mix(in srgb, var(--fl-acento) 50%, var(--fl-texto-fuerte)) 45%,
        var(--fl-texto-fuerte) 100%
    );
    border-bottom: 1px solid color-mix(in srgb, var(--fl-superficie) 15%, transparent);
    flex: none;
    z-index: 2;
}

.fl-visor-titulo {
    flex: 1;
    min-width: 0;
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-semibold);
    letter-spacing: var(--fl-ls-compacto);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.fl-visor-meta {
    font-size: var(--fl-texto-xs);
    color: color-mix(in srgb, var(--fl-superficie) 70%, transparent);
    margin-left: var(--fl-sp-2);
    padding: 2px 8px;
    background: color-mix(in srgb, var(--fl-superficie) 12%, transparent);
    border-radius: var(--fl-r-full);
    font-variant-numeric: tabular-nums;
}

.fl-visor-meta:empty {
    display: none;
}

.fl-visor-acciones {
    display: flex;
    align-items: center;
    gap: 2px;
    flex: none;
}

.fl-visor-boton {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    padding: 0;
    background: transparent;
    border: 0;
    border-radius: var(--fl-r-md);
    color: color-mix(in srgb, var(--fl-superficie) 85%, transparent);
    cursor: pointer;
    transition: background 120ms, color 120ms, transform 140ms var(--fl-ease-resorte);
}

.fl-visor-boton:hover {
    background: color-mix(in srgb, var(--fl-superficie) 18%, transparent);
    color: var(--fl-superficie);
}

.fl-visor-boton--cerrar:hover {
    transform: rotate(90deg);
    background: var(--fl-error);
    color: var(--fl-superficie);
}

.fl-visor-boton .fl-icono {
    width: 18px;
    height: 18px;
}

/* --------------------------------------------------------------------------
   Cuerpo central: aquí va el contenido por tipo.
   Padding solo para media que necesita respiración (imagen, video, audio).
   PDF/iframe y texto usan el ancho completo.
   -------------------------------------------------------------------------- */
.fl-visor-cuerpo {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    position: relative;
    padding: var(--fl-sp-4);
}

/* Cuando el contenido es PDF u Office, el cuerpo no tiene padding */
.fl-visor-cuerpo:has(> div > .fl-visor-pdf),
.fl-visor-cuerpo:has(> .fl-visor-pdf) {
    padding: 0;
}

.fl-visor-contenido,
[data-fl-visor-contenido] {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
}

/* --------------------------------------------------------------------------
   Navegación prev/next (circular, acento al hover)
   -------------------------------------------------------------------------- */
.fl-visor-nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 48px;
    height: 48px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: color-mix(in srgb, var(--fl-texto-fuerte) 80%, transparent);
    backdrop-filter: blur(6px);
    border: 1px solid color-mix(in srgb, var(--fl-superficie) 15%, transparent);
    border-radius: var(--fl-r-full);
    color: var(--fl-superficie);
    cursor: pointer;
    z-index: 2;
    transition: background 120ms, transform 200ms var(--fl-ease-resorte), border-color 120ms;
}

.fl-visor-nav:hover {
    background: var(--fl-acento);
    border-color: var(--fl-acento);
    transform: translateY(-50%) scale(1.08);
}

.fl-visor-nav:disabled {
    opacity: 0.3;
    cursor: not-allowed;
}

.fl-visor-nav--izq { left: var(--fl-sp-3); }
.fl-visor-nav--der { right: var(--fl-sp-3); }

.fl-visor-nav .fl-icono {
    width: 20px;
    height: 20px;
}

/* --------------------------------------------------------------------------
   Contenidos por tipo
   -------------------------------------------------------------------------- */

/* Imagen con zoom */
.fl-visor-imagen {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    border-radius: var(--fl-r-md);
    box-shadow: 0 20px 60px -10px rgb(0 0 0 / 0.4);
    transition: transform 200ms var(--fl-ease-salida);
    cursor: zoom-in;
    user-select: none;
    -webkit-user-drag: none;
}

.fl-visor-imagen[data-fl-zoom="true"] {
    cursor: grab;
}

/* PDF via iframe nativo — ocupa TODO el espacio disponible */
.fl-visor-pdf {
    width: 100%;
    height: 100%;
    min-height: 0;
    border: 0;
    background: var(--fl-superficie);
    display: block;
}

/* Texto / código */
.fl-visor-texto {
    width: 100%;
    max-width: 960px;
    height: 100%;
    max-height: 82vh;
    padding: var(--fl-sp-5);
    background: var(--fl-superficie);
    color: var(--fl-texto);
    border-radius: var(--fl-r-lg);
    box-shadow: 0 20px 60px -10px rgb(0 0 0 / 0.4);
    overflow-y: auto;
    font-family: var(--fl-fuente-mono);
    font-size: var(--fl-texto-sm);
    line-height: var(--fl-lh-relajada);
    white-space: pre-wrap;
    word-break: break-word;
}

/* Video */
.fl-visor-video {
    max-width: 100%;
    max-height: 100%;
    border-radius: var(--fl-r-lg);
    background: var(--fl-texto-fuerte);
    box-shadow: 0 20px 60px -10px rgb(0 0 0 / 0.5);
}

/* --------------------------------------------------------------------------
   Audio / MIDI — reproductor amplio con disco giratorio + timeline prominente
   -------------------------------------------------------------------------- */
.fl-visor-audio {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--fl-sp-5);
    padding: var(--fl-sp-7) var(--fl-sp-6);
    width: 100%;
    max-width: 820px;
    background: linear-gradient(
        135deg,
        color-mix(in srgb, var(--fl-acento) 40%, var(--fl-texto-fuerte)) 0%,
        color-mix(in srgb, var(--fl-acento) 18%, var(--fl-texto-fuerte)) 50%,
        var(--fl-texto-fuerte) 100%
    );
    border: 1px solid color-mix(in srgb, var(--fl-acento) 30%, transparent);
    border-radius: var(--fl-r-2xl);
    color: var(--fl-superficie);
    box-shadow: 0 30px 80px -20px rgb(0 0 0 / 0.5),
                inset 0 1px 0 0 color-mix(in srgb, var(--fl-superficie) 10%, transparent);
}

.fl-visor-audio-disco {
    width: 240px;
    height: 240px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: conic-gradient(
        from 0deg,
        var(--fl-acento),
        color-mix(in srgb, var(--fl-acento) 40%, var(--fl-superficie)),
        color-mix(in srgb, var(--fl-acento) 70%, var(--fl-texto-fuerte)),
        var(--fl-acento)
    );
    border-radius: 50%;
    position: relative;
    box-shadow: 0 30px 60px -15px rgb(0 0 0 / 0.6),
                inset 0 0 0 3px color-mix(in srgb, var(--fl-superficie) 18%, transparent);
    animation: fl-visor-audio-girar 8s linear infinite;
}

.fl-visor-audio-disco::before {
    content: "";
    position: absolute;
    inset: 14%;
    background: color-mix(in srgb, var(--fl-texto-fuerte) 80%, transparent);
    border-radius: 50%;
    box-shadow: inset 0 0 30px rgb(0 0 0 / 0.5);
    z-index: 1;
}

.fl-visor-audio-disco .fl-icono {
    width: 100px;
    height: 100px;
    color: var(--fl-superficie);
    filter: drop-shadow(0 4px 10px rgb(0 0 0 / 0.6));
    z-index: 2;
    position: relative;
}

@keyframes fl-visor-audio-girar {
    to { transform: rotate(360deg); }
}

.fl-visor-audio-info {
    text-align: center;
    width: 100%;
}

.fl-visor-audio-nombre {
    font-size: var(--fl-texto-xl);
    font-weight: var(--fl-peso-semibold);
    word-break: break-word;
    letter-spacing: var(--fl-ls-compacto);
    color: var(--fl-superficie);
    margin-bottom: 4px;
}

.fl-visor-audio-sub {
    font-size: var(--fl-texto-xs);
    color: color-mix(in srgb, var(--fl-superficie) 60%, transparent);
    text-transform: uppercase;
    letter-spacing: var(--fl-ls-mayus);
}

.fl-visor-audio-control {
    width: 100%;
    max-width: 700px;
}

/* ==========================================================================
   Player custom (audio + MIDI) — timeline prominente, touch-friendly
   ========================================================================== */
.fl-player {
    display: flex;
    flex-direction: column;
    width: 100%;
    max-width: 700px;
    gap: var(--fl-sp-2);
}

.fl-player-barra-control {
    display: flex;
    align-items: center;
    gap: var(--fl-sp-3);
    width: 100%;
    padding: var(--fl-sp-2-5) var(--fl-sp-3);
    background: color-mix(in srgb, var(--fl-texto-fuerte) 60%, transparent);
    border: 1px solid color-mix(in srgb, var(--fl-superficie) 10%, transparent);
    border-radius: var(--fl-r-lg);
    box-shadow: inset 0 1px 0 0 color-mix(in srgb, var(--fl-superficie) 8%, transparent);
    color: var(--fl-superficie);
    backdrop-filter: blur(10px);
}

.fl-player-play {
    flex: none;
    width: 52px;
    height: 52px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    background: var(--fl-acento);
    border: 0;
    border-radius: var(--fl-r-full);
    color: var(--fl-acento-texto-sobre);
    cursor: pointer;
    box-shadow: 0 8px 24px -6px color-mix(in srgb, var(--fl-acento) 70%, transparent);
    transition: transform 140ms var(--fl-ease-resorte), background 120ms;
}

.fl-player-play:hover {
    transform: scale(1.06);
    background: var(--fl-acento-hover);
}

.fl-player-play:active { transform: scale(0.95); }

.fl-player-play .fl-icono { width: 20px; height: 20px; }

.fl-player-tiempo,
.fl-player-total {
    flex: none;
    font-family: var(--fl-fuente-mono);
    font-size: var(--fl-texto-sm);
    color: color-mix(in srgb, var(--fl-superficie) 85%, transparent);
    font-variant-numeric: tabular-nums;
    min-width: 48px;
    text-align: center;
}

.fl-player-barra {
    flex: 1;
    min-width: 120px;
    height: 10px;
    background: color-mix(in srgb, var(--fl-superficie) 15%, transparent);
    border-radius: var(--fl-r-full);
    cursor: pointer;
    position: relative;
    touch-action: none;
}

.fl-player-barra::before {
    content: "";
    position: absolute;
    inset: -12px 0;
}

.fl-player-progreso {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    background: linear-gradient(
        90deg,
        var(--fl-acento),
        color-mix(in srgb, var(--fl-acento) 50%, var(--fl-superficie))
    );
    border-radius: var(--fl-r-full);
    box-shadow: 0 0 12px -2px color-mix(in srgb, var(--fl-acento) 70%, transparent);
    pointer-events: none;
}

.fl-player-handle {
    position: absolute;
    top: 50%;
    left: 0;
    transform: translate(-50%, -50%);
    width: 18px;
    height: 18px;
    background: var(--fl-superficie);
    border-radius: var(--fl-r-full);
    box-shadow: 0 2px 10px rgb(0 0 0 / 0.5),
                0 0 0 3px color-mix(in srgb, var(--fl-acento) 45%, transparent);
    transition: width 140ms var(--fl-ease-resorte),
                height 140ms var(--fl-ease-resorte);
    pointer-events: none;
}

.fl-player-barra:hover .fl-player-handle,
.fl-player-barra[data-fl-seeking="true"] .fl-player-handle {
    width: 24px;
    height: 24px;
}

.fl-player-volumen {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    background: transparent;
    border: 0;
    border-radius: var(--fl-r-md);
    color: color-mix(in srgb, var(--fl-superficie) 70%, transparent);
    cursor: pointer;
    transition: background 120ms, color 120ms;
}

.fl-player-volumen:hover {
    background: color-mix(in srgb, var(--fl-superficie) 12%, transparent);
    color: var(--fl-superficie);
}

.fl-player-volumen .fl-icono { width: 18px; height: 18px; }

.fl-player-error {
    color: var(--fl-superficie);
    padding: 12px;
    font-size: 13px;
    background: color-mix(in srgb, var(--fl-error) 25%, transparent);
    border-radius: var(--fl-r-md);
}

/* Mobile: disco más chico, reproductor más denso */
@media (max-width: 640px) {
    .fl-visor-audio {
        padding: var(--fl-sp-5) var(--fl-sp-3);
        gap: var(--fl-sp-3);
    }
    .fl-visor-audio-disco {
        width: 160px;
        height: 160px;
    }
    .fl-visor-audio-disco .fl-icono {
        width: 36px;
        height: 36px;
    }
    .fl-visor-audio-nombre {
        font-size: var(--fl-texto-base);
    }
    .fl-player-barra-control {
        gap: var(--fl-sp-1-5);
        padding: var(--fl-sp-2);
    }
    .fl-player-play {
        width: 44px;
        height: 44px;
    }
    .fl-player-tiempo,
    .fl-player-total {
        font-size: 10px;
        min-width: 38px;
    }
    .fl-player-barra {
        height: 10px;
    }
    .fl-player-handle {
        width: 18px;
        height: 18px;
    }
    .fl-player-volumen {
        display: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    .fl-visor-audio-disco,
    .fl-player-play {
        animation: none;
        transition: none;
    }
}

/* --------------------------------------------------------------------------
   Empty state / no hay preview
   -------------------------------------------------------------------------- */
.fl-visor-no-preview {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--fl-sp-3);
    color: color-mix(in srgb, var(--fl-superficie) 65%, transparent);
    text-align: center;
    padding: var(--fl-sp-10);
    max-width: 480px;
}

.fl-visor-no-preview-icono {
    width: 96px;
    height: 96px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: color-mix(in srgb, var(--fl-acento) 20%, transparent);
    border: 1px solid color-mix(in srgb, var(--fl-acento) 30%, transparent);
    border-radius: var(--fl-r-full);
    color: color-mix(in srgb, var(--fl-acento) 70%, var(--fl-superficie));
}

.fl-visor-no-preview-icono .fl-icono {
    width: 40px;
    height: 40px;
}

.fl-visor-no-preview-titulo {
    font-size: var(--fl-texto-lg);
    color: var(--fl-superficie);
    font-weight: var(--fl-peso-semibold);
    letter-spacing: var(--fl-ls-compacto);
}

/* Footer con info de navegación */
.fl-visor-pie {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--fl-sp-2);
    padding: var(--fl-sp-2);
    color: color-mix(in srgb, var(--fl-superficie) 60%, transparent);
    font-size: var(--fl-texto-xs);
    font-variant-numeric: tabular-nums;
    flex: none;
    background: color-mix(in srgb, var(--fl-texto-fuerte) 70%, transparent);
    backdrop-filter: blur(6px);
    border-top: 1px solid color-mix(in srgb, var(--fl-superficie) 10%, transparent);
}


/* ===== resources/css/componentes/wizard.css ===== */
/* ==========================================================================
   Flora · Wizard (formulario multi-paso)
   Indicador horizontal tipo stepper clásico: círculo arriba, etiqueta
   debajo, línea entre círculos posicionada absolutamente (siempre centrada
   entre centros de círculo, sin importar el ancho de los labels).

   Estados fuertemente diferenciados:
   · Completado: círculo sólido acento + check + conector acento
   · Actual:     círculo dark acento + halo pulsante + escala
   · Futuro:     círculo con borde dashed + bg transparente (placeholder)
   ========================================================================== */

.fl-wizard {
    display: flex;
    flex-direction: column;
    gap: var(--fl-sp-5);
    width: 100%;
}

/* --------------------------------------------------------------------------
   Indicador de pasos — full-width, circles-plus-labels-below
   -------------------------------------------------------------------------- */
.fl-wizard-pasos {
    display: flex;
    align-items: flex-start;
    gap: 0;
    padding: 10px 0 0;
    margin: 0;
    list-style: none;
    counter-reset: paso;
    width: 100%;
    box-sizing: border-box;
    position: relative;
    overflow: visible;
}

/* Cada paso ocupa la misma fracción; su círculo y etiqueta se centran
   horizontalmente dentro de esa fracción. La línea entre pasos se dibuja
   con un ::after absoluto anclado al centro del círculo, con width:100%
   — así llega exactamente al centro del siguiente paso. */
.fl-wizard-paso {
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--fl-sp-2);
    min-width: 0;
    counter-increment: paso;
    position: relative;
    padding: 0 4px;
    box-sizing: border-box;
}

.fl-wizard-paso-circulo {
    flex: none;
    width: 36px;
    height: 36px;
    border-radius: var(--fl-r-full);
    background: var(--fl-superficie);
    border: 2px solid var(--fl-borde-fuerte);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: var(--fl-texto-sm);
    font-weight: var(--fl-peso-semibold);
    color: var(--fl-texto-suave);
    transition: background var(--fl-t-medio) var(--fl-ease-salida),
                border-color var(--fl-t-medio) var(--fl-ease-salida),
                border-style var(--fl-t-medio) var(--fl-ease-salida),
                color var(--fl-t-medio) var(--fl-ease-salida),
                box-shadow var(--fl-t-medio) var(--fl-ease-salida),
                transform var(--fl-t-medio) var(--fl-ease-resorte);
    position: relative;
    z-index: 2;
}

.fl-wizard-paso-circulo::before {
    content: counter(paso);
}

.fl-wizard-paso-circulo .fl-icono {
    width: 18px;
    height: 18px;
    stroke-width: 3;
}

.fl-wizard-paso-etiqueta {
    font-size: var(--fl-texto-sm);
    color: var(--fl-texto-suave);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
    text-align: center;
    transition: color var(--fl-t-medio) var(--fl-ease-salida),
                font-weight var(--fl-t-medio) var(--fl-ease-salida);
}

/* Conector — línea CONTINUA de centro a centro de los círculos.
   Los círculos (z-index:2, background opaco) se "sientan" encima tapando la
   porción que cubren, así visualmente queda una única línea corrida desde
   el primer círculo hasta el último (sin sobresalir por los extremos).
   - top: 18px - 1.5px = 16.5px → centra la línea de 3px en el centro
     vertical del círculo de 36px.
   - left: 50%      → arranca en el centro del círculo actual.
   - width: 100%    → llega al centro del círculo del próximo paso. */
.fl-wizard-paso:not(:last-child)::after {
    content: "";
    position: absolute;
    top: 16.5px;
    left: 50%;
    width: 100%;
    height: 3px;
    background: color-mix(in srgb, var(--fl-acento) 15%, var(--fl-borde));
    transition: background var(--fl-t-medio) var(--fl-ease-salida);
    z-index: 1;
}

/* --------------------------------------------------------------------------
   Estado: COMPLETADO
   -------------------------------------------------------------------------- */
.fl-wizard-paso[data-fl-estado="completado"] .fl-wizard-paso-circulo {
    background: linear-gradient(
        135deg,
        var(--fl-acento-500) 0%,
        var(--fl-acento-700) 100%
    );
    border-color: var(--fl-acento-700);
    color: white;
    box-shadow:
        0 2px 6px -1px color-mix(in srgb, var(--fl-acento) 45%, transparent),
        inset 0 1px 0 color-mix(in srgb, white 25%, transparent);
}

.fl-wizard-paso[data-fl-estado="completado"] .fl-wizard-paso-circulo::before {
    content: none;
}

.fl-wizard-paso[data-fl-estado="completado"]::after {
    background: linear-gradient(
        to right,
        var(--fl-acento-600) 0%,
        var(--fl-acento-500) 100%
    );
}

.fl-wizard-paso[data-fl-estado="completado"] .fl-wizard-paso-etiqueta {
    color: var(--fl-texto-fuerte);
    font-weight: var(--fl-peso-medio);
}

/* --------------------------------------------------------------------------
   Estado: ACTUAL
   -------------------------------------------------------------------------- */
.fl-wizard-paso[data-fl-estado="actual"] .fl-wizard-paso-circulo {
    background: linear-gradient(
        135deg,
        var(--fl-acento-700) 0%,
        var(--fl-acento-950) 100%
    );
    border-color: var(--fl-acento-900);
    color: white;
    transform: scale(1.08);
    animation: fl-wizard-pulso-actual 2.2s ease-in-out infinite;
}

@keyframes fl-wizard-pulso-actual {
    0%, 100% {
        box-shadow:
            0 0 0 4px color-mix(in srgb, var(--fl-acento) 20%, transparent),
            0 4px 14px -2px color-mix(in srgb, var(--fl-acento) 60%, transparent),
            inset 0 1px 0 color-mix(in srgb, white 25%, transparent);
    }
    50% {
        box-shadow:
            0 0 0 8px color-mix(in srgb, var(--fl-acento) 12%, transparent),
            0 4px 16px -2px color-mix(in srgb, var(--fl-acento) 80%, transparent),
            inset 0 1px 0 color-mix(in srgb, white 25%, transparent);
    }
}

.fl-wizard-paso[data-fl-estado="actual"] .fl-wizard-paso-etiqueta {
    color: var(--fl-acento-texto);
    font-weight: var(--fl-peso-bold);
}

/* --------------------------------------------------------------------------
   Estado: FUTURO (placeholder)
   -------------------------------------------------------------------------- */
.fl-wizard-paso[data-fl-estado="futuro"] .fl-wizard-paso-circulo {
    background: var(--fl-superficie);
    border-style: dashed;
    border-color: color-mix(in srgb, var(--fl-acento) 30%, var(--fl-borde));
    color: var(--fl-texto-tenue);
    box-shadow: none;
}

.fl-wizard-paso[data-fl-estado="futuro"] .fl-wizard-paso-etiqueta {
    color: var(--fl-texto-tenue);
    font-weight: var(--fl-peso-regular);
    font-style: italic;
}

/* Pasos clickeables — sólo los completados pueden ser navegables hacia atrás */
.fl-wizard-paso[role="button"] {
    cursor: pointer;
}

.fl-wizard-paso[role="button"]:hover .fl-wizard-paso-circulo {
    transform: scale(1.1);
    box-shadow:
        0 0 0 4px color-mix(in srgb, var(--fl-acento) 30%, transparent),
        0 6px 16px -2px color-mix(in srgb, var(--fl-acento) 55%, transparent),
        inset 0 1px 0 color-mix(in srgb, white 25%, transparent);
}

/* Mobile — etiquetas más chicas y truncadas con ellipsis */
@media (max-width: 640px) {
    .fl-wizard-paso {
        padding: 0 2px;
    }
    .fl-wizard-paso-etiqueta {
        font-size: var(--fl-texto-xs);
    }
    .fl-wizard-paso-circulo {
        width: 32px;
        height: 32px;
    }
    .fl-wizard-paso-circulo .fl-icono {
        width: 16px;
        height: 16px;
    }
    .fl-wizard-paso:not(:last-child)::after {
        /* Mobile: círculo 32px → centro vertical en y=16, línea de 3px centrada */
        top: 14.5px;
    }
    .fl-wizard-paso[data-fl-estado="actual"] .fl-wizard-paso-circulo {
        transform: scale(1.05);
    }
}

@media (max-width: 420px) {
    /* En pantallas muy chicas ocultamos etiquetas completamente para
       evitar wrap/truncado feo con muchos pasos. */
    .fl-wizard-paso-etiqueta {
        display: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    .fl-wizard-paso[data-fl-estado="actual"] .fl-wizard-paso-circulo {
        animation: none;
    }
    .fl-wizard-paso-circulo {
        transition: none;
    }
}

/* --------------------------------------------------------------------------
   Panel del paso actual — cada paso como pane colapsable
   -------------------------------------------------------------------------- */
.fl-wizard-panel {
    display: none;
    animation: fl-wizard-entrada 240ms var(--fl-ease-salida);
}

.fl-wizard-panel[data-fl-activo="true"] {
    display: block;
}

@keyframes fl-wizard-entrada {
    from { opacity: 0; transform: translateX(8px); }
    to   { opacity: 1; transform: translateX(0); }
}

/* --------------------------------------------------------------------------
   Navegación al pie — prev/next
   -------------------------------------------------------------------------- */
.fl-wizard-navegacion {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--fl-sp-3);
    padding-top: var(--fl-sp-4);
    border-top: 1px solid var(--fl-borde-sutil);
}

.fl-wizard-navegacion-grupo {
    display: flex;
    gap: var(--fl-sp-2);
}


/* ===== resources/css/zz-mobile.css ===== */
/* ==========================================================================
   Flora · Mobile layer (sort-last)
   Refuerzos y overrides para que la librería sea usable en mobile:
   - Touch-targets WCAG 2.1 (min 44px) en interactivos
   - Evitar zoom iOS en inputs (font-size ≥ 16px)
   - Overlays adaptados (modal, date-picker, paleta-comandos → bottom-sheet)
   - Dropdowns/popovers constreñidos al viewport
   - Safe-area iOS (notch)

   Este archivo se carga AL FINAL del bundle (orden natural de build).
   Solo contiene reglas @media — no afecta desktop.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Safe-area & base mobile
   -------------------------------------------------------------------------- */
@supports (padding: env(safe-area-inset-bottom)) {
    :root {
        --fl-safe-top: env(safe-area-inset-top, 0);
        --fl-safe-bottom: env(safe-area-inset-bottom, 0);
        --fl-safe-left: env(safe-area-inset-left, 0);
        --fl-safe-right: env(safe-area-inset-right, 0);
    }
}

/* --------------------------------------------------------------------------
   Mobile (≤ 767px): Touch targets + inputs sin zoom
   -------------------------------------------------------------------------- */
@media (max-width: 767px) {

    /* Controles táctiles: mínimo 44x44 (WCAG 2.1 SC 2.5.5) */
    .fl-boton:not(.fl-boton--xs):not(.fl-boton--sm),
    .fl-campo-entrada,
    .fl-textarea,
    .fl-select-trigger,
    .fl-autocompletar-input,
    .fl-dropdown-item,
    .fl-menu-contextual-item,
    .fl-paleta-comandos-item,
    .fl-autocompletar-opcion,
    .fl-tabs-tab,
    .fl-paginacion-item,
    .fl-breadcrumb-item a,
    .fl-date-picker-trigger,
    .fl-time-picker-trigger,
    .fl-sidebar-item,
    .fl-navbar-item,
    .fl-acordeon-titulo,
    .fl-colapsable-titulo {
        min-height: 44px;
    }

    /* Botones sm: subir apenas para que queden usables, sin romper layouts */
    .fl-boton--sm { min-height: 40px; }

    /* Iconos-botón circulares: asegurar 44×44 */
    .fl-boton--icono:not(.fl-boton--xs):not(.fl-boton--sm) {
        min-width: 44px;
    }

    /* Checkbox/radio: ampliar área táctil mediante el label wrapper */
    .fl-checkbox,
    .fl-radio {
        min-height: 44px;
        align-items: center;
    }

    /* Iconos de check/radio propios: agrandar mínimamente para tap */
    .fl-switch { min-height: 28px; }

    /* Prevenir zoom iOS: inputs con ≥ 16px de texto */
    .fl-campo-entrada,
    .fl-textarea,
    .fl-select-trigger,
    .fl-autocompletar-input,
    .fl-codigo-otp input,
    input[type="text"],
    input[type="email"],
    input[type="password"],
    input[type="tel"],
    input[type="number"],
    input[type="search"],
    input[type="url"],
    input[type="date"],
    input[type="datetime-local"],
    input[type="time"],
    select,
    textarea {
        font-size: max(16px, var(--fl-texto-sm));
    }

    /* --------------------------------------------------------------------------
       Overlays: modal con safe-area y modal--full a pantalla completa.
       El ancho ya lo maneja modal.css vía min(Xvw, Ypx) — no forzamos
       width: 100% acá porque eso pisa el sizing fluido. */
    .fl-modal:not(.fl-modal--full) {
        padding-bottom: var(--fl-safe-bottom, 0);
    }

    /* Modal full: usa toda la pantalla */
    .fl-modal--full {
        border-radius: 0;
        height: 100dvh;
        max-height: 100dvh;
    }

    /* --------------------------------------------------------------------------
       Dropdown / Popover / Menú contextual: ancho al viewport
       -------------------------------------------------------------------------- */
    .fl-dropdown-menu--portal,
    .fl-popover,
    .fl-menu-contextual {
        max-width: calc(100vw - var(--fl-sp-4));
    }

    /* Paleta de comandos: fullscreen-ish */
    .fl-paleta-comandos-contenedor {
        inset: var(--fl-sp-4) var(--fl-sp-2) auto;
        transform: none;
        width: calc(100vw - var(--fl-sp-4));
        max-width: 100%;
    }

    /* --------------------------------------------------------------------------
       Date-picker: bottom-sheet fullscreen
       -------------------------------------------------------------------------- */
    .fl-date-picker-panel,
    .fl-time-picker-panel,
    .fl-selector-rango-fecha-panel {
        position: fixed !important;
        inset: auto 0 0 0 !important;
        max-width: 100% !important;
        width: 100% !important;
        border-radius: var(--fl-r-2xl) var(--fl-r-2xl) 0 0 !important;
        padding-bottom: var(--fl-safe-bottom, var(--fl-sp-4)) !important;
        transform: translateY(0) !important;
    }

    /* --------------------------------------------------------------------------
       Tabla-datos: scroll horizontal forzado + sticky header
       -------------------------------------------------------------------------- */
    .fl-tabla-datos-wrapper,
    .fl-tabla-datos-scroll,
    .fl-tabla-wrapper {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        max-width: 100%;
    }

    .fl-tabla-datos {
        min-width: max-content;
    }

    /* --------------------------------------------------------------------------
       Sidebar: ya tiene @media en componente, reforzar off-canvas
       -------------------------------------------------------------------------- */
    .fl-sidebar {
        padding-bottom: max(var(--fl-sp-4), var(--fl-safe-bottom, 0));
    }

    /* --------------------------------------------------------------------------
       Containers que no se desbordan
       -------------------------------------------------------------------------- */
    body,
    .docs-main,
    .fl-contenedor {
        overflow-x: hidden;
    }

    /* Grillas auto-fit: colapsan a 1 columna si minmax no lo logra */
    .fl-grilla[style*="repeat(auto-fit"] {
        grid-template-columns: 1fr !important;
    }

    /* --------------------------------------------------------------------------
       Formularios stack en mobile
       -------------------------------------------------------------------------- */
    .fl-fila:not(.fl-fila--no-wrap) {
        flex-wrap: wrap;
    }

    /* Tabs en mobile: scroll horizontal */
    .fl-tabs-lista {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }
    .fl-tabs-lista::-webkit-scrollbar { display: none; }

    /* Wizard en mobile: pasos verticales si hay espacio apretado */
    .fl-wizard-pasos {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }
    .fl-wizard-pasos::-webkit-scrollbar { display: none; }

    /* --------------------------------------------------------------------------
       Gantt / Kanban / Calendario / Grilla-turnos / Organigrama: overflow
       -------------------------------------------------------------------------- */
    .fl-gantt,
    .fl-kanban,
    .fl-calendario-grid,
    .fl-grilla-turnos,
    .fl-organigrama,
    .fl-heatmap-calendario {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        max-width: 100%;
    }

    /* --------------------------------------------------------------------------
       Header sticky puede robar espacio en mobile; darle padding inferior
       -------------------------------------------------------------------------- */
    .fl-header--sticky + * {
        padding-top: var(--fl-sp-2);
    }

    /* --------------------------------------------------------------------------
       Barra inferior mobile: respetar safe-area
       -------------------------------------------------------------------------- */
    .fl-barra-inferior-mobile {
        padding-bottom: calc(var(--fl-sp-2) + var(--fl-safe-bottom, 0));
    }

    /* --------------------------------------------------------------------------
       Cajón (drawer): full-width en mobile
       -------------------------------------------------------------------------- */
    .fl-cajon--izquierda,
    .fl-cajon--derecha {
        width: min(320px, 88vw);
    }
}

/* --------------------------------------------------------------------------
   Tablets (768-1023): ajustes menores
   -------------------------------------------------------------------------- */
@media (min-width: 768px) and (max-width: 1023px) {
    .fl-tabla-datos-wrapper,
    .fl-gantt,
    .fl-kanban,
    .fl-organigrama {
        overflow-x: auto;
    }
}


